diff --git a/src/config/CemuConfig.h b/src/config/CemuConfig.h index ff892fb8..12226247 100644 --- a/src/config/CemuConfig.h +++ b/src/config/CemuConfig.h @@ -94,6 +94,14 @@ enum FullscreenScaling kStretch, }; +enum class MSWThemeOption : int +{ + kAuto = 0, + kLight = 1, + kDark = 2, +}; +ENABLE_ENUM_ITERATORS(MSWThemeOption, MSWThemeOption::kAuto, MSWThemeOption::kDark); + enum class ScreenPosition { kDisabled = 0, diff --git a/src/gui/wxgui/CemuApp.cpp b/src/gui/wxgui/CemuApp.cpp index 78f4b83f..35027eaf 100644 --- a/src/gui/wxgui/CemuApp.cpp +++ b/src/gui/wxgui/CemuApp.cpp @@ -285,6 +285,16 @@ bool CemuApp::OnInit() } SetTranslationCallback(TranslationCallback); +#if __WXMSW__ + if (g_config.data().msw_theme.GetValue() == static_cast(MSWThemeOption::kAuto)) + { + MSWEnableDarkMode(DarkMode_Auto); + } + else if (g_config.data().msw_theme.GetValue() == static_cast(MSWThemeOption::kDark)) + { + MSWEnableDarkMode(DarkMode_Always); + } +#endif for (auto&& path : failedWriteAccess) { diff --git a/src/gui/wxgui/GeneralSettings2.cpp b/src/gui/wxgui/GeneralSettings2.cpp index ac993700..2143adda 100644 --- a/src/gui/wxgui/GeneralSettings2.cpp +++ b/src/gui/wxgui/GeneralSettings2.cpp @@ -137,18 +137,40 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook) 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->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; auto CountRowElement = [&]() { checkboxCount++; if(checkboxCount != 2) return; - second_row->AddSpacer(10); + third_row->AddSpacer(10); checkboxCount = 0; }; @@ -156,26 +178,26 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook) { while(checkboxCount != 0) CountRowElement(); - second_row->AddSpacer(10); - second_row->AddSpacer(10); - second_row->AddSpacer(10); + third_row->AddSpacer(10); + third_row->AddSpacer(10); + third_row->AddSpacer(10); }; 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->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(); //second_row->AddSpacer(10); 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")); - second_row->Add(m_save_padwindow_position_size, 0, topflag, 5); + third_row->Add(m_save_padwindow_position_size, 0, topflag, 5); CountRowElement(); const int botflag = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM; 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!")); - second_row->Add(m_discord_presence, 0, botflag, 5); + third_row->Add(m_discord_presence, 0, botflag, 5); CountRowElement(); #ifndef ENABLE_DISCORD_RPC m_discord_presence->Disable(); @@ -183,17 +205,17 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook) //second_row->AddSpacer(10); 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")); - second_row->Add(m_fullscreen_menubar, 0, botflag, 5); + third_row->Add(m_fullscreen_menubar, 0, botflag, 5); CountRowElement(); 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")); - second_row->Add(m_save_screenshot, 0, botflag, 5); + third_row->Add(m_save_screenshot, 0, botflag, 5); CountRowElement(); 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.")); - second_row->Add(m_disable_screensaver, 0, botflag, 5); + third_row->Add(m_disable_screensaver, 0, botflag, 5); CountRowElement(); // Enable/disable feral interactive gamemode @@ -210,24 +232,24 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook) #endif m_play_boot_sound = new wxCheckBox(box, wxID_ANY, _("Enable intro sound")); 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(); m_auto_update = new wxCheckBox(box, wxID_ANY, _("Automatically check for updates")); 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(); 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!")); - 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 (!std::getenv("APPIMAGE")) { m_auto_update->Disable(); } #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); @@ -268,7 +290,7 @@ wxPanel* GeneralSettings2::AddGeneralPage(wxNotebook* notebook) auto* general_gamepath_sizer = new wxStaticBoxSizer(general_gamepath_box, wxVERTICAL); 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")); 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(); #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) wxGuiConfig.feral_gamemode = m_feral_gamemode->IsChecked(); +#endif +#if BOOST_OS_WINDOWS + config.msw_theme = m_msw_theme->GetSelection(); #endif config.play_boot_sound = m_play_boot_sound->IsChecked(); config.disable_screensaver = m_disable_screensaver->IsChecked(); @@ -1144,7 +1169,6 @@ void GeneralSettings2::ValidateConfig() void GeneralSettings2::DisableSettings(bool game_launched) { - } void GeneralSettings2::OnAudioLatencyChanged(wxCommandEvent& event) @@ -1632,6 +1656,9 @@ void GeneralSettings2::ApplyConfig() m_disable_screensaver->SetValue(config.disable_screensaver); 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) m_feral_gamemode->SetValue(wxGUIconfig.feral_gamemode); #endif diff --git a/src/gui/wxgui/GeneralSettings2.h b/src/gui/wxgui/GeneralSettings2.h index 5e27d6e2..fb0cfe87 100644 --- a/src/gui/wxgui/GeneralSettings2.h +++ b/src/gui/wxgui/GeneralSettings2.h @@ -44,6 +44,9 @@ private: wxCheckBox* m_auto_update, *m_receive_untested_releases, *m_save_screenshot; wxCheckBox* m_disable_screensaver; wxCheckBox* m_play_boot_sound; +#if BOOST_OS_WINDOWS + wxChoice* m_msw_theme; +#endif #if BOOST_OS_LINUX && defined(ENABLE_FERAL_GAMEMODE) wxCheckBox* m_feral_gamemode; #endif diff --git a/src/gui/wxgui/wxCemuConfig.cpp b/src/gui/wxgui/wxCemuConfig.cpp index 87355797..ba88a358 100644 --- a/src/gui/wxgui/wxCemuConfig.cpp +++ b/src/gui/wxgui/wxCemuConfig.cpp @@ -26,6 +26,7 @@ void wxCemuConfig::AddRecentNfcFile(std::string_view file) void wxCemuConfig::Load(XMLConfigParser& parser) { language = parser.get("language", wxLANGUAGE_DEFAULT); + msw_theme = parser.get("msw_theme", msw_theme); use_discord_presence = parser.get("use_discord_presence", true); fullscreen_menubar = parser.get("fullscreen_menubar", false); feral_gamemode = parser.get("feral_gamemode", false); @@ -120,6 +121,7 @@ void wxCemuConfig::Save(XMLConfigParser& config) { // general settings config.set("language", language); + config.set("msw_theme", msw_theme); config.set("use_discord_presence", use_discord_presence); config.set("fullscreen_menubar", fullscreen_menubar); config.set("feral_gamemode", feral_gamemode); diff --git a/src/gui/wxgui/wxCemuConfig.h b/src/gui/wxgui/wxCemuConfig.h index 8024e27e..9463d4df 100644 --- a/src/gui/wxgui/wxCemuConfig.h +++ b/src/gui/wxgui/wxCemuConfig.h @@ -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 { struct @@ -67,6 +75,7 @@ struct fmt::formatter : formatter struct wxCemuConfig { ConfigValue language{wxLANGUAGE_DEFAULT}; + ConfigValue msw_theme { static_cast(MSWThemeOption::kAuto) }; ConfigValue use_discord_presence{true}; ConfigValue fullscreen{ false }; ConfigValue fullscreen_menubar{false};