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 <oliver.wolff@qt.io>
This commit is contained in:
Friedemann Kleint 2019-10-21 16:01:47 +02:00
parent 1278995778
commit 12f085e538
9 changed files with 84 additions and 2 deletions

View File

@ -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.

View File

@ -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<QWindowsNativeInterface *>(QWindowsIntegration::instance()->nativeInterface());
emit nativeInterface->darkModeChanged(darkMode);
}
return d->m_screenManager.handleScreenChanges();
}
default:
break;
}

View File

@ -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

View File

@ -219,6 +219,10 @@ static inline unsigned parseOptions(const QStringList &paramList,
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;
}

View File

@ -70,7 +70,9 @@ public:
NoNativeMenus = 0x200,
DontUseWMPointer = 0x400,
DetectAltGrModifier = 0x800,
RtlEnabled = 0x1000
RtlEnabled = 0x1000,
DarkModeWindowFrames = 0x2000,
DarkModeStyle = 0x4000
};
explicit QWindowsIntegration(const QStringList &paramList);

View File

@ -47,6 +47,7 @@
#include "qwindowsopengltester.h"
#include "qwindowsintegration.h"
#include "qwindowsmime.h"
#include "qwindowstheme.h"
#include "qwin10helpers.h"
#include <QtGui/qwindow.h>
@ -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

View File

@ -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;
};

View File

@ -63,6 +63,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qcache.h>
#include <QtCore/qthread.h>
@ -78,6 +79,7 @@
#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
#include <private/qhighdpiscaling_p.h>
#include <private/qsystemlibrary_p.h>
#include <private/qwinregistry_p.h>
#include <algorithm>
@ -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__;

View File

@ -84,6 +84,8 @@ public:
void showPlatformMenuBar() override;
static bool useNativeMenus();
static bool queryDarkMode();
static bool queryHighContrast();
void refreshFonts();