Zhao Yuhang
2023-12-12 5a0e5a9261c251dba54afb8cc0b6b32ae9d95510
src/core/contexts/win32windowcontext.cpp
@@ -1,14 +1,15 @@
#include "win32windowcontext_p.h"
#include "qwkcoreglobal_p.h"
#include <optional>
#include <QtCore/QHash>
#include <QtCore/QAbstractNativeEventFilter>
#include <QtCore/QOperatingSystemVersion>
#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,19 +24,67 @@
#include <shellscalingapi.h>
#include <dwmapi.h>
#include <timeapi.h>
#include "nativeeventfilter.h"
#include "qwkglobal_p.h"
#include "win10borderhandler_p.h"
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
Q_DECLARE_METATYPE(QMargins)
#endif
namespace QWK {
    static constexpr const auto kAutoHideTaskBarThickness =
        quint8{2}; // The thickness of an auto-hide taskbar in pixels.
    enum _DWMWINDOWATTRIBUTE {
        // [set] BOOL, Allows the use of host backdrop brushes for the window.
        _DWMWA_USE_HOSTBACKDROPBRUSH = 17,
    using WndProcHash = QHash<HWND, Win32WindowContext *>; // hWnd -> context
        // Undocumented, the same with DWMWA_USE_IMMERSIVE_DARK_MODE, but available on systems
        // before Win10 20H1.
        _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19,
        // [set] BOOL, Allows a window to either use the accent color, or dark, according to the
        // user Color Mode preferences.
        _DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
        // [set] WINDOW_CORNER_PREFERENCE, Controls the policy that rounds top-level window corners
        _DWMWA_WINDOW_CORNER_PREFERENCE = 33,
        // [get] UINT, width of the visible border around a thick frame window
        _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37,
        // [get, set] SYSTEMBACKDROP_TYPE, Controls the system-drawn backdrop material of a window,
        // including behind the non-client area.
        _DWMWA_SYSTEMBACKDROP_TYPE = 38,
        // Undocumented, use this value to enable Mica material on Win11 21H2. You should use
        // DWMWA_SYSTEMBACKDROP_TYPE instead on Win11 22H2 and newer.
        _DWMWA_MICA_EFFECT = 1029
    };
    // The thickness of an auto-hide taskbar in pixels.
    static constexpr const quint8 kAutoHideTaskBarThickness = 2;
    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 *>;
    Q_GLOBAL_STATIC(WndProcHash, g_wndProcHash)
    static WNDPROC g_qtWindowProc = nullptr; // Original Qt window proc function
    // 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);
@@ -43,37 +92,67 @@
    } g_hook{};
    struct DynamicApis {
        decltype(&::DwmFlush) pDwmFlush = nullptr;
        decltype(&::DwmIsCompositionEnabled) pDwmIsCompositionEnabled = nullptr;
        decltype(&::GetDpiForWindow) pGetDpiForWindow = nullptr;
        decltype(&::GetSystemMetricsForDpi) pGetSystemMetricsForDpi = nullptr;
        decltype(&::GetDpiForMonitor) pGetDpiForMonitor = nullptr;
        DynamicApis() {
            QSystemLibrary user32(QStringLiteral("user32.dll"));
            pGetDpiForWindow =
                reinterpret_cast<decltype(pGetDpiForWindow)>(user32.resolve("GetDpiForWindow"));
            pGetSystemMetricsForDpi = reinterpret_cast<decltype(pGetSystemMetricsForDpi)>(
                user32.resolve("GetSystemMetricsForDpi"));
            QSystemLibrary shcore(QStringLiteral("shcore.dll"));
            pGetDpiForMonitor =
                reinterpret_cast<decltype(pGetDpiForMonitor)>(shcore.resolve("GetDpiForMonitor"));
            QSystemLibrary dwmapi(QStringLiteral("dwmapi.dll"));
            pDwmFlush = reinterpret_cast<decltype(pDwmFlush)>(dwmapi.resolve("DwmFlush"));
            pDwmIsCompositionEnabled = reinterpret_cast<decltype(pDwmIsCompositionEnabled)>(
                dwmapi.resolve("DwmIsCompositionEnabled"));
        }
        ~DynamicApis() = default;
        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)
    };
@@ -158,20 +237,22 @@
    }
    static inline bool isWin8OrGreater() {
        static const bool result =
            QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8;
        static const bool result = IsWindows8OrGreater_Real();
        return result;
    }
    static inline bool isWin8Point1OrGreater() {
        static const bool result =
            QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1;
        static const bool result = IsWindows8Point1OrGreater_Real();
        return result;
    }
    static inline bool isWin10OrGreater() {
        static const bool result =
            QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
        static const bool result = IsWindows10OrGreater_Real();
        return result;
    }
    static inline bool isWin11OrGreater() {
        static const bool result = IsWindows11OrGreater_Real();
        return result;
    }
@@ -187,83 +268,134 @@
        return SUCCEEDED(apis.pDwmIsCompositionEnabled(&enabled)) && enabled;
    }
    static inline void triggerFrameChange(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return;
    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,
                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER |
                           SWP_FRAMECHANGED);
    }
    static inline quint32 getDpiForWindow(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return 0;
        }
        const DynamicApis &apis = DynamicApis::instance();
        if (apis.pGetDpiForWindow) {         // Win10
            return apis.pGetDpiForWindow(hwnd);
        } else if (apis.pGetDpiForMonitor) { // Win8.1
            HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
            UINT dpiX{USER_DEFAULT_SCREEN_DPI};
            UINT dpiY{USER_DEFAULT_SCREEN_DPI};
            UINT dpiX{0};
            UINT dpiY{0};
            apis.pGetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
            return dpiX;
        } 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 getResizeBorderThickness(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return 0;
        }
    static inline quint32 getSystemMetricsForDpi(int index, quint32 dpi) {
        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);
            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 quint32 dpi = getDpiForWindow(hwnd);
        return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) +
               getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
    }
    static inline quint32 getTitleBarHeight(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return 0;
        }
        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) {
        Q_ASSERT(hwnd);
        Q_ASSERT(window);
        if (!hwnd || !window) {
            return;
        }
    static void updateInternalWindowFrameMargins(HWND hwnd, QWindow *window) {
        const auto margins = [hwnd]() -> QMargins {
            const int titleBarHeight = getTitleBarHeight(hwnd);
            const auto titleBarHeight = int(getTitleBarHeight(hwnd));
            if (isWin10OrGreater()) {
                return {0, -titleBarHeight, 0, 0};
            } else {
                const int frameSize = getResizeBorderThickness(hwnd);
                const auto frameSize = int(getResizeBorderThickness(hwnd));
                return {-frameSize, -titleBarHeight, -frameSize, -frameSize};
            }
        }();
@@ -272,7 +404,7 @@
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        if (QPlatformWindow *platformWindow = window->handle()) {
            if (const auto ni = QGuiApplication::platformNativeInterface()) {
                ni->setWindowProperty(platformWindow, QStringLiteral("_q_windowsCustomMargins"),
                ni->setWindowProperty(platformWindow, QStringLiteral("WindowsCustomMargins"),
                                      marginsVar);
            }
        }
@@ -285,10 +417,6 @@
    }
    static inline MONITORINFOEXW getMonitorForWindow(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return {};
        }
        // Use "MONITOR_DEFAULTTONEAREST" here so that we can still get the correct
        // monitor even if the window is minimized.
        HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
@@ -299,23 +427,16 @@
    };
    static inline void moveToDesktopCenter(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return;
        }
        const auto 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;
        ::SetWindowPos(hwnd, nullptr, newX, newY, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
        ::SetWindowPos(hwnd, nullptr, newX, newY, 0, 0,
                       SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
    }
    static inline bool isFullScreen(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return false;
        }
        RECT windowRect{};
        ::GetWindowRect(hwnd, &windowRect);
        // Compare to the full area of the screen, not the work area.
@@ -323,10 +444,6 @@
    }
    static inline bool isWindowNoState(HWND hwnd) {
        Q_ASSERT(hwnd);
        if (!hwnd) {
            return false;
        }
#if 0
        WINDOWPLACEMENT wp{};
        wp.length = sizeof(wp);
@@ -338,16 +455,116 @@
#endif
    }
    static inline QPoint fromNativeLocalPosition(const QWindow *window, const QPoint &point) {
        Q_ASSERT(window);
        if (!window) {
            return point;
    static void syncPaintEventWithDwm() {
        // No need to sync with DWM if DWM composition is disabled.
        if (!isDwmCompositionEnabled()) {
            return;
        }
#if 1
        return QHighDpi::fromNativeLocalPosition(point, window);
#else
        return QPointF(QPointF(point) / window->devicePixelRatio()).toPoint();
#endif
        const DynamicApis &apis = DynamicApis::instance();
        // Dirty hack to workaround the resize flicker caused by DWM.
        LARGE_INTEGER freq{};
        ::QueryPerformanceFrequency(&freq);
        TIMECAPS tc{};
        apis.ptimeGetDevCaps(&tc, sizeof(tc));
        const UINT ms_granularity = tc.wPeriodMin;
        apis.ptimeBeginPeriod(ms_granularity);
        LARGE_INTEGER now0{};
        ::QueryPerformanceCounter(&now0);
        // ask DWM where the vertical blank falls
        DWM_TIMING_INFO dti{};
        dti.cbSize = sizeof(dti);
        apis.pDwmGetCompositionTimingInfo(nullptr, &dti);
        LARGE_INTEGER now1{};
        ::QueryPerformanceCounter(&now1);
        // - DWM told us about SOME vertical blank
        //   - past or future, possibly many frames away
        // - convert that into the NEXT vertical blank
        const auto period = qreal(dti.qpcRefreshPeriod);
        const auto dt = qreal(dti.qpcVBlank - now1.QuadPart);
        const qreal ratio = (dt / period);
        auto w = qreal(0);
        auto m = qreal(0);
        if ((dt > qreal(0)) || qFuzzyIsNull(dt)) {
            w = ratio;
        } else {
            // reach back to previous period
            // - so m represents consistent position within phase
            w = (ratio - qreal(1));
        }
        m = (dt - (period * w));
        if ((m < qreal(0)) || qFuzzyCompare(m, period) || (m > period)) {
            return;
        }
        const qreal m_ms = (qreal(1000) * m / qreal(freq.QuadPart));
        ::Sleep(static_cast<DWORD>(std::round(m_ms)));
        apis.ptimeEndPeriod(ms_granularity);
    }
    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
            // as an error so just ignore it and return early.
            return;
        }
        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)));
        // 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
        // this manually: the highlighted menu item is really only highlighted,
        // not selected, so even if the mouse cursor hovers on other menu items
        // or the user navigates to other menu items through keyboard, the original
        // 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)));
        ::EnableMenuItem(hMenu, SC_MINIMIZE, (MF_BYCOMMAND | 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
        // menu item per menu at most. Set the item ID to "UINT_MAX" (or simply "-1")
        // can clear the default item for the given menu.
        UINT defaultItemId = UINT_MAX;
        if (isWin11OrGreater()) {
            if (maxOrFull) {
                defaultItemId = SC_RESTORE;
            } else {
                defaultItemId = SC_MAXIMIZE;
            }
        }
        if (defaultItemId == UINT_MAX) {
            defaultItemId = SC_CLOSE;
        }
        ::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);
        // Unhighlight the first menu item after the popup menu is closed, otherwise it will keep
        // highlighting until we unhighlight it manually.
        ::HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | MFS_UNHILITE));
        if (!result) {
            // The user canceled the menu, no need to continue.
            return;
        }
        // Send the command that the user chooses to the corresponding window.
        ::PostMessageW(hWnd, WM_SYSCOMMAND, result, 0);
    }
    static inline Win32WindowContext::WindowPart getHitWindowPart(int hitTestResult) {
@@ -374,7 +591,8 @@
            case HTBORDER:
                return Win32WindowContext::FixedBorder;
            default:
                break; // unreachable
                // unreachable
                break;
        }
        return Win32WindowContext::Outside;
    }
@@ -418,11 +636,11 @@
    // 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 {
            Q_UNUSED(eventType);
            Q_UNUSED(eventType)
            // It has been observed that the pointer that Qt gives us is sometimes null on some
            // machines. We need to guard against it in such scenarios.
@@ -430,32 +648,42 @@
                return false;
            }
            if (lastMessageHandled) {
                *result = static_cast<QT_NATIVE_EVENT_RESULT_TYPE>(lastMessageResult);
                return true;
            // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/plugins/platforms/windows/qwindowscontext.cpp#L1546
            // Qt needs to refer to the WM_NCCALCSIZE message data that hasn't been processed, so we
            // have to process it after Qt acquires the initial data.
            auto msg = static_cast<const MSG *>(message);
            if (msg->message == WM_NCCALCSIZE && lastMessageContext) {
                LRESULT res;
                if (lastMessageContext->nonClientCalcSizeHandler(msg->hwnd, msg->message,
                                                                 msg->wParam, msg->lParam, &res)) {
                    *result = decltype(*result)(res);
                    return true;
                }
            }
            return false;
        }
        static bool lastMessageHandled;
        static LRESULT lastMessageResult;
        static WindowsNativeEventFilter *instance;
        static Win32WindowContext *lastMessageContext;
        static inline void install() {
            if (instance) {
                return;
            }
            instance = new WindowsNativeEventFilter();
            installNativeEventFilter(instance);
        }
        static inline void uninstall() {
            removeNativeEventFilter(instance);
            if (!instance) {
                return;
            }
            delete instance;
            instance = nullptr;
        }
    };
    bool WindowsNativeEventFilter::lastMessageHandled = false;
    LRESULT WindowsNativeEventFilter::lastMessageResult = 0;
    WindowsNativeEventFilter *WindowsNativeEventFilter::instance = nullptr;
    Win32WindowContext *WindowsNativeEventFilter::lastMessageContext = nullptr;
    // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/plugins/platforms/windows/qwindowscontext.cpp#L1025
    // We can see from the source code that Qt will filter out some messages first and then send the
@@ -522,24 +750,26 @@
            return ::DefWindowProcW(hWnd, message, wParam, lParam);
        }
        // Try hooked procedure and save result
        auto &handled = WindowsNativeEventFilter::lastMessageHandled;
        auto &result = WindowsNativeEventFilter::lastMessageResult;
        handled = ctx->windowProc(hWnd, message, wParam, lParam, &result);
        // TODO: Determine whether to show system menu
        // ...
        // Since Qt does the necessary processing of the WM_NCCALCSIZE afterward, we still need to
        // continue dispatching it.
        if (handled && message != WM_NCCALCSIZE) {
        // Since Qt does the necessary processing of the WM_NCCALCSIZE message, we need to
        // forward it right away and process it in our native event filter.
        if (message == WM_NCCALCSIZE) {
            WindowsNativeEventFilter::lastMessageContext = ctx;
            LRESULT result = ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam);
            WindowsNativeEventFilter::lastMessageContext = nullptr;
            return result;
        }
        // Try hooked procedure and save result
        LRESULT result;
        if (ctx->windowProc(hWnd, message, wParam, lParam, &result)) {
            return result;
        }
        // Continue dispatching.
        return ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam);
    }
    Win32WindowContext::Win32WindowContext(QObject *host, WindowItemDelegate *delegate)
        : AbstractWindowContext(host, delegate) {
    Win32WindowContext::Win32WindowContext() : AbstractWindowContext() {
    }
    Win32WindowContext::~Win32WindowContext() {
@@ -554,11 +784,55 @@
        }
    }
    bool Win32WindowContext::setup() {
        if (!m_windowHandle) {
            return false;
        }
    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 = *static_cast<const QPoint *>(data);
                auto hWnd = reinterpret_cast<HWND>(m_windowHandle->winId());
                showSystemMenu2(hWnd, qpoint2point(pos), 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;
            }
            default: {
                // unreachable
                break;
            }
        }
        AbstractWindowContext::virtual_hook(id, data);
    }
    bool Win32WindowContext::needWin10BorderHandler() const {
        return isWin10OrGreater() && !isWin11OrGreater();
    }
    void Win32WindowContext::setWin10BorderHandler(Win10BorderHandler *handler) {
        win10BorderHandler.reset(handler);
        handler->setBorderThickness(
            int(getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId))));
    }
    bool Win32WindowContext::setupHost() {
        // Install window hook
        auto winId = m_windowHandle->winId();
        auto hWnd = reinterpret_cast<HWND>(winId);
@@ -575,9 +849,7 @@
        ::SetWindowLongPtrW(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(QWKHookedWndProc));
        // Install global native event filter
        if (!WindowsNativeEventFilter::instance) {
            WindowsNativeEventFilter::install();
        }
        WindowsNativeEventFilter::install();
        // Cache window ID
        windowId = winId;
@@ -620,14 +892,22 @@
            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 auto kMessageTag = WPARAM(0x97CCEA99);
    static inline constexpr bool isTaggedMessage(WPARAM wParam) {
        return (wParam == kMessageTag);
    }
    QWK_USED static constexpr const struct {
        const WPARAM wParam = 0xF1C9ADD4;
        const LPARAM lParam = 0xAFB6F4C6;
    } kMessageTag;
    static inline quint64 getKeyState() {
        quint64 result = 0;
@@ -667,7 +947,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)) {
@@ -745,6 +1025,7 @@
                SEND_MESSAGE(hWnd, WM_MOUSELEAVE, wParamNew, lParamNew);
                break;
            default:
                // unreachable
                break;
        }
@@ -767,7 +1048,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
@@ -779,9 +1060,9 @@
                    DWORD dwScreenPos = ::GetMessagePos();
                    POINT screenPoint{GET_X_LPARAM(dwScreenPos), GET_Y_LPARAM(dwScreenPos)};
                    ::ScreenToClient(hWnd, &screenPoint);
                    QPoint qtScenePos =
                        fromNativeLocalPosition(m_windowHandle, {screenPoint.x, screenPoint.y});
                    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()
@@ -828,7 +1109,7 @@
                const WindowPart currentWindowPart = lastHitTestResult;
                if (message == WM_NCMOUSEMOVE) {
                    if (currentWindowPart != WindowPart::ChromeButton) {
                        std::ignore = m_delegate->resetQtGrabbedControl();
                        m_delegate->resetQtGrabbedControl();
                        if (mouseLeaveBlocked) {
                            emulateClientAreaMessage(hWnd, message, wParam, lParam,
                                                     WM_NCMOUSELEAVE);
@@ -890,7 +1171,7 @@
                        // 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.
                        std::ignore = m_delegate->resetQtGrabbedControl();
                        m_delegate->resetQtGrabbedControl();
                    }
                }
                break;
@@ -908,7 +1189,8 @@
            case WM_SHOWWINDOW: {
                if (!centered) {
                    // 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 lParam is zero, the message was sent because of a call to the ShowWindow
                    // function.
                    if (wParam && lParam == 0) {
                        centered = true;
                        moveToDesktopCenter(hWnd);
@@ -916,231 +1198,7 @@
                }
                break;
            }
            case WM_NCCALCSIZE: {
                // Windows是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容)
                // 和非客户区(标题栏、窗口边框、菜单栏和状态栏等Windows系统自行提供的部分
                // ,不过对于Qt来说,除了标题栏和窗口边框,非客户区基本也都是自绘的)的范
                // 围的,lParam里存放的就是新客户区的几何区域,默认是整个窗口的大小,正常
                // 的程序需要修改这个参数,告知系统窗口的客户区和非客户区的范围(一般来说可
                // 以完全交给Windows,让其自行处理,使用默认的客户区和非客户区),因此如果
                // 我们不修改lParam,就可以使客户区充满整个窗口,从而去掉标题栏和窗口边框
                // (因为这些东西都被客户区给盖住了。但边框阴影也会因此而丢失,不过我们会使
                // 用其他方式将其带回,请参考其他消息的处理,此处不过多提及)。但有个情况要
                // 特别注意,那就是窗口最大化后,窗口的实际尺寸会比屏幕的尺寸大一点,从而使
                // 用户看不到窗口的边界,这样用户就不能在窗口最大化后调整窗口的大小了(虽然
                // 这个做法听起来特别奇怪,但Windows确实就是这样做的),因此如果我们要自行
                // 处理窗口的非客户区,就要在窗口最大化后,将窗口边框的宽度和高度(一般是相
                // 等的)从客户区裁剪掉,否则我们窗口所显示的内容就会超出屏幕边界,显示不全。
                // 如果用户开启了任务栏自动隐藏,在窗口最大化后,还要考虑任务栏的位置。因为
                // 如果窗口最大化后,其尺寸和屏幕尺寸相等(因为任务栏隐藏了,所以窗口最大化
                // 后其实是充满了整个屏幕,变相的全屏了),Windows会认为窗口已经进入全屏的
                // 状态,从而导致自动隐藏的任务栏无法弹出。要避免这个状况,就要使窗口的尺寸
                // 小于屏幕尺寸。我下面的做法参考了火狐、Chromium和Windows Terminal
                // 如果没有开启任务栏自动隐藏,是不存在这个问题的,所以要先进行判断。
                // 一般情况下,*result设置为0(相当于DefWindowProc的返回值为0)就可以了,
                // 根据MSDN的说法,返回0意为此消息已经被程序自行处理了,让Windows跳过此消
                // 息,否则Windows会添加对此消息的默认处理,对于当前这个消息而言,就意味着
                // 标题栏和窗口边框又会回来,这当然不是我们想要的结果。根据MSDN,当wParam
                // 为FALSE时,只能返回0,但当其为TRUE时,可以返回0,也可以返回一个WVR_常
                // 量。根据Chromium的注释,当存在非客户区时,如果返回WVR_REDRAW会导致子
                // 窗口/子控件出现奇怪的bug(自绘控件错位),并且Lucas在Windows 10
                // 上成功复现,说明这个bug至今都没有解决。我查阅了大量资料,发现唯一的解决
                // 方案就是返回0。但如果不存在非客户区,且wParam为TRUE,最好返回
                // WVR_REDRAW,否则窗口在调整大小可能会产生严重的闪烁现象。
                // 虽然对大多数消息来说,返回0都代表让Windows忽略此消息,但实际上不同消息
                // 能接受的返回值是不一样的,请注意自行查阅MSDN。
                // Sent when the size and position of a window's client area must be
                // calculated. By processing this message, an application can
                // control the content of the window's client area when the size or
                // position of the window changes. If wParam is TRUE, lParam points
                // to an NCCALCSIZE_PARAMS structure that contains information an
                // application can use to calculate the new size and position of the
                // client rectangle. If wParam is FALSE, lParam points to a RECT
                // structure. On entry, the structure contains the proposed window
                // rectangle for the window. On exit, the structure should contain
                // the screen coordinates of the corresponding window client area.
                // The client area is the window's content area, the non-client area
                // is the area which is provided by the system, such as the title
                // bar, the four window borders, the frame shadow, the menu bar, the
                // status bar, the scroll bar, etc. But for Qt, it draws most of the
                // window area (client + non-client) itself. We now know that the
                // title bar and the window frame is in the non-client area, and we
                // can set the scope of the client area in this message, so we can
                // remove the title bar and the window frame by let the non-client
                // area be covered by the client area (because we can't really get
                // rid of the non-client area, it will always be there, all we can
                // do is to hide it) , which means we should let the client area's
                // size the same with the whole window's size. So there is no room
                // for the non-client area and then the user won't be able to see it
                // again. But how to achieve this? Very easy, just leave lParam (the
                // re-calculated client area) untouched. But of course you can
                // modify lParam, then the non-client area will be seen and the
                // window borders and the window frame will show up. However, things
                // are quite different when you try to modify the top margin of the
                // client area. DWM will always draw the whole title bar no matter
                // what margin value you set for the top, unless you don't modify it
                // and remove the whole top area (the title bar + the one pixel
                // height window border). This can be confirmed in Windows
                // Terminal's source code, you can also try yourself to verify
                // it. So things will become quite complicated if you want to
                // preserve the four window borders.
                // If `wParam` is `FALSE`, `lParam` points to a `RECT` that contains
                // the proposed window rectangle for our window. During our
                // processing of the `WM_NCCALCSIZE` message, we are expected to
                // modify the `RECT` that `lParam` points to, so that its value upon
                // our return is the new client area. We must return 0 if `wParam`
                // is `FALSE`.
                // If `wParam` is `TRUE`, `lParam` points to a `NCCALCSIZE_PARAMS`
                // struct. This struct contains an array of 3 `RECT`s, the first of
                // which has the exact same meaning as the `RECT` that is pointed to
                // by `lParam` when `wParam` is `FALSE`. The remaining `RECT`s, in
                // conjunction with our return value, can
                // be used to specify portions of the source and destination window
                // rectangles that are valid and should be preserved. We opt not to
                // implement an elaborate client-area preservation technique, and
                // simply return 0, which means "preserve the entire old client area
                // and align it with the upper-left corner of our new client area".
                const auto clientRect =
                    wParam ? &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]
                                       : reinterpret_cast<LPRECT>(lParam);
                if (isWin10OrGreater()) {
                    // Store the original top margin before the default window procedure applies the
                    // default frame.
                    const LONG originalTop = clientRect->top;
                    // Apply the default frame because we don't want to remove the whole window
                    // frame, we still need the standard window frame (the resizable frame border
                    // and the frame shadow) for the left, bottom and right edges. If we return 0
                    // here directly, the whole window frame will be removed (which means there will
                    // be no resizable frame border and the frame shadow will also disappear), and
                    // that's also how most applications customize their title bars on Windows. It's
                    // totally OK but since we want to preserve as much original frame as possible,
                    // we can't use that solution.
                    const LRESULT hitTestResult =
                        ::DefWindowProcW(hWnd, WM_NCCALCSIZE, wParam, lParam);
                    if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
                        *result = hitTestResult;
                        return true;
                    }
                    // Re-apply the original top from before the size of the default frame was
                    // applied, and the whole top frame (the title bar and the top border) is gone
                    // now. For the top frame, we only has 2 choices: (1) remove the top frame
                    // entirely, or (2) don't touch it at all. We can't preserve the top border by
                    // adjusting the top margin here. If we try to modify the top margin, the
                    // original title bar will always be painted by DWM regardless what margin we
                    // set, so here we can only remove the top frame entirely and use some special
                    // technique to bring the top border back.
                    clientRect->top = originalTop;
                }
                const bool max = IsMaximized(hWnd);
                const bool full = isFullScreen(hWnd);
                // We don't need this correction when we're fullscreen. We will
                // have the WS_POPUP size, so we don't have to worry about
                // borders, and the default frame will be fine.
                if (max && !full) {
                    // When a window is maximized, its size is actually a little bit more
                    // than the monitor's work area. The window is positioned and sized in
                    // such a way that the resize handles are outside the monitor and
                    // then the window is clipped to the monitor so that the resize handle
                    // do not appear because you don't need them (because you can't resize
                    // a window when it's maximized unless you restore it).
                    const quint32 frameSize = getResizeBorderThickness(hWnd);
                    clientRect->top += frameSize;
                    if (!isWin10OrGreater()) {
                        clientRect->bottom -= frameSize;
                        clientRect->left += frameSize;
                        clientRect->right -= frameSize;
                    }
                }
                // Attempt to detect if there's an autohide taskbar, and if
                // there is, reduce our size a bit on the side with the taskbar,
                // so the user can still mouse-over the taskbar to reveal it.
                // Make sure to use MONITOR_DEFAULTTONEAREST, so that this will
                // still find the right monitor even when we're restoring from
                // minimized.
                if (max || full) {
                    APPBARDATA abd{};
                    abd.cbSize = sizeof(abd);
                    const UINT taskbarState = ::SHAppBarMessage(ABM_GETSTATE, &abd);
                    // First, check if we have an auto-hide taskbar at all:
                    if (taskbarState & ABS_AUTOHIDE) {
                        bool top = false, bottom = false, left = false, right = false;
                        // Due to ABM_GETAUTOHIDEBAREX was introduced in Windows 8.1,
                        // we have to use another way to judge this if we are running
                        // on Windows 7 or Windows 8.
                        if (isWin8Point1OrGreater()) {
                            const RECT monitorRect = getMonitorForWindow(hWnd).rcMonitor;
                            // This helper can be used to determine if there's an
                            // auto-hide taskbar on the given edge of the monitor
                            // we're currently on.
                            const auto hasAutohideTaskbar = [monitorRect](const UINT edge) -> bool {
                                APPBARDATA abd2{};
                                abd2.cbSize = sizeof(abd2);
                                abd2.uEdge = edge;
                                abd2.rc = monitorRect;
                                const auto hTaskbar = reinterpret_cast<HWND>(
                                    ::SHAppBarMessage(ABM_GETAUTOHIDEBAREX, &abd2));
                                return (hTaskbar != nullptr);
                            };
                            top = hasAutohideTaskbar(ABE_TOP);
                            bottom = hasAutohideTaskbar(ABE_BOTTOM);
                            left = hasAutohideTaskbar(ABE_LEFT);
                            right = hasAutohideTaskbar(ABE_RIGHT);
                        } else {
                            int edge = -1;
                            APPBARDATA abd2{};
                            abd2.cbSize = sizeof(abd2);
                            abd2.hWnd = ::FindWindowW(L"Shell_TrayWnd", nullptr);
                            HMONITOR windowMonitor =
                                ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
                            HMONITOR taskbarMonitor =
                                ::MonitorFromWindow(abd2.hWnd, MONITOR_DEFAULTTOPRIMARY);
                            if (taskbarMonitor == windowMonitor) {
                                ::SHAppBarMessage(ABM_GETTASKBARPOS, &abd2);
                                edge = int(abd2.uEdge);
                            }
                            top = (edge == ABE_TOP);
                            bottom = (edge == ABE_BOTTOM);
                            left = (edge == ABE_LEFT);
                            right = (edge == ABE_RIGHT);
                        }
                        // If there's a taskbar on any side of the monitor, reduce
                        // our size a little bit on that edge.
                        // Note to future code archeologists:
                        // This doesn't seem to work for fullscreen on the primary
                        // display. However, testing a bunch of other apps with
                        // fullscreen modes and an auto-hiding taskbar has
                        // shown that _none_ of them reveal the taskbar from
                        // fullscreen mode. This includes Edge, Firefox, Chrome,
                        // Sublime Text, PowerPoint - none seemed to support this.
                        // This does however work fine for maximized.
                        if (top) {
                            // Peculiarly, when we're fullscreen,
                            clientRect->top += kAutoHideTaskBarThickness;
                        } else if (bottom) {
                            clientRect->bottom -= kAutoHideTaskBarThickness;
                        } else if (left) {
                            clientRect->left += kAutoHideTaskBarThickness;
                        } else if (right) {
                            clientRect->right -= kAutoHideTaskBarThickness;
                        }
                    }
                }
                // ### TODO: std::ignore = Utils::syncWmPaintWithDwm(); // This should be executed
                // at the very last. By returning WVR_REDRAW we can make the window resizing look
                // less broken. But we must return 0 if wParam is FALSE, according to Microsoft
                // Docs.
                // **IMPORTANT NOTE**:
                // If you are drawing something manually through D3D in your window, don't
                // try to return WVR_REDRAW here, otherwise Windows exhibits bugs where
                // client pixels and child windows are mispositioned by the width/height
                // of the upper-left non-client area. It's confirmed that this issue exists
                // from Windows 7 to Windows 10. Not tested on Windows 11 yet. Don't know
                // whether it exists on Windows XP to Windows Vista or not.
                *result = wParam ? WVR_REDRAW : FALSE;
                return true;
            }
            case WM_NCHITTEST: {
                // 原生Win32窗口只有顶边是在窗口内部resize的,其余三边都是在窗口
                // 外部进行resize的,其原理是,WS_THICKFRAME这个窗口样式会在窗
@@ -1236,14 +1294,14 @@
                auto clientWidth = RECT_WIDTH(clientRect);
                auto clientHeight = RECT_HEIGHT(clientRect);
                QPoint qtScenePos = fromNativeLocalPosition(
                    m_windowHandle, QPoint(nativeLocalPos.x, nativeLocalPos.y));
                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.
@@ -1253,22 +1311,31 @@
                    // 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 int kBorderSize = 2;
                        static constexpr const quint8 kBorderSize = 2;
                        bool isTop = (nativeLocalPos.y <= kBorderSize);
                        bool isLeft = nativeLocalPos.x <= kBorderSize;
                        bool isRight = (nativeLocalPos.x >= (clientWidth - kBorderSize));
                        if (isTop || isRight) {
                        if (isTop || isLeft || isRight) {
                            if (dontOverrideCursor) {
                                // The user doesn't want the window to be resized, so we tell
                                // Windows we are in the client area so that the controls beneath
                                // the mouse cursor can still be hovered or clicked.
                                *result = (isTitleBar ? HTCAPTION : HTCLIENT);
                            } else {
                                if (isTop && isRight) {
                                    *result = HTTOPRIGHT;
                                } else if (isTop) {
                                    *result = HTTOP;
                                if (isTop) {
                                    if (isLeft) {
                                        *result = HTTOPLEFT;
                                    } else if (isRight) {
                                        *result = HTTOPRIGHT;
                                    } else {
                                        *result = HTTOP;
                                    }
                                } else {
                                    *result = HTRIGHT;
                                    if (isLeft) {
                                        *result = HTLEFT;
                                    } else {
                                        *result = HTRIGHT;
                                    }
                                }
                            }
                        }
@@ -1278,25 +1345,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;
                            case CoreWindowAgent::Unknown:
                                break;
                            default:
                                break; // unreachable
                                // unreachable
                                break;
                        }
                    }
                    if (*result == HTNOWHERE) {
@@ -1370,9 +1436,9 @@
                        const bool isBottom = (nativeLocalPos.y >= (clientHeight - frameSize));
                        // Make the border a little wider to let the user easy to resize on corners.
                        const auto scaleFactor = ((isTop || isBottom) ? qreal(2) : qreal(1));
                        const int scaledFrameSizeX = std::round(qreal(frameSize) * scaleFactor);
                        const bool isLeft = (nativeLocalPos.x < scaledFrameSizeX);
                        const bool isRight = (nativeLocalPos.x >= (clientWidth - scaledFrameSizeX));
                        const int scaledFrameSize = std::round(qreal(frameSize) * scaleFactor);
                        const bool isLeft = (nativeLocalPos.x < scaledFrameSize);
                        const bool isRight = (nativeLocalPos.x >= (clientWidth - scaledFrameSize));
                        if (dontOverrideCursor && (isTop || isBottom || isLeft || isRight)) {
                            // Return HTCLIENT instead of HTBORDER here, because the mouse is
                            // inside the window now, return HTCLIENT to let the controls
@@ -1421,9 +1487,27 @@
                    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.
                const auto windowPos = reinterpret_cast<LPWINDOWPOS>(lParam);
                if (windowPos->flags ==
                    (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED)) {
                    windowPos->flags |= SWP_NOCOPYBITS;
                }
                break;
            }
            default:
                break;
        }
        if (!isWin10OrGreater()) {
            switch (message) {
                case WM_NCUAHDRAWCAPTION:
@@ -1487,4 +1571,397 @@
        return false;
    }
    bool Win32WindowContext::nonClientCalcSizeHandler(HWND hWnd, UINT message, WPARAM wParam,
                                                      LPARAM lParam, LRESULT *result) {
        Q_UNUSED(message)
        Q_UNUSED(this)
        // Windows是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容)
        // 和非客户区(标题栏、窗口边框、菜单栏和状态栏等Windows系统自行提供的部分
        // ,不过对于Qt来说,除了标题栏和窗口边框,非客户区基本也都是自绘的)的范
        // 围的,lParam里存放的就是新客户区的几何区域,默认是整个窗口的大小,正常
        // 的程序需要修改这个参数,告知系统窗口的客户区和非客户区的范围(一般来说可
        // 以完全交给Windows,让其自行处理,使用默认的客户区和非客户区),因此如果
        // 我们不修改lParam,就可以使客户区充满整个窗口,从而去掉标题栏和窗口边框
        // (因为这些东西都被客户区给盖住了。但边框阴影也会因此而丢失,不过我们会使
        // 用其他方式将其带回,请参考其他消息的处理,此处不过多提及)。但有个情况要
        // 特别注意,那就是窗口最大化后,窗口的实际尺寸会比屏幕的尺寸大一点,从而使
        // 用户看不到窗口的边界,这样用户就不能在窗口最大化后调整窗口的大小了(虽然
        // 这个做法听起来特别奇怪,但Windows确实就是这样做的),因此如果我们要自行
        // 处理窗口的非客户区,就要在窗口最大化后,将窗口边框的宽度和高度(一般是相
        // 等的)从客户区裁剪掉,否则我们窗口所显示的内容就会超出屏幕边界,显示不全。
        // 如果用户开启了任务栏自动隐藏,在窗口最大化后,还要考虑任务栏的位置。因为
        // 如果窗口最大化后,其尺寸和屏幕尺寸相等(因为任务栏隐藏了,所以窗口最大化
        // 后其实是充满了整个屏幕,变相的全屏了),Windows会认为窗口已经进入全屏的
        // 状态,从而导致自动隐藏的任务栏无法弹出。要避免这个状况,就要使窗口的尺寸
        // 小于屏幕尺寸。我下面的做法参考了火狐、Chromium和Windows Terminal
        // 如果没有开启任务栏自动隐藏,是不存在这个问题的,所以要先进行判断。
        // 一般情况下,*result设置为0(相当于DefWindowProc的返回值为0)就可以了,
        // 根据MSDN的说法,返回0意为此消息已经被程序自行处理了,让Windows跳过此消
        // 息,否则Windows会添加对此消息的默认处理,对于当前这个消息而言,就意味着
        // 标题栏和窗口边框又会回来,这当然不是我们想要的结果。根据MSDN,当wParam
        // 为FALSE时,只能返回0,但当其为TRUE时,可以返回0,也可以返回一个WVR_常
        // 量。根据Chromium的注释,当存在非客户区时,如果返回WVR_REDRAW会导致子
        // 窗口/子控件出现奇怪的bug(自绘控件错位),并且Lucas在Windows 10
        // 上成功复现,说明这个bug至今都没有解决。我查阅了大量资料,发现唯一的解决
        // 方案就是返回0。但如果不存在非客户区,且wParam为TRUE,最好返回
        // WVR_REDRAW,否则窗口在调整大小可能会产生严重的闪烁现象。
        // 虽然对大多数消息来说,返回0都代表让Windows忽略此消息,但实际上不同消息
        // 能接受的返回值是不一样的,请注意自行查阅MSDN。
        // Sent when the size and position of a window's client area must be
        // calculated. By processing this message, an application can
        // control the content of the window's client area when the size or
        // position of the window changes. If wParam is TRUE, lParam points
        // to an NCCALCSIZE_PARAMS structure that contains information an
        // application can use to calculate the new size and position of the
        // client rectangle. If wParam is FALSE, lParam points to a RECT
        // structure. On entry, the structure contains the proposed window
        // rectangle for the window. On exit, the structure should contain
        // the screen coordinates of the corresponding window client area.
        // The client area is the window's content area, the non-client area
        // is the area which is provided by the system, such as the title
        // bar, the four window borders, the frame shadow, the menu bar, the
        // status bar, the scroll bar, etc. But for Qt, it draws most of the
        // window area (client + non-client) itself. We now know that the
        // title bar and the window frame is in the non-client area, and we
        // can set the scope of the client area in this message, so we can
        // remove the title bar and the window frame by let the non-client
        // area be covered by the client area (because we can't really get
        // rid of the non-client area, it will always be there, all we can
        // do is to hide it) , which means we should let the client area's
        // size the same with the whole window's size. So there is no room
        // for the non-client area and then the user won't be able to see it
        // again. But how to achieve this? Very easy, just leave lParam (the
        // re-calculated client area) untouched. But of course you can
        // modify lParam, then the non-client area will be seen and the
        // window borders and the window frame will show up. However, things
        // are quite different when you try to modify the top margin of the
        // client area. DWM will always draw the whole title bar no matter
        // what margin value you set for the top, unless you don't modify it
        // and remove the whole top area (the title bar + the one pixel
        // height window border). This can be confirmed in Windows
        // Terminal's source code, you can also try yourself to verify
        // it. So things will become quite complicated if you want to
        // preserve the four window borders.
        // If `wParam` is `FALSE`, `lParam` points to a `RECT` that contains
        // the proposed window rectangle for our window. During our
        // processing of the `WM_NCCALCSIZE` message, we are expected to
        // modify the `RECT` that `lParam` points to, so that its value upon
        // our return is the new client area. We must return 0 if `wParam`
        // is `FALSE`.
        // If `wParam` is `TRUE`, `lParam` points to a `NCCALCSIZE_PARAMS`
        // struct. This struct contains an array of 3 `RECT`s, the first of
        // which has the exact same meaning as the `RECT` that is pointed to
        // by `lParam` when `wParam` is `FALSE`. The remaining `RECT`s, in
        // conjunction with our return value, can
        // be used to specify portions of the source and destination window
        // rectangles that are valid and should be preserved. We opt not to
        // implement an elaborate client-area preservation technique, and
        // simply return 0, which means "preserve the entire old client area
        // and align it with the upper-left corner of our new client area".
        const auto clientRect = wParam ? &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]
                                       : reinterpret_cast<LPRECT>(lParam);
        if (isWin10OrGreater()) {
            // Store the original top margin before the default window procedure applies the
            // default frame.
            const LONG originalTop = clientRect->top;
            // Apply the default frame because we don't want to remove the whole window
            // frame, we still need the standard window frame (the resizable frame border
            // and the frame shadow) for the left, bottom and right edges. If we return 0
            // here directly, the whole window frame will be removed (which means there will
            // be no resizable frame border and the frame shadow will also disappear), and
            // that's also how most applications customize their title bars on Windows. It's
            // totally OK but since we want to preserve as much original frame as possible,
            // we can't use that solution.
            const LRESULT hitTestResult = ::DefWindowProcW(hWnd, WM_NCCALCSIZE, wParam, lParam);
            if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
                *result = hitTestResult;
                return true;
            }
            // Re-apply the original top from before the size of the default frame was
            // applied, and the whole top frame (the title bar and the top border) is gone
            // now. For the top frame, we only has 2 choices: (1) remove the top frame
            // entirely, or (2) don't touch it at all. We can't preserve the top border by
            // adjusting the top margin here. If we try to modify the top margin, the
            // original title bar will always be painted by DWM regardless what margin we
            // set, so here we can only remove the top frame entirely and use some special
            // technique to bring the top border back.
            clientRect->top = originalTop;
        }
        const bool max = IsMaximized(hWnd);
        const bool full = isFullScreen(hWnd);
        // We don't need this correction when we're fullscreen. We will
        // have the WS_POPUP size, so we don't have to worry about
        // borders, and the default frame will be fine.
        if (max && !full) {
            // When a window is maximized, its size is actually a little bit more
            // than the monitor's work area. The window is positioned and sized in
            // such a way that the resize handles are outside the monitor and
            // then the window is clipped to the monitor so that the resize handle
            // do not appear because you don't need them (because you can't resize
            // a window when it's maximized unless you restore it).
            const quint32 frameSize = getResizeBorderThickness(hWnd);
            clientRect->top += frameSize;
            if (!isWin10OrGreater()) {
                clientRect->bottom -= frameSize;
                clientRect->left += frameSize;
                clientRect->right -= frameSize;
            }
        }
        // Attempt to detect if there's an autohide taskbar, and if
        // there is, reduce our size a bit on the side with the taskbar,
        // so the user can still mouse-over the taskbar to reveal it.
        // Make sure to use MONITOR_DEFAULTTONEAREST, so that this will
        // still find the right monitor even when we're restoring from
        // minimized.
        if (max || full) {
            APPBARDATA abd{};
            abd.cbSize = sizeof(abd);
            const UINT taskbarState = ::SHAppBarMessage(ABM_GETSTATE, &abd);
            // First, check if we have an auto-hide taskbar at all:
            if (taskbarState & ABS_AUTOHIDE) {
                bool top = false, bottom = false, left = false, right = false;
                // Due to ABM_GETAUTOHIDEBAREX was introduced in Windows 8.1,
                // we have to use another way to judge this if we are running
                // on Windows 7 or Windows 8.
                if (isWin8Point1OrGreater()) {
                    const RECT monitorRect = getMonitorForWindow(hWnd).rcMonitor;
                    // This helper can be used to determine if there's an
                    // auto-hide taskbar on the given edge of the monitor
                    // we're currently on.
                    const auto hasAutohideTaskbar = [monitorRect](const UINT edge) -> bool {
                        APPBARDATA abd2{};
                        abd2.cbSize = sizeof(abd2);
                        abd2.uEdge = edge;
                        abd2.rc = monitorRect;
                        const auto hTaskbar =
                            reinterpret_cast<HWND>(::SHAppBarMessage(ABM_GETAUTOHIDEBAREX, &abd2));
                        return (hTaskbar != nullptr);
                    };
                    top = hasAutohideTaskbar(ABE_TOP);
                    bottom = hasAutohideTaskbar(ABE_BOTTOM);
                    left = hasAutohideTaskbar(ABE_LEFT);
                    right = hasAutohideTaskbar(ABE_RIGHT);
                } else {
                    int edge = -1;
                    APPBARDATA abd2{};
                    abd2.cbSize = sizeof(abd2);
                    abd2.hWnd = ::FindWindowW(L"Shell_TrayWnd", nullptr);
                    HMONITOR windowMonitor = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
                    HMONITOR taskbarMonitor =
                        ::MonitorFromWindow(abd2.hWnd, MONITOR_DEFAULTTOPRIMARY);
                    if (taskbarMonitor == windowMonitor) {
                        ::SHAppBarMessage(ABM_GETTASKBARPOS, &abd2);
                        edge = int(abd2.uEdge);
                    }
                    top = (edge == ABE_TOP);
                    bottom = (edge == ABE_BOTTOM);
                    left = (edge == ABE_LEFT);
                    right = (edge == ABE_RIGHT);
                }
                // If there's a taskbar on any side of the monitor, reduce
                // our size a little bit on that edge.
                // Note to future code archeologists:
                // This doesn't seem to work for fullscreen on the primary
                // display. However, testing a bunch of other apps with
                // fullscreen modes and an auto-hiding taskbar has
                // shown that _none_ of them reveal the taskbar from
                // fullscreen mode. This includes Edge, Firefox, Chrome,
                // Sublime Text, PowerPoint - none seemed to support this.
                // This does however work fine for maximized.
                if (top) {
                    // Peculiarly, when we're fullscreen,
                    clientRect->top += kAutoHideTaskBarThickness;
                } else if (bottom) {
                    clientRect->bottom -= kAutoHideTaskBarThickness;
                } else if (left) {
                    clientRect->left += kAutoHideTaskBarThickness;
                } else if (right) {
                    clientRect->right -= kAutoHideTaskBarThickness;
                }
            }
        }
        // We should call this function only before the function returns.
        syncPaintEventWithDwm();
        // By returning WVR_REDRAW we can make the window resizing look
        // less broken. But we must return 0 if wParam is FALSE, according to Microsoft
        // Docs.
        // **IMPORTANT NOTE**:
        // If you are drawing something manually through D3D in your window, don't
        // try to return WVR_REDRAW here, otherwise Windows exhibits bugs where
        // client pixels and child windows are mispositioned by the width/height
        // of the upper-left non-client area. It's confirmed that this issue exists
        // from Windows 7 to Windows 10. Not tested on Windows 11 yet. Don't know
        // whether it exists on Windows XP to Windows Vista or not.
        *result = wParam ? WVR_REDRAW : FALSE;
        return true;
    }
    bool Win32WindowContext::systemMenuHandler(HWND hWnd, UINT message, WPARAM wParam,
                                               LPARAM lParam, LRESULT *result) {
        const auto getNativePosFromMouse = [lParam]() -> POINT {
            return {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
        };
        const auto getNativeGlobalPosFromKeyboard = [hWnd]() -> POINT {
            const bool maxOrFull = IsMaximized(hWnd) || isFullScreen(hWnd);
            const quint32 frameSize = getResizeBorderThickness(hWnd);
            const quint32 horizontalOffset = ((maxOrFull || !isWin10OrGreater()) ? 0 : frameSize);
            const auto verticalOffset = [hWnd, maxOrFull, frameSize]() -> quint32 {
                const quint32 titleBarHeight = getTitleBarHeight(hWnd);
                if (!isWin10OrGreater()) {
                    return titleBarHeight;
                }
                if (isWin11OrGreater()) {
                    if (maxOrFull) {
                        return (titleBarHeight + frameSize);
                    }
                    return titleBarHeight;
                }
                if (maxOrFull) {
                    return titleBarHeight;
                }
                return titleBarHeight - frameSize;
            }();
            RECT windowPos{};
            ::GetWindowRect(hWnd, &windowPos);
            return {static_cast<LONG>(windowPos.left + horizontalOffset),
                    static_cast<LONG>(windowPos.top + verticalOffset)};
        };
        bool shouldShowSystemMenu = false;
        bool broughtByKeyboard = false;
        POINT nativeGlobalPos{};
        switch (message) {
            case WM_RBUTTONUP: {
                const POINT nativeLocalPos = getNativePosFromMouse();
                const QPoint qtScenePos =
                    QHighDpi::fromNativeLocalPosition(point2qpoint(nativeLocalPos), m_windowHandle);
                if (isInTitleBarDraggableArea(qtScenePos)) {
                    shouldShowSystemMenu = true;
                    nativeGlobalPos = nativeLocalPos;
                    ::ClientToScreen(hWnd, &nativeGlobalPos);
                }
                break;
            }
            case WM_NCRBUTTONUP: {
                if (wParam == HTCAPTION) {
                    shouldShowSystemMenu = true;
                    nativeGlobalPos = getNativePosFromMouse();
                }
                break;
            }
            case WM_SYSCOMMAND: {
                const WPARAM filteredWParam = (wParam & 0xFFF0);
                if ((filteredWParam == SC_KEYMENU) && (lParam == VK_SPACE)) {
                    shouldShowSystemMenu = true;
                    broughtByKeyboard = true;
                    nativeGlobalPos = getNativeGlobalPosFromKeyboard();
                }
                break;
            }
            case WM_KEYDOWN:
            case WM_SYSKEYDOWN: {
                const bool altPressed = ((wParam == VK_MENU) || (::GetKeyState(VK_MENU) < 0));
                const bool spacePressed = ((wParam == VK_SPACE) || (::GetKeyState(VK_SPACE) < 0));
                if (altPressed && spacePressed) {
                    shouldShowSystemMenu = true;
                    broughtByKeyboard = true;
                    nativeGlobalPos = getNativeGlobalPosFromKeyboard();
                }
                break;
            }
            default:
                break;
        }
        if (shouldShowSystemMenu) {
            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
            // entering Qt's own handling logic.
            *result = FALSE;
            return true;
        }
        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));
                break;
            }
            case WM_THEMECHANGED:
            case WM_SYSCOLORCHANGE: {
                break;
            }
            case WM_DWMCOLORIZATIONCOLORCHANGED: {
                const QColor color = QColor::fromRgba(wParam);
                const auto blendWithOpacity = *reinterpret_cast<LPBOOL>(lParam);
                break;
            }
            case WM_SETTINGCHANGE: {
                if (!wParam && lParam && std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0) {
                    const QColor color = getAccentColor();
                }
                break;
            }
            case WM_SIZE: {
                const bool max = wParam == SIZE_MAXIMIZED;
                const bool min = wParam == SIZE_MINIMIZED;
                const bool full = isFullScreen(hWnd);
                break;
            }
            case WM_ACTIVATE: {
                const auto state = LOWORD(wParam);
                const bool active = state == WA_ACTIVE || state == WA_CLICKACTIVE;
                break;
            }
            default:
                break;
        }
        return false;
    }
    void Win10BorderHandler::paintBorder(QPainter &painter, const QRect &rect,
                                         const QRegion &region) {
        Q_UNUSED(rect)
        Q_UNUSED(region)
        QPen pen;
        pen.setWidth(m_borderThickness * 2);
        const bool dark = isDarkThemeActive() &&
                          isDarkWindowFrameEnabled(reinterpret_cast<HWND>(m_window->winId()));
        if (isActive()) {
            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();
        // ### TODO: do we need to enable or disable it?
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen(pen);
        painter.drawLine(QLine{
            QPoint{0,                 0},
            QPoint{m_window->width(), 0}
        });
        painter.restore();
    }
}