From e331fb1feda8891baba2a2dc1caeed67834d9d93 Mon Sep 17 00:00:00 2001 From: Zhao Yuhang <2546789017@qq.com> Date: 周五, 22 12月 2023 23:47:22 +0800 Subject: [PATCH] improve dark mode on win --- src/core/shared/qwkwindowsextra_p.h | 39 +++++++++++++++++++ src/core/qwindowkit_windows.h | 7 +++ src/core/contexts/win32windowcontext.cpp | 16 +++++-- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index ede9504..19f1864 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -937,18 +937,24 @@ if (!isWin101809OrGreater()) { return false; } + 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, }) { apis.pDwmSetWindowAttribute(hwnd, attr, &enable, sizeof(enable)); } - WINDOWCOMPOSITIONATTRIBDATA wcad{}; - wcad.Attrib = WCA_USEDARKMODECOLORS; - wcad.pvData = &enable; - wcad.cbData = sizeof(enable); - apis.pSetWindowCompositionAttribute(hwnd, &wcad); + + apis.pFlushMenuThemes(); + return true; } return false; diff --git a/src/core/qwindowkit_windows.h b/src/core/qwindowkit_windows.h index 5dfe712..8a98124 100644 --- a/src/core/qwindowkit_windows.h +++ b/src/core/qwindowkit_windows.h @@ -65,6 +65,13 @@ rovi.dwBuildNumber >= 22000); } + inline bool IsWindows101903OrGreater_Real() { + RTL_OSVERSIONINFOW rovi = GetRealOSVersion(); + return (rovi.dwMajorVersion > 10) || + (rovi.dwMajorVersion == 10 && rovi.dwMinorVersion >= 0 && + rovi.dwBuildNumber >= 18362); + } + inline bool IsWindows101809OrGreater_Real() { RTL_OSVERSIONINFOW rovi = GetRealOSVersion(); return (rovi.dwMajorVersion > 10) || diff --git a/src/core/shared/qwkwindowsextra_p.h b/src/core/shared/qwkwindowsextra_p.h index baddc07..df97727 100644 --- a/src/core/shared/qwkwindowsextra_p.h +++ b/src/core/shared/qwkwindowsextra_p.h @@ -132,7 +132,24 @@ }; using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *; + enum PREFERRED_APP_MODE + { + PAM_DEFAULT = 0, // Default behavior on systems before Win10 1809. It indicates the application doesn't support dark mode at all. + PAM_AUTO = 1, // Available since Win10 1809, let system decide whether to enable dark mode or not. + PAM_DARK = 2, // Available since Win10 1903, force dark mode regardless of the system theme. + PAM_LIGHT = 3, // Available since Win10 1903, force light mode regardless of the system theme. + PAM_MAX = 4 + }; + using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA); + + // Win10 1809 (10.0.17763) + using RefreshImmersiveColorPolicyStatePtr = VOID(WINAPI *)(VOID); // Ordinal 104 + using AllowDarkModeForWindowPtr = BOOL(WINAPI *)(HWND, BOOL); // Ordinal 133 + using AllowDarkModeForAppPtr = BOOL(WINAPI *)(BOOL); // Ordinal 135 + using FlushMenuThemesPtr = VOID(WINAPI *)(VOID); // Ordinal 136 + // Win10 1903 (10.0.18362) + using SetPreferredAppModePtr = PREFERRED_APP_MODE(WINAPI *)(PREFERRED_APP_MODE); // Ordinal 135 namespace { @@ -161,6 +178,11 @@ #undef DYNAMIC_API_DECLARE SetWindowCompositionAttributePtr pSetWindowCompositionAttribute = nullptr; + RefreshImmersiveColorPolicyStatePtr pRefreshImmersiveColorPolicyState = nullptr; + AllowDarkModeForWindowPtr pAllowDarkModeForWindow = nullptr; + AllowDarkModeForAppPtr pAllowDarkModeForApp = nullptr; + FlushMenuThemesPtr pFlushMenuThemes = nullptr; + SetPreferredAppModePtr pSetPreferredAppMode = nullptr; private: DynamicApis() { @@ -190,6 +212,18 @@ DYNAMIC_API_RESOLVE(winmm, timeEndPeriod); #undef DYNAMIC_API_RESOLVE + +#define UNDOC_API_RESOLVE(DLL, NAME, ORDINAL) \ + p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(MAKEINTRESOURCEA(ORDINAL))) + + QSystemLibrary uxtheme(QStringLiteral("uxtheme")); + UNDOC_API_RESOLVE(uxtheme, RefreshImmersiveColorPolicyState, 104); + UNDOC_API_RESOLVE(uxtheme, AllowDarkModeForWindow, 133); + UNDOC_API_RESOLVE(uxtheme, AllowDarkModeForApp, 135); + UNDOC_API_RESOLVE(uxtheme, FlushMenuThemes, 136); + UNDOC_API_RESOLVE(uxtheme, SetPreferredAppMode, 135); + +#undef UNDOC_API_RESOLVE } ~DynamicApis() = default; @@ -299,6 +333,11 @@ 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; -- Gitblit v1.9.1