From 3fbcf1aa8f91a804af50fad4e2b122f698259c94 Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 摹曛, 09 5月 2024 23:45:28 +0800
Subject: [PATCH] Remove `isHostSizeFixed` in delegate

---
 src/core/contexts/win32windowcontext.cpp |   83 ++++++++++++++++++++++++++++-------------
 1 files changed, 57 insertions(+), 26 deletions(-)

diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 93a186c..84c80ef 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -35,6 +35,12 @@
 
 namespace QWK {
 
+    enum IconButtonClickLevelFlag {
+        IconButtonClicked = 1,
+        IconButtonDoubleClicked = 2,
+        IconButtonTriggersClose = 4,
+    };
+
     // The thickness of an auto-hide taskbar in pixels.
     static constexpr const quint8 kAutoHideTaskBarThickness = 2;
 
@@ -619,6 +625,7 @@
         // Try hooked procedure and save result
         LRESULT result;
         if (ctx->windowProc(hWnd, message, wParam, lParam, &result)) {
+            // https://github.com/stdware/qwindowkit/issues/45
             // Forward the event to user-defined native event filters, there may be some messages
             // that need to be processed by the user.
             std::ignore =
@@ -693,12 +700,12 @@
                 auto hWnd = reinterpret_cast<HWND>(m_windowId);
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
                 const QPoint nativeGlobalPos =
-                    QHighDpi::toNativeGlobalPosition(pos, m_windowHandle);
+                    QHighDpi::toNativeGlobalPosition(pos, m_windowHandle.data());
 #else
-                const QPoint nativeGlobalPos = QHighDpi::toNativePixels(pos, m_windowHandle);
+                const QPoint nativeGlobalPos = QHighDpi::toNativePixels(pos, m_windowHandle.data());
 #endif
                 std::ignore = showSystemMenu_sys(hWnd, qpoint2point(nativeGlobalPos), false,
-                                                 m_delegate->isHostSizeFixed(m_host));
+                                                 isHostSizeFixed());
                 return;
             }
 
@@ -1257,7 +1264,7 @@
                     POINT screenPoint{GET_X_LPARAM(dwScreenPos), GET_Y_LPARAM(dwScreenPos)};
                     ::ScreenToClient(hWnd, &screenPoint);
                     QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(screenPoint),
-                                                                          m_windowHandle);
+                                                                          m_windowHandle.data());
                     auto dummy = WindowAgentBase::Unknown;
                     if (isInSystemButtons(qtScenePos, &dummy)) {
                         // We must record whether the last WM_MOUSELEAVE was filtered, because if
@@ -1382,13 +1389,17 @@
                                     // menu while Windows will create and execute a new event loop
                                     // until the menu returns
                                     iconButtonClickTime = ::GetTickCount64();
-                                    *result =
-                                        ::DefWindowProcW(hWnd, WM_NCLBUTTONDOWN, wParam, lParam);
-                                    if (iconButtonClickLevel == 2) {
+                                    *result = ::DefWindowProcW(hWnd, message, wParam, lParam);
+                                    iconButtonClickTime = 0;
+                                    if (iconButtonClickLevel & IconButtonTriggersClose) {
                                         ::PostMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
                                     }
-                                    // No need to reset `iconButtonClickLevel`, if it has value,
-                                    // there must be another incoming WM_NCLBUTTONDOWN
+                                    if (iconButtonClickLevel & IconButtonDoubleClicked) {
+                                        iconButtonClickLevel = 0;
+                                    }
+                                    // Otherwise, no need to reset `iconButtonClickLevel` if not to
+                                    // close, if it has value, there must be another incoming
+                                    // WM_NCLBUTTONDOWN
                                 } else {
                                     iconButtonClickLevel = 0;
                                 }
@@ -1553,10 +1564,10 @@
                 auto clientWidth = RECT_WIDTH(clientRect);
                 auto clientHeight = RECT_HEIGHT(clientRect);
 
-                QPoint qtScenePos =
-                    QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
+                QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos),
+                                                                      m_windowHandle.data());
 
-                bool isFixedSize = m_delegate->isHostSizeFixed(m_host);
+                bool isFixedSize = isHostSizeFixed();
                 bool isTitleBar = isInTitleBarDraggableArea(qtScenePos);
                 bool dontOverrideCursor = false; // ### TODO
 
@@ -2094,9 +2105,12 @@
         switch (message) {
             case WM_RBUTTONUP: {
                 const POINT nativeLocalPos = getNativePosFromMouse();
-                const QPoint qtScenePos =
-                    QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
-                if (isInTitleBarDraggableArea(qtScenePos)) {
+                const QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(
+                    point2qpoint(nativeLocalPos), m_windowHandle.data());
+                WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown;
+                if (isInTitleBarDraggableArea(qtScenePos) ||
+                    (isInSystemButtons(qtScenePos, &sysButtonType) &&
+                     sysButtonType == WindowAgentBase::WindowIcon)) {
                     shouldShowSystemMenu = true;
                     nativeGlobalPos = nativeLocalPos;
                     ::ClientToScreen(hWnd, &nativeGlobalPos);
@@ -2146,6 +2160,7 @@
         if (shouldShowSystemMenu) {
             static HHOOK mouseHook = nullptr;
             static std::optional<POINT> mouseClickPos;
+            static bool mouseDoubleClicked = false;
             bool mouseHookedLocal = false;
 
             // The menu is triggered by a click on icon button
@@ -2165,11 +2180,23 @@
                         WH_MOUSE,
                         [](int nCode, WPARAM wParam, LPARAM lParam) {
                             if (nCode >= 0) {
-                                if (wParam == WM_LBUTTONDOWN || wParam == WM_LBUTTONDBLCLK) {
-                                    auto pMouseStruct = reinterpret_cast<MOUSEHOOKSTRUCT *>(lParam);
-                                    if (pMouseStruct) {
-                                        mouseClickPos = pMouseStruct->pt;
+                                switch (wParam) {
+                                    case WM_LBUTTONDBLCLK:
+                                        mouseDoubleClicked = true;
+                                        Q_FALLTHROUGH();
+
+                                        // case WM_POINTERDOWN:
+
+                                    case WM_LBUTTONDOWN: {
+                                        auto pMouseStruct =
+                                            reinterpret_cast<MOUSEHOOKSTRUCT *>(lParam);
+                                        if (pMouseStruct) {
+                                            mouseClickPos = pMouseStruct->pt;
+                                        }
+                                        break;
                                     }
+                                    default:
+                                        break;
                                 }
                             }
                             return ::CallNextHookEx(nullptr, nCode, wParam, lParam);
@@ -2179,32 +2206,36 @@
                 }
             }
 
-            bool res = showSystemMenu_sys(hWnd, nativeGlobalPos, broughtByKeyboard,
-                                          m_delegate->isHostSizeFixed(m_host));
+            bool res =
+                showSystemMenu_sys(hWnd, nativeGlobalPos, broughtByKeyboard, isHostSizeFixed());
 
             // Uninstall mouse hook and check if it's a double-click
             if (mouseHookedLocal) {
                 ::UnhookWindowsHookEx(mouseHook);
 
                 // Emulate the Windows icon button's behavior
-                static uint32_t doubleClickTime = ::GetDoubleClickTime();
                 if (!res && mouseClickPos.has_value()) {
                     POINT nativeLocalPos = mouseClickPos.value();
                     ::ScreenToClient(hWnd, &nativeLocalPos);
                     QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(
-                        point2qpoint(nativeLocalPos), m_windowHandle);
+                        point2qpoint(nativeLocalPos), m_windowHandle.data());
                     WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown;
                     if (isInSystemButtons(qtScenePos, &sysButtonType) &&
                         sysButtonType == WindowAgentBase::WindowIcon) {
-                        iconButtonClickLevel = 1;
-                        if (::GetTickCount64() - iconButtonClickTime <= doubleClickTime) {
-                            iconButtonClickLevel = 2;
+                        iconButtonClickLevel |= IconButtonClicked;
+                        if (::GetTickCount64() - iconButtonClickTime <= ::GetDoubleClickTime()) {
+                            iconButtonClickLevel |= IconButtonTriggersClose;
                         }
                     }
                 }
 
+                if (mouseDoubleClicked) {
+                    iconButtonClickLevel |= IconButtonDoubleClicked;
+                }
+
                 mouseHook = nullptr;
                 mouseClickPos.reset();
+                mouseDoubleClicked = false;
             }
 
             // QPA's internal code will handle system menu events separately, and its

--
Gitblit v1.9.1