FullscreenUI: Add 'Automatic' theme that syncs with Qt

This commit is contained in:
Stenzek 2025-03-15 00:42:02 +10:00
parent 6e27b8ab91
commit 1189f53840
No known key found for this signature in database
12 changed files with 191 additions and 76 deletions

View File

@ -478,6 +478,13 @@ static constexpr const std::array s_ps_button_mapping{
std::make_pair(ICON_PF_RIGHT_TRIGGER_RT, ICON_PF_RIGHT_TRIGGER_R2),
};
static constexpr std::array s_theme_names = {FSUI_NSTR("Automatic"), FSUI_NSTR("Dark"), FSUI_NSTR("Light"),
FSUI_NSTR("AMOLED"), FSUI_NSTR("Cobalt Sky"), FSUI_NSTR("Grey Matter"),
FSUI_NSTR("Pinky Pals"), FSUI_NSTR("Purple Rain")};
static constexpr std::array s_theme_values = {"", "Dark", "Light", "AMOLED",
"CobaltSky", "GreyMatter", "PinkyPals", "PurpleRain"};
//////////////////////////////////////////////////////////////////////////
// State
//////////////////////////////////////////////////////////////////////////
@ -649,6 +656,30 @@ void ImGuiFullscreen::GetInputDialogHelpText(SmallStringBase& dest)
}
}
std::vector<std::string_view> FullscreenUI::GetThemeNames()
{
std::vector<std::string_view> ret;
ret.reserve(std::size(s_theme_names));
for (const char* name : s_theme_names)
ret.push_back(TRANSLATE_SV("FullscreenUI", name));
return ret;
}
std::span<const char* const> FullscreenUI::GetThemeConfigNames()
{
return s_theme_values;
}
void FullscreenUI::SetTheme()
{
TinyString theme =
Host::GetBaseTinyStringSettingValue("UI", "FullscreenUITheme", Host::GetDefaultFullscreenUITheme());
if (theme.empty())
theme = Host::GetDefaultFullscreenUITheme();
ImGuiFullscreen::SetTheme(theme);
}
//////////////////////////////////////////////////////////////////////////
// Main
//////////////////////////////////////////////////////////////////////////
@ -3701,13 +3732,6 @@ void FullscreenUI::DrawInterfaceSettingsPage()
{
SettingsInterface* bsi = GetEditingSettingsInterface();
static constexpr const char* s_theme_name[] = {
FSUI_NSTR("Dark"), FSUI_NSTR("Light"), FSUI_NSTR("AMOLED"), FSUI_NSTR("Cobalt Sky"),
FSUI_NSTR("Grey Matter"), FSUI_NSTR("Pinky Pals"), FSUI_NSTR("Purple Rain")};
static constexpr const char* s_theme_value[] = {"Dark", "Light", "AMOLED", "CobaltSky",
"GreyMatter", "PinkyPals", "PurpleRain"};
BeginMenuButtons();
MenuHeading(FSUI_CSTR("Behavior"));
@ -3782,10 +3806,11 @@ void FullscreenUI::DrawInterfaceSettingsPage()
}
}
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_PAINT_BRUSH, "Theme"),
FSUI_CSTR("Selects the color style to be used for Big Picture UI."), "UI", "FullscreenUITheme",
"Dark", s_theme_name, s_theme_value, true, LAYOUT_MENU_BUTTON_HEIGHT, UIStyle.LargeFont,
UIStyle.MediumFont, &ImGuiFullscreen::SetTheme);
DrawStringListSetting(
bsi, FSUI_ICONSTR(ICON_FA_PAINT_BRUSH, "Theme"),
FSUI_CSTR("Selects the color style to be used for Big Picture UI."), "UI", "FullscreenUITheme", "Dark",
s_theme_names, s_theme_values, true, LAYOUT_MENU_BUTTON_HEIGHT, UIStyle.LargeFont, UIStyle.MediumFont,
[](std::string_view) { Host::RunOnCPUThread([]() { GPUThread::RunOnThread(&FullscreenUI::SetTheme); }); });
if (const TinyString current_value =
bsi->GetTinyStringValue("Main", "FullscreenUIBackground", DEFAULT_BACKGROUND_NAME);
@ -8750,6 +8775,7 @@ TRANSLATE_NOOP("FullscreenUI", "Audio Backend");
TRANSLATE_NOOP("FullscreenUI", "Audio Control");
TRANSLATE_NOOP("FullscreenUI", "Audio Settings");
TRANSLATE_NOOP("FullscreenUI", "Auto-Detect");
TRANSLATE_NOOP("FullscreenUI", "Automatic");
TRANSLATE_NOOP("FullscreenUI", "Automatic Mapping");
TRANSLATE_NOOP("FullscreenUI", "Automatic based on window size");
TRANSLATE_NOOP("FullscreenUI", "Automatic mapping completed for {}.");

View File

@ -9,8 +9,10 @@
#include <functional>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#include <vector>
class SmallStringBase;
@ -39,8 +41,13 @@ void UpdateLoadingScreen(std::string_view image, std::string_view message, s32 p
s32 progress_value = -1);
void CloseLoadingScreen();
void SetTheme();
#ifndef __ANDROID__
std::vector<std::string_view> GetThemeNames();
std::span<const char* const> GetThemeConfigNames();
void OpenPauseMenu();
void OpenCheatsMenu();
void OpenDiscChangeMenu();

View File

@ -1424,6 +1424,11 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo
callback(std::string());
}
const char* Host::GetDefaultFullscreenUITheme()
{
return "";
}
bool Host::ShouldPreferHostFileSelector()
{
return false;

View File

@ -7,6 +7,7 @@
#include "settingwidgetbinder.h"
#include "ui_texturereplacementsettingsdialog.h"
#include "core/fullscreen_ui.h"
#include "core/game_database.h"
#include "core/gpu.h"
#include "core/settings.h"
@ -192,6 +193,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.osdScale, "Display", "OSDScale", 100);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.osdMargin, "Display", "OSDMargin",
ImGuiManager::DEFAULT_SCREEN_MARGIN);
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.fullscreenUITheme, "UI", "FullscreenUITheme");
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showOSDMessages, "Display", "ShowOSDMessages", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showFPS, "Display", "ShowFPS", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showSpeed, "Display", "ShowSpeed", false);
@ -206,6 +208,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showFrameTimes, "Display", "ShowFrameTimes", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.showSettings, "Display", "ShowEnhancements", false);
connect(m_ui.fullscreenUITheme, QOverload<int>::of(&QComboBox::currentIndexChanged), g_emu_thread,
&EmuThread::updateFullscreenUITheme);
// Capture Tab
SettingWidgetBinder::BindWidgetToEnumSetting(
@ -520,6 +525,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
dialog->registerWidgetHelp(
m_ui.osdScale, tr("OSD Scale"), tr("100%"),
tr("Changes the size at which on-screen elements, including status and messages are displayed."));
dialog->registerWidgetHelp(m_ui.fullscreenUITheme, tr("Theme"), tr("Automatic"),
tr("Determines the theme to use for on-screen display elements and the Big Picture UI."));
dialog->registerWidgetHelp(m_ui.showOSDMessages, tr("Show OSD Messages"), tr("Checked"),
tr("Shows on-screen-display messages when events occur such as save states being "
"created/loaded, screenshots being taken, etc."));
@ -724,6 +731,16 @@ void GraphicsSettingsWidget::setupAdditionalUi()
QString::fromUtf8(Settings::GetForceVideoTimingDisplayName(static_cast<ForceVideoTimingMode>(i))));
}
// OSD Tab
const std::vector<std::string_view> fsui_theme_names = FullscreenUI::GetThemeNames();
const std::span<const char* const> fsui_theme_values = FullscreenUI::GetThemeConfigNames();
for (size_t i = 0; i < fsui_theme_names.size(); i++)
{
m_ui.fullscreenUITheme->addItem(QtUtils::StringViewToQString(fsui_theme_names[i]),
QString::fromUtf8(fsui_theme_values[i]));
}
// Advanced Tab
for (u32 i = 0; i < static_cast<u32>(DisplayExclusiveFullscreenControl::Count); i++)

View File

@ -680,7 +680,7 @@
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="3" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QCheckBox" name="showFPS">
@ -785,6 +785,16 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Theme:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="fullscreenUITheme"/>
</item>
</layout>
</widget>
</item>

View File

@ -2238,6 +2238,7 @@ void MainWindow::connectSignals()
void MainWindow::updateTheme()
{
QtHost::UpdateApplicationTheme();
g_emu_thread->updateFullscreenUITheme();
reloadThemeSpecificImages();
}

View File

@ -1857,6 +1857,19 @@ void EmuThread::setGPUThreadRunIdle(bool active)
g_emu_thread->startBackgroundControllerPollTimer();
}
void EmuThread::updateFullscreenUITheme()
{
if (!isCurrentThread())
{
QMetaObject::invokeMethod(this, &EmuThread::updateFullscreenUITheme, Qt::QueuedConnection);
return;
}
// don't bother if nothing is running
if (GPUThread::IsFullscreenUIRequested() || GPUThread::IsGPUBackendRequested())
GPUThread::RunOnThread(&FullscreenUI::SetTheme);
}
void EmuThread::start()
{
AssertMsg(!g_emu_thread, "Emu thread does not exist");

View File

@ -214,6 +214,7 @@ public Q_SLOTS:
void captureGPUFrameDump();
void startControllerTest();
void setGPUThreadRunIdle(bool active);
void updateFullscreenUITheme();
private Q_SLOTS:
void stopInThread();

View File

@ -1,9 +1,11 @@
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com> and contributors.
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#include "interfacesettingswidget.h"
#include "qthost.h"
#include "util/imgui_fullscreen.h"
#include "common/path.h"
#include <QtCore/QFile>
@ -40,7 +42,8 @@ void QtHost::UpdateApplicationTheme()
void QtHost::SetStyleFromSettings()
{
const std::string theme = Host::GetBaseStringSettingValue("UI", "Theme", InterfaceSettingsWidget::DEFAULT_THEME_NAME);
const TinyString theme =
Host::GetBaseTinyStringSettingValue("UI", "Theme", InterfaceSettingsWidget::DEFAULT_THEME_NAME);
if (theme == "qdarkstyle")
{
@ -358,3 +361,24 @@ void QtHost::SetIconThemeFromStyle()
const bool dark = IsDarkApplicationTheme();
QIcon::setThemeName(dark ? QStringLiteral("white") : QStringLiteral("black"));
}
const char* Host::GetDefaultFullscreenUITheme()
{
const TinyString theme =
Host::GetBaseTinyStringSettingValue("UI", "Theme", InterfaceSettingsWidget::DEFAULT_THEME_NAME);
if (theme == "cobaltsky")
return "CobaltSky";
else if (theme == "greymatter")
return "GreyMatter";
else if (theme == "pinkypals")
return "PinkyPals";
else if (theme == "purplerain")
return "PurpleRain";
else if (theme == "AMOLED")
return "AMOLED";
else if (theme == "windowsvista")
return "Light";
else // if (theme == "fusion" || theme == "darkfusion" || theme == "darkfusionblue" || theme == "darkruby")
return "Dark";
}

View File

@ -535,6 +535,11 @@ void Host::OnCoverDownloaderOpenRequested()
// noop
}
const char* Host::GetDefaultFullscreenUITheme()
{
return "";
}
bool Host::ShouldPreferHostFileSelector()
{
return false;

View File

@ -406,6 +406,10 @@ void GetInputDialogHelpText(SmallStringBase& dest);
// Host UI triggers from Big Picture mode.
namespace Host {
/// Returns the name of the default Big Picture theme to use based on the host theme.
const char* GetDefaultFullscreenUITheme();
/// Returns true if native file dialogs should be preferred over Big Picture.
bool ShouldPreferHostFileSelector();
@ -415,4 +419,5 @@ using FileSelectorFilters = std::vector<std::string>;
void OpenHostFileSelectorAsync(std::string_view title, bool select_directory, FileSelectorCallback callback,
FileSelectorFilters filters = FileSelectorFilters(),
std::string_view initial_directory = std::string_view());
} // namespace Host

View File

@ -10,6 +10,7 @@
#include "input_manager.h"
// TODO: Remove me when GPUDevice config is also cleaned up.
#include "core/fullscreen_ui.h"
#include "core/gpu_thread.h"
#include "core/host.h"
#include "core/settings.h"
@ -257,7 +258,7 @@ bool ImGuiManager::Initialize(float global_scale, float screen_margin, Error* er
SetKeyMap();
SetStyle(s_state.imgui_context->Style, s_state.global_scale);
ImGuiFullscreen::SetTheme(Host::GetBaseStringSettingValue("UI", "FullscreenUITheme", "Dark"));
FullscreenUI::SetTheme();
if (!AddImGuiFonts(false, false) || !g_gpu_device->UpdateImGuiFontTexture())
{