win: fix some rare bugs, add more comments

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-11-10 16:53:25 +08:00
parent 70a71822da
commit ddb2dcc7f7
3 changed files with 115 additions and 48 deletions

View File

@ -120,7 +120,7 @@ FRAMELESSHELPER_CORE_API void enableNonClientAreaDpiScalingForWindow(const WId w
Global::DpiAwareness getDpiAwarenessForCurrentProcess(bool *highest = nullptr); Global::DpiAwareness getDpiAwarenessForCurrentProcess(bool *highest = nullptr);
FRAMELESSHELPER_CORE_API void fixupChildWindowsDpiMessage(const WId windowId); FRAMELESSHELPER_CORE_API void fixupChildWindowsDpiMessage(const WId windowId);
FRAMELESSHELPER_CORE_API void fixupDialogsDpiScaling(); FRAMELESSHELPER_CORE_API void fixupDialogsDpiScaling();
FRAMELESSHELPER_CORE_API void setDarkModeEnabledForApp(const bool enable = true); FRAMELESSHELPER_CORE_API void setDarkModeAllowedForApp(const bool allow = true);
#endif // Q_OS_WINDOWS #endif // Q_OS_WINDOWS
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX

View File

@ -318,7 +318,7 @@ void setApplicationOSThemeAware()
set = true; set = true;
#ifdef Q_OS_WINDOWS #ifdef Q_OS_WINDOWS
Utils::setDarkModeEnabledForApp(true); Utils::setDarkModeAllowedForApp(true);
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) # if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
Utils::setQtDarkModeAwareEnabled(true); Utils::setQtDarkModeAwareEnabled(true);
# endif # endif

View File

@ -432,16 +432,23 @@ EnableChildWindowDpiMessage2(const HWND hWnd, const BOOL fEnable)
using EnableChildWindowDpiMessagePtr = decltype(&::_EnableChildWindowDpiMessage); using EnableChildWindowDpiMessagePtr = decltype(&::_EnableChildWindowDpiMessage);
static const auto pEnableChildWindowDpiMessage = []() -> EnableChildWindowDpiMessagePtr { static const auto pEnableChildWindowDpiMessage = []() -> EnableChildWindowDpiMessagePtr {
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
FRAMELESSHELPER_STRING_CONSTANT(win32u)
FRAMELESSHELPER_STRING_CONSTANT(NtUserEnableChildWindowDpiMessage)
// EnableChildWindowDpiMessage() was moved to "win32u.dll" and renamed to
// "NtUserEnableChildWindowDpiMessage" since Win10 1607.
if (const auto pFunc = reinterpret_cast<EnableChildWindowDpiMessagePtr>(
SysApiLoader::resolve(kwin32u, kNtUserEnableChildWindowDpiMessage))) {
return pFunc;
}
FRAMELESSHELPER_STRING_CONSTANT(user32) FRAMELESSHELPER_STRING_CONSTANT(user32)
FRAMELESSHELPER_STRING_CONSTANT(EnableChildWindowDpiMessage) FRAMELESSHELPER_STRING_CONSTANT(EnableChildWindowDpiMessage)
// EnableChildWindowDpiMessage() was once a public API, so we can load it by name, // EnableChildWindowDpiMessage() was once a public API, so we can load it by name,
// but it got removed in some later SDK versions, so we can't link to it directly. // but it got removed in Win10 1607, so we can't link to it directly.
// I haven't check the accurate time point of its removal.
if (const auto pFunc = reinterpret_cast<EnableChildWindowDpiMessagePtr>( if (const auto pFunc = reinterpret_cast<EnableChildWindowDpiMessagePtr>(
SysApiLoader::resolve(kuser32, kEnableChildWindowDpiMessage))) { SysApiLoader::resolve(kuser32, kEnableChildWindowDpiMessage))) {
return pFunc; return pFunc;
} }
// EnableChildWindowDpiMessage() was a private API when first introduced. // EnableChildWindowDpiMessage() was made private since Win10 1607.
if (const auto pFunc = reinterpret_cast<EnableChildWindowDpiMessagePtr>( if (const auto pFunc = reinterpret_cast<EnableChildWindowDpiMessagePtr>(
SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2704)))) { SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2704)))) {
return pFunc; return pFunc;
@ -464,13 +471,12 @@ EnablePerMonitorDialogScaling2(VOID)
FRAMELESSHELPER_STRING_CONSTANT(user32) FRAMELESSHELPER_STRING_CONSTANT(user32)
FRAMELESSHELPER_STRING_CONSTANT(EnablePerMonitorDialogScaling) FRAMELESSHELPER_STRING_CONSTANT(EnablePerMonitorDialogScaling)
// EnablePerMonitorDialogScaling() was once a public API, so we can load it by name, // EnablePerMonitorDialogScaling() was once a public API, so we can load it by name,
// but it got removed in some later SDK versions, so we can't link to it directly. // but it got removed in Win10 1607, so we can't link to it directly.
// I haven't check the accurate time point of its removal.
if (const auto pFunc = reinterpret_cast<EnablePerMonitorDialogScalingPtr>( if (const auto pFunc = reinterpret_cast<EnablePerMonitorDialogScalingPtr>(
SysApiLoader::resolve(kuser32, kEnablePerMonitorDialogScaling))) { SysApiLoader::resolve(kuser32, kEnablePerMonitorDialogScaling))) {
return pFunc; return pFunc;
} }
// EnablePerMonitorDialogScaling() was a private API when first introduced. // EnablePerMonitorDialogScaling() was made private since Win10 1607.
if (const auto pFunc = reinterpret_cast<EnablePerMonitorDialogScalingPtr>( if (const auto pFunc = reinterpret_cast<EnablePerMonitorDialogScalingPtr>(
SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2577)))) { SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2577)))) {
return pFunc; return pFunc;
@ -492,6 +498,7 @@ GetDpiForWindow2(const HWND hWnd)
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
FRAMELESSHELPER_STRING_CONSTANT(user32) FRAMELESSHELPER_STRING_CONSTANT(user32)
FRAMELESSHELPER_STRING_CONSTANT(GetDpiForWindow) FRAMELESSHELPER_STRING_CONSTANT(GetDpiForWindow)
// GetDpiForWindow() was made public since Win10 1607.
if (const auto pFunc = reinterpret_cast<GetDpiForWindowPtr>( if (const auto pFunc = reinterpret_cast<GetDpiForWindowPtr>(
SysApiLoader::resolve(kuser32, kGetDpiForWindow))) { SysApiLoader::resolve(kuser32, kGetDpiForWindow))) {
return pFunc; return pFunc;
@ -502,7 +509,7 @@ GetDpiForWindow2(const HWND hWnd)
SysApiLoader::resolve(kuser32, kGetWindowDPI))) { SysApiLoader::resolve(kuser32, kGetWindowDPI))) {
return pFunc; return pFunc;
} }
// GetDpiForWindow() was a private API when first introduced. // GetWindowDPI() was made private since Win10 1607.
if (const auto pFunc = reinterpret_cast<GetDpiForWindowPtr>( if (const auto pFunc = reinterpret_cast<GetDpiForWindowPtr>(
SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2707)))) { SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2707)))) {
return pFunc; return pFunc;
@ -524,11 +531,13 @@ GetSystemMetricsForDpi2(const int nIndex, const UINT dpi)
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
FRAMELESSHELPER_STRING_CONSTANT(user32) FRAMELESSHELPER_STRING_CONSTANT(user32)
FRAMELESSHELPER_STRING_CONSTANT(GetSystemMetricsForDpi) FRAMELESSHELPER_STRING_CONSTANT(GetSystemMetricsForDpi)
// GetSystemMetricsForDpi() was made public since Win10 1607.
if (const auto pFunc = reinterpret_cast<GetSystemMetricsForDpiPtr>( if (const auto pFunc = reinterpret_cast<GetSystemMetricsForDpiPtr>(
SysApiLoader::resolve(kuser32, kGetSystemMetricsForDpi))) { SysApiLoader::resolve(kuser32, kGetSystemMetricsForDpi))) {
return pFunc; return pFunc;
} }
// GetSystemMetricsForDpi() was named "GetDpiMetrics" before made public. // GetSystemMetricsForDpi() was named "GetDpiMetrics" before made public,
// that is, when in Win10 1507 & 1511.
FRAMELESSHELPER_STRING_CONSTANT(GetDpiMetrics) FRAMELESSHELPER_STRING_CONSTANT(GetDpiMetrics)
if (const auto pFunc = reinterpret_cast<GetSystemMetricsForDpiPtr>( if (const auto pFunc = reinterpret_cast<GetSystemMetricsForDpiPtr>(
SysApiLoader::resolve(kuser32, kGetDpiMetrics))) { SysApiLoader::resolve(kuser32, kGetDpiMetrics))) {
@ -552,11 +561,12 @@ AdjustWindowRectExForDpi2(LPRECT lpRect, const DWORD dwStyle,
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
FRAMELESSHELPER_STRING_CONSTANT(user32) FRAMELESSHELPER_STRING_CONSTANT(user32)
FRAMELESSHELPER_STRING_CONSTANT(AdjustWindowRectExForDpi) FRAMELESSHELPER_STRING_CONSTANT(AdjustWindowRectExForDpi)
// AdjustWindowRectExForDpi() was made public since Win10 1607.
if (const auto pFunc = reinterpret_cast<AdjustWindowRectExForDpiPtr>( if (const auto pFunc = reinterpret_cast<AdjustWindowRectExForDpiPtr>(
SysApiLoader::resolve(kuser32, kAdjustWindowRectExForDpi))) { SysApiLoader::resolve(kuser32, kAdjustWindowRectExForDpi))) {
return pFunc; return pFunc;
} }
// AdjustWindowRectExForDpi() was a private API when first introduced. // AdjustWindowRectExForDpi() was made private in Win10 1507 & 1511.
if (const auto pFunc = reinterpret_cast<AdjustWindowRectExForDpiPtr>( if (const auto pFunc = reinterpret_cast<AdjustWindowRectExForDpiPtr>(
SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2580)))) { SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2580)))) {
return pFunc; return pFunc;
@ -715,6 +725,14 @@ struct Win32UtilsHelper
Q_GLOBAL_STATIC(Win32UtilsHelper, g_utilsHelper) Q_GLOBAL_STATIC(Win32UtilsHelper, g_utilsHelper)
struct MicaWindowData
{
QMutex mutex;
QList<WId> windowIds = {};
};
Q_GLOBAL_STATIC(MicaWindowData, g_micaData)
struct SYSTEM_METRIC struct SYSTEM_METRIC
{ {
int DPI_96 = 0; // 100%. The scale factor for the device is 1x. int DPI_96 = 0; // 100%. The scale factor for the device is 1x.
@ -1058,12 +1076,22 @@ void Utils::updateWindowFrameMargins(const WId windowId, const bool reset)
if (!API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea)) { if (!API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea)) {
return; return;
} }
const MARGINS margins = [reset]() -> MARGINS { g_micaData()->mutex.lock();
const bool micaEnabled = g_micaData()->windowIds.contains(windowId);
g_micaData()->mutex.unlock();
const auto margins = [micaEnabled, reset]() -> MARGINS {
// To make Mica/Mica Alt work for normal Win32 windows, we have to
// let the window frame extend to the whole window (or disable the
// redirection surface, but this will break GDI's rendering, so we
// can't do this, unfortunately), so we can't change the window frame
// margins in this case, otherwise Mica/Mica Alt will be broken.
if (micaEnabled) {
return {-1, -1, -1, -1};
}
if (reset || isWindowFrameBorderVisible()) { if (reset || isWindowFrameBorderVisible()) {
return {0, 0, 0, 0}; return {0, 0, 0, 0};
} else {
return {1, 1, 1, 1};
} }
return {1, 1, 1, 1};
}(); }();
const auto hwnd = reinterpret_cast<HWND>(windowId); const auto hwnd = reinterpret_cast<HWND>(windowId);
const HRESULT hr = API_CALL_FUNCTION(DwmExtendFrameIntoClientArea, hwnd, &margins); const HRESULT hr = API_CALL_FUNCTION(DwmExtendFrameIntoClientArea, hwnd, &margins);
@ -2071,8 +2099,17 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
if (WindowsVersionHelper::isWin8OrGreater()) { if (WindowsVersionHelper::isWin8OrGreater()) {
if (!(API_DWM_AVAILABLE(DwmSetWindowAttribute) if (!(API_DWM_AVAILABLE(DwmSetWindowAttribute)
&& API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea))) { && API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea))) {
WARNING << "Blur behind window is not available on current platform.";
return false; return false;
} }
const auto restoreWindowFrameMargins = [windowId]() -> void {
g_micaData()->mutex.lock();
if (g_micaData()->windowIds.contains(windowId)) {
g_micaData()->windowIds.removeAll(windowId);
}
g_micaData()->mutex.unlock();
updateWindowFrameMargins(windowId, false);
};
const BlurMode blurMode = [mode]() -> BlurMode { const BlurMode blurMode = [mode]() -> BlurMode {
if ((mode == BlurMode::Disable) || (mode == BlurMode::Windows_Aero)) { if ((mode == BlurMode::Disable) || (mode == BlurMode::Windows_Aero)) {
return mode; return mode;
@ -2102,26 +2139,23 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
return mode; return mode;
}(); }();
if (blurMode == BlurMode::Disable) { if (blurMode == BlurMode::Disable) {
bool result = true;
if (WindowsVersionHelper::isWin1122H2OrGreater()) { if (WindowsVersionHelper::isWin1122H2OrGreater()) {
const _DWM_SYSTEMBACKDROP_TYPE dwmsbt = _DWMSBT_NONE; const _DWM_SYSTEMBACKDROP_TYPE dwmsbt = _DWMSBT_NONE;
const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute, const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute,
hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &dwmsbt, sizeof(dwmsbt)); hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &dwmsbt, sizeof(dwmsbt));
if (FAILED(hr)) { if (FAILED(hr)) {
result = false;
WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr); WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr);
} }
} } else if (WindowsVersionHelper::isWin11OrGreater()) {
if (WindowsVersionHelper::isWin11OrGreater()) {
const BOOL enable = FALSE; const BOOL enable = FALSE;
HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute, HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute,
hwnd, _DWMWA_MICA_EFFECT, &enable, sizeof(enable)); hwnd, _DWMWA_MICA_EFFECT, &enable, sizeof(enable));
if (FAILED(hr)) { if (FAILED(hr)) {
result = false;
WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr); WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr);
} }
const MARGINS margins = {0, 0, 0, 0};
hr = API_CALL_FUNCTION(DwmExtendFrameIntoClientArea, hwnd, &margins);
if (FAILED(hr)) {
WARNING << __getSystemErrorMessage(kDwmExtendFrameIntoClientArea, hr);
}
} else { } else {
ACCENT_POLICY policy; ACCENT_POLICY policy;
SecureZeroMemory(&policy, sizeof(policy)); SecureZeroMemory(&policy, sizeof(policy));
@ -2132,21 +2166,43 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
wcad.pvData = &policy; wcad.pvData = &policy;
wcad.cbData = sizeof(policy); wcad.cbData = sizeof(policy);
if (SetWindowCompositionAttribute(hwnd, &wcad) == FALSE) { if (SetWindowCompositionAttribute(hwnd, &wcad) == FALSE) {
result = false;
WARNING << getSystemErrorMessage(kSetWindowCompositionAttribute); WARNING << getSystemErrorMessage(kSetWindowCompositionAttribute);
} }
} }
return true; if (WindowsVersionHelper::isWin11OrGreater()) {
restoreWindowFrameMargins();
}
return result;
} else { } else {
if (blurMode == BlurMode::Windows_Mica) { if (blurMode == BlurMode::Windows_Mica) {
g_micaData()->mutex.lock();
if (!g_micaData()->windowIds.contains(windowId)) {
g_micaData()->windowIds.append(windowId);
}
g_micaData()->mutex.unlock();
// By giving a negative value, DWM will extend the window frame into the whole // By giving a negative value, DWM will extend the window frame into the whole
// client area. We need this step because the Mica material can only be applied // client area. We need this step because the Mica material can only be applied
// to the non-client area of a window. Without this step, you'll get a window // to the non-client area of a window. Without this step, you'll get a window
// with a pure black background. // with a pure black background.
// Actually disabling the redirection surface (by enabling WS_EX_NOREDIRECTIONBITMAP
// when you call CreateWindow(), it won't have any effect if you set it after the
// window has been created) can achieve the same effect with extending the window
// frame, however, it will completely break GDI's rendering, so sadly we can't choose
// this solution. But this can be used if you can make sure your application don't
// use GDI at all, for example, you only use Direct3D to draw your window (like
// UWP/WPF applications). And one additional note, it will also break OpenGL and Vulkan
// due to they also use the legacy swap chain model. In theory you can try this flag
// for Qt Quick applications when the rhi backend is Direct3D, however, some elements
// will still be broken because Qt Quick still use GDI to render some native controls
// such as the window menu.
const MARGINS margins = {-1, -1, -1, -1}; const MARGINS margins = {-1, -1, -1, -1};
HRESULT hr = API_CALL_FUNCTION(DwmExtendFrameIntoClientArea, hwnd, &margins); HRESULT hr = API_CALL_FUNCTION(DwmExtendFrameIntoClientArea, hwnd, &margins);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
if (WindowsVersionHelper::isWin1122H2OrGreater()) { if (WindowsVersionHelper::isWin1122H2OrGreater()) {
const _DWM_SYSTEMBACKDROP_TYPE dwmsbt = _DWMSBT_MAINWINDOW; // Mica const auto dwmsbt = (
qEnvironmentVariableIntValue("FRAMELESSHELPER_USE_MICA_ALT")
? _DWMSBT_TABBEDWINDOW : _DWMSBT_MAINWINDOW);
hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hwnd, hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hwnd,
_DWMWA_SYSTEMBACKDROP_TYPE, &dwmsbt, sizeof(dwmsbt)); _DWMWA_SYSTEMBACKDROP_TYPE, &dwmsbt, sizeof(dwmsbt));
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
@ -2167,12 +2223,14 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
} else { } else {
WARNING << __getSystemErrorMessage(kDwmExtendFrameIntoClientArea, hr); WARNING << __getSystemErrorMessage(kDwmExtendFrameIntoClientArea, hr);
} }
restoreWindowFrameMargins();
} else { } else {
ACCENT_POLICY policy; ACCENT_POLICY policy;
SecureZeroMemory(&policy, sizeof(policy)); SecureZeroMemory(&policy, sizeof(policy));
if (blurMode == BlurMode::Windows_Acrylic) { if (blurMode == BlurMode::Windows_Acrylic) {
policy.State = ACCENT_ENABLE_ACRYLICBLURBEHIND; policy.State = ACCENT_ENABLE_ACRYLICBLURBEHIND;
policy.Flags = 2; // Magic number, this member must be set to 2. // Magic number, this member must be set to 2, otherwise will have no effect, don't know why.
policy.Flags = 2;
const QColor gradientColor = [&color]() -> QColor { const QColor gradientColor = [&color]() -> QColor {
if (color.isValid()) { if (color.isValid()) {
return color; return color;
@ -2195,12 +2253,14 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
wcad.pvData = &policy; wcad.pvData = &policy;
wcad.cbData = sizeof(policy); wcad.cbData = sizeof(policy);
if (SetWindowCompositionAttribute(hwnd, &wcad) != FALSE) { if (SetWindowCompositionAttribute(hwnd, &wcad) != FALSE) {
if (!WindowsVersionHelper::isWin11OrGreater()) { if ((blurMode == BlurMode::Windows_Acrylic)
&& !WindowsVersionHelper::isWin11OrGreater()) {
DEBUG << "Enabling the Acrylic blur for Win32 windows on Windows 10 " DEBUG << "Enabling the Acrylic blur for Win32 windows on Windows 10 "
"is very buggy. The only recommended way by Microsoft is to " "is very buggy. The only recommended way by Microsoft is to "
"use the XAML Island technology or use pure UWP instead. If " "use the XAML Island technology or use pure UWP instead. If "
"you find your window becomes very laggy during moving and " "you find your window becomes very laggy during moving and "
"resizing, please disable the Acrylic blur immediately."; "resizing, please disable the Acrylic blur immediately (or "
"disable the transparent effect in your personalize settings).";
} }
return true; return true;
} }
@ -2210,7 +2270,10 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
} else { } else {
// We prefer to use "DwmEnableBlurBehindWindow" on Windows 7 because it behaves // We prefer to use "DwmEnableBlurBehindWindow" on Windows 7 because it behaves
// better than the undocumented API. // better than the undocumented API.
if (API_DWM_AVAILABLE(DwmEnableBlurBehindWindow)) { if (!API_DWM_AVAILABLE(DwmEnableBlurBehindWindow)) {
WARNING << "Blur behind window is not available on current platform.";
return false;
}
DWM_BLURBEHIND dwmbb; DWM_BLURBEHIND dwmbb;
SecureZeroMemory(&dwmbb, sizeof(dwmbb)); SecureZeroMemory(&dwmbb, sizeof(dwmbb));
dwmbb.dwFlags = DWM_BB_ENABLE; dwmbb.dwFlags = DWM_BB_ENABLE;
@ -2229,7 +2292,6 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
} }
WARNING << __getSystemErrorMessage(kDwmEnableBlurBehindWindow, hr); WARNING << __getSystemErrorMessage(kDwmEnableBlurBehindWindow, hr);
} }
}
return false; return false;
} }
@ -2618,14 +2680,19 @@ void Utils::fixupDialogsDpiScaling()
WARNING << getSystemErrorMessage(kEnablePerMonitorDialogScaling); WARNING << getSystemErrorMessage(kEnablePerMonitorDialogScaling);
} }
void Utils::setDarkModeEnabledForApp(const bool enable) void Utils::setDarkModeAllowedForApp(const bool allow)
{ {
// This hack is only available since Win10 1809.
if (!WindowsVersionHelper::isWin10RS5OrGreater()) {
return;
}
// This hack is necessary to let AllowDarkModeForWindow() work ...
if (WindowsVersionHelper::isWin1019H1OrGreater()) { if (WindowsVersionHelper::isWin1019H1OrGreater()) {
if (SetPreferredAppMode(enable ? PAM_AUTO : PAM_DEFAULT) == PAM_MAX) { if (SetPreferredAppMode(allow ? PAM_AUTO : PAM_DEFAULT) == PAM_MAX) {
WARNING << getSystemErrorMessage(kSetPreferredAppMode); WARNING << getSystemErrorMessage(kSetPreferredAppMode);
} }
} else if (WindowsVersionHelper::isWin10RS5OrGreater()) { } else {
if (AllowDarkModeForApp(enable ? TRUE : FALSE) == FALSE) { if (AllowDarkModeForApp(allow ? TRUE : FALSE) == FALSE) {
WARNING << getSystemErrorMessage(kAllowDarkModeForApp); WARNING << getSystemErrorMessage(kAllowDarkModeForApp);
} }
} }