Merge 2bda317d7d into 15e6e48bef
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#define CONFIG_DIR "config"
|
||||
#define CRASH_DUMPS_DIR "crash_dumps"
|
||||
#define DUMP_DIR "dump"
|
||||
#define ICONS_DIR "icons"
|
||||
#define KEYS_DIR "keys"
|
||||
#define LOAD_DIR "load"
|
||||
#define LOG_DIR "log"
|
||||
@@ -24,7 +25,7 @@
|
||||
#define SDMC_DIR "sdmc"
|
||||
#define SHADER_DIR "shader"
|
||||
#define TAS_DIR "tas"
|
||||
#define ICONS_DIR "icons"
|
||||
#define THEMES_DIR "qt_themes"
|
||||
|
||||
// yuzu-specific files
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ public:
|
||||
GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config);
|
||||
GenerateYuzuPath(YuzuPath::CrashDumpsDir, yuzu_path / CRASH_DUMPS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR);
|
||||
GenerateYuzuPath(YuzuPath::IconsDir, yuzu_path / ICONS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR);
|
||||
GenerateYuzuPath(YuzuPath::LogDir, yuzu_path / LOG_DIR);
|
||||
@@ -130,7 +131,7 @@ public:
|
||||
GenerateYuzuPath(YuzuPath::SDMCDir, yuzu_path / SDMC_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ShaderDir, yuzu_path / SHADER_DIR);
|
||||
GenerateYuzuPath(YuzuPath::TASDir, yuzu_path / TAS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::IconsDir, yuzu_path / ICONS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ThemesDir, yuzu_path / THEMES_DIR);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -17,6 +17,7 @@ enum class YuzuPath {
|
||||
ConfigDir, // Where config files are stored.
|
||||
CrashDumpsDir, // Where crash dumps are stored.
|
||||
DumpDir, // Where dumped data is stored.
|
||||
IconsDir, // Where Icons for Windows shortcuts are stored.
|
||||
KeysDir, // Where key files are stored.
|
||||
LoadDir, // Where cheat/mod files are stored.
|
||||
LogDir, // Where log files are stored.
|
||||
@@ -26,7 +27,7 @@ enum class YuzuPath {
|
||||
SDMCDir, // Where the emulated SDMC is stored.
|
||||
ShaderDir, // Where shaders are stored.
|
||||
TASDir, // Where TAS scripts are stored.
|
||||
IconsDir, // Where Icons for Windows shortcuts are stored.
|
||||
ThemesDir, // Where users should put their custom themes
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,6 +67,7 @@ SWITCHABLE(u8, true);
|
||||
// Used in UISettings
|
||||
// TODO see if we can move this to uisettings.cpp
|
||||
SWITCHABLE(ConfirmStop, true);
|
||||
SWITCHABLE(DarkModeState, true);
|
||||
|
||||
#undef SETTING
|
||||
#undef SWITCHABLE
|
||||
|
||||
@@ -88,6 +88,7 @@ SWITCHABLE(u8, true);
|
||||
// Used in UISettings
|
||||
// TODO see if we can move this to uisettings.h
|
||||
SWITCHABLE(ConfirmStop, true);
|
||||
SWITCHABLE(DarkModeState, true);
|
||||
|
||||
#undef SETTING
|
||||
#undef SWITCHABLE
|
||||
|
||||
@@ -155,6 +155,8 @@ ENUM(ConsoleMode, Handheld, Docked);
|
||||
|
||||
ENUM(AppletMode, HLE, LLE);
|
||||
|
||||
ENUM(DarkModeState, Off, On, Auto);
|
||||
|
||||
template <typename Type>
|
||||
inline std::string CanonicalizeEnum(Type id) {
|
||||
const auto group = EnumMetadata<Type>::Canonicalizations();
|
||||
|
||||
@@ -164,7 +164,6 @@ p, li { white-space: pre-wrap; }
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../dist/qt_themes_default/default/default.qrc"/>
|
||||
<include location="../../dist/qt_themes/default/default.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
|
||||
@@ -384,10 +384,12 @@ bool QtControllerSelectorDialog::CheckIfParametersMet() {
|
||||
|
||||
void QtControllerSelectorDialog::SetSupportedControllers() {
|
||||
const QString theme = [] {
|
||||
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
return QStringLiteral("_dark");
|
||||
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
return QStringLiteral("_midnight");
|
||||
} else if (GMainWindow::CheckDarkMode() ||
|
||||
QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
// Use dark icons if current OS mode is dark, or the theme contains "dark" in its name
|
||||
return QStringLiteral("_dark");
|
||||
} else {
|
||||
return QString{};
|
||||
}
|
||||
@@ -572,10 +574,12 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
|
||||
}
|
||||
|
||||
const QString theme = [] {
|
||||
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
return QStringLiteral("_dark");
|
||||
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
return QStringLiteral("_midnight");
|
||||
} else if (GMainWindow::CheckDarkMode() ||
|
||||
QIcon::themeName().contains(QStringLiteral("dark"))) {
|
||||
// Use dark icons if current OS mode is dark, or the theme contains "dark" in its name
|
||||
return QStringLiteral("_dark");
|
||||
} else {
|
||||
return QString{};
|
||||
}
|
||||
|
||||
@@ -823,7 +823,9 @@ void QtSoftwareKeyboardDialog::SetControllerImage() {
|
||||
handheld->IsConnected() ? handheld->GetNpadStyleIndex() : player_1->GetNpadStyleIndex();
|
||||
|
||||
const QString theme = [] {
|
||||
if (QIcon::themeName().contains(QStringLiteral("dark")) ||
|
||||
// Use dark icons if current OS mode is dark, or the theme contains "dark", or "midnight" in
|
||||
// its name
|
||||
if (GMainWindow::CheckDarkMode() || QIcon::themeName().contains(QStringLiteral("dark")) ||
|
||||
QIcon::themeName().contains(QStringLiteral("midnight"))) {
|
||||
return QStringLiteral("_dark");
|
||||
} else {
|
||||
|
||||
@@ -1430,12 +1430,12 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="buttonShoulderButtonsButtonZLGroup">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>ZL</string>
|
||||
</property>
|
||||
@@ -1481,20 +1481,20 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderZLThreshold">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QSlider" name="sliderZLThreshold">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -1927,22 +1927,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderZRThreshold">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>15</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderZRThreshold">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <QString>
|
||||
#include <QToolButton>
|
||||
#include <QVariant>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/fs/path_util.h"
|
||||
@@ -29,6 +30,8 @@
|
||||
#include "ui_configure_ui.h"
|
||||
#include "yuzu/uisettings.h"
|
||||
|
||||
using Settings::DarkModeState;
|
||||
|
||||
namespace {
|
||||
constexpr std::array default_game_icon_sizes{
|
||||
std::make_pair(0, QT_TRANSLATE_NOOP("ConfigureUI", "None")),
|
||||
@@ -106,11 +109,56 @@ ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent)
|
||||
|
||||
InitializeLanguageComboBox();
|
||||
|
||||
for (const auto& theme : UISettings::themes) {
|
||||
for (const auto& theme : UISettings::included_themes) {
|
||||
ui->theme_combobox->addItem(QString::fromUtf8(theme.first),
|
||||
QString::fromUtf8(theme.second));
|
||||
}
|
||||
|
||||
// Add custom styles stored in yuzu directory
|
||||
const QDir local_dir(
|
||||
QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ThemesDir)));
|
||||
for (const QString& theme_dir :
|
||||
local_dir.entryList(QDir::NoDot | QDir::NoDotDot | QDir::Dirs)) {
|
||||
// folders ending with "_dark" are reserved for dark variant icons of other styles
|
||||
if (theme_dir.endsWith(QStringLiteral("_dark"))) {
|
||||
continue;
|
||||
}
|
||||
// Split at _ and capitalize words in name
|
||||
QStringList cased_name;
|
||||
for (QString word : theme_dir.split(QChar::fromLatin1('_'))) {
|
||||
cased_name.append(word.at(0).toUpper() + word.mid(1));
|
||||
}
|
||||
QString theme_name = cased_name.join(QChar::fromLatin1(' '));
|
||||
theme_name += QStringLiteral(" (%1)").arg(tr("Custom"));
|
||||
|
||||
ui->theme_combobox->addItem(theme_name, theme_dir);
|
||||
}
|
||||
|
||||
QByteArray current_qt_qpa = qgetenv("QT_QPA_PLATFORM");
|
||||
#ifdef _WIN32
|
||||
// Indicate which option needs a restart to be applied, depending on current environment
|
||||
// variable
|
||||
if (current_qt_qpa.contains("darkmode=2")) {
|
||||
ui->dark_mode_combobox->addItem(tr("Auto"), QVariant::fromValue(DarkModeState::Auto));
|
||||
ui->dark_mode_combobox->addItem(tr("Always On") + QStringLiteral(" (") +
|
||||
tr("Needs restart") + QStringLiteral(")"),
|
||||
QVariant::fromValue(DarkModeState::On));
|
||||
ui->dark_mode_combobox->addItem(tr("Always Off") + QStringLiteral(" (") +
|
||||
tr("Needs restart") + QStringLiteral(")"),
|
||||
QVariant::fromValue(DarkModeState::Off));
|
||||
} else {
|
||||
ui->dark_mode_combobox->addItem(tr("Auto") + QStringLiteral(" (") + tr("Needs restart") +
|
||||
QStringLiteral(")"),
|
||||
QVariant::fromValue(DarkModeState::Auto));
|
||||
ui->dark_mode_combobox->addItem(tr("Always On"), QVariant::fromValue(DarkModeState::On));
|
||||
ui->dark_mode_combobox->addItem(tr("Always Off"), QVariant::fromValue(DarkModeState::Off));
|
||||
}
|
||||
#else
|
||||
ui->dark_mode_combobox->addItem(tr("Auto"), QVariant::fromValue(DarkModeState::Auto));
|
||||
ui->dark_mode_combobox->addItem(tr("Always On"), QVariant::fromValue(DarkModeState::On));
|
||||
ui->dark_mode_combobox->addItem(tr("Always Off"), QVariant::fromValue(DarkModeState::Off));
|
||||
#endif
|
||||
|
||||
InitializeIconSizeComboBox();
|
||||
InitializeRowComboBoxes();
|
||||
|
||||
@@ -164,7 +212,9 @@ ConfigureUi::~ConfigureUi() = default;
|
||||
|
||||
void ConfigureUi::ApplyConfiguration() {
|
||||
UISettings::values.theme =
|
||||
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString();
|
||||
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
|
||||
UISettings::values.dark_mode_state =
|
||||
static_cast<DarkModeState>(ui->dark_mode_combobox->currentData().toUInt());
|
||||
UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
|
||||
UISettings::values.show_compat = ui->show_compat->isChecked();
|
||||
UISettings::values.show_size = ui->show_size->isChecked();
|
||||
@@ -191,8 +241,9 @@ void ConfigureUi::RequestGameListUpdate() {
|
||||
}
|
||||
|
||||
void ConfigureUi::SetConfiguration() {
|
||||
ui->theme_combobox->setCurrentIndex(
|
||||
ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme)));
|
||||
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
|
||||
ui->dark_mode_combobox->setCurrentIndex(
|
||||
ui->dark_mode_combobox->findData(QVariant::fromValue(UISettings::values.dark_mode_state)));
|
||||
ui->language_combobox->setCurrentIndex(ui->language_combobox->findData(
|
||||
QString::fromStdString(UISettings::values.language.GetValue())));
|
||||
ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue());
|
||||
|
||||
@@ -63,6 +63,20 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="dark_mode_label">
|
||||
<property name="text">
|
||||
<string>Dark Mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="dark_mode_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -260,9 +260,10 @@ void QtConfig::ReadShortcutValues() {
|
||||
void QtConfig::ReadUIValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Ui));
|
||||
|
||||
UISettings::values.theme = ReadStringSetting(
|
||||
std::string("theme"),
|
||||
std::string(UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second));
|
||||
UISettings::values.theme =
|
||||
QString::fromStdString(ReadStringSetting("theme", std::string(UISettings::default_theme)));
|
||||
UISettings::values.dark_mode_state = static_cast<DarkModeState>(
|
||||
ReadIntegerSetting("dark_mode_state", static_cast<int>(DarkModeState::Auto)));
|
||||
|
||||
ReadUIGamelistValues();
|
||||
ReadUILayoutValues();
|
||||
@@ -468,10 +469,10 @@ void QtConfig::SaveUIValues() {
|
||||
WriteCategory(Settings::Category::Ui);
|
||||
WriteCategory(Settings::Category::UiGeneral);
|
||||
|
||||
WriteStringSetting(
|
||||
std::string("theme"), UISettings::values.theme,
|
||||
std::make_optional(std::string(
|
||||
UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second)));
|
||||
WriteStringSetting("theme", UISettings::values.theme.toStdString(),
|
||||
std::make_optional(std::string(UISettings::default_theme)));
|
||||
WriteIntegerSetting("dark_mode_state", static_cast<int>(UISettings::values.dark_mode_state),
|
||||
std::make_optional(static_cast<int>(DarkModeState::Auto)));
|
||||
|
||||
SaveUIGamelistValues();
|
||||
SaveUILayoutValues();
|
||||
|
||||
@@ -35,9 +35,8 @@ constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{
|
||||
}};
|
||||
|
||||
bool IsDarkTheme() {
|
||||
const auto& theme = UISettings::values.theme;
|
||||
return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
|
||||
theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
|
||||
return UISettings::values.theme.contains(QStringLiteral("dark")) ||
|
||||
UISettings::values.theme.contains(QStringLiteral("midnight"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
+366
-85
@@ -8,6 +8,7 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#include "core/hle/service/am/applet_manager.h"
|
||||
#include "core/loader/nca.h"
|
||||
#include "core/tools/renderdoc.h"
|
||||
@@ -17,6 +18,9 @@
|
||||
#endif
|
||||
#ifdef __unix__
|
||||
#include <csignal>
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#include <QtDBus/QDBusMessage>
|
||||
#include <QtDBus/QtDBus>
|
||||
#include <sys/socket.h>
|
||||
#include "common/linux/gamemode.h"
|
||||
#endif
|
||||
@@ -301,18 +305,6 @@ 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());
|
||||
#else
|
||||
// TODO: Windows
|
||||
return false;
|
||||
#endif // __unix__
|
||||
}
|
||||
|
||||
GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan)
|
||||
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
|
||||
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)},
|
||||
@@ -333,15 +325,12 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
||||
ui->setupUi(this);
|
||||
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"));
|
||||
// fallback can only be set once, default theme icons are okay on both light/dark
|
||||
QIcon::setFallbackThemeName(QStringLiteral("default"));
|
||||
QIcon::setFallbackSearchPaths(QStringList(QStringLiteral(":/icons")));
|
||||
|
||||
default_theme_paths = QIcon::themeSearchPaths();
|
||||
UpdateUITheme();
|
||||
|
||||
SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue());
|
||||
discord_rpc->Update();
|
||||
@@ -359,6 +348,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
||||
|
||||
SetDefaultUIGeometry();
|
||||
RestoreUIState();
|
||||
UpdateUITheme();
|
||||
|
||||
ConnectMenuEvents();
|
||||
ConnectWidgetEvents();
|
||||
@@ -482,7 +472,10 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
||||
SDL_EnableScreenSaver();
|
||||
#endif
|
||||
|
||||
#ifdef __unix__
|
||||
SetupPrepareForSleep();
|
||||
ListenColorSchemeChange();
|
||||
#endif
|
||||
|
||||
QStringList args = QApplication::arguments();
|
||||
|
||||
@@ -1671,8 +1664,8 @@ void GMainWindow::OnDisplayTitleBars(bool show) {
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::SetupPrepareForSleep() {
|
||||
#ifdef __unix__
|
||||
void GMainWindow::SetupPrepareForSleep() {
|
||||
auto bus = QDBusConnection::systemBus();
|
||||
if (bus.isConnected()) {
|
||||
const bool success = bus.connect(
|
||||
@@ -1686,8 +1679,8 @@ void GMainWindow::SetupPrepareForSleep() {
|
||||
} else {
|
||||
LOG_WARNING(Frontend, "QDBusConnection system bus is not connected");
|
||||
}
|
||||
#endif // __unix__
|
||||
}
|
||||
#endif // __unix__
|
||||
|
||||
void GMainWindow::OnPrepareForSleep(bool prepare_sleep) {
|
||||
if (emu_thread == nullptr) {
|
||||
@@ -3731,7 +3724,8 @@ void GMainWindow::ResetWindowSize1080() {
|
||||
}
|
||||
|
||||
void GMainWindow::OnConfigure() {
|
||||
const auto old_theme = UISettings::values.theme;
|
||||
const QString old_theme = UISettings::values.theme;
|
||||
DarkModeState old_dark_mode_state = UISettings::values.dark_mode_state;
|
||||
const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue();
|
||||
const auto old_language_index = Settings::values.language_index.GetValue();
|
||||
#ifdef __unix__
|
||||
@@ -3792,7 +3786,8 @@ void GMainWindow::OnConfigure() {
|
||||
}
|
||||
InitializeHotkeys();
|
||||
|
||||
if (UISettings::values.theme != old_theme) {
|
||||
if (UISettings::values.theme != old_theme ||
|
||||
UISettings::values.dark_mode_state != old_dark_mode_state) {
|
||||
UpdateUITheme();
|
||||
}
|
||||
if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence) {
|
||||
@@ -3808,8 +3803,6 @@ void GMainWindow::OnConfigure() {
|
||||
multiplayer_state->UpdateCredentials();
|
||||
}
|
||||
|
||||
emit UpdateThemedIcons();
|
||||
|
||||
const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false);
|
||||
if (reload || Settings::values.language_index.GetValue() != old_language_index) {
|
||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||
@@ -5022,9 +5015,113 @@ void GMainWindow::filterBarSetChecked(bool state) {
|
||||
emit(OnToggleFilterBar());
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateUITheme() {
|
||||
const QString default_theme = QString::fromStdString(UISettings::default_theme.data());
|
||||
QString current_theme = UISettings::values.theme;
|
||||
if (current_theme.isEmpty()) {
|
||||
current_theme = default_theme;
|
||||
}
|
||||
|
||||
UpdateIcons(current_theme);
|
||||
|
||||
// Find the stylesheet to load
|
||||
QString theme_uri{QStringLiteral(":/%1/").arg(current_theme)};
|
||||
if (TryLoadStylesheet(theme_uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// New style not found in app, reading local directory
|
||||
LOG_DEBUG(Frontend, "Style \"{}\" not found in app package, reading local directory",
|
||||
current_theme.toStdString());
|
||||
|
||||
std::filesystem::path theme_path =
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::ThemesDir) / current_theme.toStdString();
|
||||
// Try to load theme locally
|
||||
if (TryLoadStylesheet(theme_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reading new theme failed, loading default stylesheet
|
||||
LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
|
||||
current_theme.toStdString());
|
||||
|
||||
theme_uri = QStringLiteral(":/%1/").arg(default_theme);
|
||||
if (TryLoadStylesheet(theme_uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reading default failed, loading empty stylesheet
|
||||
LOG_ERROR(Frontend, "Unable to set default style, stylesheet file not found");
|
||||
|
||||
qApp->setStyleSheet({});
|
||||
setStyleSheet({});
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateIcons(const QString& theme_used) {
|
||||
// Append _dark to the theme name to use dark variant icons
|
||||
if (CheckDarkMode()) {
|
||||
LOG_DEBUG(Frontend, "Using icons from: {}", theme_used.toStdString() + "_dark");
|
||||
QIcon::setThemeName(theme_used + QStringLiteral("_dark"));
|
||||
} else {
|
||||
LOG_DEBUG(Frontend, "Using icons from: {}", theme_used.toStdString());
|
||||
QIcon::setThemeName(theme_used);
|
||||
}
|
||||
|
||||
const QString theme_directory{
|
||||
QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ThemesDir))};
|
||||
|
||||
// Set path for default icons
|
||||
// Use icon resources from application binary and current theme local subdirectory, if it exists
|
||||
QStringList theme_paths;
|
||||
theme_paths << QString::fromStdString(":/icons") << QStringLiteral("%1").arg(theme_directory);
|
||||
QIcon::setThemeSearchPaths(theme_paths);
|
||||
|
||||
// Change current directory, to allow user themes to use their own icons
|
||||
QDir::setCurrent(QStringLiteral("%1/%2").arg(theme_directory, UISettings::values.theme));
|
||||
|
||||
emit UpdateThemedIcons();
|
||||
}
|
||||
|
||||
bool GMainWindow::TryLoadStylesheet(const QString& theme_uri) {
|
||||
QString style_path;
|
||||
|
||||
// Use themed stylesheet if it exists
|
||||
if (CheckDarkMode()) {
|
||||
style_path = theme_uri + QStringLiteral("dark.qss");
|
||||
} else {
|
||||
style_path = theme_uri + QStringLiteral("light.qss");
|
||||
}
|
||||
if (!QFile::exists(style_path)) {
|
||||
LOG_DEBUG(Frontend, "No themed (light/dark) stylesheet, using default one");
|
||||
// Use common stylesheet if themed one does not exist
|
||||
style_path = theme_uri + QStringLiteral("style.qss");
|
||||
}
|
||||
|
||||
// Loading stylesheet
|
||||
QFile style_file(style_path);
|
||||
if (style_file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
// Update the color palette before applying the stylesheet
|
||||
UpdateThemePalette();
|
||||
|
||||
LOG_DEBUG(Frontend, "Loading stylesheet in: {}", theme_uri.toStdString());
|
||||
QTextStream ts_theme(&style_file);
|
||||
qApp->setStyleSheet(ts_theme.readAll());
|
||||
setStyleSheet(ts_theme.readAll());
|
||||
SetCustomStylesheet();
|
||||
|
||||
return true;
|
||||
}
|
||||
// Opening the file failed
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GMainWindow::TryLoadStylesheet(const std::filesystem::path& theme_path) {
|
||||
return TryLoadStylesheet(QString::fromStdString(theme_path.string() + "/"));
|
||||
}
|
||||
|
||||
static void AdjustLinkColor() {
|
||||
QPalette new_pal(qApp->palette());
|
||||
if (UISettings::IsDarkTheme()) {
|
||||
if (GMainWindow::CheckDarkMode()) {
|
||||
new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
|
||||
} else {
|
||||
new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
|
||||
@@ -5034,54 +5131,233 @@ static void AdjustLinkColor() {
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateUITheme() {
|
||||
const QString default_theme = QString::fromUtf8(
|
||||
UISettings::themes[static_cast<size_t>(UISettings::default_theme)].second);
|
||||
QString current_theme = QString::fromStdString(UISettings::values.theme);
|
||||
|
||||
if (current_theme.isEmpty()) {
|
||||
current_theme = default_theme;
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateThemePalette() {
|
||||
QPalette themePalette(qApp->palette());
|
||||
#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()) {
|
||||
current_theme = QStringLiteral("default_dark");
|
||||
QColor dark(25, 25, 25);
|
||||
QString style_name;
|
||||
if (CheckDarkMode()) {
|
||||
// We check that the dark mode state is "On" and force a dark palette
|
||||
if (UISettings::values.dark_mode_state == DarkModeState::On) {
|
||||
// Set Default Windows Dark palette on Windows platforms to force Dark mode
|
||||
themePalette.setColor(QPalette::Window, Qt::black);
|
||||
themePalette.setColor(QPalette::WindowText, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
|
||||
themePalette.setColor(QPalette::Base, Qt::black);
|
||||
themePalette.setColor(QPalette::AlternateBase, dark);
|
||||
themePalette.setColor(QPalette::ToolTipBase, Qt::white);
|
||||
themePalette.setColor(QPalette::ToolTipText, Qt::black);
|
||||
themePalette.setColor(QPalette::Text, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
|
||||
themePalette.setColor(QPalette::Dark, QColor(128, 128, 128));
|
||||
themePalette.setColor(QPalette::Shadow, Qt::white);
|
||||
themePalette.setColor(QPalette::Button, Qt::black);
|
||||
themePalette.setColor(QPalette::ButtonText, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
|
||||
themePalette.setColor(QPalette::BrightText, QColor(192, 192, 192));
|
||||
themePalette.setColor(QPalette::Link, QColor(0, 140, 200));
|
||||
themePalette.setColor(QPalette::Highlight, QColor(0, 85, 255));
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(0, 85, 255));
|
||||
themePalette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white);
|
||||
}
|
||||
|
||||
// AlternateBase is kept at rgb(233, 231, 227) or rgb(245, 245, 245) on Windows dark
|
||||
// palette, fix this. Sometimes, it even is rgb(0, 0, 0), but uses a very light gray for
|
||||
// alternate rows, do not know why
|
||||
if (themePalette.alternateBase().color() == QColor(233, 231, 227) ||
|
||||
themePalette.alternateBase().color() == QColor(245, 245, 245) ||
|
||||
themePalette.alternateBase().color() == QColor(0, 0, 0)) {
|
||||
themePalette.setColor(QPalette::AlternateBase, dark);
|
||||
alternate_base_modified = true;
|
||||
}
|
||||
// Use fusion theme, since its close to windowsvista, but works well with a dark palette
|
||||
style_name = QStringLiteral("fusion");
|
||||
} else {
|
||||
QIcon::setThemeName(current_theme);
|
||||
QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons")));
|
||||
AdjustLinkColor();
|
||||
// Reset AlternateBase if it has been modified
|
||||
if (alternate_base_modified) {
|
||||
themePalette.setColor(QPalette::AlternateBase, QColor(245, 245, 245));
|
||||
alternate_base_modified = false;
|
||||
}
|
||||
// Reset light palette
|
||||
themePalette = this->style()->standardPalette();
|
||||
// Reset Windows theme to the default
|
||||
style_name = QStringLiteral("windowsvista");
|
||||
}
|
||||
LOG_DEBUG(Frontend, "Using style: {}", style_name.toStdString());
|
||||
qApp->setStyle(style_name);
|
||||
#else
|
||||
if (CheckDarkMode()) {
|
||||
// Set Dark palette on non Windows platforms (that may not have a dark palette)
|
||||
themePalette.setColor(QPalette::Window, QColor(53, 53, 53));
|
||||
themePalette.setColor(QPalette::WindowText, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
|
||||
themePalette.setColor(QPalette::Base, QColor(42, 42, 42));
|
||||
themePalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66));
|
||||
themePalette.setColor(QPalette::ToolTipBase, Qt::white);
|
||||
themePalette.setColor(QPalette::ToolTipText, QColor(53, 53, 53));
|
||||
themePalette.setColor(QPalette::Text, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
|
||||
themePalette.setColor(QPalette::Dark, QColor(35, 35, 35));
|
||||
themePalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
|
||||
themePalette.setColor(QPalette::Button, QColor(53, 53, 53));
|
||||
themePalette.setColor(QPalette::ButtonText, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
|
||||
themePalette.setColor(QPalette::BrightText, Qt::red);
|
||||
themePalette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
themePalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
|
||||
themePalette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
themePalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127));
|
||||
} else {
|
||||
// Reset light palette
|
||||
themePalette = this->style()->standardPalette();
|
||||
}
|
||||
#endif
|
||||
if (current_theme != default_theme) {
|
||||
QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)};
|
||||
QFile f(theme_uri);
|
||||
if (!f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
|
||||
UISettings::values.theme);
|
||||
current_theme = default_theme;
|
||||
qApp->setPalette(themePalette);
|
||||
AdjustLinkColor();
|
||||
}
|
||||
|
||||
void GMainWindow::SetCustomStylesheet() {
|
||||
setStyleSheet(QStringLiteral("QStatusBar::item { border: none; }"));
|
||||
|
||||
// Set "dark" qss property value, that may be used in stylesheets
|
||||
bool is_dark_mode = CheckDarkMode();
|
||||
if (renderer_status_button) {
|
||||
renderer_status_button->setProperty("dark", is_dark_mode);
|
||||
}
|
||||
if (gpu_accuracy_button) {
|
||||
gpu_accuracy_button->setProperty("dark", is_dark_mode);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
// Windows dark mode uses "fusion" style. Make it look like more "windowsvista" light style
|
||||
if (is_dark_mode) {
|
||||
/* the groove expands to the size of the slider by default. by giving it a height, it has a
|
||||
fixed size */
|
||||
/* handle is placed by default on the contents rect of the groove. Negative margin expands
|
||||
it outside the groove */
|
||||
setStyleSheet(QStringLiteral("QSlider:horizontal{ height:30px; }\
|
||||
QSlider::sub-page:horizontal { background-color: palette(highlight); }\
|
||||
QSlider::add-page:horizontal { background-color: palette(midlight);}\
|
||||
QSlider::groove:horizontal { border-width: 1px; margin: 1px 0; height: 2px;}\
|
||||
QSlider::handle:horizontal { border-width: 1px; border-style: solid; border-color: palette(dark);\
|
||||
width: 10px; margin: -10px 0px; }\
|
||||
QSlider::handle { background-color: palette(button); }\
|
||||
QSlider::handle:hover { background-color: palette(highlight); }"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
bool GMainWindow::ListenColorSchemeChange() {
|
||||
auto bus = QDBusConnection::sessionBus();
|
||||
if (bus.isConnected()) {
|
||||
const QString dbus_service = QStringLiteral("org.freedesktop.portal.Desktop");
|
||||
const QString dbus_path = QStringLiteral("/org/freedesktop/portal/desktop");
|
||||
const QString dbus_interface = QStringLiteral("org.freedesktop.portal.Settings");
|
||||
const QString dbus_method = QStringLiteral("SettingChanged");
|
||||
QStringList dbus_arguments;
|
||||
dbus_arguments << QStringLiteral("org.freedesktop.appearance")
|
||||
<< QStringLiteral("color-scheme");
|
||||
const QString dbus_signature = QStringLiteral("ssv");
|
||||
|
||||
LOG_INFO(Frontend, "Connected to DBus, listening for OS theme changes");
|
||||
return bus.connect(dbus_service, dbus_path, dbus_interface, dbus_method, dbus_arguments,
|
||||
dbus_signature, this, SLOT(UpdateUITheme()));
|
||||
}
|
||||
LOG_WARNING(Frontend, "Unable to connect to DBus to listen for OS theme changes");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool GMainWindow::CheckDarkMode() {
|
||||
bool is_dark_mode_auto;
|
||||
#ifdef _WIN32
|
||||
// Dark mode cannot be changed after the app started on Windows
|
||||
is_dark_mode_auto = qgetenv("QT_QPA_PLATFORM").contains("darkmode=2");
|
||||
#else
|
||||
is_dark_mode_auto = UISettings::values.dark_mode_state == DarkModeState::Auto;
|
||||
#endif
|
||||
if (!is_dark_mode_auto) {
|
||||
return UISettings::values.dark_mode_state == DarkModeState::On;
|
||||
} else {
|
||||
const QPalette current_palette(qApp->palette());
|
||||
#ifdef __unix__
|
||||
QProcess process;
|
||||
|
||||
// Using the freedesktop specifications for checking dark mode
|
||||
LOG_DEBUG(Frontend, "Retrieving theme from freedesktop color-scheme...");
|
||||
QStringList gdbus_arguments;
|
||||
gdbus_arguments << QStringLiteral("--dest=org.freedesktop.portal.Desktop")
|
||||
<< QStringLiteral("--object-path /org/freedesktop/portal/desktop")
|
||||
<< QStringLiteral("--method org.freedesktop.portal.Settings.Read")
|
||||
<< QStringLiteral("org.freedesktop.appearance color-scheme");
|
||||
process.start(QStringLiteral("gdbus call --session"), gdbus_arguments);
|
||||
process.waitForFinished(1000);
|
||||
QByteArray dbus_output = process.readAllStandardOutput();
|
||||
|
||||
if (!dbus_output.isEmpty()) {
|
||||
const int systemColorSchema = QString::fromUtf8(dbus_output).trimmed().right(1).toInt();
|
||||
return systemColorSchema == 1;
|
||||
}
|
||||
|
||||
// Try alternative for Gnome if the previous one failed
|
||||
QStringList gsettings_arguments;
|
||||
gsettings_arguments << QStringLiteral("get")
|
||||
<< QStringLiteral("org.gnome.desktop.interface")
|
||||
<< QStringLiteral("color-scheme");
|
||||
|
||||
LOG_DEBUG(Frontend, "failed, retrieving theme from gsettings color-scheme...");
|
||||
process.start(QStringLiteral("gsettings"), gsettings_arguments);
|
||||
process.waitForFinished(1000);
|
||||
QByteArray gsettings_output = process.readAllStandardOutput();
|
||||
|
||||
// Try older gtk-theme method if the previous one failed
|
||||
if (gsettings_output.isEmpty()) {
|
||||
LOG_DEBUG(Frontend, "failed, retrieving theme from gtk-theme...");
|
||||
gsettings_arguments.takeLast();
|
||||
gsettings_arguments << QStringLiteral("gtk-theme");
|
||||
|
||||
process.start(QStringLiteral("gsettings"), gsettings_arguments);
|
||||
process.waitForFinished(1000);
|
||||
gsettings_output = process.readAllStandardOutput();
|
||||
}
|
||||
|
||||
// Interpret gsettings value if it succeeded
|
||||
if (!gsettings_output.isEmpty()) {
|
||||
QString systeme_theme = QString::fromUtf8(gsettings_output);
|
||||
LOG_DEBUG(Frontend, "Gsettings output: {}", systeme_theme.toStdString());
|
||||
return systeme_theme.contains(QStringLiteral("dark"), Qt::CaseInsensitive);
|
||||
}
|
||||
LOG_DEBUG(Frontend, "failed, retrieving theme from palette");
|
||||
#endif
|
||||
// Use default method based on palette swap by OS. It is the only method on Windows with
|
||||
// Qt 5. Windows needs QT_QPA_PLATFORM env variable set to windows:darkmode=2 to force
|
||||
// palette change
|
||||
return (current_palette.color(QPalette::WindowText).lightness() >
|
||||
current_palette.color(QPalette::Window).lightness());
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::changeEvent(QEvent* event) {
|
||||
// PaletteChange event appears to only reach so far into the GUI, explicitly asking to
|
||||
// UpdateUITheme is a decent work around
|
||||
if (event->type() == QEvent::PaletteChange ||
|
||||
event->type() == QEvent::ApplicationPaletteChange) {
|
||||
LOG_DEBUG(Frontend,
|
||||
"Window color palette changed by event: {} (QEvent::PaletteChange is: {})",
|
||||
event->type(), QEvent::PaletteChange);
|
||||
const QPalette test_palette(qApp->palette());
|
||||
// Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
|
||||
const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
|
||||
|
||||
if (last_window_color != window_color) {
|
||||
last_window_color = window_color;
|
||||
|
||||
UpdateUITheme();
|
||||
}
|
||||
}
|
||||
|
||||
QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)};
|
||||
QFile f(theme_uri);
|
||||
if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
qApp->setStyleSheet(ts.readAll());
|
||||
setStyleSheet(ts.readAll());
|
||||
} else {
|
||||
LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found",
|
||||
UISettings::values.theme);
|
||||
qApp->setStyleSheet({});
|
||||
setStyleSheet({});
|
||||
}
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void GMainWindow::LoadTranslation() {
|
||||
@@ -5136,26 +5412,6 @@ void GMainWindow::SetGamemodeEnabled(bool state) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void GMainWindow::changeEvent(QEvent* event) {
|
||||
#ifdef __unix__
|
||||
// PaletteChange event appears to only reach so far into the GUI, explicitly asking to
|
||||
// UpdateUITheme is a decent work around
|
||||
if (event->type() == QEvent::PaletteChange) {
|
||||
const QPalette test_palette(qApp->palette());
|
||||
const QString current_theme = QString::fromStdString(UISettings::values.theme);
|
||||
// Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
|
||||
static QColor last_window_color;
|
||||
const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
|
||||
if (last_window_color != window_color && (current_theme == QStringLiteral("default") ||
|
||||
current_theme == QStringLiteral("colorful"))) {
|
||||
UpdateUITheme();
|
||||
}
|
||||
last_window_color = window_color;
|
||||
}
|
||||
#endif // __unix__
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
Service::AM::FrontendAppletParameters GMainWindow::ApplicationAppletParameters() {
|
||||
return Service::AM::FrontendAppletParameters{
|
||||
.applet_id = Service::AM::AppletId::Application,
|
||||
@@ -5282,6 +5538,31 @@ int main(int argc, char* argv[]) {
|
||||
QCoreApplication::setApplicationName(QStringLiteral("yuzu"));
|
||||
|
||||
#ifdef _WIN32
|
||||
QByteArray current_qt_qpa = qgetenv("QT_QPA_PLATFORM");
|
||||
// Follow dark mode setting, if the "-platform" launch option is not set.
|
||||
// Otherwise, just follow dark mode for the window decoration (title bar).
|
||||
if (!current_qt_qpa.contains(":darkmode=")) {
|
||||
if (UISettings::values.dark_mode_state == DarkModeState::Auto) {
|
||||
// When setting is Auto, force adapting window decoration and stylesheet palette to use
|
||||
// Windows theme. Default is darkmode:0, which always uses light palette
|
||||
if (current_qt_qpa.isEmpty()) {
|
||||
// Set the value
|
||||
qputenv("QT_QPA_PLATFORM", QByteArray("windows:darkmode=2"));
|
||||
} else {
|
||||
// Concatenate to the existing value
|
||||
qputenv("QT_QPA_PLATFORM", current_qt_qpa + ",darkmode=2");
|
||||
}
|
||||
} else {
|
||||
// When setting is no Auto, adapt window decoration to the palette used
|
||||
if (current_qt_qpa.isEmpty()) {
|
||||
// Set the value
|
||||
qputenv("QT_QPA_PLATFORM", QByteArray("windows:darkmode=1"));
|
||||
} else {
|
||||
// Concatenate to the existing value
|
||||
qputenv("QT_QPA_PLATFORM", current_qt_qpa + ",darkmode=1");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Increases the maximum open file limit to 8192
|
||||
_setmaxstdio(8192);
|
||||
#endif
|
||||
|
||||
+38
-5
@@ -23,9 +23,8 @@
|
||||
#include "yuzu/util/controller_navigation.h"
|
||||
|
||||
#ifdef __unix__
|
||||
#include <QSocketNotifier>
|
||||
#include <QVariant>
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#include <QtDBus/QtDBus>
|
||||
#endif
|
||||
|
||||
class QtConfig;
|
||||
@@ -166,7 +165,7 @@ class GMainWindow : public QMainWindow {
|
||||
|
||||
public:
|
||||
void filterBarSetChecked(bool state);
|
||||
void UpdateUITheme();
|
||||
static bool CheckDarkMode();
|
||||
explicit GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan);
|
||||
~GMainWindow() override;
|
||||
|
||||
@@ -258,12 +257,44 @@ private:
|
||||
|
||||
void SetDefaultUIGeometry();
|
||||
void RestoreUIState();
|
||||
/**
|
||||
* Load the icons used by the current theme. Use dark icons if the current mode is dark
|
||||
*/
|
||||
void UpdateIcons(const QString& theme_used);
|
||||
/**
|
||||
* Set the palette used by the stylsheet for the dark/light mode selected, according to the OS
|
||||
*/
|
||||
void UpdateThemePalette();
|
||||
/**
|
||||
* Try to load a stylesheet from its URI.
|
||||
* If the path starts with ":/", its embedded in the app, otherwise its in a local directory
|
||||
* @returns true if the text file could be opened as read-only
|
||||
*/
|
||||
bool TryLoadStylesheet(const QString& theme_uri);
|
||||
/**
|
||||
* Try to load a stylesheet from filesystem path
|
||||
* @returns true if the text file could be opened as read-only
|
||||
*/
|
||||
bool TryLoadStylesheet(const std::filesystem::path& theme_path);
|
||||
/**
|
||||
* Default customizations to the stylesheets
|
||||
*/
|
||||
void SetCustomStylesheet();
|
||||
#ifdef __unix__
|
||||
/**
|
||||
* Create a signal to update the UI theme when the OS color scheme is changed
|
||||
* @returns true if we could connect to dbus
|
||||
*/
|
||||
bool ListenColorSchemeChange();
|
||||
#endif
|
||||
|
||||
void ConnectWidgetEvents();
|
||||
void ConnectMenuEvents();
|
||||
void UpdateMenuState();
|
||||
|
||||
#ifdef __unix__
|
||||
void SetupPrepareForSleep();
|
||||
#endif
|
||||
|
||||
void PreventOSSleep();
|
||||
void AllowOSSleep();
|
||||
@@ -396,6 +427,7 @@ private slots:
|
||||
void ResetWindowSize720();
|
||||
void ResetWindowSize900();
|
||||
void ResetWindowSize1080();
|
||||
void UpdateUITheme();
|
||||
void OnAlbum();
|
||||
void OnCabinet(Service::NFP::CabinetMode mode);
|
||||
void OnMiiEdit();
|
||||
@@ -441,7 +473,7 @@ private:
|
||||
void OpenURL(const QUrl& url);
|
||||
void LoadTranslation();
|
||||
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
|
||||
bool CheckDarkMode();
|
||||
bool CheckSystemArchiveDecryption();
|
||||
bool CheckFirmwarePresence();
|
||||
void SetFirmwareVersion();
|
||||
void ConfigureFilesystemProvider(const std::string& filepath);
|
||||
@@ -525,7 +557,8 @@ private:
|
||||
QTimer update_input_timer;
|
||||
|
||||
QString startup_icon_theme;
|
||||
bool os_dark_mode = false;
|
||||
bool alternate_base_modified = false;
|
||||
QColor last_window_color;
|
||||
|
||||
// FS
|
||||
std::shared_ptr<FileSys::VfsFilesystem> vfs;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <cstring>
|
||||
#include <QByteArray>
|
||||
#include <processthreadsapi.h>
|
||||
#include <windows.h>
|
||||
#elif defined(YUZU_UNIX)
|
||||
|
||||
+5
-11
@@ -22,21 +22,15 @@ namespace FS = Common::FS;
|
||||
|
||||
namespace UISettings {
|
||||
|
||||
const Themes themes{{
|
||||
const Themes included_themes{{
|
||||
{"Default", "default"},
|
||||
{"Default Colorful", "colorful"},
|
||||
{"Dark", "qdarkstyle"},
|
||||
{"Dark Colorful", "colorful_dark"},
|
||||
{"Default monochrome", "monochrome"},
|
||||
{"Mine Shaft", "qdarkstyle"},
|
||||
{"Mine Shaft monochrome", "qdarkstyle_monochrome"},
|
||||
{"Midnight Blue", "qdarkstyle_midnight_blue"},
|
||||
{"Midnight Blue Colorful", "colorful_midnight_blue"},
|
||||
{"Midnight Blue monochrome", "qdarkstyle_midnight_blue_monochrome"},
|
||||
}};
|
||||
|
||||
bool IsDarkTheme() {
|
||||
const auto& theme = UISettings::values.theme;
|
||||
return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") ||
|
||||
theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue");
|
||||
}
|
||||
|
||||
Values values = {};
|
||||
|
||||
u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) {
|
||||
|
||||
+6
-20
@@ -18,6 +18,7 @@
|
||||
|
||||
using Settings::Category;
|
||||
using Settings::ConfirmStop;
|
||||
using Settings::DarkModeState;
|
||||
using Settings::Setting;
|
||||
using Settings::SwitchableSetting;
|
||||
|
||||
@@ -35,8 +36,6 @@ extern template class Setting<unsigned long long>;
|
||||
|
||||
namespace UISettings {
|
||||
|
||||
bool IsDarkTheme();
|
||||
|
||||
struct ContextualShortcut {
|
||||
std::string keyseq;
|
||||
std::string controller_keyseq;
|
||||
@@ -50,25 +49,10 @@ struct Shortcut {
|
||||
ContextualShortcut shortcut;
|
||||
};
|
||||
|
||||
enum class Theme {
|
||||
Default,
|
||||
DefaultColorful,
|
||||
Dark,
|
||||
DarkColorful,
|
||||
MidnightBlue,
|
||||
MidnightBlueColorful,
|
||||
};
|
||||
|
||||
static constexpr Theme default_theme{
|
||||
#ifdef _WIN32
|
||||
Theme::DarkColorful
|
||||
#else
|
||||
Theme::DefaultColorful
|
||||
#endif
|
||||
};
|
||||
static constexpr std::string_view default_theme{"default"};
|
||||
|
||||
using Themes = std::array<std::pair<const char*, const char*>, 6>;
|
||||
extern const Themes themes;
|
||||
extern const Themes included_themes;
|
||||
|
||||
struct GameDir {
|
||||
std::string path;
|
||||
@@ -160,7 +144,8 @@ struct Values {
|
||||
QStringList recent_files;
|
||||
Setting<std::string> language{linkage, {}, "language", Category::Paths};
|
||||
|
||||
std::string theme;
|
||||
QString theme;
|
||||
DarkModeState dark_mode_state;
|
||||
|
||||
// Shortcut name <Shortcut, context>
|
||||
std::vector<Shortcut> shortcuts;
|
||||
@@ -277,3 +262,4 @@ Q_DECLARE_METATYPE(Settings::RendererBackend);
|
||||
Q_DECLARE_METATYPE(Settings::ShaderBackend);
|
||||
Q_DECLARE_METATYPE(Settings::AstcRecompression);
|
||||
Q_DECLARE_METATYPE(Settings::AstcDecodeMode);
|
||||
Q_DECLARE_METATYPE(Settings::DarkModeState);
|
||||
|
||||
Reference in New Issue
Block a user