diff --git a/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h b/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h index e51e9bbf..b976394d 100644 --- a/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h +++ b/include/FramelessHelper/Core/private/framelesshelpercore_global_p.h @@ -63,6 +63,7 @@ using SetCursorCallback = std::function; using UnsetCursorCallback = std::function; using GetWidgetHandleCallback = std::function; using ForceChildrenRepaintCallback = std::function; +using ResetQtGrabbedControlCallback = std::function; struct SystemParameters { @@ -93,6 +94,7 @@ struct SystemParameters UnsetCursorCallback unsetCursor = nullptr; GetWidgetHandleCallback getWidgetHandle = nullptr; ForceChildrenRepaintCallback forceChildrenRepaint = nullptr; + ResetQtGrabbedControlCallback resetQtGrabbedControl = nullptr; }; using FramelessParams = SystemParameters *; diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index bd6a9086..42cdded1 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -92,7 +92,7 @@ enum class WindowPart : quint8 ClientArea, ChromeButton, ResizeBorder, - FixBorder, + FixedBorder, TitleBar }; @@ -157,7 +157,7 @@ Q_GLOBAL_STATIC(FramelessWin32HelperInternal, g_framelessWin32HelperData) return result; } -[[nodiscard]] static inline WindowPart getHittedWindowPart(const LRESULT hitTestResult) +[[nodiscard]] static inline WindowPart getHittedWindowPart(const int hitTestResult) { switch (hitTestResult) { case HTCLIENT: @@ -180,7 +180,7 @@ Q_GLOBAL_STATIC(FramelessWin32HelperInternal, g_framelessWin32HelperData) case HTBOTTOMRIGHT: return WindowPart::ResizeBorder; case HTBORDER: - return WindowPart::FixBorder; + return WindowPart::FixedBorder; default: break; } @@ -422,8 +422,8 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // all our mouse move events and thus break the hover state of our controls. // So we filter out these superfluous mouse leave events here. const QPoint qtScenePos = Utils::fromNativeLocalPosition(window, QPoint{ msg->pt.x, msg->pt.y }); - SystemButtonType sysButtonType = SystemButtonType::Unknown; - if (data.params.isInsideSystemButtons(qtScenePos, &sysButtonType)) { + SystemButtonType dummy = SystemButtonType::Unknown; + if (data.params.isInsideSystemButtons(qtScenePos, &dummy)) { *result = FALSE; return true; } @@ -807,8 +807,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me const bool full = Utils::isFullScreen(windowId); const int frameSizeY = Utils::getResizeBorderThickness(windowId, false, true); const bool isTop = (nativeLocalPos.y < frameSizeY); - const bool leftButtonPressed = (Utils::getKeyState() & MK_LBUTTON); - const bool isTitleBar = (data.params.isInsideTitleBarDraggableArea(qtScenePos) && leftButtonPressed); + const bool isTitleBar = data.params.isInsideTitleBarDraggableArea(qtScenePos); const bool isFixedSize = data.params.isWindowFixedSize(); const bool dontOverrideCursor = data.params.getProperty(kDontOverrideCursorVar, false).toBool(); const bool dontToggleMaximize = data.params.getProperty(kDontToggleMaximizeVar, false).toBool(); @@ -960,6 +959,9 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me } } } else { + if ((uMsg == WM_NCMOUSEMOVE) && (nowWindowPart != WindowPart::ChromeButton)) { + data.params.resetQtGrabbedControl(); + } if (nowWindowPart == WindowPart::ChromeButton) { emulateClientAreaMessage(); *result = (isXButtonMessage ? TRUE : FALSE); diff --git a/src/core/utils_mac.mm b/src/core/utils_mac.mm index d44f6f8e..205784ea 100644 --- a/src/core/utils_mac.mm +++ b/src/core/utils_mac.mm @@ -42,8 +42,8 @@ #include QT_BEGIN_NAMESPACE -[[nodiscard]] Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); // Since 5.12 -[[nodiscard]] Q_GUI_EXPORT QColor qt_mac_toQColor(const NSColor *color); // Since 5.8 +[[nodiscard]] extern Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode(); // Since 5.12 +[[nodiscard]] extern Q_GUI_EXPORT QColor qt_mac_toQColor(const NSColor *color); // Since 5.8 QT_END_NAMESPACE FRAMELESSHELPER_BEGIN_NAMESPACE diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index 9f697f67..45d3a4e7 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -215,6 +215,7 @@ void FramelessQuickHelperPrivate::attach() params.unsetCursor = [window]() -> void { window->unsetCursor(); }; params.getWidgetHandle = []() -> QObject * { return nullptr; }; params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); }; + params.resetQtGrabbedControl = []() -> void {}; FramelessManager::instance()->addWindow(¶ms); @@ -676,19 +677,24 @@ void FramelessQuickHelperPrivate::repaintAllChildren(const quint32 delay) const return; } const auto update = [window]() -> void { - window->requestUpdate(); #ifdef Q_OS_WINDOWS // Sync the internal window frame margins with the latest DPI, otherwise // we will get wrong window sizes after the DPI change. std::ignore = Utils::updateInternalWindowFrameMargins(window, true); #endif // Q_OS_WINDOWS + // No need to repaint the window when it's hidden. + if (!window->isVisible()) { + return; + } + window->requestUpdate(); const QList items = window->findChildren(); if (items.isEmpty()) { return; } for (auto &&item : std::as_const(items)) { // Only items with the "QQuickItem::ItemHasContents" flag enabled are allowed to call "update()". - if (item->flags() & QQuickItem::ItemHasContents) { + // And don't repaint the item if it's hidden. + if ((item->flags() & QQuickItem::ItemHasContents) && item->isVisible()) { item->update(); } } diff --git a/src/widgets/framelesswidgetshelper.cpp b/src/widgets/framelesswidgetshelper.cpp index bced1cb6..486c0edf 100644 --- a/src/widgets/framelesswidgetshelper.cpp +++ b/src/widgets/framelesswidgetshelper.cpp @@ -48,6 +48,8 @@ # define QWIDGETSIZE_MAX ((1 << 24) - 1) #endif // QWIDGETSIZE_MAX +extern Q_WIDGETS_EXPORT QWidget *qt_button_down; + FRAMELESSHELPER_BEGIN_NAMESPACE [[maybe_unused]] static Q_LOGGING_CATEGORY(lcFramelessWidgetsHelper, "wangwenx190.framelesshelper.widgets.framelesswidgetshelper") @@ -115,6 +117,21 @@ static inline void forceWidgetRepaint(QWidget * const widget) if (!widget) { return; } +#ifdef Q_OS_WINDOWS + // There's some additional things to do for top level windows on Windows. + if (widget->isWindow()) { + // Don't crash if the QWindow instance has not been created yet. + if (QWindow * const window = widget->windowHandle()) { + // Sync the internal window frame margins with the latest DPI, otherwise + // we will get wrong window sizes after the DPI change. + std::ignore = Utils::updateInternalWindowFrameMargins(window, true); + } + } +#endif // Q_OS_WINDOWS + // Don't do unnecessary repaints if the widget is hidden. + if (!widget->isVisible()) { + return; + } // Tell the widget to repaint itself, but it may not happen due to QWidget's // internal painting optimizations. widget->update(); @@ -137,17 +154,6 @@ static inline void forceWidgetRepaint(QWidget * const widget) widget->move(originalPosition + offset); widget->move(originalPosition); } -#ifdef Q_OS_WINDOWS - // There's some additional things to do for top level windows on Windows. - if (widget->isWindow()) { - // Don't crash if the QWindow instance has not been created yet. - if (QWindow * const window = widget->windowHandle()) { - // Sync the internal window frame margins with the latest DPI, otherwise - // we will get wrong window sizes after the DPI change. - std::ignore = Utils::updateInternalWindowFrameMargins(window, true); - } - } -#endif // Q_OS_WINDOWS // Let's try again with the ordinary way. widget->update(); // ### TODO: I observed the font size is often wrong after DPI changes, @@ -573,6 +579,7 @@ void FramelessWidgetsHelperPrivate::attach() params.unsetCursor = [window]() -> void { window->unsetCursor(); }; params.getWidgetHandle = [window]() -> QObject * { return window; }; params.forceChildrenRepaint = [this](const int delay) -> void { repaintAllChildren(delay); }; + params.resetQtGrabbedControl = []() -> void { qt_button_down = nullptr; }; FramelessManager::instance()->addWindow(¶ms);