diff options
| author | Maufeat <sahyno1996@gmail.com> | 2025-08-10 22:14:12 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2025-08-10 22:14:12 +0200 |
| commit | 3f02d7713f1bfb36245486019bc014ecc49a1b19 (patch) | |
| tree | b98ccf0920f17e2eedf66b866ed1138407f91c40 /src/yuzu/main.cpp | |
| parent | bdf5674d7e3cb6e142079339d72dbc05a20ed6e1 (diff) | |
[qt] Fix title bar for windows being forced to light theme (#236)
Fixed the title bar being forced to light theme and properly handle it the qt6.5 way
See: https://stackoverflow.com/a/78854851
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/236
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: Maufeat <sahyno1996@gmail.com>
Co-committed-by: Maufeat <sahyno1996@gmail.com>
Diffstat (limited to 'src/yuzu/main.cpp')
| -rw-r--r-- | src/yuzu/main.cpp | 118 |
1 files changed, 102 insertions, 16 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9cf2f9b76c..38c0e4b3ce 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -96,6 +96,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include <QStandardPaths> #include <QStatusBar> #include <QString> +#include <QStyleHints> #include <QSysInfo> #include <QUrl> #include <QtConcurrent/QtConcurrent> @@ -172,6 +173,91 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "yuzu/util/clickable_label.h" #include "yuzu/vk_device_info.h" +#ifdef _WIN32 +#include <QPlatformSurfaceEvent> +#include <dwmapi.h> +#include <windows.h> +#pragma comment(lib, "Dwmapi.lib") + +static inline void ApplyWindowsTitleBarDarkMode(HWND hwnd, bool enabled) { + if (!hwnd) + return; + BOOL val = enabled ? TRUE : FALSE; + // 20 = Win11/21H2+ + if (SUCCEEDED(DwmSetWindowAttribute(hwnd, 20, &val, sizeof(val)))) + return; + // 19 = pre-21H2 + DwmSetWindowAttribute(hwnd, 19, &val, sizeof(val)); +} + +static inline void ApplyDarkToTopLevel(QWidget* w, bool on) { + if (!w || !w->isWindow()) + return; + ApplyWindowsTitleBarDarkMode(reinterpret_cast<HWND>(w->winId()), on); +} + +namespace { +struct TitlebarFilter final : QObject { + bool dark; + explicit TitlebarFilter(bool is_dark) : QObject(qApp), dark(is_dark) {} + + void setDark(bool is_dark) { + dark = is_dark; + } + + void onFocusChanged(QWidget*, QWidget* now) { + if (now) + ApplyDarkToTopLevel(now->window(), dark); + } + + bool eventFilter(QObject* obj, QEvent* ev) override { + if (auto* w = qobject_cast<QWidget*>(obj)) { + switch (ev->type()) { + case QEvent::WinIdChange: + case QEvent::Show: + case QEvent::ShowToParent: + case QEvent::Polish: + case QEvent::WindowStateChange: + case QEvent::ZOrderChange: + ApplyDarkToTopLevel(w, dark); + break; + default: + break; + } + } + return QObject::eventFilter(obj, ev); + } +}; + +static TitlebarFilter* g_filter = nullptr; +static QMetaObject::Connection g_focusConn; + +} // namespace + +static void ApplyGlobalDarkTitlebar(bool is_dark) { + if (!g_filter) { + g_filter = new TitlebarFilter(is_dark); + qApp->installEventFilter(g_filter); + g_focusConn = QObject::connect(qApp, &QApplication::focusChanged, g_filter, + &TitlebarFilter::onFocusChanged); + } else { + g_filter->setDark(is_dark); + } + for (QWidget* w : QApplication::topLevelWidgets()) + ApplyDarkToTopLevel(w, is_dark); +} + +static void RemoveTitlebarFilter() { + if (!g_filter) + return; + qApp->removeEventFilter(g_filter); + QObject::disconnect(g_focusConn); + g_filter->deleteLater(); + g_filter = nullptr; +} + +#endif + #ifdef YUZU_CRASH_DUMPS #include "yuzu/breakpad.h" #endif @@ -299,16 +385,16 @@ static void OverrideWindowsFont() { } #endif -bool GMainWindow::CheckDarkMode() { -#ifdef __unix__ - const QPalette test_palette(qApp->palette()); - const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text); - const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window); - return (text_color.value() > window_color.value()); +inline static bool isDarkMode() { +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + const auto scheme = QGuiApplication::styleHints()->colorScheme(); + return scheme == Qt::ColorScheme::Dark; #else - // TODO: Windows - return false; -#endif // __unix__ + const QPalette defaultPalette; + const auto text = defaultPalette.color(QPalette::WindowText); + const auto window = defaultPalette.color(QPalette::Window); + return text.lightness() > window.lightness(); +#endif // QT_VERSION } GMainWindow::GMainWindow(bool has_broken_vulkan) @@ -358,7 +444,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) statusBar()->hide(); // Check dark mode before a theme is loaded - os_dark_mode = CheckDarkMode(); startup_icon_theme = QIcon::themeName(); // fallback can only be set once, colorful theme icons are okay on both light/dark QIcon::setFallbackThemeName(QStringLiteral("colorful")); @@ -5383,15 +5468,11 @@ void GMainWindow::UpdateUITheme() { current_theme = default_theme; } -#ifdef _WIN32 - QIcon::setThemeName(current_theme); - AdjustLinkColor(); -#else if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) { QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme : startup_icon_theme); QIcon::setThemeSearchPaths(QStringList(default_theme_paths)); - if (CheckDarkMode()) { + if (isDarkMode()) { current_theme = QStringLiteral("default_dark"); } } else { @@ -5399,7 +5480,7 @@ void GMainWindow::UpdateUITheme() { QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons"))); AdjustLinkColor(); } -#endif + if (current_theme != default_theme) { QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)}; QFile f(theme_uri); @@ -5422,6 +5503,11 @@ void GMainWindow::UpdateUITheme() { qApp->setStyleSheet({}); setStyleSheet({}); } + +#ifdef _WIN32 + RemoveTitlebarFilter(); + ApplyGlobalDarkTitlebar(UISettings::IsDarkTheme()); +#endif } void GMainWindow::LoadTranslation() { |
