From f14f27f41385fd8593457413de2cf5a9c5c357e9 Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 周三, 13 12月 2023 18:34:14 +0800
Subject: [PATCH] Change to Apache 2.0 License

---
 src/core/contexts/win32windowcontext.cpp |  209 ++++++++++++++++++++++++++++++++++------------------
 1 files changed, 136 insertions(+), 73 deletions(-)

diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 22d9f1c..7dfd543 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -4,6 +4,7 @@
 
 #include <QtCore/QHash>
 #include <QtCore/QScopeGuard>
+#include <QtCore/QTimer>
 #include <QtGui/QGuiApplication>
 #include <QtGui/QPainter>
 #include <QtGui/QPalette>
@@ -26,7 +27,7 @@
 #include <dwmapi.h>
 #include <timeapi.h>
 
-#include "nativeeventfilter.h"
+#include "nativeeventfilter_p.h"
 #include "qwkglobal_p.h"
 
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
@@ -65,7 +66,7 @@
     // The thickness of an auto-hide taskbar in pixels.
     static constexpr const quint8 kAutoHideTaskBarThickness = 2;
 
-    static constexpr const struct {
+    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
@@ -357,44 +358,37 @@
         }
     }
 
-    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) {
+    static void updateInternalWindowFrameMargins(HWND hwnd, QWindow *window) {
         const auto margins = [hwnd]() -> QMargins {
             const auto titleBarHeight = int(getTitleBarHeight(hwnd));
             if (isWin10OrGreater()) {
@@ -460,7 +454,7 @@
 #endif
     }
 
-    static inline void syncPaintEventWithDwm() {
+    static void syncPaintEventWithDwm() {
         // No need to sync with DWM if DWM composition is disabled.
         if (!isDwmCompositionEnabled()) {
             return;
@@ -505,9 +499,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
@@ -809,35 +803,17 @@
                 return;
             }
 
-            case NeedsDrawBordersHook: {
-                auto &result = *static_cast<bool *>(data);
-                result = isWin10OrGreater() && !isWin11OrGreater();
+            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 BorderThicknessHook: {
-                auto args = static_cast<void **>(data);
-                const bool requireNative = *static_cast<const bool *>(args[0]);
-                quint32 &thickness = *static_cast<quint32 *>(args[1]);
-                const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId());
-                const auto nativeThickness = getWindowFrameBorderThickness(hwnd);
-                thickness = requireNative
-                                ? nativeThickness
-                                : QHighDpi::fromNativePixels(nativeThickness, m_windowHandle);
-                return;
-            }
-
-            case BorderColorsHook: {
-                auto arr = *reinterpret_cast<QList<QColor> *>(data);
-                arr.clear();
-                arr.push_back(kWindowsColorSet.activeLight);
-                arr.push_back(kWindowsColorSet.activeDark);
-                arr.push_back(kWindowsColorSet.inactiveLight);
-                arr.push_back(kWindowsColorSet.inactiveDark);
-                return;
-            }
-
-            case DrawBordersHook: {
+            case DrawWindows10BorderHook: {
                 auto args = static_cast<void **>(data);
                 auto &painter = *static_cast<QPainter *>(args[0]);
                 const auto &rect = *static_cast<const QRect *>(args[1]);
@@ -845,13 +821,10 @@
                 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_delegate->isWindowActive(m_host);
-                const bool dark = isDarkThemeActive() && isDarkWindowFrameEnabled(hwnd);
+                pen.setWidth(getWindowFrameBorderThickness(hwnd) * 2);
 
-                if (active) {
+                const bool dark = isDarkThemeActive() && isDarkWindowFrameEnabled(hwnd);
+                if (m_delegate->isWindowActive(m_host)) {
                     if (isWindowFrameBorderColorized()) {
                         pen.setColor(getAccentColor());
                     } else {
@@ -873,11 +846,10 @@
 
                 painter.setPen(pen);
                 painter.drawLine(QLine{
-                    QPoint{0,            0},
-                    QPoint{rect.width(), 0}
+                    QPoint{0,                       0},
+                    QPoint{m_windowHandle->width(), 0}
                 });
                 painter.restore();
-                return;
             }
 
             default: {
@@ -886,6 +858,14 @@
             }
         }
         AbstractWindowContext::virtual_hook(id, data);
+    }
+
+    bool Win32WindowContext::needBorderPainter() const {
+        return isWin10OrGreater() && !isWin11OrGreater();
+    }
+
+    int Win32WindowContext::borderThickness() const {
+        return getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId));
     }
 
     bool Win32WindowContext::setupHost() {
@@ -948,16 +928,21 @@
             return true;
         }
 
+        // Whether to show system menu
         if (systemMenuHandler(hWnd, message, wParam, lParam, result)) {
+            return true;
+        }
+
+        if (themeStuffHandler(hWnd, message, wParam, lParam, result)) {
             return true;
         }
 
         return false; // Not handled
     }
 
-    static constexpr const struct {
-        const WPARAM wParam = 0xF1C9ADD4;
-        const LPARAM lParam = 0xAFB6F4C6;
+    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() {
@@ -1099,7 +1084,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
@@ -1362,7 +1347,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));
@@ -1938,4 +1923,82 @@
         return false;
     }
 
+    bool Win32WindowContext::themeStuffHandler(HWND hWnd, UINT message, WPARAM wParam,
+                                               LPARAM lParam, LRESULT *resul) {
+        switch (message) {
+            case WM_DPICHANGED: {
+                const auto dpiX = UINT(LOWORD(wParam));
+                const auto dpiY = UINT(HIWORD(wParam));
+
+                QEvent e(QEvent::ScreenChangeInternal);
+                dispatch(&e);
+                break;
+            }
+
+            case WM_THEMECHANGED:
+            case WM_SYSCOLORCHANGE: {
+                QEvent e(QEvent::UpdateLater);
+                dispatch(&e);
+                break;
+            }
+
+            case WM_DWMCOLORIZATIONCOLORCHANGED: {
+                const QColor color = QColor::fromRgba(wParam);
+                const auto blendWithOpacity = *reinterpret_cast<LPBOOL>(lParam);
+
+                QEvent e(QEvent::UpdateLater);
+                dispatch(&e);
+                break;
+            }
+
+            case WM_SETTINGCHANGE: {
+                if (!wParam && lParam &&
+                    std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0) {
+                    const QColor color = getAccentColor();
+                }
+
+                QEvent e(QEvent::UpdateLater);
+                dispatch(&e);
+                break;
+            }
+
+            // case WM_SIZE: {
+            //     const bool max = wParam == SIZE_MAXIMIZED;
+            //     const bool min = wParam == SIZE_MINIMIZED;
+            //     const bool full = isFullScreen(hWnd);
+
+            //     Qt::WindowStates states{};
+            //     if (max) {
+            //         states |= Qt::WindowMaximized;
+            //     }
+            //     if (min) {
+            //         states |= Qt::WindowMinimized;
+            //     }
+            //     if (full) {
+            //         states |= Qt::WindowFullScreen;
+            //     }
+
+            //     // QTimer::singleShot(0, this, [this, states] {
+            //     QWindowStateChangeEvent e(states);
+            //     dispatch(&e);
+            //     // });
+            //     break;
+            // }
+
+            // case WM_ACTIVATE: {
+            //     const auto state = LOWORD(wParam);
+            //     const bool active = state == WA_ACTIVE || state == WA_CLICKACTIVE;
+            //     Q_UNUSED(state)
+
+            //     // QTimer::singleShot(0, this, [this, active] {
+            //     QEvent e(active ? QEvent::WindowActivate : QEvent::WindowDeactivate);
+            //     dispatch(&e);
+            //     // });
+            //     break;
+            // }
+            default:
+                break;
+        }
+        return false;
+    }
 }

--
Gitblit v1.9.1