5#ifndef QWKWINDOWSEXTRA_P_H
6#define QWKWINDOWSEXTRA_P_H
19#include <QWKCore/qwindowkit_windows.h>
21#include <QtGui/QGuiApplication>
22#include <QtGui/QStyleHints>
23#include <QtGui/QPalette>
25#include <QtCore/private/qsystemlibrary_p.h>
29typedef struct _MARGINS
37typedef enum MONITOR_DPI_TYPE {
38 MDT_EFFECTIVE_DPI = 0,
41 MDT_DEFAULT = MDT_EFFECTIVE_DPI
44typedef struct _DWM_BLURBEHIND
49 BOOL fTransitionOnMaximized;
50} DWM_BLURBEHIND, *PDWM_BLURBEHIND;
53 UINT WINAPI GetDpiForWindow(HWND);
54 UINT WINAPI GetDpiForSystem();
55 int WINAPI GetSystemMetricsForDpi(
int, UINT);
56 BOOL WINAPI AdjustWindowRectExForDpi(LPRECT, DWORD, BOOL, DWORD, UINT);
57 HRESULT WINAPI GetDpiForMonitor(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *);
58 HRESULT WINAPI DwmFlush();
59 HRESULT WINAPI DwmIsCompositionEnabled(BOOL*);
60 HRESULT WINAPI DwmGetWindowAttribute(HWND, DWORD, PVOID, DWORD);
61 HRESULT WINAPI DwmSetWindowAttribute(HWND, DWORD, LPCVOID, DWORD);
62 HRESULT WINAPI DwmExtendFrameIntoClientArea(HWND,
const MARGINS*);
63 HRESULT WINAPI DwmEnableBlurBehindWindow(HWND,
const DWM_BLURBEHIND*);
68 enum _DWMWINDOWATTRIBUTE {
70 _DWMWA_USE_HOSTBACKDROPBRUSH = 17,
74 _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19,
78 _DWMWA_USE_IMMERSIVE_DARK_MODE = 20,
81 _DWMWA_WINDOW_CORNER_PREFERENCE = 33,
84 _DWMWA_BORDER_COLOR = 34,
87 _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37,
91 _DWMWA_SYSTEMBACKDROP_TYPE = 38,
95 _DWMWA_MICA_EFFECT = 1029
99 enum _DWM_SYSTEMBACKDROP_TYPE {
105 _DWMSBT_TRANSIENTWINDOW,
107 _DWMSBT_TABBEDWINDOW,
111 enum WINDOWCOMPOSITIONATTRIB {
113 WCA_NCRENDERING_ENABLED = 1,
114 WCA_NCRENDERING_POLICY = 2,
115 WCA_TRANSITIONS_FORCEDISABLED = 3,
116 WCA_ALLOW_NCPAINT = 4,
117 WCA_CAPTION_BUTTON_BOUNDS = 5,
118 WCA_NONCLIENT_RTL_LAYOUT = 6,
119 WCA_FORCE_ICONIC_REPRESENTATION = 7,
120 WCA_EXTENDED_FRAME_BOUNDS = 8,
121 WCA_HAS_ICONIC_BITMAP = 9,
122 WCA_THEME_ATTRIBUTES = 10,
123 WCA_NCRENDERING_EXILED = 11,
124 WCA_NCADORNMENTINFO = 12,
125 WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
126 WCA_VIDEO_OVERLAY_ACTIVE = 14,
127 WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
128 WCA_DISALLOW_PEEK = 16,
131 WCA_ACCENT_POLICY = 19,
132 WCA_FREEZE_REPRESENTATION = 20,
133 WCA_EVER_UNCLOAKED = 21,
134 WCA_VISUAL_OWNER = 22,
135 WCA_HOLOGRAPHIC = 23,
136 WCA_EXCLUDED_FROM_DDA = 24,
137 WCA_PASSIVEUPDATEMODE = 25,
138 WCA_USEDARKMODECOLORS = 26,
139 WCA_CORNER_STYLE = 27,
141 WCA_DISABLE_MOVESIZE_FEEDBACK = 29,
147 ACCENT_ENABLE_GRADIENT = 1,
148 ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
149 ACCENT_ENABLE_BLURBEHIND = 3,
150 ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
151 ACCENT_ENABLE_HOST_BACKDROP = 5,
152 ACCENT_INVALID_STATE = 6
157 ACCENT_ENABLE_ACRYLIC = 1,
158 ACCENT_ENABLE_ACRYLIC_WITH_LUMINOSITY = 482
161 struct ACCENT_POLICY {
164 DWORD dwGradientColor;
167 using PACCENT_POLICY = ACCENT_POLICY *;
169 struct WINDOWCOMPOSITIONATTRIBDATA {
170 WINDOWCOMPOSITIONATTRIB Attrib;
174 using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *;
176 enum PREFERRED_APP_MODE {
187 using SetWindowCompositionAttributePtr = BOOL(WINAPI *)(HWND, PWINDOWCOMPOSITIONATTRIBDATA);
190 using RefreshImmersiveColorPolicyStatePtr = VOID(WINAPI *)(VOID);
191 using AllowDarkModeForWindowPtr = BOOL(WINAPI *)(HWND, BOOL);
192 using AllowDarkModeForAppPtr = BOOL(WINAPI *)(BOOL);
193 using FlushMenuThemesPtr = VOID(WINAPI *)(VOID);
195 using SetPreferredAppModePtr = PREFERRED_APP_MODE(WINAPI *)(PREFERRED_APP_MODE);
200 static inline const DynamicApis &instance() {
201 static const DynamicApis inst;
205#define DYNAMIC_API_DECLARE(NAME) decltype(&::NAME) p##NAME = nullptr
207 DYNAMIC_API_DECLARE(DwmFlush);
208 DYNAMIC_API_DECLARE(DwmIsCompositionEnabled);
209 DYNAMIC_API_DECLARE(DwmGetWindowAttribute);
210 DYNAMIC_API_DECLARE(DwmSetWindowAttribute);
211 DYNAMIC_API_DECLARE(DwmExtendFrameIntoClientArea);
212 DYNAMIC_API_DECLARE(DwmEnableBlurBehindWindow);
213 DYNAMIC_API_DECLARE(GetDpiForWindow);
214 DYNAMIC_API_DECLARE(GetDpiForSystem);
215 DYNAMIC_API_DECLARE(GetSystemMetricsForDpi);
216 DYNAMIC_API_DECLARE(AdjustWindowRectExForDpi);
217 DYNAMIC_API_DECLARE(GetDpiForMonitor);
219#undef DYNAMIC_API_DECLARE
221 SetWindowCompositionAttributePtr pSetWindowCompositionAttribute =
nullptr;
222 RefreshImmersiveColorPolicyStatePtr pRefreshImmersiveColorPolicyState =
nullptr;
223 AllowDarkModeForWindowPtr pAllowDarkModeForWindow =
nullptr;
224 AllowDarkModeForAppPtr pAllowDarkModeForApp =
nullptr;
225 FlushMenuThemesPtr pFlushMenuThemes =
nullptr;
226 SetPreferredAppModePtr pSetPreferredAppMode =
nullptr;
229 inline DynamicApis() {
230#define DYNAMIC_API_RESOLVE(DLL, NAME) \
231 p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(#NAME))
233 QSystemLibrary user32(QStringLiteral(
"user32"));
234 DYNAMIC_API_RESOLVE(user32, GetDpiForWindow);
235 DYNAMIC_API_RESOLVE(user32, GetDpiForSystem);
236 DYNAMIC_API_RESOLVE(user32, GetSystemMetricsForDpi);
237 DYNAMIC_API_RESOLVE(user32, SetWindowCompositionAttribute);
238 DYNAMIC_API_RESOLVE(user32, AdjustWindowRectExForDpi);
240 QSystemLibrary shcore(QStringLiteral(
"shcore"));
241 DYNAMIC_API_RESOLVE(shcore, GetDpiForMonitor);
243 QSystemLibrary dwmapi(QStringLiteral(
"dwmapi"));
244 DYNAMIC_API_RESOLVE(dwmapi, DwmFlush);
245 DYNAMIC_API_RESOLVE(dwmapi, DwmIsCompositionEnabled);
246 DYNAMIC_API_RESOLVE(dwmapi, DwmGetWindowAttribute);
247 DYNAMIC_API_RESOLVE(dwmapi, DwmSetWindowAttribute);
248 DYNAMIC_API_RESOLVE(dwmapi, DwmExtendFrameIntoClientArea);
249 DYNAMIC_API_RESOLVE(dwmapi, DwmEnableBlurBehindWindow);
251#undef DYNAMIC_API_RESOLVE
253#define UNDOC_API_RESOLVE(DLL, NAME, ORDINAL) \
254 p##NAME = reinterpret_cast<decltype(p##NAME)>(DLL.resolve(MAKEINTRESOURCEA(ORDINAL)))
256 QSystemLibrary uxtheme(QStringLiteral(
"uxtheme"));
257 UNDOC_API_RESOLVE(uxtheme, RefreshImmersiveColorPolicyState, 104);
258 UNDOC_API_RESOLVE(uxtheme, AllowDarkModeForWindow, 133);
259 UNDOC_API_RESOLVE(uxtheme, AllowDarkModeForApp, 135);
260 UNDOC_API_RESOLVE(uxtheme, FlushMenuThemes, 136);
261 UNDOC_API_RESOLVE(uxtheme, SetPreferredAppMode, 135);
263#undef UNDOC_API_RESOLVE
266 inline ~DynamicApis() =
default;
268 Q_DISABLE_COPY(DynamicApis)
273 inline constexpr bool operator==(
const POINT &lhs,
const POINT &rhs)
noexcept {
274 return ((lhs.x == rhs.x) && (lhs.y == rhs.y));
277 inline constexpr bool operator!=(
const POINT &lhs,
const POINT &rhs)
noexcept {
278 return !operator==(lhs, rhs);
281 inline constexpr bool operator==(
const SIZE &lhs,
const SIZE &rhs)
noexcept {
282 return ((lhs.cx == rhs.cx) && (lhs.cy == rhs.cy));
285 inline constexpr bool operator!=(
const SIZE &lhs,
const SIZE &rhs)
noexcept {
286 return !operator==(lhs, rhs);
289 inline constexpr bool operator==(
const RECT &lhs,
const RECT &rhs)
noexcept {
290 return ((lhs.left == rhs.left) && (lhs.top == rhs.top) && (lhs.right == rhs.right) &&
291 (lhs.bottom == rhs.bottom));
294 inline constexpr bool operator!=(
const RECT &lhs,
const RECT &rhs)
noexcept {
295 return !operator==(lhs, rhs);
298 inline constexpr QPoint point2qpoint(
const POINT &point) {
299 return QPoint{int(point.x), int(point.y)};
302 inline constexpr POINT qpoint2point(
const QPoint &point) {
303 return POINT{LONG(point.x()), LONG(point.y())};
306 inline constexpr QSize size2qsize(
const SIZE &size) {
307 return QSize{int(size.cx), int(size.cy)};
310 inline constexpr SIZE qsize2size(
const QSize &size) {
311 return SIZE{LONG(size.width()), LONG(size.height())};
314 inline constexpr QRect rect2qrect(
const RECT &rect) {
316 QPoint{int(rect.left), int(rect.top) },
317 QSize{int(RECT_WIDTH(rect)), int(RECT_HEIGHT(rect))}
321 inline constexpr RECT qrect2rect(
const QRect &qrect) {
322 return RECT{LONG(qrect.left()), LONG(qrect.top()), LONG(qrect.right()),
323 LONG(qrect.bottom())};
326 inline constexpr QMargins margins2qmargins(
const MARGINS &margins) {
327 return {margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth,
328 margins.cyBottomHeight};
331 inline constexpr MARGINS qmargins2margins(
const QMargins &qmargins) {
332 return {qmargins.left(), qmargins.right(), qmargins.top(), qmargins.bottom()};
335 inline QString hwnd2str(
const WId windowId) {
337 return QStringLiteral(
"0x00000000");
339 return QStringLiteral(
"0x") +
340 QString::number(windowId, 16).toUpper().rightJustified(8, u
'0');
343 inline QString hwnd2str(HWND hwnd) {
345 return hwnd2str(
reinterpret_cast<WId
>(hwnd));
348 inline bool isDwmCompositionEnabled() {
349 if (isWin8OrGreater()) {
352 const DynamicApis &apis = DynamicApis::instance();
353 if (!apis.pDwmIsCompositionEnabled) {
356 BOOL enabled = FALSE;
357 return SUCCEEDED(apis.pDwmIsCompositionEnabled(&enabled)) && enabled;
360 inline bool isWindowFrameBorderColorized() {
361 WindowsRegistryKey registry(HKEY_CURRENT_USER, LR
"(Software\Microsoft\Windows\DWM)");
362 if (!registry.isValid()) {
365 auto value = registry.dwordValue(L
"ColorPrevalence");
372 inline bool isHighContrastModeEnabled() {
374 hc.cbSize =
sizeof(hc);
375 ::SystemParametersInfoW(SPI_GETHIGHCONTRAST,
sizeof(hc), &hc, FALSE);
376 return (hc.dwFlags & HCF_HIGHCONTRASTON);
379 inline bool isDarkThemeActive() {
380 if (!isWin101809OrGreater()) {
383#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
384 return QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark;
386 WindowsRegistryKey registry(
387 HKEY_CURRENT_USER, LR
"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)");
388 if (!registry.isValid()) {
391 auto value = registry.dwordValue(L
"AppsUseLightTheme");
399 inline bool isDarkWindowFrameEnabled(HWND hwnd) {
401 if (!isWin101809OrGreater()) {
404 BOOL enabled = FALSE;
405 const DynamicApis &apis = DynamicApis::instance();
406 const auto attr = isWin1020H1OrGreater() ? _DWMWA_USE_IMMERSIVE_DARK_MODE
407 : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1;
408 return SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, attr, &enabled,
sizeof(enabled))) &&
412 inline QColor getAccentColor() {
413 WindowsRegistryKey registry(HKEY_CURRENT_USER, LR
"(Software\Microsoft\Windows\DWM)");
414 if (!registry.isValid()) {
417 auto value = registry.dwordValue(L
"AccentColor");
423 QColor color = QColor::fromRgba(value.first);
424 if (!color.isValid()) {
427 return QColor::fromRgb(color.blue(), color.green(), color.red(), color.alpha());
430 inline quint32 getSystemDpi() {
431 const DynamicApis &apis = DynamicApis::instance();
432 if (apis.pGetDpiForSystem)
433 return apis.pGetDpiForSystem();
435 HDC hdc = ::GetDC(
nullptr);
437 return USER_DEFAULT_SCREEN_DPI;
438 const int dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX);
439 ::ReleaseDC(
nullptr, hdc);
440 return dpiX > 0 ? quint32(dpiX) : quint32(USER_DEFAULT_SCREEN_DPI);
443 inline quint32 getDpiForWindow(HWND hwnd) {
445 const DynamicApis &apis = DynamicApis::instance();
446 if (apis.pGetDpiForWindow) {
447 const UINT dpi = apis.pGetDpiForWindow(hwnd);
451 if (apis.pGetDpiForMonitor) {
452 HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
455 const HRESULT hr = apis.pGetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
456 if (SUCCEEDED(hr) && dpiX != 0)
459 return getSystemDpi();
462 inline int getSystemMetricsForDpi(
int index, quint32 dpi) {
467 const DynamicApis &apis = DynamicApis::instance();
468 if (apis.pGetSystemMetricsForDpi) {
469 return apis.pGetSystemMetricsForDpi(index, dpi);
473 return ::MulDiv(::GetSystemMetrics(index),
int(dpi),
int(getSystemDpi()));
476 inline int getWindowFrameBorderThickness(HWND hwnd) {
478 const DynamicApis &apis = DynamicApis::instance();
479 if (isWin11OrGreater()) {
481 if (SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS,
482 &result,
sizeof(result))) &&
483 result <=
static_cast<UINT
>((std::numeric_limits<int>::max)())) {
484 return static_cast<int>(result);
487 if (isWin10OrGreater()) {
488 const quint32 dpi = getDpiForWindow(hwnd);
490 return getSystemMetricsForDpi(SM_CXBORDER, dpi);
496 inline int getResizeBorderThickness(HWND hwnd) {
498 const quint32 dpi = getDpiForWindow(hwnd);
502 return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) +
503 getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
506 inline int getTitleBarHeight(HWND hwnd) {
508 const quint32 dpi = getDpiForWindow(hwnd);
512 return getSystemMetricsForDpi(SM_CYCAPTION, dpi) +
513 getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) +
514 getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
QWindowKit namespace.
Definition abstractwindowcontext.cpp:13