From c229915e9d4b2818155f3650869726fdcbe7e21d Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 摹曛, 21 12月 2023 14:12:26 +0800
Subject: [PATCH] Prepare to add mica

---
 src/core/contexts/win32windowcontext.cpp |   85 +++++++++++++++++++++++++++++++-----------
 1 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 145b19c..1b969cf 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -379,16 +379,7 @@
                getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
     }
 
-    static 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)
@@ -829,7 +820,20 @@
         return ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam);
     }
 
-    static inline void addManagedWindow(HWND hWnd, Win32WindowContext *ctx) {
+    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};
+            }
+        }();
+
+        // Inform Qt we want and have set custom margins
+        setInternalWindowFrameMargins(window, margins);
+
         // Store original window proc
         if (!g_qtWindowProc) {
             g_qtWindowProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtrW(hWnd, GWLP_WNDPROC));
@@ -872,18 +876,24 @@
     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)
@@ -904,13 +914,38 @@
                 const auto &oldVar = *static_cast<const QVariant *>(args[2]);
 
                 if (key == QStringLiteral("no-frame-shadow")) {
+                    if (!windowId)
+                        return;
                     if (newVar.toBool()) {
                         // TODO: set off
                     } else {
                         // TODO: set on
                     }
-                }
+                } else if (key == QStringLiteral("mica-material")) {
+                    if (!windowId || !isWin11OrGreater())
+                        return;
+                    const auto hwnd = reinterpret_cast<HWND>(windowId);
+                    if (newVar.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};
+                        ::DwmExtendFrameIntoClientArea(hwnd, &margins);
+
+                        // Use official DWM API to enable Mica/Mica Alt, available since Windows 11
+                        // (10.0.22000).
+                        const DWM_SYSTEMBACKDROP_TYPE blurType =
+                            DWMSBT_MAINWINDOW; // This one is Mica, if you want to enable Mica Alt,
+                                               // use DWMSBT_TABBEDWINDOW instead.
+                        DynamicApis::instance().pDwmSetWindowAttribute(
+                            hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &blurType, sizeof(blurType));
+
+                        */
+                    } else {
+                        // TODO: set off
+                    }
+                }
                 return;
             }
 
@@ -925,6 +960,9 @@
             }
 
             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]);
@@ -964,9 +1002,8 @@
                 return;
             }
 
-            default: {
+            default:
                 break;
-            }
         }
         AbstractWindowContext::virtual_hook(id, data);
     }
@@ -979,8 +1016,13 @@
         return getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId));
     }
 
-    void Win32WindowContext::winIdChanged(QWindow *oldWindow) {
-        removeManagedWindow(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;
         }
@@ -999,11 +1041,8 @@
         }
 #endif
 
-        // Inform Qt we want and have set custom margins
-        updateInternalWindowFrameMargins(hWnd, m_windowHandle);
-
         // Add managed window
-        addManagedWindow(hWnd, this);
+        addManagedWindow(m_windowHandle, hWnd, this);
 
         // Cache win id
         windowId = winId;
@@ -1296,9 +1335,9 @@
                         // 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 area message, and it
+                        // 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 messages in the client area, so the grab remains, and other
+                        // 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
@@ -1609,7 +1648,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

--
Gitblit v1.9.1