From e79a6253813cd67954e371805da547c48ea32d3d Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Sat, 14 Sep 2019 18:47:13 +0800 Subject: QCursor: Allow bitmap() and mask() to return by-value The previous versions of these functions that returned by-pointer are held over from Qt 1 times. They are inconsistent with the rest of the Qt API. [ChangeLog][QtGui][QCursor] QCursor::bitmap() and QCursor::mask() can now return by-value instead of by-pointer. Task-number: QTBUG-48701 Change-Id: I3ca4f0c28d5c831727a60309facfb49c74673bb7 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/windows/qwindowscursor.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/plugins/platforms/windows') diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 59457f1720..19de3d5939 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -80,10 +80,10 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0) { if (!bitmapCacheKey) { - Q_ASSERT(c.bitmap()); - Q_ASSERT(c.mask()); - bitmapCacheKey = c.bitmap()->cacheKey(); - maskCacheKey = c.mask()->cacheKey(); + Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull()); + Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull()); + bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey(); + maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey(); } } @@ -169,9 +169,9 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, // Create a cursor from image and mask of the format QImage::Format_Mono. static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1) { - Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap()); - QImage bbits = cursor.bitmap()->toImage(); - QImage mbits = cursor.mask()->toImage(); + Q_ASSERT(cursor.shape() == Qt::BitmapCursor && !cursor.bitmap(Qt::ReturnByValue).isNull()); + QImage bbits = cursor.bitmap(Qt::ReturnByValue).toImage(); + QImage mbits = cursor.mask(Qt::ReturnByValue).toImage(); scaleFactor /= bbits.devicePixelRatioF(); if (!qFuzzyCompare(scaleFactor, 1)) { const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize(); -- cgit v1.2.3 From 1278995778a3ab576231c372969336a2f6621e02 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 14 Jan 2020 10:08:22 +0100 Subject: Windows QPA: Better disambiguate Window class names Use a standard prefix for Window class names containing version, build and namespace which should reduce conflicts. Task-number: QTBUG-81347 Change-Id: Ia7c20af71d364e362781f791a4e51b77d605c918 Reviewed-by: Oliver Wolff --- .../platforms/windows/qwindowsclipboard.cpp | 2 +- src/plugins/platforms/windows/qwindowscontext.cpp | 26 ++++++++++++++++++---- src/plugins/platforms/windows/qwindowscontext.h | 1 + .../platforms/windows/qwindowsglcontext.cpp | 2 +- .../platforms/windows/qwindowssystemtrayicon.cpp | 2 +- 5 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src/plugins/platforms/windows') diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index ccd4e50a8b..efcb0b6e6e 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -190,7 +190,7 @@ void QWindowsClipboard::releaseIData() void QWindowsClipboard::registerViewer() { m_clipboardViewer = QWindowsContext::instance()-> - createDummyWindow(QStringLiteral("Qt5ClipboardView"), L"Qt5ClipboardView", + createDummyWindow(QStringLiteral("ClipboardView"), L"QtClipboardView", qClipboardViewerWndProc, WS_OVERLAPPED); // Try format listener API (Vista onwards) first. diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index d31352b854..c85d04b816 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -72,6 +72,7 @@ #include #include +#include #include #include #include @@ -426,7 +427,7 @@ bool QWindowsContext::initPowerNotificationHandler() if (d->m_powerNotification) return false; - d->m_powerDummyWindow = createDummyWindow(QStringLiteral("QtPowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc); + d->m_powerDummyWindow = createDummyWindow(QStringLiteral("PowerDummyWindow"), L"QtPowerDummyWindow", qWindowsPowerWindowProc); if (!d->m_powerDummyWindow) return false; @@ -536,6 +537,23 @@ void QWindowsContext::setKeyGrabber(QWindow *w) d->m_keyMapper.setKeyGrabber(w); } +QString QWindowsContext::classNamePrefix() +{ + static QString result; + if (result.isEmpty()) { + QTextStream str(&result); + str << "Qt" << QT_VERSION_MAJOR << QT_VERSION_MINOR << QT_VERSION_PATCH; + if (QLibraryInfo::isDebugBuild()) + str << 'd'; +#ifdef QT_NAMESPACE +# define xstr(s) str(s) +# define str(s) #s + str << xstr(QT_NAMESPACE); +#endif + } + return result; +} + // Window class registering code (from qapplication_win.cpp) QString QWindowsContext::registerWindowClass(const QWindow *w) @@ -567,8 +585,8 @@ QString QWindowsContext::registerWindowClass(const QWindow *w) break; } // Create a unique name for the flag combination - QString cname; - cname += QLatin1String("Qt5QWindow"); + QString cname = classNamePrefix(); + cname += QLatin1String("QWindow"); switch (type) { case Qt::Tool: cname += QLatin1String("Tool"); @@ -878,7 +896,7 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn, { if (!wndProc) wndProc = DefWindowProc; - QString className = registerWindowClass(classNameIn, wndProc); + QString className = registerWindowClass(classNamePrefix() + classNameIn, wndProc); return CreateWindowEx(0, reinterpret_cast(className.utf16()), windowName, style, CW_USEDEFAULT, CW_USEDEFAULT, diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 8027f09389..43ab8416ab 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -180,6 +180,7 @@ public: int defaultDPI() const; + static QString classNamePrefix(); QString registerWindowClass(const QWindow *w); QString registerWindowClass(QString cname, WNDPROC proc, unsigned style = 0, HBRUSH brush = nullptr, diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index f2d31d5783..f5d0a8780a 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -802,7 +802,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext, static inline HWND createDummyGLWindow() { return QWindowsContext::instance()-> - createDummyWindow(QStringLiteral("QtOpenGLDummyWindow"), + createDummyWindow(QStringLiteral("OpenGLDummyWindow"), L"OpenGLDummyWindow", nullptr, WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); } diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index 66c558df1e..53562c87dd 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -168,7 +168,7 @@ static inline HWND createTrayIconMessageWindow() return nullptr; // Register window class in the platform plugin. const QString className = - ctx->registerWindowClass(QStringLiteral("QTrayIconMessageWindowClass"), + ctx->registerWindowClass(QWindowsContext::classNamePrefix() + QStringLiteral("TrayIconMessageWindowClass"), qWindowsTrayIconWndProc); const wchar_t windowName[] = L"QTrayIconMessageWindow"; return CreateWindowEx(0, reinterpret_cast(className.utf16()), -- cgit v1.2.3 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/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 ++ 8 files changed, 69 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms/windows') 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.3 From eb26563dd5483ab83a7a5addf8f98a4921d1edc1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 3 Jan 2020 16:10:40 +0100 Subject: Windows QPA: Add setting of dark window borders Implement dark mode support level 1: change the window borders to dark and back, tracking the activation of dark mode. Task-number: QTBUG-72028 Change-Id: I6e8b31e7ee574f4d90438405f361cd940faee7fd Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowscontext.cpp | 5 +++ src/plugins/platforms/windows/qwindowswindow.cpp | 44 +++++++++++++++++++++++ src/plugins/platforms/windows/qwindowswindow.h | 3 ++ 3 files changed, 52 insertions(+) (limited to 'src/plugins/platforms/windows') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index d322b0e92b..5578259399 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1221,6 +1221,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, auto nativeInterface = static_cast(QWindowsIntegration::instance()->nativeInterface()); emit nativeInterface->darkModeChanged(darkMode); + const auto options = QWindowsIntegration::instance()->options(); + if ((options & QWindowsIntegration::DarkModeWindowFrames) != 0) { + for (QWindowsWindow *w : d->m_windows) + w->setDarkBorder(QWindowsContextPrivate::m_darkMode); + } } return d->m_screenManager.handleScreenChanges(); } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index a7aad15749..b7536066d0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -749,6 +749,11 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag } } +static inline bool shouldApplyDarkFrame(const QWindow *w) +{ + return w->isTopLevel() && !w->flags().testFlag(Qt::FramelessWindowHint); +} + QWindowsWindowData WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const { @@ -816,6 +821,12 @@ QWindowsWindowData return result; } + if (QWindowsContext::isDarkMode() + && (QWindowsIntegration::instance()->options() & QWindowsIntegration::DarkModeWindowFrames) != 0 + && shouldApplyDarkFrame(w)) { + QWindowsWindow::setDarkBorderToWindow(result.hwnd, true); + } + if (mirrorParentWidth != 0) { context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width() - context->obtainedPos.x()); @@ -2892,6 +2903,39 @@ bool QWindowsWindow::isTopLevel() const return window()->isTopLevel() && !m_data.embedded; } +enum : WORD { + DwmwaUseImmersiveDarkMode = 20, + DwmwaUseImmersiveDarkModeBefore20h1 = 19 +}; + +static bool queryDarkBorder(HWND hwnd) +{ + BOOL result = FALSE; + const bool ok = + SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result))) + || SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result))); + if (!ok) + qWarning("%s: Unable to retrieve dark window border setting.", __FUNCTION__); + return result == TRUE; +} + +bool QWindowsWindow::setDarkBorderToWindow(HWND hwnd, bool d) +{ + const BOOL darkBorder = d ? TRUE : FALSE; + const bool ok = + SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &darkBorder, sizeof(darkBorder))) + || SUCCEEDED(DwmSetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &darkBorder, sizeof(darkBorder))); + if (!ok) + qWarning("%s: Unable to set dark window border.", __FUNCTION__); + return ok; +} + +void QWindowsWindow::setDarkBorder(bool d) +{ + if (shouldApplyDarkFrame(window()) && queryDarkBorder(m_data.hwnd) != d) + setDarkBorderToWindow(m_data.hwnd, d); +} + QWindowsMenuBar *QWindowsWindow::menuBar() const { return m_menuBar.data(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 1f8800272b..7c37c6b115 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -287,6 +287,9 @@ public: HWND handle() const override { return m_data.hwnd; } bool isTopLevel() const override; + static bool setDarkBorderToWindow(HWND hwnd, bool d); + void setDarkBorder(bool d); + QWindowsMenuBar *menuBar() const; void setMenuBar(QWindowsMenuBar *mb); -- cgit v1.2.3 From 859307d7a590873d8df5f8094e13043370fccaa7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 25 Sep 2019 15:04:36 +0200 Subject: Windows QPA: Provide an experimental palette for dark mode Provide a simple palette for dark mode, implementing dark mode support level 2. Task-number: QTBUG-72028 Change-Id: I6f71870b251ccb7da30c01abb22c224e600f2b27 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowscontext.cpp | 5 + src/plugins/platforms/windows/qwindowstheme.cpp | 112 +++++++++++++++++----- src/plugins/platforms/windows/qwindowstheme.h | 2 +- 3 files changed, 95 insertions(+), 24 deletions(-) (limited to 'src/plugins/platforms/windows') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 5578259399..2591966d54 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1226,6 +1226,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, for (QWindowsWindow *w : d->m_windows) w->setDarkBorder(QWindowsContextPrivate::m_darkMode); } + if ((options & QWindowsIntegration::DarkModeStyle) != 0) { + QWindowsTheme::instance()->refresh(); + for (QWindowsWindow *w : d->m_windows) + QWindowSystemInterface::handleThemeChange(w->window()); + } } return d->m_screenManager.handleScreenChanges(); } diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 2f9dd0b40b..325956b7ba 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -243,6 +243,15 @@ static bool shGetFileInfoBackground(const QString &fileName, DWORD attributes, return result; } +// Dark Mode constants +enum DarkModeColors : QRgb { + darkModeBtnHighlightRgb = 0xc0c0c0, + darkModeBtnShadowRgb = 0x808080, + darkModeHighlightRgb = 0x0055ff, // deviating from 0x800080 + darkModeMenuHighlightRgb = darkModeHighlightRgb, + darkModeGrayTextRgb = 0x00ff00 +}; + // from QStyle::standardPalette static inline QPalette standardPalette() { @@ -260,23 +269,55 @@ static inline QPalette standardPalette() return palette; } -static inline QPalette systemPalette() +static void populateLightSystemBasePalette(QPalette &result) { - QPalette result = standardPalette(); result.setColor(QPalette::WindowText, getSysColor(COLOR_WINDOWTEXT)); - result.setColor(QPalette::Button, getSysColor(COLOR_BTNFACE)); - result.setColor(QPalette::Light, getSysColor(COLOR_BTNHIGHLIGHT)); + const QColor btnFace = getSysColor(COLOR_BTNFACE); + result.setColor(QPalette::Button, btnFace); + const QColor btnHighlight = getSysColor(COLOR_BTNHIGHLIGHT); + result.setColor(QPalette::Light, btnHighlight); result.setColor(QPalette::Dark, getSysColor(COLOR_BTNSHADOW)); result.setColor(QPalette::Mid, result.button().color().darker(150)); result.setColor(QPalette::Text, getSysColor(COLOR_WINDOWTEXT)); - result.setColor(QPalette::BrightText, getSysColor(COLOR_BTNHIGHLIGHT)); + result.setColor(QPalette::BrightText, btnHighlight); result.setColor(QPalette::Base, getSysColor(COLOR_WINDOW)); - result.setColor(QPalette::Window, getSysColor(COLOR_BTNFACE)); + result.setColor(QPalette::Window, btnFace); result.setColor(QPalette::ButtonText, getSysColor(COLOR_BTNTEXT)); result.setColor(QPalette::Midlight, getSysColor(COLOR_3DLIGHT)); result.setColor(QPalette::Shadow, getSysColor(COLOR_3DDKSHADOW)); result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT)); result.setColor(QPalette::HighlightedText, getSysColor(COLOR_HIGHLIGHTTEXT)); +} + +static void populateDarkSystemBasePalette(QPalette &result) +{ + const QColor darkModeWindowText = Qt::white; + result.setColor(QPalette::WindowText, darkModeWindowText); + const QColor darkModebtnFace = Qt::black; + result.setColor(QPalette::Button, darkModebtnFace); + const QColor btnHighlight = QColor(darkModeBtnHighlightRgb); + result.setColor(QPalette::Light, btnHighlight); + result.setColor(QPalette::Dark, QColor(darkModeBtnShadowRgb)); + result.setColor(QPalette::Mid, result.button().color().darker(150)); + result.setColor(QPalette::Text, darkModeWindowText); + result.setColor(QPalette::BrightText, btnHighlight); + result.setColor(QPalette::Base, darkModebtnFace); + result.setColor(QPalette::Window, darkModebtnFace); + result.setColor(QPalette::ButtonText, darkModeWindowText); + result.setColor(QPalette::Midlight, darkModeWindowText); + result.setColor(QPalette::Shadow, darkModeWindowText); + result.setColor(QPalette::Highlight, QColor(darkModeHighlightRgb)); + result.setColor(QPalette::HighlightedText, darkModeWindowText); +} + +static QPalette systemPalette(bool light) +{ + QPalette result = standardPalette(); + if (light) + populateLightSystemBasePalette(result); + else + populateDarkSystemBasePalette(result); + result.setColor(QPalette::Link, Qt::blue); result.setColor(QPalette::LinkVisited, Qt::magenta); result.setColor(QPalette::Inactive, QPalette::Button, result.button().color()); @@ -302,19 +343,19 @@ static inline QPalette systemPalette() result.setColor(QPalette::Disabled, QPalette::Text, disabled); result.setColor(QPalette::Disabled, QPalette::ButtonText, disabled); result.setColor(QPalette::Disabled, QPalette::Highlight, - getSysColor(COLOR_HIGHLIGHT)); + light ? getSysColor(COLOR_HIGHLIGHT) : QColor(darkModeHighlightRgb)); result.setColor(QPalette::Disabled, QPalette::HighlightedText, - getSysColor(COLOR_HIGHLIGHTTEXT)); + light ? getSysColor(COLOR_HIGHLIGHTTEXT) : QColor(Qt::white)); result.setColor(QPalette::Disabled, QPalette::Base, result.window().color()); return result; } -static inline QPalette toolTipPalette(const QPalette &systemPalette) +static inline QPalette toolTipPalette(const QPalette &systemPalette, bool light) { QPalette result(systemPalette); - const QColor tipBgColor(getSysColor(COLOR_INFOBK)); - const QColor tipTextColor(getSysColor(COLOR_INFOTEXT)); + const QColor tipBgColor = light ? getSysColor(COLOR_INFOBK) : QColor(Qt::black); + const QColor tipTextColor = light ? getSysColor(COLOR_INFOTEXT) : QColor(Qt::white); result.setColor(QPalette::All, QPalette::Button, tipBgColor); result.setColor(QPalette::All, QPalette::Window, tipBgColor); @@ -339,12 +380,13 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette) return result; } -static inline QPalette menuPalette(const QPalette &systemPalette) +static inline QPalette menuPalette(const QPalette &systemPalette, bool light) { QPalette result(systemPalette); - const QColor menuColor(getSysColor(COLOR_MENU)); - const QColor menuTextColor(getSysColor(COLOR_MENUTEXT)); - const QColor disabled(getSysColor(COLOR_GRAYTEXT)); + const QColor menuColor = light ? getSysColor(COLOR_MENU) : QColor(Qt::black); + const QColor menuTextColor = light ? getSysColor(COLOR_MENUTEXT) : QColor(Qt::white); + const QColor disabled = light + ? getSysColor(COLOR_GRAYTEXT) : QColor(darkModeGrayTextRgb); // we might need a special color group for the result. result.setColor(QPalette::Active, QPalette::Button, menuColor); result.setColor(QPalette::Active, QPalette::Text, menuTextColor); @@ -353,8 +395,10 @@ static inline QPalette menuPalette(const QPalette &systemPalette) result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); - result.setColor(QPalette::Disabled, QPalette::Highlight, - getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)); + const QColor highlightColor = light + ? (getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)) + : QColor(darkModeMenuHighlightRgb); + result.setColor(QPalette::Disabled, QPalette::Highlight, highlightColor); result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled); result.setColor(QPalette::Disabled, QPalette::Button, result.color(QPalette::Active, QPalette::Button)); @@ -375,12 +419,12 @@ static inline QPalette menuPalette(const QPalette &systemPalette) return result; } -static inline QPalette *menuBarPalette(const QPalette &menuPalette) +static inline QPalette *menuBarPalette(const QPalette &menuPalette, bool light) { QPalette *result = nullptr; if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) { result = new QPalette(menuPalette); - const QColor menubar(getSysColor(COLOR_MENUBAR)); + const QColor menubar(light ? getSysColor(COLOR_MENUBAR) : QColor(Qt::black)); result->setColor(QPalette::Active, QPalette::Button, menubar); result->setColor(QPalette::Disabled, QPalette::Button, menubar); result->setColor(QPalette::Inactive, QPalette::Button, menubar); @@ -487,10 +531,26 @@ void QWindowsTheme::refreshPalettes() if (!QGuiApplication::desktopSettingsAware()) return; - m_palettes[SystemPalette] = new QPalette(systemPalette()); - m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette])); - m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette])); - m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette]); + const bool light = + !QWindowsContext::isDarkMode() + || (QWindowsIntegration::instance()->options() & QWindowsIntegration::DarkModeStyle) == 0; + m_palettes[SystemPalette] = new QPalette(systemPalette(light)); + m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette], light)); + m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette], light)); + m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light); + if (!light) { + m_palettes[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]); + m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u)); + const QColor checkBoxBlue(0x0078d7u); + const QColor white(Qt::white); + m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]); + m_palettes[CheckBoxPalette]->setColor(QPalette::Window, checkBoxBlue); + m_palettes[CheckBoxPalette]->setColor(QPalette::Base, checkBoxBlue); + m_palettes[CheckBoxPalette]->setColor(QPalette::Button, checkBoxBlue); + m_palettes[CheckBoxPalette]->setColor(QPalette::ButtonText, white); + m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]); + + } } void QWindowsTheme::clearFonts() @@ -499,6 +559,12 @@ void QWindowsTheme::clearFonts() std::fill(m_fonts, m_fonts + NFonts, nullptr); } +void QWindowsTheme::refresh() +{ + refreshPalettes(); + refreshFonts(); +} + void QWindowsTheme::refreshFonts() { clearFonts(); diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index d557c0b4fd..af28f2878c 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -88,11 +88,11 @@ public: static bool queryHighContrast(); void refreshFonts(); + void refresh(); static const char *name; private: - void refresh() { refreshPalettes(); refreshFonts(); } void clearPalettes(); void refreshPalettes(); void clearFonts(); -- cgit v1.2.3