UI: Add dark mode setting to options

This commit is contained in:
Crementif 2025-07-02 14:13:25 +02:00
parent e00037a7fd
commit d076f3c1d7
6 changed files with 76 additions and 17 deletions

View file

@ -94,6 +94,14 @@ enum FullscreenScaling
kStretch, kStretch,
}; };
enum class MSWThemeOption : int
{
kAuto = 0,
kLight = 1,
kDark = 2,
};
ENABLE_ENUM_ITERATORS(MSWThemeOption, MSWThemeOption::kAuto, MSWThemeOption::kDark);
enum class ScreenPosition enum class ScreenPosition
{ {
kDisabled = 0, kDisabled = 0,

View file

@ -285,6 +285,16 @@ bool CemuApp::OnInit()
} }
SetTranslationCallback(TranslationCallback); SetTranslationCallback(TranslationCallback);
#if __WXMSW__
if (g_config.data().msw_theme.GetValue() == static_cast<int>(MSWThemeOption::kAuto))
{
MSWEnableDarkMode(DarkMode_Auto);
}
else if (g_config.data().msw_theme.GetValue() == static_cast<int>(MSWThemeOption::kDark))
{
MSWEnableDarkMode(DarkMode_Always);
}
#endif
for (auto&& path : failedWriteAccess) for (auto&& path : failedWriteAccess)
{ {

View file

@ -137,18 +137,40 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
box_sizer->Add(first_row, 1, wxEXPAND, 5); box_sizer->Add(first_row, 1, wxEXPAND, 5);
} }
#if BOOST_OS_WINDOWS
{ {
auto* second_row = new wxFlexGridSizer(0, 3, 0, 0); auto* second_row = new wxFlexGridSizer(0, 2, 0, 0);
second_row->SetFlexibleDirection(wxBOTH); second_row->SetFlexibleDirection(wxBOTH);
second_row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); second_row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
second_row->Add(new wxStaticText(box, wxID_ANY, _("Theme"), wxDefaultPosition, wxDefaultSize, 0), 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
m_msw_theme = new wxChoice(box, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_msw_theme->SetToolTip(_("Changes the Windows theme used by Cemu\nThis only works on Windows 10 and later\nA restart will be required for any changes to take effect"));
m_msw_theme->AppendString(_("Follow Windows theme"));
m_msw_theme->AppendString(_("Light Theme"));
m_msw_theme->AppendString(_("Dark Theme"));
m_msw_theme->SetSelection(0);
second_row->Add(m_msw_theme, 0, wxALL, 5);
box_sizer->Add(second_row, 0, wxEXPAND, 5);
}
#endif
{
auto* third_row = new wxFlexGridSizer(0, 3, 0, 0);
third_row->SetFlexibleDirection(wxBOTH);
third_row->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
sint32 checkboxCount = 0; sint32 checkboxCount = 0;
auto CountRowElement = [&]() auto CountRowElement = [&]()
{ {
checkboxCount++; checkboxCount++;
if(checkboxCount != 2) if(checkboxCount != 2)
return; return;
second_row->AddSpacer(10); third_row->AddSpacer(10);
checkboxCount = 0; checkboxCount = 0;
}; };
@ -156,26 +178,26 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
{ {
while(checkboxCount != 0) while(checkboxCount != 0)
CountRowElement(); CountRowElement();
second_row->AddSpacer(10); third_row->AddSpacer(10);
second_row->AddSpacer(10); third_row->AddSpacer(10);
second_row->AddSpacer(10); third_row->AddSpacer(10);
}; };
const int topflag = wxALIGN_CENTER_VERTICAL | wxALL; const int topflag = wxALIGN_CENTER_VERTICAL | wxALL;
m_save_window_position_size = new wxCheckBox(box, wxID_ANY, _("Remember main window position")); m_save_window_position_size = new wxCheckBox(box, wxID_ANY, _("Remember main window position"));
m_save_window_position_size->SetToolTip(_("Restores the last known window position and size when starting Cemu")); m_save_window_position_size->SetToolTip(_("Restores the last known window position and size when starting Cemu"));
second_row->Add(m_save_window_position_size, 0, topflag, 5); third_row->Add(m_save_window_position_size, 0, topflag, 5);
CountRowElement(); CountRowElement();
//second_row->AddSpacer(10); //second_row->AddSpacer(10);
m_save_padwindow_position_size = new wxCheckBox(box, wxID_ANY, _("Remember pad window position")); m_save_padwindow_position_size = new wxCheckBox(box, wxID_ANY, _("Remember pad window position"));
m_save_padwindow_position_size->SetToolTip(_("Restores the last known pad window position and size when opening it")); m_save_padwindow_position_size->SetToolTip(_("Restores the last known pad window position and size when opening it"));
second_row->Add(m_save_padwindow_position_size, 0, topflag, 5); third_row->Add(m_save_padwindow_position_size, 0, topflag, 5);
CountRowElement(); CountRowElement();
const int botflag = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM; const int botflag = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM;
m_discord_presence = new wxCheckBox(box, wxID_ANY, _("Discord Presence")); m_discord_presence = new wxCheckBox(box, wxID_ANY, _("Discord Presence"));
m_discord_presence->SetToolTip(_("Enables the Discord Rich Presence feature\nYou will also need to enable it in the Discord settings itself!")); m_discord_presence->SetToolTip(_("Enables the Discord Rich Presence feature\nYou will also need to enable it in the Discord settings itself!"));
second_row->Add(m_discord_presence, 0, botflag, 5); third_row->Add(m_discord_presence, 0, botflag, 5);
CountRowElement(); CountRowElement();
#ifndef ENABLE_DISCORD_RPC #ifndef ENABLE_DISCORD_RPC
m_discord_presence->Disable(); m_discord_presence->Disable();
@ -183,17 +205,17 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
//second_row->AddSpacer(10); //second_row->AddSpacer(10);
m_fullscreen_menubar = new wxCheckBox(box, wxID_ANY, _("Fullscreen menu bar")); m_fullscreen_menubar = new wxCheckBox(box, wxID_ANY, _("Fullscreen menu bar"));
m_fullscreen_menubar->SetToolTip(_("Displays the menu bar when Cemu is running in fullscreen mode and the mouse cursor is moved to the top")); m_fullscreen_menubar->SetToolTip(_("Displays the menu bar when Cemu is running in fullscreen mode and the mouse cursor is moved to the top"));
second_row->Add(m_fullscreen_menubar, 0, botflag, 5); third_row->Add(m_fullscreen_menubar, 0, botflag, 5);
CountRowElement(); CountRowElement();
m_save_screenshot = new wxCheckBox(box, wxID_ANY, _("Save screenshot")); m_save_screenshot = new wxCheckBox(box, wxID_ANY, _("Save screenshot"));
m_save_screenshot->SetToolTip(_("Pressing the screenshot key (F12) will save a screenshot directly to the screenshots folder")); m_save_screenshot->SetToolTip(_("Pressing the screenshot key (F12) will save a screenshot directly to the screenshots folder"));
second_row->Add(m_save_screenshot, 0, botflag, 5); third_row->Add(m_save_screenshot, 0, botflag, 5);
CountRowElement(); CountRowElement();
m_disable_screensaver = new wxCheckBox(box, wxID_ANY, _("Disable screen saver")); m_disable_screensaver = new wxCheckBox(box, wxID_ANY, _("Disable screen saver"));
m_disable_screensaver->SetToolTip(_("Prevents the system from activating the screen saver or going to sleep while running a game.")); m_disable_screensaver->SetToolTip(_("Prevents the system from activating the screen saver or going to sleep while running a game."));
second_row->Add(m_disable_screensaver, 0, botflag, 5); third_row->Add(m_disable_screensaver, 0, botflag, 5);
CountRowElement(); CountRowElement();
// Enable/disable feral interactive gamemode // Enable/disable feral interactive gamemode
@ -210,24 +232,24 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
#endif #endif
m_play_boot_sound = new wxCheckBox(box, wxID_ANY, _("Enable intro sound")); m_play_boot_sound = new wxCheckBox(box, wxID_ANY, _("Enable intro sound"));
m_play_boot_sound->SetToolTip(_("Play bootSound file while compiling shaders/pipelines.")); m_play_boot_sound->SetToolTip(_("Play bootSound file while compiling shaders/pipelines."));
second_row->Add(m_play_boot_sound, 0, botflag, 5); third_row->Add(m_play_boot_sound, 0, botflag, 5);
CountRowElement(); CountRowElement();
m_auto_update = new wxCheckBox(box, wxID_ANY, _("Automatically check for updates")); m_auto_update = new wxCheckBox(box, wxID_ANY, _("Automatically check for updates"));
m_auto_update->SetToolTip(_("Automatically checks for new cemu versions on startup")); m_auto_update->SetToolTip(_("Automatically checks for new cemu versions on startup"));
second_row->Add(m_auto_update, 0, botflag, 5); third_row->Add(m_auto_update, 0, botflag, 5);
CountRowElement(); CountRowElement();
m_receive_untested_releases = new wxCheckBox(box, wxID_ANY, _("Receive untested updates")); m_receive_untested_releases = new wxCheckBox(box, wxID_ANY, _("Receive untested updates"));
m_receive_untested_releases->SetToolTip(_("When checking for updates, include brand new and untested releases. These may contain bugs!")); m_receive_untested_releases->SetToolTip(_("When checking for updates, include brand new and untested releases. These may contain bugs!"));
second_row->Add(m_receive_untested_releases, 0, botflag, 5); third_row->Add(m_receive_untested_releases, 0, botflag, 5);
#if BOOST_OS_LINUX #if BOOST_OS_LINUX
if (!std::getenv("APPIMAGE")) { if (!std::getenv("APPIMAGE")) {
m_auto_update->Disable(); m_auto_update->Disable();
} }
#endif #endif
box_sizer->Add(second_row, 0, wxEXPAND, 5); box_sizer->Add(third_row, 0, wxEXPAND, 5);
} }
general_panel_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5); general_panel_sizer->Add(box_sizer, 0, wxEXPAND | wxALL, 5);
@ -268,7 +290,7 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook)
auto* general_gamepath_sizer = new wxStaticBoxSizer(general_gamepath_box, wxVERTICAL); auto* general_gamepath_sizer = new wxStaticBoxSizer(general_gamepath_box, wxVERTICAL);
m_game_paths = new wxListBox(general_gamepath_box, wxID_ANY); m_game_paths = new wxListBox(general_gamepath_box, wxID_ANY);
m_game_paths->SetMinSize(wxSize(150, 100)); m_game_paths->SetMinSize(wxSize(150, 70));
m_game_paths->SetToolTip(_("Add the root directory of your game(s). It will scan all directories in it for games")); m_game_paths->SetToolTip(_("Add the root directory of your game(s). It will scan all directories in it for games"));
general_gamepath_sizer->Add(m_game_paths, 1, wxALL | wxEXPAND, 5); general_gamepath_sizer->Add(m_game_paths, 1, wxALL | wxEXPAND, 5);
@ -969,6 +991,9 @@ void GeneralSettings2::StoreConfig()
wxGuiConfig.receive_untested_updates = m_receive_untested_releases->IsChecked(); wxGuiConfig.receive_untested_updates = m_receive_untested_releases->IsChecked();
#if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE)
wxGuiConfig.feral_gamemode = m_feral_gamemode->IsChecked(); wxGuiConfig.feral_gamemode = m_feral_gamemode->IsChecked();
#endif
#if BOOST_OS_WINDOWS
config.msw_theme = m_msw_theme->GetSelection();
#endif #endif
config.play_boot_sound = m_play_boot_sound->IsChecked(); config.play_boot_sound = m_play_boot_sound->IsChecked();
config.disable_screensaver = m_disable_screensaver->IsChecked(); config.disable_screensaver = m_disable_screensaver->IsChecked();
@ -1144,7 +1169,6 @@ void GeneralSettings2::ValidateConfig()
void GeneralSettings2::DisableSettings(bool game_launched) void GeneralSettings2::DisableSettings(bool game_launched)
{ {
} }
void GeneralSettings2::OnAudioLatencyChanged(wxCommandEvent& event) void GeneralSettings2::OnAudioLatencyChanged(wxCommandEvent& event)
@ -1632,6 +1656,9 @@ void GeneralSettings2::ApplyConfig()
m_disable_screensaver->SetValue(config.disable_screensaver); m_disable_screensaver->SetValue(config.disable_screensaver);
m_play_boot_sound->SetValue(config.play_boot_sound); m_play_boot_sound->SetValue(config.play_boot_sound);
#if BOOST_OS_WINDOWS
m_msw_theme->SetSelection(config.msw_theme);
#endif
#if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE)
m_feral_gamemode->SetValue(wxGUIconfig.feral_gamemode); m_feral_gamemode->SetValue(wxGUIconfig.feral_gamemode);
#endif #endif

View file

@ -44,6 +44,9 @@ private:
wxCheckBox* m_auto_update, *m_receive_untested_releases, *m_save_screenshot; wxCheckBox* m_auto_update, *m_receive_untested_releases, *m_save_screenshot;
wxCheckBox* m_disable_screensaver; wxCheckBox* m_disable_screensaver;
wxCheckBox* m_play_boot_sound; wxCheckBox* m_play_boot_sound;
#if BOOST_OS_WINDOWS
wxChoice* m_msw_theme;
#endif
#if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE)
wxCheckBox* m_feral_gamemode; wxCheckBox* m_feral_gamemode;
#endif #endif

View file

@ -26,6 +26,7 @@ void wxCemuConfig::AddRecentNfcFile(std::string_view file)
void wxCemuConfig::Load(XMLConfigParser& parser) void wxCemuConfig::Load(XMLConfigParser& parser)
{ {
language = parser.get<sint32>("language", wxLANGUAGE_DEFAULT); language = parser.get<sint32>("language", wxLANGUAGE_DEFAULT);
msw_theme = parser.get<sint32>("msw_theme", msw_theme);
use_discord_presence = parser.get("use_discord_presence", true); use_discord_presence = parser.get("use_discord_presence", true);
fullscreen_menubar = parser.get("fullscreen_menubar", false); fullscreen_menubar = parser.get("fullscreen_menubar", false);
feral_gamemode = parser.get("feral_gamemode", false); feral_gamemode = parser.get("feral_gamemode", false);
@ -120,6 +121,7 @@ void wxCemuConfig::Save(XMLConfigParser& config)
{ {
// general settings // general settings
config.set<sint32>("language", language); config.set<sint32>("language", language);
config.set<sint32>("msw_theme", msw_theme);
config.set<bool>("use_discord_presence", use_discord_presence); config.set<bool>("use_discord_presence", use_discord_presence);
config.set<bool>("fullscreen_menubar", fullscreen_menubar); config.set<bool>("fullscreen_menubar", fullscreen_menubar);
config.set<bool>("feral_gamemode", feral_gamemode); config.set<bool>("feral_gamemode", feral_gamemode);

View file

@ -20,6 +20,14 @@ namespace DefaultColumnSize
}; };
}; };
enum class MSWThemeOption : int
{
kAuto = 0,
kLight = 1,
kDark = 2,
};
ENABLE_ENUM_ITERATORS(MSWThemeOption, MSWThemeOption::kAuto, MSWThemeOption::kDark);
typedef union typedef union
{ {
struct struct
@ -67,6 +75,7 @@ struct fmt::formatter<sHotkeyCfg> : formatter<string_view>
struct wxCemuConfig struct wxCemuConfig
{ {
ConfigValue<sint32> language{wxLANGUAGE_DEFAULT}; ConfigValue<sint32> language{wxLANGUAGE_DEFAULT};
ConfigValue<int> msw_theme { static_cast<int>(MSWThemeOption::kAuto) };
ConfigValue<bool> use_discord_presence{true}; ConfigValue<bool> use_discord_presence{true};
ConfigValue<bool> fullscreen{ false }; ConfigValue<bool> fullscreen{ false };
ConfigValue<bool> fullscreen_menubar{false}; ConfigValue<bool> fullscreen_menubar{false};