| | |
| | | #include <timeapi.h> |
| | | |
| | | #include <QWKCore/qwindowkit_windows.h> |
| | | #include <QtCore/private/qsystemlibrary_p.h> |
| | | |
| | | #include <QtCore/QtMath> |
| | | #include <QtGui/QGuiApplication> |
| | | #include <QtGui/QStyleHints> |
| | | #include <QtGui/QPalette> |
| | | |
| | | #include <QtCore/private/qsystemlibrary_p.h> |
| | | |
| | | // Don't include this header in any header files. |
| | | |
| | |
| | | |
| | | DYNAMIC_API_DECLARE(DwmFlush); |
| | | DYNAMIC_API_DECLARE(DwmIsCompositionEnabled); |
| | | DYNAMIC_API_DECLARE(DwmGetCompositionTimingInfo); |
| | | DYNAMIC_API_DECLARE(DwmGetWindowAttribute); |
| | | DYNAMIC_API_DECLARE(DwmSetWindowAttribute); |
| | | DYNAMIC_API_DECLARE(DwmExtendFrameIntoClientArea); |
| | |
| | | DYNAMIC_API_DECLARE(GetSystemMetricsForDpi); |
| | | DYNAMIC_API_DECLARE(AdjustWindowRectExForDpi); |
| | | DYNAMIC_API_DECLARE(GetDpiForMonitor); |
| | | DYNAMIC_API_DECLARE(timeGetDevCaps); |
| | | DYNAMIC_API_DECLARE(timeBeginPeriod); |
| | | DYNAMIC_API_DECLARE(timeEndPeriod); |
| | | |
| | | #undef DYNAMIC_API_DECLARE |
| | | |
| | |
| | | QSystemLibrary dwmapi(QStringLiteral("dwmapi")); |
| | | DYNAMIC_API_RESOLVE(dwmapi, DwmFlush); |
| | | DYNAMIC_API_RESOLVE(dwmapi, DwmIsCompositionEnabled); |
| | | DYNAMIC_API_RESOLVE(dwmapi, DwmGetCompositionTimingInfo); |
| | | DYNAMIC_API_RESOLVE(dwmapi, DwmGetWindowAttribute); |
| | | DYNAMIC_API_RESOLVE(dwmapi, DwmSetWindowAttribute); |
| | | DYNAMIC_API_RESOLVE(dwmapi, DwmExtendFrameIntoClientArea); |
| | | DYNAMIC_API_RESOLVE(dwmapi, DwmEnableBlurBehindWindow); |
| | | |
| | | QSystemLibrary winmm(QStringLiteral("winmm")); |
| | | DYNAMIC_API_RESOLVE(winmm, timeGetDevCaps); |
| | | DYNAMIC_API_RESOLVE(winmm, timeBeginPeriod); |
| | | DYNAMIC_API_RESOLVE(winmm, timeEndPeriod); |
| | | |
| | | #undef DYNAMIC_API_RESOLVE |
| | | |
| | |
| | | if (!registry.isValid()) { |
| | | return false; |
| | | } |
| | | auto value = registry.value<DWORD>(L"ColorPrevalence"); |
| | | return value.value_or(false); |
| | | auto value = registry.dwordValue(L"ColorPrevalence"); |
| | | if (!value.second) { |
| | | return false; |
| | | } |
| | | return value.first; |
| | | } |
| | | |
| | | inline bool isHighContrastModeEnabled() { |
| | |
| | | if (!registry.isValid()) { |
| | | return false; |
| | | } |
| | | auto value = registry.value<DWORD>(L"AppsUseLightTheme"); |
| | | return value.value_or(false); |
| | | auto value = registry.dwordValue(L"AppsUseLightTheme"); |
| | | if (!value.second) { |
| | | return false; |
| | | } |
| | | return !value.first; |
| | | #endif |
| | | } |
| | | |
| | |
| | | } |
| | | BOOL enabled = FALSE; |
| | | const DynamicApis &apis = DynamicApis::instance(); |
| | | const auto attr = isWin1020H1OrGreater() ? _DWMWA_USE_IMMERSIVE_DARK_MODE : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1; |
| | | return SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, attr, &enabled, sizeof(enabled))) && enabled; |
| | | const auto attr = isWin1020H1OrGreater() ? _DWMWA_USE_IMMERSIVE_DARK_MODE |
| | | : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1; |
| | | return SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, attr, &enabled, sizeof(enabled))) && |
| | | enabled; |
| | | } |
| | | |
| | | inline QColor getAccentColor() { |
| | |
| | | if (!registry.isValid()) { |
| | | return {}; |
| | | } |
| | | auto value = registry.value<DWORD>(L"AccentColor"); |
| | | if (!value) { |
| | | 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. |
| | | QColor color = QColor::fromRgba(*value); |
| | | QColor color = QColor::fromRgba(value.first); |
| | | if (!color.isValid()) { |
| | | return {}; |
| | | } |
| | |
| | | |
| | | inline quint32 getDpiForWindow(HWND hwnd) { |
| | | const DynamicApis &apis = DynamicApis::instance(); |
| | | if (apis.pGetDpiForWindow) { // Win10 |
| | | if (apis.pGetDpiForWindow) { // Win10 |
| | | return apis.pGetDpiForWindow(hwnd); |
| | | } else if (apis.pGetDpiForMonitor) { // Win8.1 |
| | | HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); |
| | |
| | | if (apis.pGetSystemMetricsForDpi) { |
| | | return apis.pGetSystemMetricsForDpi(index, dpi); |
| | | } |
| | | return ::GetSystemMetrics(index); |
| | | const int result = ::GetSystemMetrics(index); |
| | | // GetSystemMetrics() always give you scaled value. |
| | | if (dpi != USER_DEFAULT_SCREEN_DPI) { |
| | | return result; |
| | | } |
| | | const qreal dpr = qreal(dpi) / qreal(USER_DEFAULT_SCREEN_DPI); |
| | | // ### Not sure how Windows itself rounds non-integer value. |
| | | return qFloor(qreal(result) / dpr); |
| | | } |
| | | |
| | | inline quint32 getWindowFrameBorderThickness(HWND hwnd) { |
| | |
| | | } |
| | | } |
| | | if (isWin10OrGreater()) { |
| | | return static_cast<quint32>(qreal(1) * qreal(getDpiForWindow(hwnd)) / qreal(USER_DEFAULT_SCREEN_DPI)); |
| | | const quint32 dpi = getDpiForWindow(hwnd); |
| | | // When DPI is 96, it should be 1px. |
| | | return getSystemMetricsForDpi(SM_CXBORDER, dpi); |
| | | } |
| | | // There's no such thing (a visible frame border line) before Win10. |
| | | return 0; |
| | | } |
| | | |
| | | inline quint32 getResizeBorderThickness(HWND hwnd) { |
| | | const quint32 dpi = getDpiForWindow(hwnd); |
| | | // When DPI is 96, SM_CXSIZEFRAME is 4px, SM_CXPADDEDBORDER is also 4px, |
| | | // so the result should be 8px. This result won't be affected by OS version, |
| | | // it's 8px in Win7, and so in Win11. |
| | | return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + |
| | | getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); |
| | | } |
| | | |
| | | inline quint32 getTitleBarHeight(HWND hwnd) { |
| | | const quint32 dpi = getDpiForWindow(hwnd); |
| | | // When DPI is 96, SM_CYCAPTION is 23px, so the result should be 31px. |
| | | // However, according to latest MS design manual, the title bar height |
| | | // should be 32px, maybe there's some rounding issue. |
| | | return getSystemMetricsForDpi(SM_CYCAPTION, dpi) + |
| | | getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + |
| | | getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); |