Sine Striker
2023-12-24 46285db399f75154ad6c451e12f2cae2e59ace25
src/core/contexts/win32windowcontext.cpp
@@ -5,6 +5,7 @@
#include <QtCore/QHash>
#include <QtCore/QScopeGuard>
#include <QtCore/QTimer>
#include <QtCore/QDateTime>
#include <QtGui/QGuiApplication>
#include <QtGui/QPainter>
#include <QtGui/QPalette>
@@ -48,6 +49,21 @@
    // Original Qt window proc function
    static WNDPROC g_qtWindowProc = nullptr;
    static inline bool
#if !QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
        constexpr
#endif
        isSystemBorderEnabled() {
        return
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
            isWin10OrGreater()
#else
            false
#endif
                ;
    }
    static inline void triggerFrameChange(HWND hwnd) {
        ::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0,
@@ -548,7 +564,7 @@
    static inline void addManagedWindow(QWindow *window, HWND hWnd, Win32WindowContext *ctx) {
        const auto margins = [hWnd]() -> QMargins {
            const auto titleBarHeight = int(getTitleBarHeight(hWnd));
            if (isWin10OrGreater()) {
            if (isSystemBorderEnabled()) {
                return {0, -titleBarHeight, 0, 0};
            } else {
                const auto frameSize = int(getResizeBorderThickness(hWnd));
@@ -643,6 +659,7 @@
            }
            case DrawWindows10BorderHook: {
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
                if (!windowId)
                    return;
@@ -653,7 +670,7 @@
                const auto hwnd = reinterpret_cast<HWND>(windowId);
                QPen pen;
                pen.setWidth(getWindowFrameBorderThickness(hwnd) * 2);
                pen.setWidth(int(getWindowFrameBorderThickness(hwnd)) * 2);
                const bool dark = isDarkThemeActive() && isDarkWindowFrameEnabled(hwnd);
                if (m_delegate->isWindowActive(m_host)) {
@@ -673,7 +690,7 @@
                }
                painter.save();
                // We needs anti-aliasing to give us better result.
                // We need antialiasing to give us better result.
                painter.setRenderHint(QPainter::Antialiasing);
                painter.setPen(pen);
@@ -682,6 +699,33 @@
                    QPoint{m_windowHandle->width(), 0}
                });
                painter.restore();
                return;
#endif
            }
            case DrawWindows10BorderHook2: {
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
                if (!m_windowHandle)
                    return;
                // https://github.com/microsoft/terminal/blob/71a6f26e6ece656084e87de1a528c4a8072eeabd/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp#L1025
                // https://docs.microsoft.com/en-us/windows/win32/dwm/customframe#extending-the-client-frame
                // Draw a black rectangle to make Windows native top border show
                auto hWnd = reinterpret_cast<HWND>(windowId);
                HDC hdc = ::GetDC(hWnd);
                RECT windowRect{};
                ::GetClientRect(hWnd, &windowRect);
                RECT rcTopBorder = {
                    0,
                    0,
                    RECT_WIDTH(windowRect),
                    int(getWindowFrameBorderThickness(hWnd)),
                };
                ::FillRect(hdc, &rcTopBorder,
                           reinterpret_cast<HBRUSH>(::GetStockObject(BLACK_BRUSH)));
                ::ReleaseDC(hWnd, hdc);
#endif
                return;
            }
@@ -692,11 +736,20 @@
    }
    bool Win32WindowContext::needBorderPainter() const {
        return isWin10OrGreater() && !isWin11OrGreater();
        Q_UNUSED(this)
        return isSystemBorderEnabled() && !isWin11OrGreater();
    }
    int Win32WindowContext::borderThickness() const {
        return getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId));
        return int(getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId)));
    }
    void Win32WindowContext::resume(const QByteArray &eventType, void *message,
                                    QT_NATIVE_EVENT_RESULT_TYPE *result) {
        const auto msg = static_cast<const MSG *>(message);
        LRESULT res =
            ::CallWindowProcW(g_qtWindowProc, msg->hwnd, msg->message, msg->wParam, msg->lParam);
        *result = decltype(*result)(res);
    }
    void Win32WindowContext::winIdChanged() {
@@ -714,19 +767,15 @@
        auto winId = m_windowHandle->winId();
        auto hWnd = reinterpret_cast<HWND>(winId);
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
        if (!isWin10OrGreater()) {
        if (!isSystemBorderEnabled()) {
            static constexpr const MARGINS margins = {1, 1, 1, 1};
            DynamicApis::instance().pDwmExtendFrameIntoClientArea(hWnd, &margins);
        }
#else
        {
            static const MARGINS margins =
                isWin10OrGreater() ? MARGINS{0, 0, 0, 0} : MARGINS{1, 1, 1, 1};
        } else if (isWin10OrGreater() && !isWin11OrGreater()) {
            // https://github.com/microsoft/terminal/blob/71a6f26e6ece656084e87de1a528c4a8072eeabd/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp#L940
            // Must call DWM API to extend top frame to client area
            static constexpr const MARGINS margins = {0, 0, 1, 0};
            DynamicApis::instance().pDwmExtendFrameIntoClientArea(hWnd, &margins);
        }
#endif
        {
            auto style = ::GetWindowLongPtrW(hWnd, GWL_STYLE);
@@ -804,7 +853,7 @@
        const DynamicApis &apis = DynamicApis::instance();
        static constexpr const MARGINS extendMargins = {-1, -1, -1, -1};
        static const auto defaultMargins =
            isWin10OrGreater() ? MARGINS{0, 0, 0, 0} : MARGINS{1, 1, 1, 1};
            isSystemBorderEnabled() ? MARGINS{0, 0, 0, 0} : MARGINS{1, 1, 1, 1};
        if (key == QStringLiteral("mica")) {
            if (!isWin11OrGreater()) {
                return false;
@@ -949,13 +998,11 @@
            }
            BOOL enable = attribute.toBool();
            if (isWin101903OrGreater()) {
                apis.pSetPreferredAppMode(enable ? PAM_AUTO : PAM_DEFAULT);
            } else {
                apis.pAllowDarkModeForApp(enable);
            }
            for (const auto attr : {
                     _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1,
                     _DWMWA_USE_IMMERSIVE_DARK_MODE,
@@ -964,7 +1011,6 @@
            }
            apis.pFlushMenuThemes();
            return true;
        }
        return false;
@@ -1495,8 +1541,7 @@
                int frameSize = getResizeBorderThickness(hWnd);
                bool isTop = (nativeLocalPos.y < frameSize);
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
                if (isWin10OrGreater()) {
                if (isSystemBorderEnabled()) {
                    // This will handle the left, right and bottom parts of the frame
                    // because we didn't change them.
                    LRESULT originalHitTestResult = ::DefWindowProcW(hWnd, WM_NCHITTEST, 0, lParam);
@@ -1538,9 +1583,7 @@
                    }
                    *result = HTCLIENT;
                    return true;
                } else
#endif
                {
                } else {
                    if (full) {
                        *result = HTCLIENT;
                        return true;
@@ -1626,7 +1669,7 @@
                break;
        }
        if (!isWin10OrGreater()) {
        if (!isSystemBorderEnabled()) {
            switch (message) {
                case WM_NCUAHDRAWCAPTION:
                case WM_NCUAHDRAWFRAME: {
@@ -1777,8 +1820,7 @@
        // 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 QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
        if (isWin10OrGreater()) {
        if (isSystemBorderEnabled()) {
            // Store the original top margin before the default window procedure applies the
            // default frame.
            const LONG originalTop = clientRect->top;
@@ -1805,7 +1847,7 @@
            // technique to bring the top border back.
            clientRect->top = originalTop;
        }
#endif
        const bool max = IsMaximized(hWnd);
        const bool full = isFullScreen(hWnd);
        // We don't need this correction when we're fullscreen. We will
@@ -1820,16 +1862,11 @@
            // a window when it's maximized unless you restore it).
            const quint32 frameSize = getResizeBorderThickness(hWnd);
            clientRect->top += frameSize;
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
            if (!isWin10OrGreater()) {
#endif
            if (!isSystemBorderEnabled()) {
                clientRect->bottom -= frameSize;
                clientRect->left += frameSize;
                clientRect->right -= frameSize;
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
            }
#endif
        }
        // Attempt to detect if there's an autohide taskbar, and if
        // there is, reduce our size a bit on the side with the taskbar,
@@ -1928,10 +1965,11 @@
        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 quint32 horizontalOffset =
                ((maxOrFull || !isSystemBorderEnabled()) ? 0 : frameSize);
            const auto verticalOffset = [hWnd, maxOrFull, frameSize]() -> quint32 {
                const quint32 titleBarHeight = getTitleBarHeight(hWnd);
                if (!isWin10OrGreater()) {
                if (!isSystemBorderEnabled()) {
                    return titleBarHeight;
                }
                if (isWin11OrGreater()) {