diff --git a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h index 8bb00e5e..bb82381a 100644 --- a/include/FramelessHelper/Quick/private/framelessquickhelper_p.h +++ b/include/FramelessHelper/Quick/private/framelessquickhelper_p.h @@ -65,7 +65,7 @@ class FRAMELESSHELPER_QUICK_API FramelessQuickHelperPrivate : public QObject Q_NODISCARD bool isWindowFixedSize() const; void setWindowFixedSize(const bool value); - void emitSignalForAllInstances(const char *signal); + void emitSignalForAllInstances(const QByteArray &signal); private: Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const; diff --git a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h index f1d69f40..555f0582 100644 --- a/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h +++ b/include/FramelessHelper/Widgets/private/framelesswidgetshelper_p.h @@ -61,7 +61,7 @@ class FRAMELESSHELPER_WIDGETS_API FramelessWidgetsHelperPrivate : public QObject Q_NODISCARD bool isWindowFixedSize() const; void setWindowFixedSize(const bool value); - void emitSignalForAllInstances(const char *signal); + void emitSignalForAllInstances(const QByteArray &signal); private: Q_NODISCARD QRect mapWidgetGeometryToScene(const QWidget * const widget) const; diff --git a/src/core/framelessconfig.cpp b/src/core/framelessconfig.cpp index 91dbfb9c..b60780d3 100644 --- a/src/core/framelessconfig.cpp +++ b/src/core/framelessconfig.cpp @@ -34,17 +34,23 @@ using namespace Global; FRAMELESSHELPER_STRING_CONSTANT2(ConfigFileName, ".framelesshelper.ini") -static constexpr const struct +static const struct { - const char *env = nullptr; - const char *ini = nullptr; + const QByteArray env = {}; + const QByteArray cfg = {}; } OptionsTable[] = { - {"FRAMELESSHELPER_USE_CROSS_PLATFORM_QT_IMPLEMENTATION", "Options/UseCrossPlatformQtImplementation"}, - {"FRAMELESSHELPER_FORCE_HIDE_WINDOW_FRAME_BORDER", "Options/ForceHideWindowFrameBorder"}, - {"FRAMELESSHELPER_FORCE_SHOW_WINDOW_FRAME_BORDER", "Options/ForceShowWindowFrameBorder"}, - {"FRAMELESSHELPER_DISABLE_WINDOWS_SNAP_LAYOUTS", "Options/DisableWindowsSnapLayouts"}, - {"FRAMELESSHELPER_WINDOW_USE_ROUND_CORNERS", "Options/WindowUseRoundCorners"}, - {"FRAMELESSHELPER_CENTER_WINDOW_BEFORE_SHOW", "Options/CenterWindowBeforeShow"} + {FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_USE_CROSS_PLATFORM_QT_IMPLEMENTATION"), + FRAMELESSHELPER_BYTEARRAY_LITERAL("Options/UseCrossPlatformQtImplementation")}, + {FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_FORCE_HIDE_WINDOW_FRAME_BORDER"), + FRAMELESSHELPER_BYTEARRAY_LITERAL("Options/ForceHideWindowFrameBorder")}, + {FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_FORCE_SHOW_WINDOW_FRAME_BORDER"), + FRAMELESSHELPER_BYTEARRAY_LITERAL("Options/ForceShowWindowFrameBorder")}, + {FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_DISABLE_WINDOWS_SNAP_LAYOUTS"), + FRAMELESSHELPER_BYTEARRAY_LITERAL("Options/DisableWindowsSnapLayouts")}, + {FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_WINDOW_USE_ROUND_CORNERS"), + FRAMELESSHELPER_BYTEARRAY_LITERAL("Options/WindowUseRoundCorners")}, + {FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_CENTER_WINDOW_BEFORE_SHOW"), + FRAMELESSHELPER_BYTEARRAY_LITERAL("Options/CenterWindowBeforeShow")} }; static constexpr const auto OptionCount = std::size(OptionsTable); @@ -86,8 +92,9 @@ void FramelessConfig::reload(const bool force) return new QSettings(appDir.filePath(kConfigFileName), QSettings::IniFormat); }()); for (int i = 0; i != OptionCount; ++i) { - const bool on = (qEnvironmentVariableIsSet(OptionsTable[i].env) && (qEnvironmentVariableIntValue(OptionsTable[i].env) > 0)) - || (!configFile.isNull() && configFile->value(QUtf8String(OptionsTable[i].ini), false).toBool()); + const bool on = (qEnvironmentVariableIsSet(OptionsTable[i].env.constData()) + && (qEnvironmentVariableIntValue(OptionsTable[i].env.constData()) > 0)) + || (!configFile.isNull() && configFile->value(QUtf8String(OptionsTable[i].cfg), false).toBool()); g_data()->options[i] = on; } g_data()->loaded = true; diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index abdd4c06..516265f1 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -111,7 +111,7 @@ void FramelessQuickHelperPrivate::setTitleBarItem(QQuickItem *value) return; } data->titleBarItem = value; - emitSignalForAllInstances("titleBarItemChanged"); + emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("titleBarItemChanged")); } void FramelessQuickHelperPrivate::attachToWindow() @@ -184,7 +184,7 @@ void FramelessQuickHelperPrivate::attachToWindow() if (FramelessConfig::instance()->isSet(Option::CenterWindowBeforeShow)) { moveWindowToDesktopCenter(); } - emitSignalForAllInstances("ready"); + emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("ready")); }); } @@ -305,7 +305,7 @@ void FramelessQuickHelperPrivate::bringWindowToFront() window->show(); } if (window->visibility() == QQuickWindow::Minimized) { - window->showNormal(); // ### FIXME + window->showNormal(); // ### FIXME: we should not show normal, we should restore the previous state. } window->raise(); window->requestActivate(); @@ -353,10 +353,10 @@ void FramelessQuickHelperPrivate::setWindowFixedSize(const bool value) Q_EMIT q->windowFixedSizeChanged(); } -void FramelessQuickHelperPrivate::emitSignalForAllInstances(const char *signal) +void FramelessQuickHelperPrivate::emitSignalForAllInstances(const QByteArray &signal) { - Q_ASSERT(signal); - if (!signal) { + Q_ASSERT(!signal.isEmpty()); + if (signal.isEmpty()) { return; } Q_Q(FramelessQuickHelper); @@ -370,7 +370,7 @@ void FramelessQuickHelperPrivate::emitSignalForAllInstances(const char *signal) return; } for (auto &&instance : qAsConst(instances)) { - QMetaObject::invokeMethod(instance, signal); + QMetaObject::invokeMethod(instance, signal.constData()); } } @@ -397,31 +397,31 @@ bool FramelessQuickHelperPrivate::isInSystemButtons(const QPoint &pos, QuickGlob } *button = QuickGlobal::SystemButtonType::Unknown; const QuickHelperData data = getWindowData(); - if (data.windowIconButton) { + if (data.windowIconButton && data.windowIconButton->isVisible() && data.windowIconButton->isEnabled()) { if (mapItemGeometryToScene(data.windowIconButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::WindowIcon; return true; } } - if (data.contextHelpButton) { + if (data.contextHelpButton && data.contextHelpButton->isVisible() && data.contextHelpButton->isEnabled()) { if (mapItemGeometryToScene(data.contextHelpButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Help; return true; } } - if (data.minimizeButton) { + if (data.minimizeButton && data.minimizeButton->isVisible() && data.minimizeButton->isEnabled()) { if (mapItemGeometryToScene(data.minimizeButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Minimize; return true; } } - if (data.maximizeButton) { + if (data.maximizeButton && data.maximizeButton->isVisible() && data.maximizeButton->isEnabled()) { if (mapItemGeometryToScene(data.maximizeButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Maximize; return true; } } - if (data.closeButton) { + if (data.closeButton && data.closeButton->isVisible() && data.closeButton->isEnabled()) { if (mapItemGeometryToScene(data.closeButton).contains(pos)) { *button = QuickGlobal::SystemButtonType::Close; return true; @@ -434,20 +434,38 @@ bool FramelessQuickHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) c { const QuickHelperData data = getWindowData(); if (!data.titleBarItem) { + // There's no title bar at all, the mouse will always be in the client area. return false; } - QRegion region = mapItemGeometryToScene(data.titleBarItem); + if (!data.titleBarItem->isVisible() || !data.titleBarItem->isEnabled()) { + // The title bar is hidden or disabled for some reason, treat it as there's no title bar. + return false; + } + Q_Q(const FramelessQuickHelper); + const QQuickWindow * const window = q->window(); + if (!window) { + // The FramelessQuickHelper item has not been attached to a specific window yet, + // so we assume there's no title bar. + return false; + } + const QRect windowRect = {QPoint(0, 0), window->size()}; + const QRect titleBarRect = mapItemGeometryToScene(data.titleBarItem); + if (!titleBarRect.intersects(windowRect)) { + // The title bar is totally outside of the window for some reason, + // also treat it as there's no title bar. + return false; + } + QRegion region = titleBarRect; const auto systemButtons = {data.windowIconButton, data.contextHelpButton, data.minimizeButton, data.maximizeButton, data.closeButton}; for (auto &&button : qAsConst(systemButtons)) { - if (button) { + if (button && button->isVisible() && button->isEnabled()) { region -= mapItemGeometryToScene(button); } } if (!data.hitTestVisibleItems.isEmpty()) { for (auto &&item : qAsConst(data.hitTestVisibleItems)) { - Q_ASSERT(item); - if (item) { + if (item && item->isVisible() && item->isEnabled()) { region -= mapItemGeometryToScene(item); } } diff --git a/src/quick/framelessquickmodule.cpp b/src/quick/framelessquickmodule.cpp index 648b2d83..887191da 100644 --- a/src/quick/framelessquickmodule.cpp +++ b/src/quick/framelessquickmodule.cpp @@ -69,6 +69,7 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine) Q_UNUSED(scriptEngine); return new FramelessQuickUtils; }); + qmlRegisterRevision(QUICK_URI_FULL); qmlRegisterRevision(QUICK_URI_FULL); qmlRegisterRevision(QUICK_URI_FULL); qmlRegisterType(QUICK_URI_EXPAND("FramelessHelper")); diff --git a/src/quick/quickstandardtitlebar.cpp b/src/quick/quickstandardtitlebar.cpp index 5e81bb68..ccc58260 100644 --- a/src/quick/quickstandardtitlebar.cpp +++ b/src/quick/quickstandardtitlebar.cpp @@ -57,6 +57,13 @@ void QuickStandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value) } m_labelAlignment = value; QQuickAnchors * const labelAnchors = QQuickItemPrivate::get(m_windowTitleLabel.data())->anchors(); + //labelAnchors->setMargins(0); + labelAnchors->resetFill(); + labelAnchors->resetCenterIn(); + labelAnchors->resetTop(); + labelAnchors->resetBottom(); + labelAnchors->resetLeft(); + labelAnchors->resetRight(); const QQuickItemPrivate * const titleBarPriv = QQuickItemPrivate::get(this); if (m_labelAlignment & Qt::AlignTop) { labelAnchors->setTop(titleBarPriv->top()); @@ -75,13 +82,13 @@ void QuickStandardTitleBar::setTitleLabelAlignment(const Qt::Alignment value) labelAnchors->setRightMargin(kDefaultTitleBarContentsMargin); } if (m_labelAlignment & Qt::AlignVCenter) { - labelAnchors->setTopMargin(0); - labelAnchors->setBottomMargin(0); + //labelAnchors->setTopMargin(0); + //labelAnchors->setBottomMargin(0); labelAnchors->setVerticalCenter(titleBarPriv->verticalCenter()); } if (m_labelAlignment & Qt::AlignHCenter) { - labelAnchors->setLeftMargin(0); - labelAnchors->setRightMargin(0); + //labelAnchors->setLeftMargin(0); + //labelAnchors->setRightMargin(0); labelAnchors->setHorizontalCenter(titleBarPriv->horizontalCenter()); } Q_EMIT titleLabelAlignmentChanged(); diff --git a/src/widgets/framelesswidgetshelper.cpp b/src/widgets/framelesswidgetshelper.cpp index ec21af9d..d87fbaa3 100644 --- a/src/widgets/framelesswidgetshelper.cpp +++ b/src/widgets/framelesswidgetshelper.cpp @@ -130,10 +130,10 @@ void FramelessWidgetsHelperPrivate::setWindowFixedSize(const bool value) Q_EMIT q->windowFixedSizeChanged(); } -void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal) +void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const QByteArray &signal) { - Q_ASSERT(signal); - if (!signal) { + Q_ASSERT(!signal.isEmpty()); + if (signal.isEmpty()) { return; } const QWidget * const window = getWindow(); @@ -145,7 +145,7 @@ void FramelessWidgetsHelperPrivate::emitSignalForAllInstances(const char *signal return; } for (auto &&instance : qAsConst(instances)) { - QMetaObject::invokeMethod(instance, signal); + QMetaObject::invokeMethod(instance, signal.constData()); } } @@ -164,7 +164,7 @@ void FramelessWidgetsHelperPrivate::setTitleBarWidget(QWidget *widget) return; } data->titleBarWidget = widget; - emitSignalForAllInstances("titleBarWidgetChanged"); + emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("titleBarWidgetChanged")); } QWidget *FramelessWidgetsHelperPrivate::getTitleBarWidget() const @@ -268,7 +268,7 @@ void FramelessWidgetsHelperPrivate::attachToWindow() if (FramelessConfig::instance()->isSet(Option::CenterWindowBeforeShow)) { moveWindowToDesktopCenter(); } - emitSignalForAllInstances("ready"); + emitSignalForAllInstances(FRAMELESSHELPER_BYTEARRAY_LITERAL("ready")); }); } @@ -338,31 +338,31 @@ bool FramelessWidgetsHelperPrivate::isInSystemButtons(const QPoint &pos, SystemB } *button = SystemButtonType::Unknown; const WidgetsHelperData data = getWindowData(); - if (data.windowIconButton) { + if (data.windowIconButton && data.windowIconButton->isVisible() && data.windowIconButton->isEnabled()) { if (data.windowIconButton->geometry().contains(pos)) { *button = SystemButtonType::WindowIcon; return true; } } - if (data.contextHelpButton) { + if (data.contextHelpButton && data.contextHelpButton->isVisible() && data.contextHelpButton->isEnabled()) { if (data.contextHelpButton->geometry().contains(pos)) { *button = SystemButtonType::Help; return true; } } - if (data.minimizeButton) { + if (data.minimizeButton && data.minimizeButton->isVisible() && data.minimizeButton->isEnabled()) { if (data.minimizeButton->geometry().contains(pos)) { *button = SystemButtonType::Minimize; return true; } } - if (data.maximizeButton) { + if (data.maximizeButton && data.maximizeButton->isVisible() && data.maximizeButton->isEnabled()) { if (data.maximizeButton->geometry().contains(pos)) { *button = SystemButtonType::Maximize; return true; } } - if (data.closeButton) { + if (data.closeButton && data.closeButton->isVisible() && data.closeButton->isEnabled()) { if (data.closeButton->geometry().contains(pos)) { *button = SystemButtonType::Close; return true; @@ -375,20 +375,37 @@ bool FramelessWidgetsHelperPrivate::isInTitleBarDraggableArea(const QPoint &pos) { const WidgetsHelperData data = getWindowData(); if (!data.titleBarWidget) { + // There's no title bar at all, the mouse will always be in the client area. return false; } - QRegion region = mapWidgetGeometryToScene(data.titleBarWidget); + if (!data.titleBarWidget->isVisible() || !data.titleBarWidget->isEnabled()) { + // The title bar is hidden or disabled for some reason, treat it as there's no title bar. + return false; + } + const QWidget * const window = getWindow(); + if (!window) { + // The FramelessWidgetsHelper object has not been attached to a specific window yet, + // so we assume there's no title bar. + return false; + } + const QRect windowRect = {QPoint(0, 0), window->size()}; + const QRect titleBarRect = mapWidgetGeometryToScene(data.titleBarWidget); + if (!titleBarRect.intersects(windowRect)) { + // The title bar is totally outside of the window for some reason, + // also treat it as there's no title bar. + return false; + } + QRegion region = titleBarRect; const auto systemButtons = {data.windowIconButton, data.contextHelpButton, data.minimizeButton, data.maximizeButton, data.closeButton}; for (auto &&button : qAsConst(systemButtons)) { - if (button) { + if (button && button->isVisible() && button->isEnabled()) { region -= mapWidgetGeometryToScene(button); } } if (!data.hitTestVisibleWidgets.isEmpty()) { for (auto &&widget : qAsConst(data.hitTestVisibleWidgets)) { - Q_ASSERT(widget); - if (widget) { + if (widget && widget->isVisible() && widget->isEnabled()) { region -= mapWidgetGeometryToScene(widget); } }