summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Kyle K2022-07-28 07:50:20 -0700
committerGravatar Kyle K2022-08-05 05:22:27 -0700
commitb51db125676fb1257e3bacbd19df3ae686ae69df (patch)
treefab6123cf5823d5be438cf342ad053a4f3cf1648 /src
parentMerge pull request #8702 from liamwhite/format-swap (diff)
downloadyuzu-b51db125676fb1257e3bacbd19df3ae686ae69df.tar.gz
yuzu-b51db125676fb1257e3bacbd19df3ae686ae69df.tar.xz
yuzu-b51db125676fb1257e3bacbd19df3ae686ae69df.zip
Linux: handle dark system themes nicely
yuzu's default theme doesn't specify everything, which is fine for windows, but in linux anything unspecified is set to the users theme. Symptoms of this are that a linux user with a dark theme won't think to change the theme to a dark theme when first using yuzu Idea here is to try and support arbitrary themes on linux. preliminary work on a "default_dark" theme, used only as overlay for any themes that are measured to be dark mode. Other work done: FreeDesktop standard icon names: plus -> list-add delete refresh, we use view-refresh remove duplicated icons for qdarkstyle_midnight_blue referencing icon aliases in the qrc files is the way to go Note: Dynamic style changing doesn't appear to work with AppImage
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/game_list.cpp2
-rw-r--r--src/yuzu/game_list_p.h2
-rw-r--r--src/yuzu/main.cpp82
-rw-r--r--src/yuzu/main.h5
4 files changed, 77 insertions, 14 deletions
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 041e6ac11..c4b1f65bd 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -286,7 +286,7 @@ void GameList::OnUpdateThemedIcons() {
286 } 286 }
287 case GameListItemType::AddDir: 287 case GameListItemType::AddDir:
288 child->setData( 288 child->setData(
289 QIcon::fromTheme(QStringLiteral("plus")) 289 QIcon::fromTheme(QStringLiteral("list-add"))
290 .pixmap(icon_size) 290 .pixmap(icon_size)
291 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), 291 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
292 Qt::DecorationRole); 292 Qt::DecorationRole);
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index e7667cf60..0e19be22d 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -294,7 +294,7 @@ public:
294 294
295 const int icon_size = UISettings::values.folder_icon_size.GetValue(); 295 const int icon_size = UISettings::values.folder_icon_size.GetValue();
296 296
297 setData(QIcon::fromTheme(QStringLiteral("plus")) 297 setData(QIcon::fromTheme(QStringLiteral("list-add"))
298 .pixmap(icon_size) 298 .pixmap(icon_size)
299 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), 299 .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
300 Qt::DecorationRole); 300 Qt::DecorationRole);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f8c234082..e473ac6da 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -257,6 +257,18 @@ static QString PrettyProductName() {
257 return QSysInfo::prettyProductName(); 257 return QSysInfo::prettyProductName();
258} 258}
259 259
260bool GMainWindow::check_dark_mode() {
261#ifdef __linux__
262 const QPalette test_palette(qApp->palette());
263 const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text);
264 const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
265 return (text_color.value() > window_color.value());
266#else
267 // TODO: Windows
268 return false;
269#endif // __linux__
270}
271
260GMainWindow::GMainWindow(bool has_broken_vulkan) 272GMainWindow::GMainWindow(bool has_broken_vulkan)
261 : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, 273 : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
262 input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, 274 input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
@@ -274,6 +286,13 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
274 ui->setupUi(this); 286 ui->setupUi(this);
275 statusBar()->hide(); 287 statusBar()->hide();
276 288
289 // Check dark mode before a theme is loaded
290 os_dark_mode = check_dark_mode();
291 startup_icon_theme = QIcon::themeName();
292 // fallback can only be set once, colorful theme icons are okay on both light/dark
293 QIcon::setFallbackThemeName(QStringLiteral("colorful"));
294 QIcon::setFallbackSearchPaths(QStringList(QStringLiteral(":/icons")));
295
277 default_theme_paths = QIcon::themeSearchPaths(); 296 default_theme_paths = QIcon::themeSearchPaths();
278 UpdateUITheme(); 297 UpdateUITheme();
279 298
@@ -3930,8 +3949,21 @@ void GMainWindow::filterBarSetChecked(bool state) {
3930 emit(OnToggleFilterBar()); 3949 emit(OnToggleFilterBar());
3931} 3950}
3932 3951
3952static void AdjustLinkColor() {
3953 QPalette new_pal(qApp->palette());
3954 if (UISettings::IsDarkTheme()) {
3955 new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
3956 } else {
3957 new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
3958 }
3959 if (qApp->palette().color(QPalette::Link) != new_pal.color(QPalette::Link)) {
3960 qApp->setPalette(new_pal);
3961 }
3962}
3963
3933void GMainWindow::UpdateUITheme() { 3964void GMainWindow::UpdateUITheme() {
3934 const QString default_theme = QStringLiteral("default"); 3965 const QString default_theme =
3966 QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);
3935 QString current_theme = UISettings::values.theme; 3967 QString current_theme = UISettings::values.theme;
3936 QStringList theme_paths(default_theme_paths); 3968 QStringList theme_paths(default_theme_paths);
3937 3969
@@ -3939,6 +3971,23 @@ void GMainWindow::UpdateUITheme() {
3939 current_theme = default_theme; 3971 current_theme = default_theme;
3940 } 3972 }
3941 3973
3974#ifdef _WIN32
3975 QIcon::setThemeName(current_theme);
3976 AdjustLinkColor();
3977#else
3978 if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) {
3979 QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme
3980 : startup_icon_theme);
3981 QIcon::setThemeSearchPaths(theme_paths);
3982 if (check_dark_mode()) {
3983 current_theme = QStringLiteral("default_dark");
3984 }
3985 } else {
3986 QIcon::setThemeName(current_theme);
3987 QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons")));
3988 AdjustLinkColor();
3989 }
3990#endif
3942 if (current_theme != default_theme) { 3991 if (current_theme != default_theme) {
3943 QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)}; 3992 QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)};
3944 QFile f(theme_uri); 3993 QFile f(theme_uri);
@@ -3961,17 +4010,6 @@ void GMainWindow::UpdateUITheme() {
3961 qApp->setStyleSheet({}); 4010 qApp->setStyleSheet({});
3962 setStyleSheet({}); 4011 setStyleSheet({});
3963 } 4012 }
3964
3965 QPalette new_pal(qApp->palette());
3966 if (UISettings::IsDarkTheme()) {
3967 new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
3968 } else {
3969 new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
3970 }
3971 qApp->setPalette(new_pal);
3972
3973 QIcon::setThemeName(current_theme);
3974 QIcon::setThemeSearchPaths(theme_paths);
3975} 4013}
3976 4014
3977void GMainWindow::LoadTranslation() { 4015void GMainWindow::LoadTranslation() {
@@ -4022,6 +4060,26 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
4022 discord_rpc->Update(); 4060 discord_rpc->Update();
4023} 4061}
4024 4062
4063void GMainWindow::changeEvent(QEvent* event) {
4064#ifdef __linux__
4065 // PaletteChange event appears to only reach so far into the GUI, explicitly asking to
4066 // UpdateUITheme is a decent work around
4067 if (event->type() == QEvent::PaletteChange) {
4068 const QPalette test_palette(qApp->palette());
4069 const QString current_theme = UISettings::values.theme;
4070 // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
4071 static QColor last_window_color;
4072 const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
4073 if (last_window_color != window_color && (current_theme == QStringLiteral("default") ||
4074 current_theme == QStringLiteral("colorful"))) {
4075 UpdateUITheme();
4076 }
4077 last_window_color = window_color;
4078 }
4079#endif // __linux__
4080 QWidget::changeEvent(event);
4081}
4082
4025#ifdef main 4083#ifdef main
4026#undef main 4084#undef main
4027#endif 4085#endif
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 23b67a14e..2d1c8857b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -251,6 +251,7 @@ private:
251 bool ConfirmForceLockedExit(); 251 bool ConfirmForceLockedExit();
252 void RequestGameExit(); 252 void RequestGameExit();
253 void RequestGameResume(); 253 void RequestGameResume();
254 void changeEvent(QEvent* event) override;
254 void closeEvent(QCloseEvent* event) override; 255 void closeEvent(QCloseEvent* event) override;
255 256
256#ifdef __linux__ 257#ifdef __linux__
@@ -392,6 +393,10 @@ private:
392 QTimer mouse_hide_timer; 393 QTimer mouse_hide_timer;
393 QTimer mouse_center_timer; 394 QTimer mouse_center_timer;
394 395
396 QString startup_icon_theme;
397 bool os_dark_mode = false;
398 bool check_dark_mode();
399
395 // FS 400 // FS
396 std::shared_ptr<FileSys::VfsFilesystem> vfs; 401 std::shared_ptr<FileSys::VfsFilesystem> vfs;
397 std::unique_ptr<FileSys::ManualContentProvider> provider; 402 std::unique_ptr<FileSys::ManualContentProvider> provider;