From a5d13e19dd7f6037e10b649c49805922ae5e0fa6 Mon Sep 17 00:00:00 2001
From: SineStriker <trueful@163.com>
Date: 周五, 22 12月 2023 17:04:29 +0800
Subject: [PATCH] Prepare to remove style support again

---
 src/core/contexts/win32windowcontext.cpp |  955 +++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 531 insertions(+), 424 deletions(-)

diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 603079c..969a275 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -4,13 +4,12 @@
 
 #include <QtCore/QHash>
 #include <QtCore/QScopeGuard>
+#include <QtCore/QTimer>
 #include <QtGui/QGuiApplication>
 #include <QtGui/QPainter>
 #include <QtGui/QPalette>
 #include <QtGui/QStyleHints>
 
-#include <QtCore/private/qwinregistry_p.h>
-#include <QtCore/private/qsystemlibrary_p.h>
 #include <QtGui/private/qhighdpiscaling_p.h>
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
 #  include <QtGui/private/qguiapplication_p.h>
@@ -22,11 +21,8 @@
 #  include <QtGui/qpa/qplatformwindow_p.h>
 #endif
 
-#include <shellscalingapi.h>
-#include <dwmapi.h>
-#include <timeapi.h>
-
-#include "nativeeventfilter.h"
+#include "qwkglobal_p.h"
+#include "qwkwindowsextra_p.h"
 
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
 Q_DECLARE_METATYPE(QMargins)
@@ -34,27 +30,15 @@
 
 namespace QWK {
 
-    using _DWMWINDOWATTRIBUTE = enum _DWMWINDOWATTRIBUTE
-    {
-        _DWMWA_USE_HOSTBACKDROPBRUSH = 17, // [set] BOOL, Allows the use of host backdrop brushes for the window.
-        _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, // Undocumented, the same with DWMWA_USE_IMMERSIVE_DARK_MODE, but available on systems before Win10 20H1.
-        _DWMWA_USE_IMMERSIVE_DARK_MODE = 20, // [set] BOOL, Allows a window to either use the accent color, or dark, according to the user Color Mode preferences.
-        _DWMWA_WINDOW_CORNER_PREFERENCE = 33, // [set] WINDOW_CORNER_PREFERENCE, Controls the policy that rounds top-level window corners
-        _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37, // [get] UINT, width of the visible border around a thick frame window
-        _DWMWA_SYSTEMBACKDROP_TYPE = 38, // [get, set] SYSTEMBACKDROP_TYPE, Controls the system-drawn backdrop material of a window, including behind the non-client area.
-        _DWMWA_MICA_EFFECT = 1029 // Undocumented, use this value to enable Mica material on Win11 21H2. You should use DWMWA_SYSTEMBACKDROP_TYPE instead on Win11 22H2 and newer.
-    };
-
     // The thickness of an auto-hide taskbar in pixels.
-    static constexpr const auto kAutoHideTaskBarThickness = quint8{2};
+    static constexpr const quint8 kAutoHideTaskBarThickness = 2;
 
-    static inline constexpr const auto kFrameBorderActiveColorLight =
-        QColor{110, 110, 110};                                                           // #6E6E6E
-    static inline constexpr const auto kFrameBorderActiveColorDark = QColor{51, 51, 51}; // #333333
-    static inline constexpr const auto kFrameBorderInactiveColorLight =
-        QColor{167, 167, 167};                                                           // #A7A7A7
-    static inline constexpr const auto kFrameBorderInactiveColorDark =
-        QColor{61, 61, 62};                                                              // #3D3D3E
+    QWK_USED static constexpr const struct {
+        const uint32_t activeLight = MAKE_RGBA_COLOR(110, 110, 110, 255);   // #6E6E6E
+        const uint32_t activeDark = MAKE_RGBA_COLOR(51, 51, 51, 255);       // #333333
+        const uint32_t inactiveLight = MAKE_RGBA_COLOR(167, 167, 167, 255); // #A7A7A7
+        const uint32_t inactiveDark = MAKE_RGBA_COLOR(61, 61, 62, 255);     // #3D3D3E
+    } kWindowsColorSet;
 
     // hWnd -> context
     using WndProcHash = QHash<HWND, Win32WindowContext *>;
@@ -62,256 +46,6 @@
 
     // Original Qt window proc function
     static WNDPROC g_qtWindowProc = nullptr;
-
-    // ### FIXME FIXME FIXME
-    // ### FIXME: Tell the user to call in the documentation, instead of automatically
-    // calling it directly.
-    // ### FIXME FIXME FIXME
-    static struct QWK_Hook {
-        QWK_Hook() {
-            qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
-        }
-    } g_hook{};
-
-    struct DynamicApis {
-        static const DynamicApis &instance() {
-            static const DynamicApis inst{};
-            return inst;
-        }
-
-//        template <typename T>
-//        struct DefaultFunc;
-//
-//        template <typename Return, typename... Args>
-//        struct DefaultFunc<Return(QT_WIN_CALLBACK *)(Args...)> {
-//            static Return STDAPICALLTYPE func(Args...) {
-//                return Return{};
-//            }
-//        };
-//
-// #define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME =
-// DefaultFunc<decltype(&::NAME)>::func
-
-#define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME = nullptr
-
-        DYNAMIC_API_DECLARE(DwmFlush);
-        DYNAMIC_API_DECLARE(DwmIsCompositionEnabled);
-        DYNAMIC_API_DECLARE(DwmGetCompositionTimingInfo);
-        DYNAMIC_API_DECLARE(DwmGetWindowAttribute);
-        DYNAMIC_API_DECLARE(GetDpiForWindow);
-        DYNAMIC_API_DECLARE(GetSystemMetricsForDpi);
-        DYNAMIC_API_DECLARE(GetDpiForMonitor);
-        DYNAMIC_API_DECLARE(timeGetDevCaps);
-        DYNAMIC_API_DECLARE(timeBeginPeriod);
-        DYNAMIC_API_DECLARE(timeEndPeriod);
-
-#undef DYNAMIC_API_DECLARE
-
-    private:
-        DynamicApis() {
-#define DYNAMIC_API_RESOLVE(DLL, NAME)                                                             \
-    p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME))
-
-            QSystemLibrary user32(QStringLiteral("user32"));
-            DYNAMIC_API_RESOLVE(user32, GetDpiForWindow);
-            DYNAMIC_API_RESOLVE(user32, GetSystemMetricsForDpi);
-
-            QSystemLibrary shcore(QStringLiteral("shcore"));
-            DYNAMIC_API_RESOLVE(shcore, GetDpiForMonitor);
-
-            QSystemLibrary dwmapi(QStringLiteral("dwmapi"));
-            DYNAMIC_API_RESOLVE(dwmapi, DwmFlush);
-            DYNAMIC_API_RESOLVE(dwmapi, DwmIsCompositionEnabled);
-            DYNAMIC_API_RESOLVE(dwmapi, DwmGetCompositionTimingInfo);
-            DYNAMIC_API_RESOLVE(dwmapi, DwmGetWindowAttribute);
-
-            QSystemLibrary winmm(QStringLiteral("winmm"));
-            DYNAMIC_API_RESOLVE(winmm, timeGetDevCaps);
-            DYNAMIC_API_RESOLVE(winmm, timeBeginPeriod);
-            DYNAMIC_API_RESOLVE(winmm, timeEndPeriod);
-
-#undef DYNAMIC_API_RESOLVE
-        }
-
-        ~DynamicApis() = default;
-
-        Q_DISABLE_COPY_MOVE(DynamicApis)
-    };
-
-    static inline constexpr bool operator==(const POINT &lhs, const POINT &rhs) noexcept {
-        return ((lhs.x == rhs.x) && (lhs.y == rhs.y));
-    }
-
-    static inline constexpr bool operator!=(const POINT &lhs, const POINT &rhs) noexcept {
-        return !operator==(lhs, rhs);
-    }
-
-    static inline constexpr bool operator==(const SIZE &lhs, const SIZE &rhs) noexcept {
-        return ((lhs.cx == rhs.cx) && (lhs.cy == rhs.cy));
-    }
-
-    static inline constexpr bool operator!=(const SIZE &lhs, const SIZE &rhs) noexcept {
-        return !operator==(lhs, rhs);
-    }
-
-    static inline constexpr bool operator>(const SIZE &lhs, const SIZE &rhs) noexcept {
-        return ((lhs.cx * lhs.cy) > (rhs.cx * rhs.cy));
-    }
-
-    static inline constexpr bool operator>=(const SIZE &lhs, const SIZE &rhs) noexcept {
-        return (operator>(lhs, rhs) || operator==(lhs, rhs));
-    }
-
-    static inline constexpr bool operator<(const SIZE &lhs, const SIZE &rhs) noexcept {
-        return (operator!=(lhs, rhs) && !operator>(lhs, rhs));
-    }
-
-    static inline constexpr bool operator<=(const SIZE &lhs, const SIZE &rhs) noexcept {
-        return (operator<(lhs, rhs) || operator==(lhs, rhs));
-    }
-
-    static inline constexpr bool operator==(const RECT &lhs, const RECT &rhs) noexcept {
-        return ((lhs.left == rhs.left) && (lhs.top == rhs.top) && (lhs.right == rhs.right) &&
-                (lhs.bottom == rhs.bottom));
-    }
-
-    static inline constexpr bool operator!=(const RECT &lhs, const RECT &rhs) noexcept {
-        return !operator==(lhs, rhs);
-    }
-
-    static inline constexpr QPoint point2qpoint(const POINT &point) {
-        return QPoint{int(point.x), int(point.y)};
-    }
-
-    static inline constexpr POINT qpoint2point(const QPoint &point) {
-        return POINT{LONG(point.x()), LONG(point.y())};
-    }
-
-    static inline constexpr QSize size2qsize(const SIZE &size) {
-        return QSize{int(size.cx), int(size.cy)};
-    }
-
-    static inline constexpr SIZE qsize2size(const QSize &size) {
-        return SIZE{LONG(size.width()), LONG(size.height())};
-    }
-
-    static inline constexpr QRect rect2qrect(const RECT &rect) {
-        return QRect{
-            QPoint{int(rect.left),        int(rect.top)         },
-            QSize{int(RECT_WIDTH(rect)), int(RECT_HEIGHT(rect))}
-        };
-    }
-
-    static inline constexpr RECT qrect2rect(const QRect &qrect) {
-        return RECT{LONG(qrect.left()), LONG(qrect.top()), LONG(qrect.right()),
-                    LONG(qrect.bottom())};
-    }
-
-    static inline /*constexpr*/ QString hwnd2str(const WId windowId) {
-        // NULL handle is allowed here.
-        return QLatin1String("0x") +
-               QString::number(windowId, 16).toUpper().rightJustified(8, u'0');
-    }
-
-    static inline /*constexpr*/ QString hwnd2str(HWND hwnd) {
-        // NULL handle is allowed here.
-        return hwnd2str(reinterpret_cast<WId>(hwnd));
-    }
-
-    static inline bool isWin8OrGreater() {
-        static const bool result = IsWindows8OrGreater_Real();
-        return result;
-    }
-
-    static inline bool isWin8Point1OrGreater() {
-        static const bool result = IsWindows8Point1OrGreater_Real();
-        return result;
-    }
-
-    static inline bool isWin10OrGreater() {
-        static const bool result = IsWindows10OrGreater_Real();
-        return result;
-    }
-
-    static inline bool isWin11OrGreater() {
-        static const bool result = IsWindows11OrGreater_Real();
-        return result;
-    }
-
-    static inline bool isDwmCompositionEnabled() {
-        if (isWin8OrGreater()) {
-            return true;
-        }
-        const DynamicApis &apis = DynamicApis::instance();
-        if (!apis.pDwmIsCompositionEnabled) {
-            return false;
-        }
-        BOOL enabled = FALSE;
-        return SUCCEEDED(apis.pDwmIsCompositionEnabled(&enabled)) && enabled;
-    }
-
-    static inline bool isWindowFrameBorderColorized() {
-        const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
-        if (!registry.isValid()) {
-            return false;
-        }
-        const auto value = registry.dwordValue(L"ColorPrevalence");
-        if (!value.second) {
-            return false;
-        }
-        return value.first;
-    }
-
-    static inline bool isDarkThemeActive() {
-#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
-        return QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark;
-#else
-        const QWinRegistryKey registry(
-            HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)");
-        if (!registry.isValid()) {
-            return false;
-        }
-        const auto value = registry.dwordValue(L"AppsUseLightTheme");
-        if (!value.second) {
-            return false;
-        }
-        return !value.first;
-#endif
-    }
-
-    static inline bool isDarkWindowFrameEnabled(HWND hwnd) {
-        BOOL enabled = FALSE;
-        const DynamicApis &apis = DynamicApis::instance();
-        if (SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_USE_IMMERSIVE_DARK_MODE, &enabled, sizeof(enabled)))) {
-            return enabled;
-        } else if (SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, &enabled, sizeof(enabled)))) {
-            return enabled;
-        } else {
-            return false;
-        }
-    }
-
-    static inline QColor getAccentColor() {
-#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
-        return QGuiApplication::palette().color(QPalette::Accent);
-#else
-        const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
-        if (!registry.isValid()) {
-            return {};
-        }
-        const auto value = registry.dwordValue(L"AccentColor");
-        if (!value.second) {
-            return {};
-        }
-        // The retrieved value is in the #AABBGGRR format, we need to
-        // convert it to the #AARRGGBB format which Qt expects.
-        const QColor abgr = QColor::fromRgba(value.first);
-        if (!abgr.isValid()) {
-            return {};
-        }
-        return QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
-#endif
-    }
 
     static inline void triggerFrameChange(HWND hwnd) {
         ::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
@@ -321,7 +55,7 @@
 
     static inline quint32 getDpiForWindow(HWND hwnd) {
         const DynamicApis &apis = DynamicApis::instance();
-        if (apis.pGetDpiForWindow) {         // Win10
+        if (apis.pGetDpiForWindow) { // Win10
             return apis.pGetDpiForWindow(hwnd);
         } else if (apis.pGetDpiForMonitor) { // Win8.1
             HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
@@ -332,58 +66,43 @@
         } else { // Win2K
             HDC hdc = ::GetDC(nullptr);
             const int dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX);
-            //const int dpiY = ::GetDeviceCaps(hdc, LOGPIXELSY);
+            // const int dpiY = ::GetDeviceCaps(hdc, LOGPIXELSY);
             ::ReleaseDC(nullptr, hdc);
             return quint32(dpiX);
         }
     }
 
-    static inline quint32 getWindowFrameBorderThickness(HWND hwnd) {
-        UINT result{ 0 };
+    static inline quint32 getSystemMetricsForDpi(int index, quint32 dpi) {
         const DynamicApis &apis = DynamicApis::instance();
-        if (SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &result, sizeof(result)))) {
-            return result;
-        } else {
-            const quint32 dpi = getDpiForWindow(hwnd);
-            result = quint32(std::round(qreal(1) * qreal(dpi) / qreal(USER_DEFAULT_SCREEN_DPI)));
+        if (apis.pGetSystemMetricsForDpi) {
+            return ::GetSystemMetricsForDpi(index, dpi);
+        }
+        return ::GetSystemMetrics(index);
+    }
+
+    static inline quint32 getWindowFrameBorderThickness(HWND hwnd) {
+        const DynamicApis &apis = DynamicApis::instance();
+        if (UINT result = 0; SUCCEEDED(apis.pDwmGetWindowAttribute(
+                hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &result, sizeof(result)))) {
             return result;
         }
+        return getSystemMetricsForDpi(SM_CXBORDER, getDpiForWindow(hwnd));
     }
 
     static inline quint32 getResizeBorderThickness(HWND hwnd) {
-        const DynamicApis &apis = DynamicApis::instance();
-        if (apis.pGetSystemMetricsForDpi) {
-            const quint32 dpi = getDpiForWindow(hwnd);
-            return apis.pGetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) +
-                   apis.pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
-        } else {
-            return ::GetSystemMetrics(SM_CXSIZEFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER);
-        }
+        const quint32 dpi = getDpiForWindow(hwnd);
+        return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) +
+               getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
     }
 
     static inline quint32 getTitleBarHeight(HWND hwnd) {
-        const auto captionHeight = [hwnd]() -> int {
-            const DynamicApis &apis = DynamicApis::instance();
-            if (apis.pGetSystemMetricsForDpi) {
-                const quint32 dpi = getDpiForWindow(hwnd);
-                return apis.pGetSystemMetricsForDpi(SM_CYCAPTION, dpi);
-            } else {
-                return ::GetSystemMetrics(SM_CYCAPTION);
-            }
-        }();
-        return captionHeight + getResizeBorderThickness(hwnd);
+        const quint32 dpi = getDpiForWindow(hwnd);
+        return getSystemMetricsForDpi(SM_CYCAPTION, dpi) +
+               getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) +
+               getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
     }
 
-    static inline void updateInternalWindowFrameMargins(HWND hwnd, QWindow *window) {
-        const auto margins = [hwnd]() -> QMargins {
-            const auto titleBarHeight = int(getTitleBarHeight(hwnd));
-            if (isWin10OrGreater()) {
-                return {0, -titleBarHeight, 0, 0};
-            } else {
-                const auto frameSize = int(getResizeBorderThickness(hwnd));
-                return {-frameSize, -titleBarHeight, -frameSize, -frameSize};
-            }
-        }();
+    static void setInternalWindowFrameMargins(QWindow *window, const QMargins &margins) {
         const QVariant marginsVar = QVariant::fromValue(margins);
         window->setProperty("_q_windowsCustomMargins", marginsVar);
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@@ -409,16 +128,83 @@
         monitorInfo.cbSize = sizeof(monitorInfo);
         ::GetMonitorInfoW(monitor, &monitorInfo);
         return monitorInfo;
-    };
+    }
 
-    static inline void moveToDesktopCenter(HWND hwnd) {
-        const auto monitorInfo = getMonitorForWindow(hwnd);
+    static inline void moveWindowToDesktopCenter(HWND hwnd) {
+        MONITORINFOEXW monitorInfo = getMonitorForWindow(hwnd);
         RECT windowRect{};
         ::GetWindowRect(hwnd, &windowRect);
-        const auto newX = (RECT_WIDTH(monitorInfo.rcMonitor) - RECT_WIDTH(windowRect)) / 2;
-        const auto newY = (RECT_HEIGHT(monitorInfo.rcMonitor) - RECT_HEIGHT(windowRect)) / 2;
+        const auto newX = monitorInfo.rcMonitor.left +
+                          (RECT_WIDTH(monitorInfo.rcMonitor) - RECT_WIDTH(windowRect)) / 2;
+        const auto newY = monitorInfo.rcMonitor.top +
+                          (RECT_HEIGHT(monitorInfo.rcMonitor) - RECT_HEIGHT(windowRect)) / 2;
         ::SetWindowPos(hwnd, nullptr, newX, newY, 0, 0,
                        SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
+    }
+
+    static inline void moveWindowToMonitor(HWND hwnd, const MONITORINFOEXW &activeMonitor) {
+        RECT currentMonitorRect = getMonitorForWindow(hwnd).rcMonitor;
+        RECT activeMonitorRect = activeMonitor.rcMonitor;
+        // We are in the same monitor, nothing to adjust here.
+        if (currentMonitorRect == activeMonitorRect) {
+            return;
+        }
+        RECT currentWindowRect{};
+        ::GetWindowRect(hwnd, &currentWindowRect);
+        auto newWindowX =
+            activeMonitorRect.left + (currentWindowRect.left - currentMonitorRect.left);
+        auto newWindowY = activeMonitorRect.top + (currentWindowRect.top - currentMonitorRect.top);
+        ::SetWindowPos(hwnd, nullptr, newWindowX, newWindowY, RECT_WIDTH(currentWindowRect),
+                       RECT_HEIGHT(currentWindowRect),
+                       SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
+    }
+
+    static inline void bringWindowToFront(HWND hwnd) {
+        HWND oldForegroundWindow = ::GetForegroundWindow();
+        if (!oldForegroundWindow) {
+            // The foreground window can be NULL, it's not an API error.
+            return;
+        }
+        MONITORINFOEXW activeMonitor = getMonitorForWindow(oldForegroundWindow);
+        // We need to show the window first, otherwise we won't be able to bring it to front.
+        if (!::IsWindowVisible(hwnd)) {
+            ::ShowWindow(hwnd, SW_SHOW);
+        }
+        if (IsMinimized(hwnd)) {
+            // Restore the window if it is minimized.
+            ::ShowWindow(hwnd, SW_RESTORE);
+            // Once we've been restored, throw us on the active monitor.
+            moveWindowToMonitor(hwnd, activeMonitor);
+            // When the window is restored, it will always become the foreground window.
+            // So return early here, we don't need the following code to bring it to front.
+            return;
+        }
+        // OK, our window is not minimized, so now we will try to bring it to front manually.
+        // First try to send a message to the current foreground window to check whether
+        // it is currently hanging or not.
+        if (!::SendMessageTimeoutW(oldForegroundWindow, WM_NULL, 0, 0,
+                                   SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000,
+                                   nullptr)) {
+            // The foreground window hangs, can't activate current window.
+            return;
+        }
+        DWORD windowThreadProcessId = ::GetWindowThreadProcessId(oldForegroundWindow, nullptr);
+        DWORD currentThreadId = ::GetCurrentThreadId();
+        // We won't be able to change a window's Z order if it's not our own window,
+        // so we use this small technique to pretend the foreground window is ours.
+        ::AttachThreadInput(windowThreadProcessId, currentThreadId, TRUE);
+
+        [[maybe_unused]] const auto &cleaner =
+            qScopeGuard([windowThreadProcessId, currentThreadId]() {
+                ::AttachThreadInput(windowThreadProcessId, currentThreadId, FALSE); //
+            });
+
+        ::BringWindowToTop(hwnd);
+        // Activate the window too. This will force us to the virtual desktop this
+        // window is on, if it's on another virtual desktop.
+        ::SetActiveWindow(hwnd);
+        // Throw us on the active monitor.
+        moveWindowToMonitor(hwnd, activeMonitor);
     }
 
     static inline bool isFullScreen(HWND hwnd) {
@@ -435,12 +221,15 @@
         ::GetWindowPlacement(hwnd, &wp);
         return ((wp.showCmd == SW_NORMAL) || (wp.showCmd == SW_RESTORE));
 #else
+        if (isFullScreen(hwnd)) {
+            return false;
+        }
         const auto style = static_cast<DWORD>(::GetWindowLongPtrW(hwnd, GWL_STYLE));
         return (!(style & (WS_MINIMIZE | WS_MAXIMIZE)));
 #endif
     }
 
-    static inline void syncPaintEventWithDwm() {
+    static void syncPaintEventWithDwm() {
         // No need to sync with DWM if DWM composition is disabled.
         if (!isDwmCompositionEnabled()) {
             return;
@@ -485,9 +274,9 @@
         apis.ptimeEndPeriod(ms_granularity);
     }
 
-    static inline void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry,
-                                       const bool fixedSize) {
-        const HMENU hMenu = ::GetSystemMenu(hWnd, FALSE);
+    static void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry,
+                                const bool fixedSize) {
+        HMENU hMenu = ::GetSystemMenu(hWnd, FALSE);
         if (!hMenu) {
             // The corresponding window doesn't have a system menu, most likely due to the
             // lack of the "WS_SYSMENU" window style. This situation should not be treated
@@ -621,7 +410,7 @@
     // DefWindowProc(). Consequently, we have to add a global native filter that forwards the result
     // of the hook function, telling Qt whether we have filtered the events before. Since Qt only
     // handles Windows window messages in the main thread, it is safe to do so.
-    class WindowsNativeEventFilter : public NativeEventFilter {
+    class WindowsNativeEventFilter : public AppNativeEventFilter {
     public:
         bool nativeEventFilter(const QByteArray &eventType, void *message,
                                QT_NATIVE_EVENT_RESULT_TYPE *result) override {
@@ -754,94 +543,19 @@
         return ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam);
     }
 
-    Win32WindowContext::Win32WindowContext() : AbstractWindowContext() {
-    }
-
-    Win32WindowContext::~Win32WindowContext() {
-        // Remove window handle mapping
-        if (auto hWnd = reinterpret_cast<HWND>(windowId); hWnd) {
-            g_wndProcHash->remove(hWnd);
-
-            // Remove event filter if the all windows has been destroyed
-            if (g_wndProcHash->empty()) {
-                WindowsNativeEventFilter::uninstall();
+    static inline void addManagedWindow(QWindow *window, HWND hWnd, Win32WindowContext *ctx) {
+        const auto margins = [hWnd]() -> QMargins {
+            const auto titleBarHeight = int(getTitleBarHeight(hWnd));
+            if (isWin10OrGreater()) {
+                return {0, -titleBarHeight, 0, 0};
+            } else {
+                const auto frameSize = int(getResizeBorderThickness(hWnd));
+                return {-frameSize, -titleBarHeight, -frameSize, -frameSize};
             }
-        }
-    }
-
-    QString Win32WindowContext::key() const {
-        return QStringLiteral("win32");
-    }
-
-    void Win32WindowContext::virtual_hook(int id, void *data) {
-        switch (id) {
-            case CentralizeHook: {
-                const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId());
-                moveToDesktopCenter(hwnd);
-                return;
-            }
-            case ShowSystemMenuHook: {
-                const auto &pos = *reinterpret_cast<const QPoint *>(data);
-                auto hWnd = reinterpret_cast<HWND>(m_windowHandle->winId());
-                showSystemMenu2(hWnd, qpoint2point(pos), false,
-                                m_delegate->isHostSizeFixed(m_host));
-                return;
-            }
-            case NeedsDrawBordersHook: {
-                auto &result = *reinterpret_cast<bool *>(data);
-                result = isWin10OrGreater() && !isWin11OrGreater();
-                return;
-            }
-            case DrawBordersHook: {
-                auto args = reinterpret_cast<void **>(data);
-                auto &painter = *reinterpret_cast<QPainter *>(args[0]);
-                auto &rect = *reinterpret_cast<const QRect *>(args[1]);
-                auto &region = *reinterpret_cast<const QRegion *>(args[2]);
-                const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId());
-                QPen pen{};
-                const auto borderThickness = int(QHighDpi::fromNativePixels(getWindowFrameBorderThickness(hwnd), m_windowHandle));
-                pen.setWidth(borderThickness * 2);
-                const bool active = m_host->isWidgetType() ? m_host->property("isActiveWindow").toBool() : m_host->property("active").toBool();
-                const bool dark = isDarkThemeActive() && isDarkWindowFrameEnabled(hwnd);
-                if (active) {
-                    if (isWindowFrameBorderColorized()) {
-                        pen.setColor(getAccentColor());
-                    } else {
-                        if (dark) {
-                            pen.setColor(kFrameBorderActiveColorDark);
-                        } else {
-                            pen.setColor(kFrameBorderActiveColorLight);
-                        }
-                    }
-                } else {
-                    if (dark) {
-                        pen.setColor(kFrameBorderInactiveColorDark);
-                    } else {
-                        pen.setColor(kFrameBorderInactiveColorLight);
-                    }
-                }
-                painter.save();
-                painter.setRenderHint(QPainter::Antialiasing); // ### TODO: do we need to enable or disable it?
-                painter.setPen(pen);
-                painter.drawLine(QLine{ QPoint{ 0, 0 }, QPoint{ rect.width(), 0 } });
-                painter.restore();
-                return;
-            }
-            default: {
-                // unreachable
-                break;
-            }
-        }
-        AbstractWindowContext::virtual_hook(id, data);
-    }
-
-    bool Win32WindowContext::setupHost() {
-        // Install window hook
-        auto winId = m_windowHandle->winId();
-        auto hWnd = reinterpret_cast<HWND>(winId);
+        }();
 
         // Inform Qt we want and have set custom margins
-        updateInternalWindowFrameMargins(hWnd, m_windowHandle);
+        setInternalWindowFrameMargins(window, margins);
 
         // Store original window proc
         if (!g_qtWindowProc) {
@@ -854,13 +568,170 @@
         // Install global native event filter
         WindowsNativeEventFilter::install();
 
-        // Cache window ID
-        windowId = winId;
-
         // Save window handle mapping
-        g_wndProcHash->insert(hWnd, this);
+        g_wndProcHash->insert(hWnd, ctx);
+    }
 
-        return true;
+    static inline void removeManagedWindow(HWND hWnd) {
+        // Remove window handle mapping
+        if (!g_wndProcHash->remove(hWnd))
+            return;
+
+        // Remove event filter if the all windows has been destroyed
+        if (g_wndProcHash->empty()) {
+            WindowsNativeEventFilter::uninstall();
+        }
+    }
+
+    Win32WindowContext::Win32WindowContext() : AbstractWindowContext() {
+    }
+
+    Win32WindowContext::~Win32WindowContext() {
+        if (windowId) {
+            removeManagedWindow(reinterpret_cast<HWND>(windowId));
+        }
+    }
+
+    QString Win32WindowContext::key() const {
+        return QStringLiteral("win32");
+    }
+
+    void Win32WindowContext::virtual_hook(int id, void *data) {
+        switch (id) {
+            case CentralizeHook: {
+                if (!windowId)
+                    return;
+                const auto hwnd = reinterpret_cast<HWND>(windowId);
+                moveWindowToDesktopCenter(hwnd);
+                return;
+            }
+
+            case RaiseWindowHook: {
+                if (!windowId)
+                    return;
+                const auto hwnd = reinterpret_cast<HWND>(windowId);
+                bringWindowToFront(hwnd);
+                return;
+            }
+
+            case ShowSystemMenuHook: {
+                if (!windowId)
+                    return;
+                const auto &pos = *static_cast<const QPoint *>(data);
+                auto hWnd = reinterpret_cast<HWND>(windowId);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+                const QPoint nativeGlobalPos =
+                    QHighDpi::toNativeGlobalPosition(pos, m_windowHandle);
+#else
+                const QPoint nativeGlobalPos = QHighDpi::toNativePixels(pos, m_windowHandle);
+#endif
+                showSystemMenu2(hWnd, qpoint2point(nativeGlobalPos), false,
+                                m_delegate->isHostSizeFixed(m_host));
+                return;
+            }
+
+            case DefaultColorsHook: {
+                auto &map = *static_cast<QMap<QString, QColor> *>(data);
+                map.clear();
+                map.insert(QStringLiteral("activeLight"), kWindowsColorSet.activeLight);
+                map.insert(QStringLiteral("activeDark"), kWindowsColorSet.activeDark);
+                map.insert(QStringLiteral("inactiveLight"), kWindowsColorSet.inactiveLight);
+                map.insert(QStringLiteral("inactiveDark"), kWindowsColorSet.inactiveDark);
+                return;
+            }
+
+            case DrawWindows10BorderHook: {
+                if (!windowId)
+                    return;
+
+                auto args = static_cast<void **>(data);
+                auto &painter = *static_cast<QPainter *>(args[0]);
+                const auto &rect = *static_cast<const QRect *>(args[1]);
+                const auto &region = *static_cast<const QRegion *>(args[2]);
+                const auto hwnd = reinterpret_cast<HWND>(windowId);
+
+                QPen pen;
+                pen.setWidth(getWindowFrameBorderThickness(hwnd) * 2);
+
+                const bool dark = isDarkThemeActive() && isDarkWindowFrameEnabled(hwnd);
+                if (m_delegate->isWindowActive(m_host)) {
+                    if (isWindowFrameBorderColorized()) {
+                        pen.setColor(getAccentColor());
+                    } else {
+                        static QColor frameBorderActiveColorLight(kWindowsColorSet.activeLight);
+                        static QColor frameBorderActiveColorDark(kWindowsColorSet.activeDark);
+                        pen.setColor(dark ? frameBorderActiveColorDark
+                                          : frameBorderActiveColorLight);
+                    }
+                } else {
+                    static QColor frameBorderInactiveColorLight(kWindowsColorSet.inactiveLight);
+                    static QColor frameBorderInactiveColorDark(kWindowsColorSet.inactiveDark);
+                    pen.setColor(dark ? frameBorderInactiveColorDark
+                                      : frameBorderInactiveColorLight);
+                }
+                painter.save();
+
+                // We needs anti-aliasing to give us better result.
+                painter.setRenderHint(QPainter::Antialiasing);
+
+                painter.setPen(pen);
+                painter.drawLine(QLine{
+                    QPoint{0,                       0},
+                    QPoint{m_windowHandle->width(), 0}
+                });
+                painter.restore();
+                return;
+            }
+
+            default:
+                break;
+        }
+        AbstractWindowContext::virtual_hook(id, data);
+    }
+
+    bool Win32WindowContext::needBorderPainter() const {
+        return isWin10OrGreater() && !isWin11OrGreater();
+    }
+
+    int Win32WindowContext::borderThickness() const {
+        return getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId));
+    }
+
+    void Win32WindowContext::winIdChanged() {
+        // If the original window id is valid, remove all resources related
+        if (windowId) {
+            removeManagedWindow(reinterpret_cast<HWND>(windowId));
+            windowId = 0;
+        }
+
+        if (!m_windowHandle) {
+            return;
+        }
+
+        // Install window hook
+        auto winId = m_windowHandle->winId();
+        auto hWnd = reinterpret_cast<HWND>(winId);
+
+        if (!isWin10OrGreater()) {
+            static constexpr const MARGINS margins = {1, 1, 1, 1};
+            DynamicApis::instance().pDwmExtendFrameIntoClientArea(hWnd, &margins);
+        }
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
+        for (const auto attr : {
+                 _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1,
+                 _DWMWA_USE_IMMERSIVE_DARK_MODE,
+             }) {
+            const BOOL enable = TRUE;
+            DynamicApis::instance().pDwmSetWindowAttribute(hWnd, attr, &enable, sizeof(enable));
+        }
+#endif
+
+        // Add managed window
+        addManagedWindow(m_windowHandle, hWnd, this);
+
+        // Cache win id
+        windowId = winId;
     }
 
     bool Win32WindowContext::windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam,
@@ -895,16 +766,184 @@
             return true;
         }
 
+        // Whether to show system menu
         if (systemMenuHandler(hWnd, message, wParam, lParam, result)) {
             return true;
         }
 
+        // Forward to native event filter subscribers
+        if (!m_nativeEventFilters.isEmpty()) {
+            MSG msg;
+            msg.hwnd = hWnd;
+            msg.message = message;
+            msg.wParam = wParam;
+            msg.lParam = lParam;
+            QT_NATIVE_EVENT_RESULT_TYPE res = 0;
+            if (dispatch(QByteArrayLiteral("windows_generic_MSG"), &msg, &res)) {
+                *result = LRESULT(res);
+                return true;
+            }
+        }
         return false; // Not handled
     }
 
-    static constexpr const struct {
-        const WPARAM wParam = 0xF1C9ADD4;
-        const LPARAM lParam = 0xAFB6F4C6;
+    bool Win32WindowContext::windowAttributeChanged(const QString &key, const QVariant &attribute,
+                                                    const QVariant &oldAttribute) {
+        const auto hwnd = reinterpret_cast<HWND>(window->winId());
+        const DynamicApis &apis = DynamicApis::instance();
+        if (key == QStringLiteral("mica")) {
+            if (!isWin11OrGreater()) {
+                return false;
+            }
+            if (attribute.toBool()) {
+                // We need to extend the window frame into the whole client area to be able
+                // to see the blurred window background.
+                static constexpr const MARGINS margins = {-1, -1, -1, -1};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+                if (isWin1122H2OrGreater()) {
+                    // Use official DWM API to enable Mica, available since Windows 11 22H2
+                    // (10.0.22621).
+                    const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_MAINWINDOW;
+                    apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType,
+                                                sizeof(backdropType));
+                } else {
+                    // Use undocumented DWM API to enable Mica, available since Windows 11
+                    // (10.0.22000).
+                    const BOOL enable = TRUE;
+                    apis.pDwmSetWindowAttribute(hwnd, _DWMWA_MICA_EFFECT, &enable, sizeof(enable));
+                }
+            } else {
+                if (isWin1122H2OrGreater()) {
+                    const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_AUTO;
+                    apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType,
+                                                sizeof(backdropType));
+                } else {
+                    const BOOL enable = FALSE;
+                    apis.pDwmSetWindowAttribute(hwnd, _DWMWA_MICA_EFFECT, &enable, sizeof(enable));
+                }
+                static constexpr const MARGINS margins = {0, 0, 0, 0};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+            }
+            return true;
+        } else if (key == QStringLiteral("mica-alt")) {
+            if (!isWin1122H2OrGreater()) {
+                return false;
+            }
+            if (attribute.toBool()) {
+                // We need to extend the window frame into the whole client area to be able
+                // to see the blurred window background.
+                static constexpr const MARGINS margins = {-1, -1, -1, -1};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+                // Use official DWM API to enable Mica Alt, available since Windows 11 22H2
+                // (10.0.22621).
+                const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_TABBEDWINDOW;
+                apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType,
+                                            sizeof(backdropType));
+            } else {
+                const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_AUTO;
+                apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType,
+                                            sizeof(backdropType));
+                static constexpr const MARGINS margins = {0, 0, 0, 0};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+            }
+            return true;
+        } else if (key == QStringLiteral("acrylic-material")) {
+            if (!isWin10OrGreater()) {
+                return false;
+            }
+            if (attribute.userType() == QMetaType::QColor) {
+                // We need to extend the window frame into the whole client area to be able
+                // to see the blurred window background.
+                static constexpr const MARGINS margins = {-1, -1, -1, -1};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+                if (isWin11OrGreater()) {
+                    const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_TRANSIENTWINDOW;
+                    apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType,
+                                                sizeof(backdropType));
+                } else {
+                    auto gradientColor = attribute.value<QColor>();
+
+                    ACCENT_POLICY policy{};
+                    policy.dwAccentState = ACCENT_ENABLE_ACRYLICBLURBEHIND;
+                    policy.dwAccentFlags = ACCENT_ENABLE_ACRYLIC_WITH_LUMINOSITY;
+                    // This API expects the #AABBGGRR format.
+                    policy.dwGradientColor =
+                        DWORD(qRgba(gradientColor.blue(), gradientColor.green(),
+                                    gradientColor.red(), gradientColor.alpha()));
+                    WINDOWCOMPOSITIONATTRIBDATA wcad{};
+                    wcad.Attrib = WCA_ACCENT_POLICY;
+                    wcad.pvData = &policy;
+                    wcad.cbData = sizeof(policy);
+                    apis.pSetWindowCompositionAttribute(hwnd, &wcad);
+                }
+            } else {
+                if (isWin11OrGreater()) {
+                    const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_AUTO;
+                    apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType,
+                                                sizeof(backdropType));
+                } else {
+                    ACCENT_POLICY policy{};
+                    policy.dwAccentState = ACCENT_DISABLED;
+                    policy.dwAccentFlags = ACCENT_NONE;
+                    WINDOWCOMPOSITIONATTRIBDATA wcad{};
+                    wcad.Attrib = WCA_ACCENT_POLICY;
+                    wcad.pvData = &policy;
+                    wcad.cbData = sizeof(policy);
+                    apis.pSetWindowCompositionAttribute(hwnd, &wcad);
+                }
+                static constexpr const MARGINS margins = {0, 0, 0, 0};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+            }
+            return true;
+        } else if (key == QStringLiteral("dwm-blur")) {
+            if (attribute.toBool()) {
+                // We need to extend the window frame into the whole client area to be able
+                // to see the blurred window background.
+                static constexpr const MARGINS margins = {-1, -1, -1, -1};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+                if (isWin8OrGreater()) {
+                    ACCENT_POLICY policy{};
+                    policy.dwAccentState = ACCENT_ENABLE_BLURBEHIND;
+                    policy.dwAccentFlags = ACCENT_NONE;
+                    WINDOWCOMPOSITIONATTRIBDATA wcad{};
+                    wcad.Attrib = WCA_ACCENT_POLICY;
+                    wcad.pvData = &policy;
+                    wcad.cbData = sizeof(policy);
+                    apis.pSetWindowCompositionAttribute(hwnd, &wcad);
+                } else {
+                    DWM_BLURBEHIND bb{};
+                    bb.fEnable = TRUE;
+                    bb.fTransitionOnMaximized = TRUE;
+                    bb.dwFlags = DWM_BB_ENABLE | DWM_BB_TRANSITIONONMAXIMIZED;
+                    apis.pDwmEnableBlurBehindWindow(hwnd, &bb);
+                }
+            } else {
+                if (isWin8OrGreater()) {
+                    ACCENT_POLICY policy{};
+                    policy.dwAccentState = ACCENT_DISABLED;
+                    policy.dwAccentFlags = ACCENT_NONE;
+                    WINDOWCOMPOSITIONATTRIBDATA wcad{};
+                    wcad.Attrib = WCA_ACCENT_POLICY;
+                    wcad.pvData = &policy;
+                    wcad.cbData = sizeof(policy);
+                    apis.pSetWindowCompositionAttribute(hwnd, &wcad);
+                } else {
+                    DWM_BLURBEHIND bb{};
+                    bb.fEnable = FALSE;
+                    bb.dwFlags = DWM_BB_ENABLE;
+                    apis.pDwmEnableBlurBehindWindow(hwnd, &bb);
+                }
+                static constexpr const MARGINS margins = {0, 0, 0, 0};
+                apis.pDwmExtendFrameIntoClientArea(hwnd, &margins);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    QWK_USED static constexpr const struct {
+        const WPARAM wParam = MAKEWPARAM(44500, 61897);
+        const LPARAM lParam = MAKELPARAM(62662, 44982); // Not used. Reserve for future use.
     } kMessageTag;
 
     static inline quint64 getKeyState() {
@@ -1046,7 +1085,7 @@
                                                LPARAM lParam, LRESULT *result) {
         switch (message) {
             case WM_MOUSELEAVE: {
-                if (wParam == kMessageTag.wParam) {
+                if (wParam != kMessageTag.wParam) {
                     // Qt will call TrackMouseEvent() to get the WM_MOUSELEAVE message when it
                     // receives WM_MOUSEMOVE messages, and since we are converting every
                     // WM_NCMOUSEMOVE message to WM_MOUSEMOVE message and send it back to the window
@@ -1107,7 +1146,54 @@
                 const WindowPart currentWindowPart = lastHitTestResult;
                 if (message == WM_NCMOUSEMOVE) {
                     if (currentWindowPart != WindowPart::ChromeButton) {
-                        m_delegate->resetQtGrabbedControl();
+                        // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/widgets/kernel/qwidgetwindow.cpp#L472
+                        // When the mouse press event arrives, QWidgetWindow will implicitly grab
+                        // the top widget right under the mouse, and set `qt_button_down` to this
+                        // widget. At this time, no other widgets will accept the mouse event until
+                        // QWidgetWindow receives the mouse release event, then set `qt_button_down`
+                        // to null.
+
+                        // Imagine the following situation, now the main window has a pop-up menu,
+                        // the focus is not on the main window, if we click outside the pop-up menu,
+                        // the menu will close, which seems to be completely fine. But if we close
+                        // the menu by clicking on the title bar draggable area, then other widgets
+                        // won't accept the mouse message afterwards.
+
+                        // Here's the reason.
+                        // When the mouse is placed in the draggable area of the title bar, there
+                        // are two situations.
+
+                        // 1. If the focus is on the main window, and the last result of
+                        // WM_NCHITTEST is HTCAPTION, the mouse click event in the title bar is
+                        // taken over by Windows and Qt does not receive the mouse click event.
+
+                        // 2. If the main window has a pop-up menu, it is completely different. When
+                        // the mouse is pressed on the title bar, Windows sends the WM_LBUTTONDOWN
+                        // message to the window plane of the pop-up menu, the menu is closed, but
+                        // Qt will continue to forward the event to the QWidget under the mouse, and
+                        // the event will be processed by QWidgetWindow, causing the title bar
+                        // widget to be implicitly grabbed. After the menu is closed, Windows
+                        // immediately sends WM_NCHITTEST, because the mouse is in the title bar
+                        // draggable area, the result is HTCAPTION, so when the mouse is released,
+                        // Windows sends WM_NCLBUTTONUP, which is a non-client message, and it
+                        // will be ignored by Qt. As a consequence, QWidgetWindow can't receive a
+                        // mouse release message in the client area, so the grab remains, and other
+                        // widgets cannot receive mouse events.
+
+                        // Since we didn't watch the menu window, we cannot capture any mouse
+                        // press events sent by Windows, so we cannot solve this problem by
+                        // recording mouse events. Fortunately, we found that the main window will
+                        // receive a WM_NCMOUSEMOVE message immediately after the menu is closed, so
+                        // we just manually send a mouse release event when this message arrives and
+                        // set qt_button_down to null. Don't worry, when receiving WM_NCMOUSEMOVE,
+                        // there shouldn't be any control in the state of being grabbed.
+
+                        // In the native window, although QWidgetWindow handles the forwarded mouse
+                        // press event when the menu is closed, since the native title bar is not a
+                        // QWidget, no widget will be grabbed, and `qt_button_down` remains empty,
+                        // the above problems would not arise.
+
+                        m_delegate->resetQtGrabbedControl(m_host);
                         if (mouseLeaveBlocked) {
                             emulateClientAreaMessage(hWnd, message, wParam, lParam,
                                                      WM_NCMOUSELEAVE);
@@ -1169,7 +1255,9 @@
                         // window from client area, which means we will get previous window part as
                         // HTCLIENT if the mouse leaves window from client area and enters window
                         // from non-client area, but it has no bad effect.
-                        m_delegate->resetQtGrabbedControl();
+
+                        // Why do we need to call this function here?
+                        m_delegate->resetQtGrabbedControl(m_host);
                     }
                 }
                 break;
@@ -1189,13 +1277,14 @@
                     // If wParam is TRUE, the window is being shown.
                     // If lParam is zero, the message was sent because of a call to the ShowWindow
                     // function.
-                    if (wParam && lParam == 0) {
+                    if (wParam && !lParam) {
                         centered = true;
-                        moveToDesktopCenter(hWnd);
+                        moveWindowToDesktopCenter(hWnd);
                     }
                 }
                 break;
             }
+
             case WM_NCHITTEST: {
                 // 鍘熺敓Win32绐楀彛鍙湁椤惰竟鏄湪绐楀彛鍐呴儴resize鐨勶紝鍏朵綑涓夎竟閮芥槸鍦ㄧ獥鍙�
                 // 澶栭儴杩涜resize鐨勶紝鍏跺師鐞嗘槸锛學S_THICKFRAME杩欎釜绐楀彛鏍峰紡浼氬湪绐�
@@ -1277,7 +1366,6 @@
                 // Terminal does, however, later I found that if we choose a proper
                 // color, our homemade top border can almost have exactly the same
                 // appearance with the system's one.
-
                 [[maybe_unused]] const auto &hitTestRecorder = qScopeGuard([this, result]() {
                     lastHitTestResult = getHitWindowPart(int(*result)); //
                 });
@@ -1308,7 +1396,7 @@
                     // this is also the normal behavior of a native Win32 window (but only when the
                     // window is not maximized/fullscreen/minimized, of course).
                     if (isWindowNoState(hWnd)) {
-                        static constexpr const auto kBorderSize = quint8{2};
+                        static constexpr const quint8 kBorderSize = 2;
                         bool isTop = (nativeLocalPos.y <= kBorderSize);
                         bool isLeft = nativeLocalPos.x <= kBorderSize;
                         bool isRight = (nativeLocalPos.x >= (clientWidth - kBorderSize));
@@ -1400,7 +1488,7 @@
                         *result = (isTitleBar ? HTCAPTION : HTCLIENT);
                         return true;
                     }
-                    // At this point, we know that the cursor is inside the client area
+                    // At this point, we know that the cursor is inside the client area,
                     // so it has to be either the little border at the top of our custom
                     // title bar or the drag bar. Apparently, it must be the drag bar or
                     // the little border at the top which the user can use to move or
@@ -1484,9 +1572,28 @@
                     return true;
                 }
             }
+
+            case WM_WINDOWPOSCHANGING: {
+                // ### FIXME: How does this problem happen and why is it solved?
+                // When toggling the "Show theme color in title bar and window border" setting in
+                // Windows Settings, or calling `DrawMenuBar()`, Windows sends a message of
+                // WM_WINDOWPOSCHANGING with flags 0x37. If we do not process this message,
+                // the client area as a whole will shift to the left, which looks very abnormal if
+                // we don't repaint it. This exception disappears if we add SWP_NOCOPYBITS flag.
+                // But I don't know what caused the problem, or why this would solve it.
+                static constexpr const auto kBadWindowPosFlag =
+                    SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED;
+                const auto windowPos = reinterpret_cast<LPWINDOWPOS>(lParam);
+                if (windowPos->flags == kBadWindowPosFlag) {
+                    windowPos->flags |= SWP_NOCOPYBITS;
+                }
+                break;
+            }
+
             default:
                 break;
         }
+
         if (!isWin10OrGreater()) {
             switch (message) {
                 case WM_NCUAHDRAWCAPTION:

--
Gitblit v1.9.1