win32: add support for dark theme menu
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
fcf51d6d73
commit
b9f5cf79c0
|
@ -134,7 +134,7 @@ void Dialog::setupUi()
|
|||
// with making the window un-resizable: we still want the window be able to resize
|
||||
// programatically, but we also want the user not able to resize the window manually.
|
||||
// So apparently we can't use QWidget::setFixedWidth/Height/Size() here.
|
||||
FramelessWidgetsHelperPrivate::get(helper)->setProperty(FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_DONT_OVERRIDE_CURSOR"), true);
|
||||
FramelessWidgetsHelperPrivate::get(helper)->setProperty(kDontOverrideCursorVar, true);
|
||||
connect(helper, &FramelessWidgetsHelper::ready, this, [this, helper](){
|
||||
const QScopedPointer<QSettings> settings(appConfigFile());
|
||||
const QByteArray data = settings->value(kIniKeyPath).toByteArray();
|
||||
|
|
|
@ -58,8 +58,8 @@
|
|||
# define _WIN32_WINNT_WIN10 0x0A00
|
||||
#endif
|
||||
|
||||
#ifndef NTDDI_WIN10_CO
|
||||
# define NTDDI_WIN10_CO 0x0A00000B
|
||||
#ifndef NTDDI_WIN10_NI
|
||||
# define NTDDI_WIN10_NI 0x0A00000C
|
||||
#endif
|
||||
|
||||
#ifndef WINVER
|
||||
|
@ -71,7 +71,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef NTDDI_VERSION
|
||||
# define NTDDI_VERSION NTDDI_WIN10_CO
|
||||
# define NTDDI_VERSION NTDDI_WIN10_NI
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
@ -375,9 +375,6 @@ using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *;
|
|||
using NPWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA NEAR *;
|
||||
using LPWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA FAR *;
|
||||
|
||||
using GetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
|
||||
using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
|
||||
|
||||
using _WINDOWTHEMEATTRIBUTETYPE = enum _WINDOWTHEMEATTRIBUTETYPE
|
||||
{
|
||||
_WTA_NONCLIENT = 1
|
||||
|
@ -390,6 +387,37 @@ using WTA_OPTIONS2 = struct WTA_OPTIONS2
|
|||
};
|
||||
using PWTA_OPTIONS2 = WTA_OPTIONS2 *;
|
||||
|
||||
using IMMERSIVE_HC_CACHE_MODE = enum IMMERSIVE_HC_CACHE_MODE
|
||||
{
|
||||
IHCM_USE_CACHED_VALUE = 0,
|
||||
IHCM_REFRESH = 1
|
||||
};
|
||||
|
||||
using PREFERRED_APP_MODE = enum PREFERRED_APP_MODE
|
||||
{
|
||||
PAM_DEFAULT = 0,
|
||||
PAM_ALLOW_DARK = 1,
|
||||
PAM_FORCE_DARK = 2,
|
||||
PAM_FORCE_LIGHT = 3,
|
||||
PAM_MAX = 4
|
||||
};
|
||||
|
||||
using GetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
|
||||
using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
|
||||
// Win10 1809 (10.0.17763)
|
||||
using ShouldAppsUseDarkModePtr = BOOL(WINAPI *)(VOID); // Ordinal 132
|
||||
using AllowDarkModeForWindowPtr = BOOL(WINAPI *)(HWND, BOOL); // Ordinal 133
|
||||
using AllowDarkModeForAppPtr = BOOL(WINAPI *)(BOOL); // Ordinal 135
|
||||
using FlushMenuThemesPtr = VOID(WINAPI *)(VOID); // Ordinal 136
|
||||
using RefreshImmersiveColorPolicyStatePtr = VOID(WINAPI *)(VOID); // Ordinal 104
|
||||
using IsDarkModeAllowedForWindowPtr = BOOL(WINAPI *)(HWND); // Ordinal 137
|
||||
using GetIsImmersiveColorUsingHighContrastPtr = BOOL(WINAPI *)(IMMERSIVE_HC_CACHE_MODE); // Ordinal 106
|
||||
using OpenNcThemeDataPtr = HTHEME(WINAPI *)(HWND, LPCWSTR); // Ordinal 49
|
||||
// Win10 1903 (10.0.18362)
|
||||
using ShouldSystemUseDarkModePtr = BOOL(WINAPI *)(VOID); // Ordinal 138
|
||||
using SetPreferredAppModePtr = PREFERRED_APP_MODE(WINAPI *)(PREFERRED_APP_MODE); // Ordinal 135
|
||||
using IsDarkModeAllowedForAppPtr = BOOL(WINAPI *)(VOID); // Ordinal 139
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
DECLSPEC_IMPORT MMRESULT WINAPI
|
||||
|
|
|
@ -235,6 +235,11 @@ Q_NAMESPACE_EXPORT(FRAMELESSHELPER_CORE_API)
|
|||
[[maybe_unused]] inline Q_CONSTEXPR2 const QColor kDefaultSystemButtonBackgroundColor = {204, 204, 204}; // #CCCCCC
|
||||
[[maybe_unused]] inline Q_CONSTEXPR2 const QColor kDefaultSystemCloseButtonBackgroundColor = {232, 17, 35}; // #E81123
|
||||
|
||||
[[maybe_unused]] inline const QByteArray kDontOverrideCursorVar
|
||||
= FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_DONT_OVERRIDE_CURSOR");
|
||||
[[maybe_unused]] inline const QByteArray kDontToggleMaximizeVar
|
||||
= FRAMELESSHELPER_BYTEARRAY_LITERAL("FRAMELESSHELPER_DONT_TOGGLE_MAXIMIZE");
|
||||
|
||||
enum class Option
|
||||
{
|
||||
UseCrossPlatformQtImplementation = 0,
|
||||
|
@ -373,10 +378,10 @@ Q_ENUM_NS(RegistryRootKey)
|
|||
enum class WindowEdge
|
||||
{
|
||||
Unspecified = 0x00000000,
|
||||
Left = 0x00000002,
|
||||
Top = 0x00000004,
|
||||
Right = 0x00000008,
|
||||
Bottom = 0x00000010
|
||||
Left = 0x00000001,
|
||||
Top = 0x00000002,
|
||||
Right = 0x00000004,
|
||||
Bottom = 0x00000008
|
||||
};
|
||||
Q_ENUM_NS(WindowEdge)
|
||||
Q_DECLARE_FLAGS(WindowEdges, WindowEdge)
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
|
||||
Q_NODISCARD static SysApiLoader *instance();
|
||||
|
||||
Q_NODISCARD static QFunctionPointer resolve(const QString &library, const char *function);
|
||||
Q_NODISCARD static QFunctionPointer resolve(const QString &library, const QByteArray &function);
|
||||
Q_NODISCARD static QFunctionPointer resolve(const QString &library, const QString &function);
|
||||
|
||||
|
|
|
@ -96,7 +96,6 @@ FRAMELESSHELPER_CORE_API void showSystemMenu(
|
|||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeight(const WId windowId, const bool scaled);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId windowId,
|
||||
const bool scaled);
|
||||
FRAMELESSHELPER_CORE_API void updateWindowFrameBorderColor(const WId windowId, const bool dark);
|
||||
FRAMELESSHELPER_CORE_API void maybeFixupQtInternals(const WId windowId);
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isWindowFrameBorderVisible();
|
||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool isFrameBorderColorized();
|
||||
|
@ -115,6 +114,7 @@ FRAMELESSHELPER_CORE_API void forceSquareCornersForWindow(const WId windowId, co
|
|||
FRAMELESSHELPER_CORE_API void disableOriginalTitleBarFunctionalities
|
||||
(const WId windowId, const bool disable = true);
|
||||
FRAMELESSHELPER_CORE_API void setQtDarkModeAwareEnabled(const bool enable);
|
||||
FRAMELESSHELPER_CORE_API void refreshWin32ThemeResources(const WId windowId, const bool dark);
|
||||
#endif // Q_OS_WINDOWS
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
|
|
|
@ -40,10 +40,10 @@ function(setup_compile_params arg_target)
|
|||
)
|
||||
if(WIN32) # Needed by both MSVC and MinGW
|
||||
set(_WIN32_WINNT_WIN10 0x0A00)
|
||||
set(NTDDI_WIN10_CO 0x0A00000B)
|
||||
set(NTDDI_WIN10_NI 0x0A00000C)
|
||||
target_compile_definitions(${arg_target} PRIVATE
|
||||
WINVER=${_WIN32_WINNT_WIN10} _WIN32_WINNT=${_WIN32_WINNT_WIN10}
|
||||
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_CO}
|
||||
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_NI}
|
||||
)
|
||||
endif()
|
||||
if(MSVC)
|
||||
|
|
|
@ -41,9 +41,6 @@ Q_LOGGING_CATEGORY(lcFramelessHelperQt, "wangwenx190.framelesshelper.core.impl.q
|
|||
|
||||
using namespace Global;
|
||||
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontOverrideCursorVar, "FRAMELESSHELPER_DONT_OVERRIDE_CURSOR")
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontToggleMaximizeVar, "FRAMELESSHELPER_DONT_TOGGLE_MAXIMIZE")
|
||||
|
||||
struct QtHelperData
|
||||
{
|
||||
SystemParameters params = {};
|
||||
|
|
|
@ -72,8 +72,6 @@ FRAMELESSHELPER_STRING_CONSTANT(SetWindowPos)
|
|||
FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontOverrideCursorVar, "FRAMELESSHELPER_DONT_OVERRIDE_CURSOR")
|
||||
FRAMELESSHELPER_BYTEARRAY_CONSTANT2(DontToggleMaximizeVar, "FRAMELESSHELPER_DONT_TOGGLE_MAXIMIZE")
|
||||
FRAMELESSHELPER_STRING_CONSTANT(DestroyWindow)
|
||||
[[maybe_unused]] static constexpr const char kFallbackTitleBarErrorMessage[] =
|
||||
"FramelessHelper is unable to create the fallback title bar window, and thus the snap layout feature will be disabled"
|
||||
|
@ -524,15 +522,15 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms)
|
|||
if (WindowsVersionHelper::isWin10RS1OrGreater()) {
|
||||
// Tell DWM we may need dark theme non-client area (title bar & frame border).
|
||||
FramelessHelper::Core::setApplicationOSThemeAware();
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||
if (WindowsVersionHelper::isWin10RS5OrGreater()) {
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
static const bool isQtQuickApplication = (params.getCurrentApplicationType() == ApplicationType::Quick);
|
||||
if (isQtQuickApplication) {
|
||||
// Tell UXTheme we may need dark theme controls.
|
||||
// Causes some QtWidgets paint incorrectly, so only apply to Qt Quick applications.
|
||||
Utils::updateGlobalWin32ControlsTheme(windowId, dark);
|
||||
}
|
||||
Utils::refreshWin32ThemeResources(windowId, dark);
|
||||
if (WindowsVersionHelper::isWin11OrGreater()) {
|
||||
const FramelessConfig * const config = FramelessConfig::instance();
|
||||
// Set the frame corner style, only Win11 provides official public API to do it.
|
||||
|
@ -1199,16 +1197,14 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
|||
if ((wParam == 0) && (lParam != 0) // lParam sometimes may be NULL.
|
||||
&& (std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), kThemeSettingChangeEventName) == 0)) {
|
||||
systemThemeChanged = true;
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
Utils::updateWindowFrameBorderColor(windowId, dark);
|
||||
#endif
|
||||
if (WindowsVersionHelper::isWin10RS5OrGreater()) {
|
||||
const bool dark = Utils::shouldAppsUseDarkMode();
|
||||
static const bool isQtQuickApplication = (data.params.getCurrentApplicationType() == ApplicationType::Quick);
|
||||
if (isQtQuickApplication) {
|
||||
// Causes some QtWidgets paint incorrectly, so only apply to Qt Quick applications.
|
||||
Utils::updateGlobalWin32ControlsTheme(windowId, dark);
|
||||
}
|
||||
Utils::refreshWin32ThemeResources(windowId, dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,20 @@ SysApiLoader *SysApiLoader::instance()
|
|||
return g_sysApiLoader();
|
||||
}
|
||||
|
||||
QFunctionPointer SysApiLoader::resolve(const QString &library, const char *function)
|
||||
{
|
||||
Q_ASSERT(!library.isEmpty());
|
||||
Q_ASSERT(function);
|
||||
if (library.isEmpty() || !function) {
|
||||
return nullptr;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return QSystemLibrary::resolve(library, function);
|
||||
#else
|
||||
return QLibrary::resolve(library, function.constData());
|
||||
#endif
|
||||
}
|
||||
|
||||
QFunctionPointer SysApiLoader::resolve(const QString &library, const QByteArray &function)
|
||||
{
|
||||
Q_ASSERT(!library.isEmpty());
|
||||
|
@ -57,11 +71,7 @@ QFunctionPointer SysApiLoader::resolve(const QString &library, const QByteArray
|
|||
if (library.isEmpty() || function.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
#ifdef Q_OS_WINDOWS
|
||||
return QSystemLibrary::resolve(library, function.constData());
|
||||
#else
|
||||
return QLibrary::resolve(library, function.constData());
|
||||
#endif
|
||||
return SysApiLoader::resolve(library, function.constData());
|
||||
}
|
||||
|
||||
QFunctionPointer SysApiLoader::resolve(const QString &library, const QString &function)
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
*/
|
||||
|
||||
#include "utils.h"
|
||||
#ifdef Q_OS_WINDOWS
|
||||
# include "winverhelper_p.h"
|
||||
#endif
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qscreen.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
|
@ -140,8 +143,7 @@ QString Utils::getSystemButtonIconCode(const SystemButtonType button)
|
|||
// Windows 11: Segoe Fluent Icons (https://docs.microsoft.com/en-us/windows/apps/design/style/segoe-fluent-icons-font)
|
||||
// Windows 10: Segoe MDL2 Assets (https://docs.microsoft.com/en-us/windows/apps/design/style/segoe-ui-symbol-font)
|
||||
// Windows 7~8.1: Micon (http://xtoolkit.github.io/Micon/)
|
||||
static const bool isWin10OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1507);
|
||||
if (isWin10OrGreater) {
|
||||
if (WindowsVersionHelper::isWin10OrGreater()) {
|
||||
return QChar(icon.segoe);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -42,9 +42,48 @@
|
|||
#include "sysapiloader_p.h"
|
||||
#include "registrykey_p.h"
|
||||
#include "winverhelper_p.h"
|
||||
#include <uxtheme.h>
|
||||
#include <d2d1.h>
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
GetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvData)
|
||||
{
|
||||
Q_ASSERT(hWnd);
|
||||
Q_ASSERT(pvData);
|
||||
if (!hWnd || !pvData) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(user32)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(GetWindowCompositionAttribute)
|
||||
const auto loader = SysApiLoader::instance();
|
||||
if (!loader->isAvailable(kuser32, kGetWindowCompositionAttribute)) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return (loader->get<GetWindowCompositionAttributePtr>(kGetWindowCompositionAttribute))(hWnd, pvData);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
SetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvData)
|
||||
{
|
||||
Q_ASSERT(hWnd);
|
||||
Q_ASSERT(pvData);
|
||||
if (!hWnd || !pvData) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(user32)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(SetWindowCompositionAttribute)
|
||||
const auto loader = SysApiLoader::instance();
|
||||
if (!loader->isAvailable(kuser32, kSetWindowCompositionAttribute)) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return (loader->get<SetWindowCompositionAttributePtr>(kSetWindowCompositionAttribute))(hWnd, pvData);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API HRESULT WINAPI
|
||||
SetWindowThemeAttribute2(const HWND hWnd, const _WINDOWTHEMEATTRIBUTETYPE attrib,
|
||||
PVOID pvData, const DWORD cbData
|
||||
|
@ -55,13 +94,14 @@ SetWindowThemeAttribute2(const HWND hWnd, const _WINDOWTHEMEATTRIBUTETYPE attrib
|
|||
if (!hWnd || !pvData) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(SetWindowThemeAttribute)
|
||||
const auto loader = FRAMELESSHELPER_PREPEND_NAMESPACE(SysApiLoader)::instance();
|
||||
const auto loader = SysApiLoader::instance();
|
||||
if (!loader->isAvailable(kuxtheme, kSetWindowThemeAttribute)) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
return (loader->get<decltype(&::SetWindowThemeAttribute2)>(kSetWindowThemeAttribute))(hWnd, attrib, pvData, cbData);
|
||||
return (loader->get<decltype(&SetWindowThemeAttribute2)>(kSetWindowThemeAttribute))(hWnd, attrib, pvData, cbData);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API HRESULT WINAPI
|
||||
|
@ -73,6 +113,187 @@ SetWindowThemeNonClientAttributes2(const HWND hWnd, const DWORD dwMask, const DW
|
|||
return SetWindowThemeAttribute2(hWnd, _WTA_NONCLIENT, &options, sizeof(options));
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
ShouldAppsUseDarkMode(VOID)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pShouldAppsUseDarkMode
|
||||
= reinterpret_cast<ShouldAppsUseDarkModePtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(132)));
|
||||
if (!pShouldAppsUseDarkMode) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pShouldAppsUseDarkMode();
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
AllowDarkModeForWindow(const HWND hWnd, const BOOL bAllow)
|
||||
{
|
||||
Q_ASSERT(hWnd);
|
||||
if (!hWnd) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pAllowDarkModeForWindow
|
||||
= reinterpret_cast<AllowDarkModeForWindowPtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(133)));
|
||||
if (!pAllowDarkModeForWindow) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pAllowDarkModeForWindow(hWnd, bAllow);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
AllowDarkModeForApp(const BOOL bAllow)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pAllowDarkModeForApp
|
||||
= reinterpret_cast<AllowDarkModeForAppPtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135)));
|
||||
if (!pAllowDarkModeForApp) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pAllowDarkModeForApp(bAllow);
|
||||
}
|
||||
|
||||
EXTERN_C FRAMELESSHELPER_CORE_API VOID WINAPI
|
||||
FlushMenuThemes(VOID)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pFlushMenuThemes
|
||||
= reinterpret_cast<FlushMenuThemesPtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(136)));
|
||||
if (!pFlushMenuThemes) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return;
|
||||
}
|
||||
pFlushMenuThemes();
|
||||
}
|
||||
|
||||
EXTERN_C FRAMELESSHELPER_CORE_API VOID WINAPI
|
||||
RefreshImmersiveColorPolicyState(VOID)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pRefreshImmersiveColorPolicyState
|
||||
= reinterpret_cast<RefreshImmersiveColorPolicyStatePtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(104)));
|
||||
if (!pRefreshImmersiveColorPolicyState) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return;
|
||||
}
|
||||
pRefreshImmersiveColorPolicyState();
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
IsDarkModeAllowedForWindow(const HWND hWnd)
|
||||
{
|
||||
Q_ASSERT(hWnd);
|
||||
if (!hWnd) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pIsDarkModeAllowedForWindow
|
||||
= reinterpret_cast<IsDarkModeAllowedForWindowPtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(137)));
|
||||
if (!pIsDarkModeAllowedForWindow) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pIsDarkModeAllowedForWindow(hWnd);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
GetIsImmersiveColorUsingHighContrast(const IMMERSIVE_HC_CACHE_MODE mode)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pGetIsImmersiveColorUsingHighContrast
|
||||
= reinterpret_cast<GetIsImmersiveColorUsingHighContrastPtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(106)));
|
||||
if (!pGetIsImmersiveColorUsingHighContrast) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pGetIsImmersiveColorUsingHighContrast(mode);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API HTHEME WINAPI
|
||||
OpenNcThemeData(const HWND hWnd, LPCWSTR pszClassList)
|
||||
{
|
||||
Q_ASSERT(hWnd);
|
||||
Q_ASSERT(pszClassList);
|
||||
if (!hWnd || !pszClassList) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pOpenNcThemeData
|
||||
= reinterpret_cast<OpenNcThemeDataPtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(49)));
|
||||
if (!pOpenNcThemeData) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pOpenNcThemeData(hWnd, pszClassList);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
ShouldSystemUseDarkMode(VOID)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pShouldSystemUseDarkMode
|
||||
= reinterpret_cast<ShouldSystemUseDarkModePtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(138)));
|
||||
if (!pShouldSystemUseDarkMode) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pShouldSystemUseDarkMode();
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API PREFERRED_APP_MODE WINAPI
|
||||
SetPreferredAppMode(const PREFERRED_APP_MODE mode)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pSetPreferredAppMode
|
||||
= reinterpret_cast<SetPreferredAppModePtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135)));
|
||||
if (!pSetPreferredAppMode) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return PAM_MAX;
|
||||
}
|
||||
return pSetPreferredAppMode(mode);
|
||||
}
|
||||
|
||||
EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI
|
||||
IsDarkModeAllowedForApp(VOID)
|
||||
{
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
FRAMELESSHELPER_STRING_CONSTANT(uxtheme)
|
||||
static const auto pIsDarkModeAllowedForApp
|
||||
= reinterpret_cast<IsDarkModeAllowedForAppPtr>(
|
||||
SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(139)));
|
||||
if (!pIsDarkModeAllowedForApp) {
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
return pIsDarkModeAllowedForApp();
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QMargins)
|
||||
|
||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||
|
@ -169,6 +390,11 @@ FRAMELESSHELPER_STRING_CONSTANT(DeleteDC)
|
|||
FRAMELESSHELPER_STRING_CONSTANT(d2d1)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(D2D1CreateFactory)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(ReloadSystemMetrics)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(SetPreferredAppMode)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(AllowDarkModeForApp)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(AllowDarkModeForWindow)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(FlushMenuThemes)
|
||||
FRAMELESSHELPER_STRING_CONSTANT(RefreshImmersiveColorPolicyState)
|
||||
|
||||
struct Win32UtilsHelperData
|
||||
{
|
||||
|
@ -474,8 +700,7 @@ bool Utils::isWindowsVersionOrGreater(const WindowsVersion version)
|
|||
bool Utils::isDwmCompositionEnabled()
|
||||
{
|
||||
// DWM composition is always enabled and can't be disabled since Windows 8.
|
||||
static const bool isWin8OrGreater = isWindowsVersionOrGreater(WindowsVersion::_8);
|
||||
if (isWin8OrGreater) {
|
||||
if (WindowsVersionHelper::isWin8OrGreater()) {
|
||||
return true;
|
||||
}
|
||||
const auto resultFromRegistry = []() -> bool {
|
||||
|
@ -627,8 +852,7 @@ QColor Utils::getDwmColorizationColor()
|
|||
DwmColorizationArea Utils::getDwmColorizationArea()
|
||||
{
|
||||
// It's a Win10 only feature. (TO BE VERIFIED)
|
||||
static const bool isWin10OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1507);
|
||||
if (!isWin10OrGreater) {
|
||||
if (!WindowsVersionHelper::isWin10OrGreater()) {
|
||||
return DwmColorizationArea::None_;
|
||||
}
|
||||
const RegistryKey themeRegistry(RegistryRootKey::CurrentUser, personalizeRegistryKey());
|
||||
|
@ -1035,8 +1259,7 @@ quint32 Utils::getFrameBorderThickness(const WId windowId, const bool scaled)
|
|||
return 0;
|
||||
}
|
||||
// There's no window frame border before Windows 10.
|
||||
static const bool isWin10OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1507);
|
||||
if (!isWin10OrGreater) {
|
||||
if (!WindowsVersionHelper::isWin10OrGreater()) {
|
||||
return 0;
|
||||
}
|
||||
if (!API_DWM_AVAILABLE(DwmGetWindowAttribute)) {
|
||||
|
@ -1061,8 +1284,7 @@ QColor Utils::getFrameBorderColor(const bool active)
|
|||
{
|
||||
// There's no window frame border before Windows 10.
|
||||
// So we just return a default value which is based on most window managers.
|
||||
static const bool isWin10OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1507);
|
||||
if (!isWin10OrGreater) {
|
||||
if (!WindowsVersionHelper::isWin10OrGreater()) {
|
||||
return (active ? kDefaultBlackColor : kDefaultDarkGrayColor);
|
||||
}
|
||||
const bool dark = shouldAppsUseDarkMode();
|
||||
|
@ -1077,30 +1299,6 @@ QColor Utils::getFrameBorderColor(const bool active)
|
|||
}
|
||||
}
|
||||
|
||||
void Utils::updateWindowFrameBorderColor(const WId windowId, const bool dark)
|
||||
{
|
||||
Q_ASSERT(windowId);
|
||||
if (!windowId) {
|
||||
return;
|
||||
}
|
||||
// There's no global dark theme before Win10 1607.
|
||||
static const bool isWin10RS1OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1607);
|
||||
if (!isWin10RS1OrGreater) {
|
||||
return;
|
||||
}
|
||||
if (!API_DWM_AVAILABLE(DwmSetWindowAttribute)) {
|
||||
return;
|
||||
}
|
||||
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||
static const bool isWin1020H1OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_2004);
|
||||
const DWORD mode = (isWin1020H1OrGreater ? _DWMWA_USE_IMMERSIVE_DARK_MODE : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1);
|
||||
const BOOL value = (dark ? TRUE : FALSE);
|
||||
const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hwnd, mode, &value, sizeof(value));
|
||||
if (FAILED(hr)) {
|
||||
WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Utils::maybeFixupQtInternals(const WId windowId)
|
||||
{
|
||||
Q_ASSERT(windowId);
|
||||
|
@ -1216,8 +1414,7 @@ bool Utils::isWindowFrameBorderVisible()
|
|||
if (config->isSet(Option::ForceHideWindowFrameBorder)) {
|
||||
return false;
|
||||
}
|
||||
static const bool isWin10OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1507);
|
||||
return isWin10OrGreater;
|
||||
return WindowsVersionHelper::isWin10OrGreater();
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
@ -1225,8 +1422,7 @@ bool Utils::isWindowFrameBorderVisible()
|
|||
bool Utils::isTitleBarColorized()
|
||||
{
|
||||
// CHECK: is it supported on win7?
|
||||
static const bool isWin10OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1507);
|
||||
if (!isWin10OrGreater) {
|
||||
if (!WindowsVersionHelper::isWin10OrGreater()) {
|
||||
return false;
|
||||
}
|
||||
const DwmColorizationArea area = getDwmColorizationArea();
|
||||
|
@ -1407,8 +1603,7 @@ SystemTheme Utils::getSystemTheme()
|
|||
if (isHighContrastModeEnabled()) {
|
||||
return SystemTheme::HighContrast;
|
||||
}
|
||||
static const bool isWin10RS1OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1607);
|
||||
if (isWin10RS1OrGreater && shouldAppsUseDarkMode()) {
|
||||
if (WindowsVersionHelper::isWin10RS1OrGreater() && shouldAppsUseDarkMode()) {
|
||||
return SystemTheme::Dark;
|
||||
}
|
||||
return SystemTheme::Light;
|
||||
|
@ -1421,8 +1616,7 @@ void Utils::updateGlobalWin32ControlsTheme(const WId windowId, const bool dark)
|
|||
return;
|
||||
}
|
||||
// There's no global dark theme for common Win32 controls before Win10 1809.
|
||||
static const bool isWin10RS5OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1809);
|
||||
if (!isWin10RS5OrGreater) {
|
||||
if (!WindowsVersionHelper::isWin10RS5OrGreater()) {
|
||||
return;
|
||||
}
|
||||
if (!API_THEME_AVAILABLE(SetWindowTheme)) {
|
||||
|
@ -1439,8 +1633,7 @@ void Utils::updateGlobalWin32ControlsTheme(const WId windowId, const bool dark)
|
|||
bool Utils::shouldAppsUseDarkMode_windows()
|
||||
{
|
||||
// The global dark mode was first introduced in Windows 10 1607.
|
||||
static const bool isWin10RS1OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1607);
|
||||
if (!isWin10RS1OrGreater) {
|
||||
if (!WindowsVersionHelper::isWin10RS1OrGreater()) {
|
||||
return false;
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
|
@ -1486,8 +1679,7 @@ void Utils::forceSquareCornersForWindow(const WId windowId, const bool force)
|
|||
return;
|
||||
}
|
||||
// We cannot change the window corner style until Windows 11.
|
||||
static const bool isWin11OrGreater = isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
|
||||
if (!isWin11OrGreater) {
|
||||
if (!WindowsVersionHelper::isWin11OrGreater()) {
|
||||
return;
|
||||
}
|
||||
if (!API_DWM_AVAILABLE(DwmSetWindowAttribute)) {
|
||||
|
@ -1508,44 +1700,34 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
|
|||
return false;
|
||||
}
|
||||
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||
static const bool isWin8OrGreater = isWindowsVersionOrGreater(WindowsVersion::_8);
|
||||
if (isWin8OrGreater) {
|
||||
if (!API_USER_AVAILABLE(SetWindowCompositionAttribute)) {
|
||||
return false;
|
||||
}
|
||||
if (WindowsVersionHelper::isWin8OrGreater()) {
|
||||
if (!API_DWM_AVAILABLE(DwmSetWindowAttribute)) {
|
||||
return false;
|
||||
}
|
||||
if (!API_DWM_AVAILABLE(DwmExtendFrameIntoClientArea)) {
|
||||
return false;
|
||||
}
|
||||
const auto pSetWindowCompositionAttribute =
|
||||
reinterpret_cast<SetWindowCompositionAttributePtr>(
|
||||
SysApiLoader::instance()->get(kSetWindowCompositionAttribute));
|
||||
static const bool isWin1122H2OrGreater = isWindowsVersionOrGreater(WindowsVersion::_11_22H2);
|
||||
static const bool isWin11OrGreater = isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
|
||||
static const bool isWin10OrGreater = isWindowsVersionOrGreater(WindowsVersion::_10_1507);
|
||||
const BlurMode blurMode = [mode]() -> BlurMode {
|
||||
if ((mode == BlurMode::Disable) || (mode == BlurMode::Windows_Aero)) {
|
||||
return mode;
|
||||
}
|
||||
if ((mode == BlurMode::Windows_Mica) && !isWin11OrGreater) {
|
||||
if ((mode == BlurMode::Windows_Mica) && !WindowsVersionHelper::isWin11OrGreater()) {
|
||||
WARNING << "The Mica material is not supported on your system, fallback to the Acrylic blur instead...";
|
||||
if (isWin10OrGreater) {
|
||||
if (WindowsVersionHelper::isWin10OrGreater()) {
|
||||
return BlurMode::Windows_Acrylic;
|
||||
}
|
||||
WARNING << "The Acrylic blur is not supported on your system, fallback to the traditional DWM blur instead...";
|
||||
return BlurMode::Windows_Aero;
|
||||
}
|
||||
if ((mode == BlurMode::Windows_Acrylic) && !isWin10OrGreater) {
|
||||
if ((mode == BlurMode::Windows_Acrylic) && !WindowsVersionHelper::isWin10OrGreater()) {
|
||||
WARNING << "The Acrylic blur is not supported on your system, fallback to the traditional DWM blur instead...";
|
||||
return BlurMode::Windows_Aero;
|
||||
}
|
||||
if (mode == BlurMode::Default) {
|
||||
if (isWin11OrGreater) {
|
||||
if (WindowsVersionHelper::isWin11OrGreater()) {
|
||||
return BlurMode::Windows_Mica;
|
||||
}
|
||||
if (isWin10OrGreater) {
|
||||
if (WindowsVersionHelper::isWin10OrGreater()) {
|
||||
return BlurMode::Windows_Acrylic;
|
||||
}
|
||||
return BlurMode::Windows_Aero;
|
||||
|
@ -1554,7 +1736,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
|
|||
return mode;
|
||||
}();
|
||||
if (blurMode == BlurMode::Disable) {
|
||||
if (isWin1122H2OrGreater) {
|
||||
if (WindowsVersionHelper::isWin1122H2OrGreater()) {
|
||||
const _DWM_SYSTEMBACKDROP_TYPE dwmsbt = _DWMSBT_NONE;
|
||||
const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute,
|
||||
hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &dwmsbt, sizeof(dwmsbt));
|
||||
|
@ -1562,7 +1744,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
|
|||
WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr);
|
||||
}
|
||||
}
|
||||
if (isWin11OrGreater) {
|
||||
if (WindowsVersionHelper::isWin11OrGreater()) {
|
||||
const BOOL enable = FALSE;
|
||||
HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute,
|
||||
hwnd, _DWMWA_MICA_EFFECT, &enable, sizeof(enable));
|
||||
|
@ -1583,7 +1765,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
|
|||
wcad.Attrib = WCA_ACCENT_POLICY;
|
||||
wcad.pvData = &policy;
|
||||
wcad.cbData = sizeof(policy);
|
||||
if (pSetWindowCompositionAttribute(hwnd, &wcad) == FALSE) {
|
||||
if (SetWindowCompositionAttribute(hwnd, &wcad) == FALSE) {
|
||||
WARNING << getSystemErrorMessage(kSetWindowCompositionAttribute);
|
||||
}
|
||||
}
|
||||
|
@ -1597,7 +1779,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
|
|||
const MARGINS margins = {-1, -1, -1, -1};
|
||||
HRESULT hr = API_CALL_FUNCTION(DwmExtendFrameIntoClientArea, hwnd, &margins);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (isWin1122H2OrGreater) {
|
||||
if (WindowsVersionHelper::isWin1122H2OrGreater()) {
|
||||
const _DWM_SYSTEMBACKDROP_TYPE dwmsbt = _DWMSBT_MAINWINDOW; // Mica
|
||||
hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hwnd,
|
||||
_DWMWA_SYSTEMBACKDROP_TYPE, &dwmsbt, sizeof(dwmsbt));
|
||||
|
@ -1646,8 +1828,8 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode,
|
|||
wcad.Attrib = WCA_ACCENT_POLICY;
|
||||
wcad.pvData = &policy;
|
||||
wcad.cbData = sizeof(policy);
|
||||
if (pSetWindowCompositionAttribute(hwnd, &wcad) != FALSE) {
|
||||
if (!isWin11OrGreater) {
|
||||
if (SetWindowCompositionAttribute(hwnd, &wcad) != FALSE) {
|
||||
if (!WindowsVersionHelper::isWin11OrGreater()) {
|
||||
DEBUG << "Enabling the Acrylic blur for Win32 windows on Windows 10 "
|
||||
"is very buggy. The only recommended way by Microsoft is to "
|
||||
"use the XAML Island technology or use pure UWP instead. If "
|
||||
|
@ -1749,8 +1931,7 @@ bool Utils::isBlurBehindWindowSupported()
|
|||
if (FramelessConfig::instance()->isSet(Option::ForceNonNativeBackgroundBlur)) {
|
||||
return false;
|
||||
}
|
||||
static const bool isWin11OrGreater = isWindowsVersionOrGreater(WindowsVersion::_11_21H2);
|
||||
return isWin11OrGreater;
|
||||
return WindowsVersionHelper::isWin11OrGreater();
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
@ -1817,4 +1998,98 @@ void Utils::registerThemeChangeNotification()
|
|||
// top level windows by default.
|
||||
}
|
||||
|
||||
void Utils::refreshWin32ThemeResources(const WId windowId, const bool dark)
|
||||
{
|
||||
Q_ASSERT(windowId);
|
||||
if (!windowId) {
|
||||
return;
|
||||
}
|
||||
// We have no way to adjust such things until Win10 1809.
|
||||
if (!WindowsVersionHelper::isWin10RS5OrGreater()) {
|
||||
return;
|
||||
}
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
if (!API_DWM_AVAILABLE(DwmSetWindowAttribute)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
const auto hWnd = reinterpret_cast<HWND>(windowId);
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
const DWORD borderFlag = (WindowsVersionHelper::isWin1020H1OrGreater()
|
||||
? _DWMWA_USE_IMMERSIVE_DARK_MODE : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1);
|
||||
#endif
|
||||
const PREFERRED_APP_MODE appMode = (dark ? PAM_ALLOW_DARK : PAM_DEFAULT);
|
||||
const BOOL darkFlag = (dark ? TRUE : FALSE);
|
||||
WINDOWCOMPOSITIONATTRIBDATA wcad;
|
||||
SecureZeroMemory(&wcad, sizeof(wcad));
|
||||
wcad.Attrib = WCA_USEDARKMODECOLORS;
|
||||
wcad.pvData = const_cast<BOOL *>(&darkFlag);
|
||||
wcad.cbData = sizeof(darkFlag);
|
||||
if (dark) {
|
||||
if (WindowsVersionHelper::isWin1019H1OrGreater()) {
|
||||
if (SetPreferredAppMode(appMode) == PAM_MAX) {
|
||||
WARNING << getSystemErrorMessage(kSetPreferredAppMode);
|
||||
}
|
||||
} else {
|
||||
if (AllowDarkModeForApp(darkFlag) == FALSE) {
|
||||
WARNING << getSystemErrorMessage(kAllowDarkModeForApp);
|
||||
}
|
||||
}
|
||||
if (AllowDarkModeForWindow(hWnd, darkFlag) == FALSE) {
|
||||
WARNING << getSystemErrorMessage(kAllowDarkModeForWindow);
|
||||
}
|
||||
if (SetWindowCompositionAttribute(hWnd, &wcad) == FALSE) {
|
||||
WARNING << getSystemErrorMessage(kSetWindowCompositionAttribute);
|
||||
}
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hWnd, borderFlag, &darkFlag, sizeof(darkFlag));
|
||||
if (FAILED(hr)) {
|
||||
WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr);
|
||||
}
|
||||
#endif
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
FlushMenuThemes();
|
||||
if (GetLastError() != ERROR_SUCCESS) {
|
||||
WARNING << getSystemErrorMessage(kFlushMenuThemes);
|
||||
}
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
RefreshImmersiveColorPolicyState();
|
||||
if (GetLastError() != ERROR_SUCCESS) {
|
||||
WARNING << getSystemErrorMessage(kRefreshImmersiveColorPolicyState);
|
||||
}
|
||||
} else {
|
||||
if (AllowDarkModeForWindow(hWnd, darkFlag) == FALSE) {
|
||||
WARNING << getSystemErrorMessage(kAllowDarkModeForWindow);
|
||||
}
|
||||
if (SetWindowCompositionAttribute(hWnd, &wcad) == FALSE) {
|
||||
WARNING << getSystemErrorMessage(kSetWindowCompositionAttribute);
|
||||
}
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hWnd, borderFlag, &darkFlag, sizeof(darkFlag));
|
||||
if (FAILED(hr)) {
|
||||
WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr);
|
||||
}
|
||||
#endif
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
FlushMenuThemes();
|
||||
if (GetLastError() != ERROR_SUCCESS) {
|
||||
WARNING << getSystemErrorMessage(kFlushMenuThemes);
|
||||
}
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
RefreshImmersiveColorPolicyState();
|
||||
if (GetLastError() != ERROR_SUCCESS) {
|
||||
WARNING << getSystemErrorMessage(kRefreshImmersiveColorPolicyState);
|
||||
}
|
||||
if (WindowsVersionHelper::isWin1019H1OrGreater()) {
|
||||
if (SetPreferredAppMode(appMode) == PAM_MAX) {
|
||||
WARNING << getSystemErrorMessage(kSetPreferredAppMode);
|
||||
}
|
||||
} else {
|
||||
if (AllowDarkModeForApp(darkFlag) == FALSE) {
|
||||
WARNING << getSystemErrorMessage(kAllowDarkModeForApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FRAMELESSHELPER_END_NAMESPACE
|
||||
|
|
|
@ -29,14 +29,14 @@ target_sources(${PROJECT_NAME} PRIVATE
|
|||
)
|
||||
|
||||
set(_WIN32_WINNT_WIN10 0x0A00)
|
||||
set(NTDDI_WIN10_CO 0x0A00000B)
|
||||
set(NTDDI_WIN10_NI 0x0A00000C)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
_CRT_NON_CONFORMING_SWPRINTFS _CRT_SECURE_NO_WARNINGS
|
||||
_CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS
|
||||
_CRT_NONSTDC_NO_DEPRECATE _ENABLE_EXTENDED_ALIGNED_STORAGE
|
||||
NOMINMAX UNICODE _UNICODE WIN32_LEAN_AND_MEAN WINRT_LEAN_AND_MEAN
|
||||
WINVER=${_WIN32_WINNT_WIN10} _WIN32_WINNT=${_WIN32_WINNT_WIN10}
|
||||
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_CO}
|
||||
_WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_NI}
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
|
|
Loading…
Reference in New Issue