Sine Striker
2023-12-26 c8a5a82994e513acb00ba0e1f0b882ccbb18a6db
clean code
8个文件已修改
250 ■■■■■ 已修改文件
src/core/contexts/win32windowcontext.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/win32windowcontext_p.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/qwindowkit_windows.cpp 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/qwindowkit_windows.h 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/shared/qwkwindowsextra_p.h 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/style/styleagent_win.cpp 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/quick/quickwindowagent_win.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/widgets/widgetwindowagent_win.cpp 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/contexts/win32windowcontext.cpp
@@ -9,7 +9,6 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QPainter>
#include <QtGui/QPalette>
#include <QtGui/QStyleHints>
#include <QtGui/private/qhighdpiscaling_p.h>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -1319,12 +1318,12 @@
                                                 LPARAM lParam, LRESULT *result) {
        switch (message) {
            case WM_SHOWWINDOW: {
                if (!centered) {
                if (!initialCentered) {
                    // 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 (wParam && !lParam) {
                        centered = true;
                        initialCentered = true;
                        moveWindowToDesktopCenter(hWnd);
                    }
                }
src/core/contexts/win32windowcontext_p.h
@@ -69,7 +69,7 @@
        // WM_MOUSELEAVE.
        bool mouseLeaveBlocked = false;
        bool centered = false;
        bool initialCentered = false;
    };
}
src/core/qwindowkit_windows.cpp
@@ -2,17 +2,24 @@
namespace QWK {
    RTL_OSVERSIONINFOW GetRealOSVersion() {
        static const auto result = []() -> RTL_OSVERSIONINFOW {
    static RTL_OSVERSIONINFOW GetRealOSVersionImpl() {
            HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
            using RtlGetVersionPtr = NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW);
            auto pRtlGetVersion = reinterpret_cast<RtlGetVersionPtr>(::GetProcAddress(hMod, "RtlGetVersion"));
        auto pRtlGetVersion =
            reinterpret_cast<RtlGetVersionPtr>(::GetProcAddress(hMod, "RtlGetVersion"));
            RTL_OSVERSIONINFOW rovi{};
            rovi.dwOSVersionInfoSize = sizeof(rovi);
            pRtlGetVersion(&rovi);
            return rovi;
        }();
    }
    namespace Private {
        RTL_OSVERSIONINFOW GetRealOSVersion() {
            static const auto result = GetRealOSVersionImpl();
        return result;
    }
}
}
src/core/qwindowkit_windows.h
@@ -49,6 +49,8 @@
namespace QWK {
    namespace Private {
    QWK_CORE_EXPORT RTL_OSVERSIONINFOW GetRealOSVersion();
    inline bool IsWindows1122H2OrGreater_Real() {
@@ -87,12 +89,14 @@
    inline bool IsWindows8Point1OrGreater_Real() {
        RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
        return (rovi.dwMajorVersion > 6) || (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 3);
            return (rovi.dwMajorVersion > 6) ||
                   (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 3);
    }
    inline bool IsWindows8OrGreater_Real() {
        RTL_OSVERSIONINFOW rovi = GetRealOSVersion();
        return (rovi.dwMajorVersion > 6) || (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 2);
            return (rovi.dwMajorVersion > 6) ||
                   (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 2);
    }
    inline bool IsWindows10_Real() {
@@ -101,6 +105,61 @@
}
    //
    // Version Helpers
    //
    static inline bool isWin8OrGreater() {
        static const bool result = Private::IsWindows8OrGreater_Real();
        return result;
    }
    static inline bool isWin8Point1OrGreater() {
        static const bool result = Private::IsWindows8Point1OrGreater_Real();
        return result;
    }
    static inline bool isWin10OrGreater() {
        static const bool result = Private::IsWindows10OrGreater_Real();
        return result;
    }
    static inline bool isWin101809OrGreater() {
        static const bool result = Private::IsWindows101809OrGreater_Real();
        return result;
    }
    static inline bool isWin101903OrGreater() {
        static const bool result = Private::IsWindows101903OrGreater_Real();
        return result;
    }
    static inline bool isWin11OrGreater() {
        static const bool result = Private::IsWindows11OrGreater_Real();
        return result;
    }
    static inline bool isWin1122H2OrGreater() {
        static const bool result = Private::IsWindows1122H2OrGreater_Real();
        return result;
    }
    static inline bool isWin10() {
        static const bool result = Private::IsWindows10_Real();
        return result;
    };
    //
    // Native Event Helpers
    //
    inline bool isImmersiveColorSetChange(WPARAM wParam, LPARAM lParam) {
        return !wParam && lParam &&
               std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0;
    }
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
Q_DECLARE_METATYPE(QMargins)
#endif
src/core/shared/qwkwindowsextra_p.h
@@ -308,7 +308,7 @@
    }
    static inline constexpr MARGINS qmargins2margins(const QMargins &qmargins) {
        return MARGINS{qmargins.left(), qmargins.right(), qmargins.top(), qmargins.bottom()};
        return {qmargins.left(), qmargins.right(), qmargins.top(), qmargins.bottom()};
    }
    static inline /*constexpr*/ QString hwnd2str(const WId windowId) {
@@ -320,41 +320,6 @@
    static inline /*constexpr*/ QString hwnd2str(HWND hwnd) {
        // NULL handle is allowed here.
        return hwnd2str(reinterpret_cast<WId>(hwnd));
    }
    static inline bool isWin8OrGreater() {
        static const bool result = IsWindows8OrGreater_Real();
        return result;
    }
    static inline bool isWin8Point1OrGreater() {
        static const bool result = IsWindows8Point1OrGreater_Real();
        return result;
    }
    static inline bool isWin10OrGreater() {
        static const bool result = IsWindows10OrGreater_Real();
        return result;
    }
    static inline bool isWin101809OrGreater() {
        static const bool result = IsWindows101809OrGreater_Real();
        return result;
    }
    static inline bool isWin101903OrGreater() {
        static const bool result = IsWindows101903OrGreater_Real();
        return result;
    }
    static inline bool isWin11OrGreater() {
        static const bool result = IsWindows11OrGreater_Real();
        return result;
    }
    static inline bool isWin1122H2OrGreater() {
        static const bool result = IsWindows1122H2OrGreater_Real();
        return result;
    }
    static inline bool isDwmCompositionEnabled() {
@@ -370,11 +335,11 @@
    }
    static inline bool isWindowFrameBorderColorized() {
        const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
        QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
        if (!registry.isValid()) {
            return false;
        }
        const auto value = registry.dwordValue(L"ColorPrevalence");
        auto value = registry.dwordValue(L"ColorPrevalence");
        if (!value.second) {
            return false;
        }
@@ -392,12 +357,12 @@
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
        return QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark;
#else
        const QWinRegistryKey registry(
        QWinRegistryKey registry(
            HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)");
        if (!registry.isValid()) {
            return false;
        }
        const auto value = registry.dwordValue(L"AppsUseLightTheme");
        auto value = registry.dwordValue(L"AppsUseLightTheme");
        if (!value.second) {
            return false;
        }
@@ -423,21 +388,21 @@
#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)");
        QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
        if (!registry.isValid()) {
            return {};
        }
        const auto value = registry.dwordValue(L"AccentColor");
        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()) {
        QColor color = QColor::fromRgba(value.first);
        if (!color.isValid()) {
            return {};
        }
        return QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
        return QColor::fromRgb(color.blue(), color.green(), color.red(), color.alpha());
#endif
    }
src/core/style/styleagent_win.cpp
@@ -30,9 +30,7 @@
                        return true;
                    case WM_SETTINGCHANGE: {
                        if (!msg->wParam && msg->lParam &&
                            std::wcscmp(reinterpret_cast<LPCWSTR>(msg->lParam), L"ImmersiveColorSet") ==
                            0) {
                        if (isImmersiveColorSetChange(msg->wParam, msg->lParam)) {
                            return true;
                        }
                        break;
src/quick/quickwindowagent_win.cpp
@@ -8,6 +8,10 @@
namespace QWK {
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
    // TODO: Find a way to draw native border
    // We haven't found a way to place hooks in the Quick program and call the GDI API to draw
    // the native border area so that we'll use the emulated drawn border for now.
    class BorderItem : public QQuickPaintedItem,
                       public NativeEventFilter,
                       public SharedEventFilter {
@@ -107,9 +111,7 @@
            }
            case WM_SETTINGCHANGE: {
                if (!msg->wParam && msg->lParam &&
                    std::wcscmp(reinterpret_cast<LPCWSTR>(msg->lParam), L"ImmersiveColorSet") ==
                        0) {
                if (isImmersiveColorSetChange(msg->wParam, msg->lParam)) {
                    update();
                }
                break;
src/widgets/widgetwindowagent_win.cpp
@@ -9,6 +9,28 @@
namespace QWK {
#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER)
    // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/plugins/platforms/windows/qwindowsbackingstore.cpp#L42
    // In QtWidgets applications, when repainting happens, QPA at the last calls
    // QWindowsBackingStore::flush() to draw the contents of the buffer to the screen, we need to
    // call GDI drawing the top border after that.
    // After debugging, we know that there are two situations that will lead to redrawing.
    //
    // 1. Windows sends a WM_PAINT message, after which Qt immediately generates a QExposeEvent or
    // QResizeEvent and send it to the corresponding QWidgetWindow instance, calling "flush" at the
    // end of its handler.
    //
    // 2. When a timer or user input triggers Qt to redraw spontaneously, the corresponding
    // QWidget receives a QEvent::UpdateRequest event and also calls "flush" at the end of its
    // handler.
    //
    // The above two cases are mutually exclusive, so we just need to intercept the two events
    // separately and draw the border area after the "flush" is called.
    // https://github.com/qt/qtbase/blob/e26a87f1ecc40bc8c6aa5b889fce67410a57a702/src/plugins/platforms/windows/qwindowswindow.cpp#L2440
    // Note that we can not draw the border right after WM_PAINT comes or right before the WndProc
    // returns, because Qt calls BeginPaint() and EndPaint() itself. We should make sure that we
    // draw the top border between these two calls, otherwise some display exceptions may arise.
    class WidgetBorderHandler : public QObject, public NativeEventFilter, public SharedEventFilter {
    public:
@@ -21,6 +43,8 @@
            // Must extend top frame to client area
            static QVariant defaultMargins = QVariant::fromValue(QMargins(0, 1, 0, 0));
            ctx->setWindowAttribute(QStringLiteral("extra-margins"), defaultMargins);
            // Enable dark mode by default, otherwise the frame borders are white
            ctx->setWindowAttribute(QStringLiteral("dark-mode"), true);
            ctx->installNativeEventFilter(this);
@@ -41,6 +65,37 @@
            } else {
                widget->setContentsMargins({});
            }
        }
        inline void resumeWidgetEvent(QWidget *w, QEvent *event) {
            // Friend class helping to call `event`
            class HackedWidget : public QWidget {
            public:
                friend class QWK::WidgetBorderHandler;
            };
            // Let the widget paint first
            static_cast<HackedWidget *>(w)->event(event);
            // Due to the timer or user action, Qt will redraw some regions spontaneously,
            // even if there is no WM_PAINT message, we must wait for it to finish redrawing
            // and then update the top border area.
            ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook2, nullptr);
        }
        inline void resumeWindowEvent(QWindow *window, QEvent *event) {
            // Friend class helping to call `event`
            class HackedWindow : public QWindow {
            public:
                friend class QWK::WidgetBorderHandler;
            };
            // Let Qt paint first
            static_cast<HackedWindow *>(window)->event(event);
            // Upon receiving the WM_PAINT message, Qt will redraw the entire view, and we
            // must wait for it to finish redrawing before drawing this top border area.
            ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook2, nullptr);
        }
    protected:
@@ -83,28 +138,22 @@
            Q_UNUSED(obj)
            auto window = widget->windowHandle();
            if (event->type() == QEvent::Expose) {
                // Qt will absolutely send a QExposeEvent to the QWindow when it receives a
                // WM_PAINT message. When the control flow enters the expose handler, Qt must
                // have already called BeginPaint() and it's the best time for us to draw the
            // Qt will absolutely send a QExposeEvent or QResizeEvent to the QWindow when it
            // receives a WM_PAINT message. When the control flow enters the expose handler, Qt
            // must have already called BeginPaint() and it's the best time for us to draw the
                // top border.
            // Since a QExposeEvent will be sent immediately after the QResizeEvent, we can simply
            // ignore it.
            if (event->type() == QEvent::Expose) {
                auto ee = static_cast<QExposeEvent *>(event);
                if (isNormalWindow() && window->isExposed() && !ee->region().isNull()) {
                    // Friend class helping to call `event`
                    class HackedWindow : public QWindow {
                    public:
                        friend class QWK::WidgetBorderHandler;
                    };
                    // Let Qt paint first
                    static_cast<HackedWindow *>(window)->event(event);
                    // Upon receiving the WM_PAINT message, Qt will redraw the entire view, and we
                    // must wait for it to finish redrawing before drawing this top border area.
                    ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook2, nullptr);
                if (window->isExposed() && !ee->region().isNull()) {
                    resumeWindowEvent(window, event);
                    return true;
                }
            }
            return false;
        }
@@ -114,20 +163,7 @@
                case QEvent::UpdateRequest: {
                    if (!isNormalWindow())
                        break;
                    // Friend class helping to call `event`
                    class HackedWidget : public QWidget {
                    public:
                        friend class QWK::WidgetBorderHandler;
                    };
                    // Let the widget paint first
                    static_cast<HackedWidget *>(widget)->event(event);
                    // Due to the timer or user action, Qt will redraw some regions spontaneously,
                    // even if there is no WM_PAINT message, we must wait for it to finish redrawing
                    // and then update the top border area.
                    ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook2, nullptr);
                    resumeWidgetEvent(widget, event);
                    return true;
                }