Эх сурвалжийг харах

Merge pull request #11356 from lat9nq/console-mode-pg

general,config-qt: Present Console Mode as an enum with separate options in game properties
liamwhite 2 жил өмнө
parent
commit
6c4abd23be

+ 4 - 1
src/android/app/src/main/jni/config.cpp

@@ -11,6 +11,7 @@
 #include "common/fs/path_util.h"
 #include "common/logging/log.h"
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "input_common/main.h"
 #include "jni/config.h"
@@ -144,7 +145,9 @@ void Config::ReadValues() {
                                                     Service::Account::MAX_USERS - 1);
 
     // Disable docked mode by default on Android
-    Settings::values.use_docked_mode = config->GetBoolean("System", "use_docked_mode", false);
+    Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false)
+                                                  ? Settings::ConsoleMode::Docked
+                                                  : Settings::ConsoleMode::Handheld);
 
     const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false);
     if (rng_seed_enabled) {

+ 1 - 1
src/android/app/src/main/jni/native.cpp

@@ -420,7 +420,7 @@ public:
             return false;
         }
 
-        return !Settings::values.use_docked_mode.GetValue();
+        return !Settings::IsDockedMode();
     }
 
     void SetDeviceType([[maybe_unused]] int index, int type) {

+ 5 - 0
src/common/settings.cpp

@@ -2,6 +2,7 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include <version>
+#include "common/settings_enums.h"
 #if __cpp_lib_chrono >= 201907L
 #include <chrono>
 #include <exception>
@@ -145,6 +146,10 @@ bool IsFastmemEnabled() {
     return true;
 }
 
+bool IsDockedMode() {
+    return values.use_docked_mode.GetValue() == Settings::ConsoleMode::Docked;
+}
+
 float Volume() {
     if (values.audio_muted) {
         return 0.0f;

+ 9 - 1
src/common/settings.h

@@ -379,7 +379,13 @@ struct Values {
 
     Setting<s32> current_user{linkage, 0, "current_user", Category::System};
 
-    SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
+    SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
+                                                   ConsoleMode::Docked,
+                                                   "use_docked_mode",
+                                                   Category::System,
+                                                   Specialization::Radio,
+                                                   true,
+                                                   true};
 
     // Controls
     InputSetting<std::array<PlayerInput, 10>> players;
@@ -519,6 +525,8 @@ bool IsGPULevelHigh();
 
 bool IsFastmemEnabled();
 
+bool IsDockedMode();
+
 float Volume();
 
 std::string GetTimeZoneString(TimeZone time_zone);

+ 1 - 0
src/common/settings_common.h

@@ -56,6 +56,7 @@ enum Specialization : u8 {
     Scalar = 5,      // Values are continuous
     Countable = 6,   // Can be stepped through
     Paired = 7,      // Another setting is associated with this setting
+    Radio = 8,       // Setting should be presented in a radio group
 
     Percentage = (1 << SpecializationAttributeOffset), // Should be represented as a percentage
 };

+ 2 - 0
src/common/settings_enums.h

@@ -146,6 +146,8 @@ ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
 
 ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
 
+ENUM(ConsoleMode, Handheld, Docked);
+
 template <typename Type>
 inline std::string CanonicalizeEnum(Type id) {
     const auto group = EnumMetadata<Type>::Canonicalizations();

+ 3 - 1
src/core/frontend/applets/controller.cpp

@@ -3,6 +3,8 @@
 
 #include "common/assert.h"
 #include "common/logging/log.h"
+#include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/frontend/applets/controller.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
@@ -62,7 +64,7 @@ void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callbac
                 controller->Connect(true);
             }
         } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
-                   !Settings::values.use_docked_mode.GetValue()) {
+                   !Settings::IsDockedMode()) {
             // We should *never* reach here under any normal circumstances.
             controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
             controller->Connect(true);

+ 2 - 1
src/core/frontend/framebuffer_layout.cpp

@@ -5,6 +5,7 @@
 
 #include "common/assert.h"
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/frontend/framebuffer_layout.h"
 
 namespace Layout {
@@ -49,7 +50,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
 }
 
 FramebufferLayout FrameLayoutFromResolutionScale(f32 res_scale) {
-    const bool is_docked = Settings::values.use_docked_mode.GetValue();
+    const bool is_docked = Settings::IsDockedMode();
     const u32 screen_width = is_docked ? ScreenDocked::Width : ScreenUndocked::Width;
     const u32 screen_height = is_docked ? ScreenDocked::Height : ScreenUndocked::Height;
 

+ 3 - 2
src/core/hle/service/am/am.cpp

@@ -6,6 +6,7 @@
 #include <cinttypes>
 #include <cstring>
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/core.h"
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/patch_manager.h"
@@ -833,7 +834,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 4};
     rb.Push(ResultSuccess);
 
-    if (Settings::values.use_docked_mode.GetValue()) {
+    if (Settings::IsDockedMode()) {
         rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
         rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
     } else {
@@ -921,7 +922,7 @@ void IStorage::Open(HLERequestContext& ctx) {
 }
 
 void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
-    const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()};
+    const bool use_docked_mode{Settings::IsDockedMode()};
     LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
 
     IPC::ResponseBuilder rb{ctx, 3};

+ 2 - 2
src/core/hle/service/apm/apm_controller.cpp

@@ -7,6 +7,7 @@
 
 #include "common/logging/log.h"
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/core_timing.h"
 #include "core/hle/service/apm/apm_controller.h"
 
@@ -67,8 +68,7 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
 }
 
 PerformanceMode Controller::GetCurrentPerformanceMode() const {
-    return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Boost
-                                                       : PerformanceMode::Normal;
+    return Settings::IsDockedMode() ? PerformanceMode::Boost : PerformanceMode::Normal;
 }
 
 PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {

+ 1 - 1
src/core/hle/service/hid/controllers/gesture.cpp

@@ -331,7 +331,7 @@ Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties()
         };
 
         // Hack: There is no touch in docked but games still allow it
-        if (Settings::values.use_docked_mode.GetValue()) {
+        if (Settings::IsDockedMode()) {
             gesture.points[id] = {
                 .x = static_cast<s32>(active_x * Layout::ScreenDocked::Width),
                 .y = static_cast<s32>(active_y * Layout::ScreenDocked::Height),

+ 1 - 1
src/core/hle/service/hid/controllers/npad.cpp

@@ -1518,7 +1518,7 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
             return false;
         }
         // Handheld shouldn't be supported in docked mode
-        if (Settings::values.use_docked_mode.GetValue()) {
+        if (Settings::IsDockedMode()) {
             return false;
         }
 

+ 1 - 1
src/core/hle/service/vi/vi.cpp

@@ -217,7 +217,7 @@ private:
         IPC::ResponseBuilder rb{ctx, 6};
         rb.Push(ResultSuccess);
 
-        if (Settings::values.use_docked_mode.GetValue()) {
+        if (Settings::IsDockedMode()) {
             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
         } else {

+ 2 - 1
src/core/telemetry_session.cpp

@@ -14,6 +14,7 @@
 #include "common/logging/log.h"
 
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/patch_manager.h"
 #include "core/loader/loader.h"
@@ -275,7 +276,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
              static_cast<u32>(Settings::values.shader_backend.GetValue()));
     AddField(field_type, "Renderer_UseAsynchronousShaders",
              Settings::values.use_asynchronous_shaders.GetValue());
-    AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue());
+    AddField(field_type, "System_UseDockedMode", Settings::IsDockedMode());
 }
 
 bool TelemetrySession::SubmitTestcase() {

+ 9 - 5
src/yuzu/applets/qt_controller.cpp

@@ -5,6 +5,8 @@
 #include <thread>
 
 #include "common/assert.h"
+#include "common/settings.h"
+#include "common/settings_enums.h"
 #include "common/string_util.h"
 #include "core/core.h"
 #include "core/hid/emulated_controller.h"
@@ -226,9 +228,11 @@ int QtControllerSelectorDialog::exec() {
 }
 
 void QtControllerSelectorDialog::ApplyConfiguration() {
-    const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
-    Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
-    OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue(), system);
+    const bool pre_docked_mode = Settings::IsDockedMode();
+    const bool docked_mode_selected = ui->radioDocked->isChecked();
+    Settings::values.use_docked_mode.SetValue(
+        docked_mode_selected ? Settings::ConsoleMode::Docked : Settings::ConsoleMode::Handheld);
+    OnDockedModeChanged(pre_docked_mode, docked_mode_selected, system);
 
     Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
     Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
@@ -616,8 +620,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
     ui->radioDocked->setEnabled(!is_handheld);
     ui->radioUndocked->setEnabled(!is_handheld);
 
-    ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
-    ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
+    ui->radioDocked->setChecked(Settings::IsDockedMode());
+    ui->radioUndocked->setChecked(!Settings::IsDockedMode());
 
     // Also force into undocked mode if the controller type is handheld.
     if (is_handheld) {

+ 2 - 2
src/yuzu/bootmanager.cpp

@@ -928,8 +928,8 @@ void GRenderWindow::CaptureScreenshot(const QString& screenshot_path) {
     const Layout::FramebufferLayout layout{[]() {
         u32 height = UISettings::values.screenshot_height.GetValue();
         if (height == 0) {
-            height = Settings::values.use_docked_mode.GetValue() ? Layout::ScreenDocked::Height
-                                                                 : Layout::ScreenUndocked::Height;
+            height = Settings::IsDockedMode() ? Layout::ScreenDocked::Height
+                                              : Layout::ScreenUndocked::Height;
             height *= Settings::values.resolution_info.up_factor;
         }
         const u32 width =

+ 5 - 4
src/yuzu/configuration/config.cpp

@@ -9,6 +9,7 @@
 #include "common/fs/path_util.h"
 #include "common/settings.h"
 #include "common/settings_common.h"
+#include "common/settings_enums.h"
 #include "core/core.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/hid/controllers/npad.h"
@@ -85,9 +86,9 @@ const std::map<Settings::ScalingFilter, QString> Config::scaling_filter_texts_ma
     {Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "FSR"))},
 };
 
-const std::map<bool, QString> Config::use_docked_mode_texts_map = {
-    {true, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
-    {false, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
+const std::map<Settings::ConsoleMode, QString> Config::use_docked_mode_texts_map = {
+    {Settings::ConsoleMode::Docked, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Docked"))},
+    {Settings::ConsoleMode::Handheld, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "Handheld"))},
 };
 
 const std::map<Settings::GpuAccuracy, QString> Config::gpu_accuracy_texts_map = {
@@ -376,7 +377,7 @@ void Config::ReadControlValues() {
     const auto controller_type = Settings::values.players.GetValue()[0].controller_type;
     if (controller_type == Settings::ControllerType::Handheld) {
         Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig());
-        Settings::values.use_docked_mode.SetValue(false);
+        Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
     }
 
     if (IsCustomConfig()) {

+ 2 - 1
src/yuzu/configuration/config.h

@@ -9,6 +9,7 @@
 #include <QMetaType>
 #include <QVariant>
 #include "common/settings.h"
+#include "common/settings_enums.h"
 #include "yuzu/uisettings.h"
 
 class QSettings;
@@ -51,7 +52,7 @@ public:
 
     static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map;
     static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map;
-    static const std::map<bool, QString> use_docked_mode_texts_map;
+    static const std::map<Settings::ConsoleMode, QString> use_docked_mode_texts_map;
     static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map;
     static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map;
     static const std::map<Settings::ShaderBackend, QString> shader_backend_texts_map;

+ 9 - 5
src/yuzu/configuration/configure_input.cpp

@@ -4,6 +4,8 @@
 #include <memory>
 #include <thread>
 
+#include "common/settings.h"
+#include "common/settings_enums.h"
 #include "core/core.h"
 #include "core/hid/emulated_controller.h"
 #include "core/hid/hid_core.h"
@@ -197,9 +199,11 @@ void ConfigureInput::ApplyConfiguration() {
 
     advanced->ApplyConfiguration();
 
-    const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
-    Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
-    OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue(), system);
+    const bool pre_docked_mode = Settings::IsDockedMode();
+    const bool docked_mode_selected = ui->radioDocked->isChecked();
+    Settings::values.use_docked_mode.SetValue(
+        docked_mode_selected ? Settings::ConsoleMode::Docked : Settings::ConsoleMode::Handheld);
+    OnDockedModeChanged(pre_docked_mode, docked_mode_selected, system);
 
     Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
     Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
@@ -267,8 +271,8 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
     ui->radioDocked->setEnabled(!is_handheld);
     ui->radioUndocked->setEnabled(!is_handheld);
 
-    ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
-    ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
+    ui->radioDocked->setChecked(Settings::IsDockedMode());
+    ui->radioUndocked->setChecked(!Settings::IsDockedMode());
 
     // Also force into undocked mode if the controller type is handheld.
     if (is_handheld) {

+ 7 - 0
src/yuzu/configuration/configure_per_game.cpp

@@ -18,6 +18,7 @@
 
 #include "common/fs/fs_util.h"
 #include "common/settings_enums.h"
+#include "common/settings_input.h"
 #include "configuration/shared_widget.h"
 #include "core/core.h"
 #include "core/file_sys/control_metadata.h"
@@ -98,6 +99,12 @@ void ConfigurePerGame::ApplyConfiguration() {
     addons_tab->ApplyConfiguration();
     input_tab->ApplyConfiguration();
 
+    if (Settings::IsDockedMode() && Settings::values.players.GetValue()[0].controller_type ==
+                                        Settings::ControllerType::Handheld) {
+        Settings::values.use_docked_mode.SetValue(Settings::ConsoleMode::Handheld);
+        Settings::values.use_docked_mode.SetGlobal(true);
+    }
+
     system.ApplySettings();
     Settings::LogSettings();
 

+ 5 - 0
src/yuzu/configuration/configure_system.cpp

@@ -106,6 +106,11 @@ void ConfigureSystem::Setup(const ConfigurationShared::Builder& builder) {
     push(Settings::values.linkage.by_category[Settings::Category::System]);
 
     for (auto setting : settings) {
+        if (setting->Id() == Settings::values.use_docked_mode.Id() &&
+            Settings::IsConfiguringGlobal()) {
+            continue;
+        }
+
         ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs);
 
         if (widget == nullptr) {

+ 4 - 1
src/yuzu/configuration/shared_translation.cpp

@@ -135,7 +135,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
     INSERT(Settings, region_index, "Region:", "");
     INSERT(Settings, time_zone_index, "Time Zone:", "");
     INSERT(Settings, sound_index, "Sound Output Mode:", "");
-    INSERT(Settings, use_docked_mode, "", "");
+    INSERT(Settings, use_docked_mode, "Console Mode:", "");
     INSERT(Settings, current_user, "", "");
 
     // Controls
@@ -379,6 +379,9 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) {
                               PAIR(MemoryLayout, Memory_6Gb, "6GB DRAM (Unsafe)"),
                               PAIR(MemoryLayout, Memory_8Gb, "8GB DRAM (Unsafe)"),
                           }});
+    translations->insert(
+        {Settings::EnumMetadata<Settings::ConsoleMode>::Index(),
+         {PAIR(ConsoleMode, Docked, "Docked"), PAIR(ConsoleMode, Handheld, "Handheld")}});
 
 #undef PAIR
 #undef CTX_PAIR

+ 67 - 1
src/yuzu/configuration/shared_widget.cpp

@@ -23,6 +23,7 @@
 #include <QLineEdit>
 #include <QObject>
 #include <QPushButton>
+#include <QRadioButton>
 #include <QRegularExpression>
 #include <QSizePolicy>
 #include <QSlider>
@@ -171,6 +172,65 @@ QWidget* Widget::CreateCombobox(std::function<std::string()>& serializer,
     return combobox;
 }
 
+QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
+                                  std::function<void()>& restore_func,
+                                  const std::function<void()>& touch) {
+    const auto type = setting.EnumIndex();
+
+    QWidget* group = new QWidget(this);
+    QHBoxLayout* layout = new QHBoxLayout(group);
+    layout->setContentsMargins(0, 0, 0, 0);
+    group->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+    const ComboboxTranslations* enumeration{nullptr};
+    if (combobox_enumerations.contains(type)) {
+        enumeration = &combobox_enumerations.at(type);
+        for (const auto& [id, name] : *enumeration) {
+            QRadioButton* radio_button = new QRadioButton(name, group);
+            layout->addWidget(radio_button);
+            radio_buttons.push_back({id, radio_button});
+        }
+    } else {
+        return group;
+    }
+
+    const auto get_selected = [=]() -> u32 {
+        for (const auto& [id, button] : radio_buttons) {
+            if (button->isChecked()) {
+                return id;
+            }
+        }
+        return -1;
+    };
+
+    const auto set_index = [=](u32 value) {
+        for (const auto& [id, button] : radio_buttons) {
+            button->setChecked(id == value);
+        }
+    };
+
+    const u32 setting_value = std::stoi(setting.ToString());
+    set_index(setting_value);
+
+    serializer = [get_selected]() {
+        int current = get_selected();
+        return std::to_string(current);
+    };
+
+    restore_func = [this, set_index]() {
+        const u32 global_value = std::stoi(RelevantDefault(setting));
+        set_index(global_value);
+    };
+
+    if (!Settings::IsConfiguringGlobal()) {
+        for (const auto& [id, button] : radio_buttons) {
+            QObject::connect(button, &QAbstractButton::clicked, [touch]() { touch(); });
+        }
+    }
+
+    return group;
+}
+
 QWidget* Widget::CreateLineEdit(std::function<std::string()>& serializer,
                                 std::function<void()>& restore_func,
                                 const std::function<void()>& touch, bool managed) {
@@ -411,6 +471,8 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
             return RequestType::Slider;
         case Settings::Specialization::Countable:
             return RequestType::SpinBox;
+        case Settings::Specialization::Radio:
+            return RequestType::RadioGroup;
         default:
             break;
         }
@@ -439,7 +501,11 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
     if (setting.TypeId() == typeid(bool)) {
         data_component = CreateCheckBox(&setting, label, serializer, restore_func, touch);
     } else if (setting.IsEnum()) {
-        data_component = CreateCombobox(serializer, restore_func, touch);
+        if (request == RequestType::RadioGroup) {
+            data_component = CreateRadioGroup(serializer, restore_func, touch);
+        } else {
+            data_component = CreateCombobox(serializer, restore_func, touch);
+        }
     } else if (type == typeid(u32) || type == typeid(int) || type == typeid(u16) ||
                type == typeid(s64) || type == typeid(u8)) {
         switch (request) {

+ 6 - 0
src/yuzu/configuration/shared_widget.h

@@ -22,6 +22,7 @@ class QObject;
 class QPushButton;
 class QSlider;
 class QSpinBox;
+class QRadioButton;
 
 namespace Settings {
 class BasicSetting;
@@ -38,6 +39,7 @@ enum class RequestType {
     LineEdit,
     HexEdit,
     DateTimeEdit,
+    RadioGroup,
     MaxEnum,
 };
 
@@ -91,6 +93,7 @@ public:
     QSlider* slider{};
     QComboBox* combobox{};
     QDateTimeEdit* date_time_edit{};
+    std::vector<std::pair<u32, QRadioButton*>> radio_buttons{};
 
 private:
     void SetupComponent(const QString& label, std::function<void()>& load_func, bool managed,
@@ -106,6 +109,9 @@ private:
     QWidget* CreateCombobox(std::function<std::string()>& serializer,
                             std::function<void()>& restore_func,
                             const std::function<void()>& touch);
+    QWidget* CreateRadioGroup(std::function<std::string()>& serializer,
+                              std::function<void()>& restore_func,
+                              const std::function<void()>& touch);
     QWidget* CreateLineEdit(std::function<std::string()>& serializer,
                             std::function<void()>& restore_func, const std::function<void()>& touch,
                             bool managed = true);

+ 9 - 8
src/yuzu/main.cpp

@@ -1158,9 +1158,9 @@ void GMainWindow::InitializeWidgets() {
             [this](const QPoint& menu_location) {
                 QMenu context_menu;
 
-                for (auto const& docked_mode_pair : Config::use_docked_mode_texts_map) {
-                    context_menu.addAction(docked_mode_pair.second, [this, docked_mode_pair] {
-                        if (docked_mode_pair.first != Settings::values.use_docked_mode.GetValue()) {
+                for (auto const& pair : Config::use_docked_mode_texts_map) {
+                    context_menu.addAction(pair.second, [this, &pair] {
+                        if (pair.first != Settings::values.use_docked_mode.GetValue()) {
                             OnToggleDockedMode();
                         }
                     });
@@ -3674,7 +3674,7 @@ void GMainWindow::OnTasReset() {
 }
 
 void GMainWindow::OnToggleDockedMode() {
-    const bool is_docked = Settings::values.use_docked_mode.GetValue();
+    const bool is_docked = Settings::IsDockedMode();
     auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
     auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
 
@@ -3688,7 +3688,8 @@ void GMainWindow::OnToggleDockedMode() {
         controller_dialog->refreshConfiguration();
     }
 
-    Settings::values.use_docked_mode.SetValue(!is_docked);
+    Settings::values.use_docked_mode.SetValue(is_docked ? Settings::ConsoleMode::Handheld
+                                                        : Settings::ConsoleMode::Docked);
     UpdateDockedButton();
     OnDockedModeChanged(is_docked, !is_docked, *system);
 }
@@ -4118,10 +4119,10 @@ void GMainWindow::UpdateGPUAccuracyButton() {
 }
 
 void GMainWindow::UpdateDockedButton() {
-    const bool is_docked = Settings::values.use_docked_mode.GetValue();
-    dock_status_button->setChecked(is_docked);
+    const auto console_mode = Settings::values.use_docked_mode.GetValue();
+    dock_status_button->setChecked(Settings::IsDockedMode());
     dock_status_button->setText(
-        Config::use_docked_mode_texts_map.find(is_docked)->second.toUpper());
+        Config::use_docked_mode_texts_map.find(console_mode)->second.toUpper());
 }
 
 void GMainWindow::UpdateAPIText() {