From 12f085e538a1e3060fc5be3e21cefbb6d4c492b5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 21 Oct 2019 16:01:47 +0200 Subject: Windows QPA: Add detection of dark mode Read the dark mode setting and make it accessible via native interface. Add a command line option to set the support level. Task-number: QTBUG-72028 Change-Id: I1e9fe296a6b1bda81512d003183038b866b67545 Reviewed-by: Oliver Wolff --- src/gui/kernel/qguiapplication.cpp | 15 +++++++++++++++ src/plugins/platforms/windows/qwindowscontext.cpp | 20 +++++++++++++++++++- src/plugins/platforms/windows/qwindowscontext.h | 2 ++ .../platforms/windows/qwindowsintegration.cpp | 4 ++++ src/plugins/platforms/windows/qwindowsintegration.h | 4 +++- .../platforms/windows/qwindowsnativeinterface.cpp | 12 ++++++++++++ .../platforms/windows/qwindowsnativeinterface.h | 8 ++++++++ src/plugins/platforms/windows/qwindowstheme.cpp | 19 +++++++++++++++++++ src/plugins/platforms/windows/qwindowstheme.h | 2 ++ 9 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 445ad6b835..1190bd1936 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -592,6 +592,21 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME \list \li \c {altgr}, detect the key \c {AltGr} found on some keyboards as Qt::GroupSwitchModifier (since Qt 5.12). + \li \c {darkmode=[1|2]} controls how Qt responds to the activation + of the \e{Dark Mode for applications} introduced in Windows 10 + 1903 (since Qt 5.15). + + A value of 1 causes Qt to switch the window borders to black + when \e{Dark Mode for applications} is activated and no High + Contrast Theme is in use. This is intended for applications + that implement their own theming. + + A value of 2 will in addition cause the Windows Vista style to + be deactivated and switch to the Windows style using a + simplified palette in dark mode. This is currently + experimental pending the introduction of new style that + properly adapts to dark mode. + \li \c {dialogs=[xp|none]}, \c xp uses XP-style native dialogs and \c none disables them. diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index c85d04b816..d322b0e92b 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -42,6 +42,7 @@ #include "qwindowsintegration.h" #include "qwindowswindow.h" #include "qwindowskeymapper.h" +#include "qwindowsnativeinterface.h" #include "qwindowsmousehandler.h" #include "qwindowspointerhandler.h" #include "qtwindowsglobal.h" @@ -277,8 +278,11 @@ struct QWindowsContextPrivate { bool m_asyncExpose = false; HPOWERNOTIFY m_powerNotification = nullptr; HWND m_powerDummyWindow = nullptr; + static bool m_darkMode; }; +bool QWindowsContextPrivate::m_darkMode = false; + QWindowsContextPrivate::QWindowsContextPrivate() : m_oleInitializeResult(OleInitialize(nullptr)) { @@ -293,6 +297,7 @@ QWindowsContextPrivate::QWindowsContextPrivate() m_systemInfo |= QWindowsContext::SI_RTL_Extensions; m_keyMapper.setUseRTLExtensions(true); } + m_darkMode = QWindowsTheme::queryDarkMode(); if (FAILED(m_oleInitializeResult)) { qWarning() << "QWindowsContext: OleInitialize() failed: " << QWindowsContext::comErrorString(m_oleInitializeResult); @@ -485,6 +490,11 @@ void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiA } } +bool QWindowsContext::isDarkMode() +{ + return QWindowsContextPrivate::m_darkMode; +} + QWindowsContext *QWindowsContext::instance() { return m_instance; @@ -1203,9 +1213,17 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, t->displayChanged(); QWindowsWindow::displayChanged(); return d->m_screenManager.handleDisplayChange(wParam, lParam); - case QtWindows::SettingChangedEvent: + case QtWindows::SettingChangedEvent: { QWindowsWindow::settingsChanged(); + const bool darkMode = QWindowsTheme::queryDarkMode(); + if (darkMode != QWindowsContextPrivate::m_darkMode) { + QWindowsContextPrivate::m_darkMode = darkMode; + auto nativeInterface = + static_cast(QWindowsIntegration::instance()->nativeInterface()); + emit nativeInterface->darkModeChanged(darkMode); + } return d->m_screenManager.handleScreenChanges(); + } default: break; } diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 43ab8416ab..1831ac6ec0 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -226,6 +226,8 @@ public: void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness); static int processDpiAwareness(); + static bool isDarkMode(); + void setDetectAltGrModifier(bool a); // Returns a combination of SystemInfoFlags diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 32bd29a842..4b4047ac0c 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -219,6 +219,10 @@ static inline unsigned parseOptions(const QStringList ¶mList, options |= QWindowsIntegration::DontUseWMPointer; } else if (param == u"reverse") { options |= QWindowsIntegration::RtlEnabled; + } else if (param == u"darkmode=1") { + options |= QWindowsIntegration::DarkModeWindowFrames; + } else if (param == u"darkmode=2") { + options |= QWindowsIntegration::DarkModeWindowFrames | QWindowsIntegration::DarkModeStyle; } else { qWarning() << "Unknown option" << param; } diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index b49d21022b..1f16d13769 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -70,7 +70,9 @@ public: NoNativeMenus = 0x200, DontUseWMPointer = 0x400, DetectAltGrModifier = 0x800, - RtlEnabled = 0x1000 + RtlEnabled = 0x1000, + DarkModeWindowFrames = 0x2000, + DarkModeStyle = 0x4000 }; explicit QWindowsIntegration(const QStringList ¶mList); diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index d1d181d66e..1195f15a59 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -47,6 +47,7 @@ #include "qwindowsopengltester.h" #include "qwindowsintegration.h" #include "qwindowsmime.h" +#include "qwindowstheme.h" #include "qwin10helpers.h" #include @@ -316,4 +317,15 @@ QVariant QWindowsNativeInterface::gpuList() const return result; } +bool QWindowsNativeInterface::isDarkMode() const +{ + return QWindowsContext::isDarkMode(); +} + +// Dark mode support level 2 (style) +bool QWindowsNativeInterface::isDarkModeStyle() const +{ + return (QWindowsIntegration::instance()->options() & QWindowsIntegration::DarkModeStyle) != 0; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index ce395dc5a4..90ba7a44c9 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -65,6 +65,8 @@ class QWindowsNativeInterface : public QPlatformNativeInterface { Q_OBJECT Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose) + Q_PROPERTY(bool darkMode READ isDarkMode STORED false NOTIFY darkModeChanged) + Q_PROPERTY(bool darkModeStyle READ isDarkModeStyle STORED false) Q_PROPERTY(QVariant gpu READ gpu STORED false) Q_PROPERTY(QVariant gpuList READ gpuList STORED false) @@ -92,6 +94,9 @@ public: bool asyncExpose() const; void setAsyncExpose(bool value); + bool isDarkMode() const; + bool isDarkModeStyle() const; + QVariant gpu() const; QVariant gpuList() const; @@ -109,6 +114,9 @@ public: QFunctionPointer platformFunction(const QByteArray &function) const override; +Q_SIGNALS: + void darkModeChanged(bool); + private: static QWindowsWindowFunctions::WindowActivationBehavior m_windowActivationBehavior; }; diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 010aea2068..2f9dd0b40b 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,7 @@ #include #include #include +#include #include @@ -946,6 +948,23 @@ bool QWindowsTheme::useNativeMenus() return result; } +bool QWindowsTheme::queryDarkMode() +{ + if (QOperatingSystemVersion::current() + < QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 17763) + || queryHighContrast()) { + return false; + } + const auto setting = QWinRegistryKey(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)") + .dwordValue(L"AppsUseLightTheme"); + return setting.second && setting.first == 0; +} + +bool QWindowsTheme::queryHighContrast() +{ + return booleanSystemParametersInfo(SPI_GETHIGHCONTRAST, false); +} + QPlatformMenuItem *QWindowsTheme::createPlatformMenuItem() const { qCDebug(lcQpaMenus) << __FUNCTION__; diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index 7a8c321da4..d557c0b4fd 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -84,6 +84,8 @@ public: void showPlatformMenuBar() override; static bool useNativeMenus(); + static bool queryDarkMode(); + static bool queryHighContrast(); void refreshFonts(); -- cgit v1.2.1