From 1b9ac9ea6998ac8a4e51413e06aeed859e784b26 Mon Sep 17 00:00:00 2001
From: Sine Striker <trueful@163.com>
Date: 周一, 11 12月 2023 20:09:19 +0800
Subject: [PATCH] minor tweaks

---
 src/core/contexts/win32windowcontext.cpp |  191 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 151 insertions(+), 40 deletions(-)

diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 4d08adc..ccc318d 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -1,13 +1,15 @@
 #include "win32windowcontext_p.h"
-#include "qwkcoreglobal_p.h"
 
 #include <optional>
 
 #include <QtCore/QHash>
-#include <QtCore/QAbstractNativeEventFilter>
 #include <QtCore/QScopeGuard>
 #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)
@@ -23,7 +25,8 @@
 #include <shellscalingapi.h>
 #include <dwmapi.h>
 #include <timeapi.h>
-#include <versionhelpers.h>
+
+#include "nativeeventfilter.h"
 
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
 Q_DECLARE_METATYPE(QMargins)
@@ -33,6 +36,14 @@
 
     // The thickness of an auto-hide taskbar in pixels.
     static constexpr const auto kAutoHideTaskBarThickness = quint8{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
 
     // hWnd -> context
     using WndProcHash = QHash<HWND, Win32WindowContext *>;
@@ -62,7 +73,8 @@
 //            }
 //        };
 //
-// #define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME = DefaultFunc<decltype(&::NAME)>::func
+// #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);
@@ -78,7 +90,8 @@
 #undef DYNAMIC_API_DECLARE
 
         DynamicApis() {
-#define DYNAMIC_API_RESOLVE(DLL, NAME) p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME))
+#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);
@@ -192,22 +205,22 @@
     }
 
     static inline bool isWin8OrGreater() {
-        static const bool result = ::IsWindows8OrGreater();
+        static const bool result = IsWindows8OrGreater_Real();
         return result;
     }
 
     static inline bool isWin8Point1OrGreater() {
-        static const bool result = ::IsWindows8Point1OrGreater();
+        static const bool result = IsWindows8Point1OrGreater_Real();
         return result;
     }
 
     static inline bool isWin10OrGreater() {
-        static const bool result = ::IsWindows10OrGreater();
+        static const bool result = IsWindows10OrGreater_Real();
         return result;
     }
 
     static inline bool isWin11OrGreater() {
-        static const bool result = ::IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 22000);
+        static const bool result = IsWindows11OrGreater_Real();
         return result;
     }
 
@@ -221,6 +234,57 @@
         }
         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 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) {
@@ -383,8 +447,8 @@
         apis.ptimeEndPeriod(ms_granularity);
     }
 
-    static inline void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry, const bool fixedSize)
-    {
+    static inline void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry,
+                                       const bool fixedSize) {
         const HMENU hMenu = ::GetSystemMenu(hWnd, FALSE);
         if (!hMenu) {
             // The corresponding window doesn't have a system menu, most likely due to the
@@ -395,8 +459,10 @@
 
         const bool maxOrFull = IsMaximized(hWnd) || isFullScreen(hWnd);
         ::EnableMenuItem(hMenu, SC_CLOSE, (MF_BYCOMMAND | MFS_ENABLED));
-        ::EnableMenuItem(hMenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
-        ::EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
+        ::EnableMenuItem(hMenu, SC_MAXIMIZE,
+                         (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
+        ::EnableMenuItem(hMenu, SC_RESTORE,
+                         (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
         // The first menu item should be selected by default if the menu is brought
         // up by keyboard. I don't know how to pre-select a menu item but it seems
         // highlight can do the job. However, there's an annoying issue if we do
@@ -406,9 +472,11 @@
         // highlight bar will not move accordingly, the OS will generate another
         // highlight bar to indicate the current selected menu item, which will make
         // the menu look kind of weird. Currently I don't know how to fix this issue.
-        ::HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
+        ::HiliteMenuItem(hWnd, hMenu, SC_RESTORE,
+                         (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
         ::EnableMenuItem(hMenu, SC_MINIMIZE, (MF_BYCOMMAND | MFS_ENABLED));
-        ::EnableMenuItem(hMenu, SC_SIZE, (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
+        ::EnableMenuItem(hMenu, SC_SIZE,
+                         (MF_BYCOMMAND | ((maxOrFull || fixedSize) ? MFS_DISABLED : MFS_ENABLED)));
         ::EnableMenuItem(hMenu, SC_MOVE, (MF_BYCOMMAND | (maxOrFull ? MFS_DISABLED : MFS_ENABLED)));
 
         // The default menu item will appear in bold font. There can only be one default
@@ -428,7 +496,10 @@
         ::SetMenuDefaultItem(hMenu, defaultItemId, FALSE);
 
         // Popup the system menu at the required position.
-        const auto result = ::TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), pos.x, pos.y, 0, hWnd, nullptr);
+        const auto result = ::TrackPopupMenu(
+            hMenu,
+            (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)),
+            pos.x, pos.y, 0, hWnd, nullptr);
 
         // Unhighlight the first menu item after the popup menu is closed, otherwise it will keep
         // highlighting until we unhighlight it manually.
@@ -467,7 +538,8 @@
             case HTBORDER:
                 return Win32WindowContext::FixedBorder;
             default:
-                break; // unreachable
+                // unreachable
+                break;
         }
         return Win32WindowContext::Outside;
     }
@@ -511,7 +583,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 QAbstractNativeEventFilter {
+    class WindowsNativeEventFilter : public NativeEventFilter {
     public:
         bool nativeEventFilter(const QByteArray &eventType, void *message,
                                QT_NATIVE_EVENT_RESULT_TYPE *result) override {
@@ -546,14 +618,12 @@
                 return;
             }
             instance = new WindowsNativeEventFilter();
-            installNativeEventFilter(instance);
         }
 
         static inline void uninstall() {
             if (!instance) {
                 return;
             }
-            removeNativeEventFilter(instance);
             delete instance;
             instance = nullptr;
         }
@@ -661,6 +731,41 @@
         }
     }
 
+    QString Win32WindowContext::key() const {
+        return "win32";
+    }
+
+    void Win32WindowContext::virtual_hook(int id, void *data) {
+        switch (id) {
+            case ShowSystemMenuHook: {
+                const auto &pos = *reinterpret_cast<const QPoint *>(data);
+                auto winId = m_windowHandle->winId();
+                auto hWnd = reinterpret_cast<HWND>(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]);
+                // ### TODO
+                return;
+            }
+            default: {
+                // unreachable
+                break;
+            }
+        }
+        AbstractWindowContext::virtual_hook(id, data);
+    }
+
     bool Win32WindowContext::setupHost() {
         // Install window hook
         auto winId = m_windowHandle->winId();
@@ -728,11 +833,10 @@
         return false; // Not handled
     }
 
-    static constexpr const auto kMessageTag = WPARAM(0x97CCEA99);
-
-    static inline constexpr bool isTaggedMessage(WPARAM wParam) {
-        return (wParam == kMessageTag);
-    }
+    static constexpr const struct {
+        const WPARAM wParam = 0xF1C9ADD4;
+        const LPARAM lParam = 0xAFB6F4C6;
+    } kMessageTag;
 
     static inline quint64 getKeyState() {
         quint64 result = 0;
@@ -772,7 +876,7 @@
                 // wParam is always ignored in mouse leave messages, but here we
                 // give them a special tag to be able to distinguish which messages
                 // are sent by ourselves.
-                return kMessageTag;
+                return kMessageTag.wParam;
             }
             const quint64 keyState = getKeyState();
             if ((myMsg >= WM_NCXBUTTONDOWN) && (myMsg <= WM_NCXBUTTONDBLCLK)) {
@@ -850,6 +954,7 @@
                 SEND_MESSAGE(hWnd, WM_MOUSELEAVE, wParamNew, lParamNew);
                 break;
             default:
+                // unreachable
                 break;
         }
 
@@ -872,7 +977,7 @@
                                                LPARAM lParam, LRESULT *result) {
         switch (message) {
             case WM_MOUSELEAVE: {
-                if (!isTaggedMessage(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
@@ -884,8 +989,9 @@
                     DWORD dwScreenPos = ::GetMessagePos();
                     POINT screenPoint{GET_X_LPARAM(dwScreenPos), GET_Y_LPARAM(dwScreenPos)};
                     ::ScreenToClient(hWnd, &screenPoint);
-                    QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(screenPoint), m_windowHandle);
-                    auto dummy = CoreWindowAgent::Unknown;
+                    QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(screenPoint),
+                                                                          m_windowHandle);
+                    auto dummy = WindowAgentBase::Unknown;
                     if (isInSystemButtons(qtScenePos, &dummy)) {
                         // We must record whether the last WM_MOUSELEAVE was filtered, because if
                         // Qt does not receive this message it will not call TrackMouseEvent()
@@ -1116,13 +1222,14 @@
                 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);
 
                 bool isFixedSize = m_delegate->isHostSizeFixed(m_host);
                 bool isTitleBar = isInTitleBarDraggableArea(qtScenePos);
                 bool dontOverrideCursor = false; // ### TODO
 
-                CoreWindowAgent::SystemButton sysButtonType = CoreWindowAgent::Unknown;
+                WindowAgentBase::SystemButton sysButtonType = WindowAgentBase::Unknown;
                 if (!isFixedSize && isInSystemButtons(qtScenePos, &sysButtonType)) {
                     // Firstly, we set the hit test result to a default value to be able to detect
                     // whether we have changed it or not afterwards.
@@ -1166,23 +1273,24 @@
                         // exact role of our button. The Snap Layout feature introduced in Windows
                         // 11 won't work without this.
                         switch (sysButtonType) {
-                            case CoreWindowAgent::WindowIcon:
+                            case WindowAgentBase::WindowIcon:
                                 *result = HTSYSMENU;
                                 break;
-                            case CoreWindowAgent::Help:
+                            case WindowAgentBase::Help:
                                 *result = HTHELP;
                                 break;
-                            case CoreWindowAgent::Minimize:
+                            case WindowAgentBase::Minimize:
                                 *result = HTREDUCE;
                                 break;
-                            case CoreWindowAgent::Maximize:
+                            case WindowAgentBase::Maximize:
                                 *result = HTZOOM;
                                 break;
-                            case CoreWindowAgent::Close:
+                            case WindowAgentBase::Close:
                                 *result = HTCLOSE;
                                 break;
                             default:
-                                break; // unreachable
+                                // unreachable
+                                break;
                         }
                     }
                     if (*result == HTNOWHERE) {
@@ -1628,7 +1736,8 @@
             }();
             RECT windowPos{};
             ::GetWindowRect(hWnd, &windowPos);
-            return {static_cast<LONG>(windowPos.left + horizontalOffset), static_cast<LONG>(windowPos.top + verticalOffset)};
+            return {static_cast<LONG>(windowPos.left + horizontalOffset),
+                    static_cast<LONG>(windowPos.top + verticalOffset)};
         };
         bool shouldShowSystemMenu = false;
         bool broughtByKeyboard = false;
@@ -1636,7 +1745,8 @@
         switch (message) {
             case WM_RBUTTONUP: {
                 const POINT nativeLocalPos = getNativePosFromMouse();
-                const QPoint qtScenePos = QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
+                const QPoint qtScenePos =
+                    QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
                 if (isInTitleBarDraggableArea(qtScenePos)) {
                     shouldShowSystemMenu = true;
                     nativeGlobalPos = nativeLocalPos;
@@ -1675,7 +1785,8 @@
                 break;
         }
         if (shouldShowSystemMenu) {
-            showSystemMenu2(hWnd, nativeGlobalPos, broughtByKeyboard, m_delegate->isHostSizeFixed(m_host));
+            showSystemMenu2(hWnd, nativeGlobalPos, broughtByKeyboard,
+                            m_delegate->isHostSizeFixed(m_host));
             // QPA's internal code will handle system menu events separately, and its
             // behavior is not what we would want to see because it doesn't know our
             // window doesn't have any window frame now, so return early here to avoid

--
Gitblit v1.9.1