summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/configuration/config.cpp51
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp10
-rw-r--r--src/yuzu/configuration/configuration_shared.h3
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp1
-rw-r--r--src/yuzu/configuration/configure_graphics.ui2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui22
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp37
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp45
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h2
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp1
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp2
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp105
-rw-r--r--src/yuzu/configuration/configure_ringcon.h14
-rw-r--r--src/yuzu/configuration/configure_ringcon.ui396
-rw-r--r--src/yuzu/configuration/configure_system.cpp10
-rw-r--r--src/yuzu/configuration/configure_system.h6
-rw-r--r--src/yuzu/configuration/configure_tas.cpp1
-rw-r--r--src/yuzu/configuration/input_profiles.cpp7
-rw-r--r--src/yuzu/debugger/controller.cpp5
-rw-r--r--src/yuzu/debugger/profiler.cpp5
-rw-r--r--src/yuzu/discord_impl.cpp67
-rw-r--r--src/yuzu/hotkeys.cpp6
-rw-r--r--src/yuzu/hotkeys.h1
-rw-r--r--src/yuzu/install_dialog.cpp1
-rw-r--r--src/yuzu/main.cpp17
-rw-r--r--src/yuzu/multiplayer/direct_connect.cpp21
-rw-r--r--src/yuzu/multiplayer/direct_connect.ui23
-rw-r--r--src/yuzu/multiplayer/lobby.cpp16
-rw-r--r--src/yuzu/multiplayer/lobby.h2
-rw-r--r--src/yuzu/multiplayer/lobby.ui7
-rw-r--r--src/yuzu/multiplayer/validation.h25
-rw-r--r--src/yuzu/uisettings.h1
-rw-r--r--src/yuzu/util/limitable_input_dialog.cpp2
-rw-r--r--src/yuzu/util/sequence_dialog/sequence_dialog.cpp1
36 files changed, 622 insertions, 297 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index dfc675cc8..06d982d9b 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -353,7 +353,7 @@ if (USE_DISCORD_PRESENCE)
discord_impl.cpp
discord_impl.h
)
- target_link_libraries(yuzu PRIVATE DiscordRPC::discord-rpc)
+ target_link_libraries(yuzu PRIVATE DiscordRPC::discord-rpc httplib::httplib)
target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE)
endif()
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 0db62baa3..35fef506a 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -70,28 +70,28 @@ const std::array<int, 2> Config::default_ringcon_analogs{{
// UISetting::values.shortcuts, which is alphabetically ordered.
// clang-format off
const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut}},
- {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F9"), QStringLiteral("Home+R"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F4"), QStringLiteral("Home+Plus"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Esc"), QStringLiteral(""), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit yuzu")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+Q"), QStringLiteral("Home+Minus"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F11"), QStringLiteral("Home+B"), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral(""), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral(""), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
+ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut, false}},
}};
// clang-format on
@@ -440,6 +440,7 @@ void Config::ReadControlValues() {
ReadBasicSetting(Settings::values.emulate_analog_keyboard);
Settings::values.mouse_panning = false;
ReadBasicSetting(Settings::values.mouse_panning_sensitivity);
+ ReadBasicSetting(Settings::values.enable_joycon_driver);
ReadBasicSetting(Settings::values.tas_enable);
ReadBasicSetting(Settings::values.tas_loop);
@@ -747,7 +748,7 @@ void Config::ReadShortcutValues() {
for (const auto& [name, group, shortcut] : default_hotkeys) {
qt_config->beginGroup(group);
qt_config->beginGroup(name);
- // No longer using ReadSetting for shortcut.second as it innacurately returns a value of 1
+ // No longer using ReadSetting for shortcut.second as it inaccurately returns a value of 1
// for WidgetWithChildrenShortcut which is a value of 3. Needed to fix shortcuts the open
// a file dialog in windowed mode
UISettings::values.shortcuts.push_back(
@@ -756,7 +757,7 @@ void Config::ReadShortcutValues() {
{ReadSetting(QStringLiteral("KeySeq"), shortcut.keyseq).toString(),
ReadSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq)
.toString(),
- shortcut.context}});
+ shortcut.context, ReadSetting(QStringLiteral("Repeat"), shortcut.repeat).toBool()}});
qt_config->endGroup();
qt_config->endGroup();
}
@@ -1139,6 +1140,7 @@ void Config::SaveControlValues() {
WriteGlobalSetting(Settings::values.enable_accurate_vibrations);
WriteGlobalSetting(Settings::values.motion_enabled);
WriteBasicSetting(Settings::values.enable_raw_input);
+ WriteBasicSetting(Settings::values.enable_joycon_driver);
WriteBasicSetting(Settings::values.keyboard_enabled);
WriteBasicSetting(Settings::values.emulate_analog_keyboard);
WriteBasicSetting(Settings::values.mouse_panning_sensitivity);
@@ -1393,6 +1395,7 @@ void Config::SaveShortcutValues() {
WriteSetting(QStringLiteral("Controller_KeySeq"), shortcut.controller_keyseq,
default_hotkey.controller_keyseq);
WriteSetting(QStringLiteral("Context"), shortcut.context, default_hotkey.context);
+ WriteSetting(QStringLiteral("Repeat"), shortcut.repeat, default_hotkey.repeat);
qt_config->endGroup();
qt_config->endGroup();
}
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index 97fb664bf..ac42cc7fc 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -92,3 +92,13 @@ void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index
combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text);
combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX);
}
+
+int ConfigurationShared::GetComboboxIndex(int global_setting_index, const QComboBox* combobox) {
+ if (Settings::IsConfiguringGlobal()) {
+ return combobox->currentIndex();
+ }
+ if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
+ return global_setting_index;
+ }
+ return combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET;
+}
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index e597dcdb5..04c88758c 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -69,4 +69,7 @@ void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global);
// Adds the "Use Global Configuration" selection and separator to the beginning of a QComboBox
void InsertGlobalItem(QComboBox* combobox, int global_index);
+// Returns the correct index of a QComboBox taking into account global configuration
+int GetComboboxIndex(int global_setting_index, const QComboBox* combobox);
+
} // namespace ConfigurationShared
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 4301313cf..2aaefcc05 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -66,7 +66,6 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
web_tab->SetWebServiceConfigEnabled(enable_web_config);
hotkeys_tab->Populate(registry);
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
input_tab->Initialize(input_subsystem);
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index bb9910a53..a45ec69ec 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -460,7 +460,7 @@
</item>
<item>
<property name="text">
- <string>AMD FidelityFX™️ Super Resolution (Vulkan Only)</string>
+ <string>AMD FidelityFX™️ Super Resolution</string>
</property>
</item>
</widget>
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index 235b813d9..77b976e74 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -138,6 +138,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
Settings::values.controller_navigation = ui->controller_navigation->isChecked();
Settings::values.enable_ring_controller = ui->enable_ring_controller->isChecked();
Settings::values.enable_ir_sensor = ui->enable_ir_sensor->isChecked();
+ Settings::values.enable_joycon_driver = ui->enable_joycon_driver->isChecked();
}
void ConfigureInputAdvanced::LoadConfiguration() {
@@ -172,6 +173,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
ui->controller_navigation->setChecked(Settings::values.controller_navigation.GetValue());
ui->enable_ring_controller->setChecked(Settings::values.enable_ring_controller.GetValue());
ui->enable_ir_sensor->setChecked(Settings::values.enable_ir_sensor.GetValue());
+ ui->enable_joycon_driver->setChecked(Settings::values.enable_joycon_driver.GetValue());
UpdateUIEnabled();
}
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index fac8cf827..75d96d3ab 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2696,6 +2696,22 @@
</widget>
</item>
<item row="5" column="0">
+ <widget class="QCheckBox" name="enable_joycon_driver">
+ <property name="toolTip">
+ <string>Requires restarting yuzu</string>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Enable direct JoyCon driver</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
<widget class="QCheckBox" name="mouse_panning">
<property name="minimumSize">
<size>
@@ -2708,7 +2724,7 @@
</property>
</widget>
</item>
- <item row="5" column="2">
+ <item row="6" column="2">
<widget class="QSpinBox" name="mouse_panning_sensitivity">
<property name="toolTip">
<string>Mouse sensitivity</string>
@@ -2730,14 +2746,14 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="motion_touch">
<property name="text">
<string>Motion / Touch</string>
</property>
</widget>
</item>
- <item row="6" column="2">
+ <item row="7" column="2">
<widget class="QPushButton" name="buttonMotionTouch">
<property name="text">
<string>Configure</string>
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index c40d980c9..723690e71 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -66,6 +66,18 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
return QObject::tr("R");
case Common::Input::ButtonNames::TriggerL:
return QObject::tr("L");
+ case Common::Input::ButtonNames::TriggerZR:
+ return QObject::tr("ZR");
+ case Common::Input::ButtonNames::TriggerZL:
+ return QObject::tr("ZL");
+ case Common::Input::ButtonNames::TriggerSR:
+ return QObject::tr("SR");
+ case Common::Input::ButtonNames::TriggerSL:
+ return QObject::tr("SL");
+ case Common::Input::ButtonNames::ButtonStickL:
+ return QObject::tr("Stick L");
+ case Common::Input::ButtonNames::ButtonStickR:
+ return QObject::tr("Stick R");
case Common::Input::ButtonNames::ButtonA:
return QObject::tr("A");
case Common::Input::ButtonNames::ButtonB:
@@ -76,6 +88,14 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
return QObject::tr("Y");
case Common::Input::ButtonNames::ButtonStart:
return QObject::tr("Start");
+ case Common::Input::ButtonNames::ButtonPlus:
+ return QObject::tr("Plus");
+ case Common::Input::ButtonNames::ButtonMinus:
+ return QObject::tr("Minus");
+ case Common::Input::ButtonNames::ButtonHome:
+ return QObject::tr("Home");
+ case Common::Input::ButtonNames::ButtonCapture:
+ return QObject::tr("Capture");
case Common::Input::ButtonNames::L1:
return QObject::tr("L1");
case Common::Input::ButtonNames::L2:
@@ -162,12 +182,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : "");
const QString invert = QString::fromStdString(param.Get("invert", "+") == "-" ? "-" : "");
+ const QString turbo = QString::fromStdString(param.Get("turbo", false) ? "$" : "");
const auto common_button_name = input_subsystem->GetButtonName(param);
// Retrieve the names from Qt
if (param.Get("engine", "") == "keyboard") {
const QString button_str = GetKeyName(param.Get("code", 0));
- return QObject::tr("%1%2%3").arg(toggle, inverted, button_str);
+ return QObject::tr("%1%2%3%4").arg(turbo, toggle, inverted, button_str);
}
if (common_button_name == Common::Input::ButtonNames::Invalid) {
@@ -181,7 +202,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
if (common_button_name == Common::Input::ButtonNames::Value) {
if (param.Has("hat")) {
const QString hat = GetDirectionName(param.Get("direction", ""));
- return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat);
+ return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, hat);
}
if (param.Has("axis")) {
const QString axis = QString::fromStdString(param.Get("axis", ""));
@@ -199,13 +220,13 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
}
if (param.Has("button")) {
const QString button = QString::fromStdString(param.Get("button", ""));
- return QObject::tr("%1%2Button %3").arg(toggle, inverted, button);
+ return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button);
}
}
QString button_name = GetButtonName(common_button_name);
if (param.Has("hat")) {
- return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name);
+ return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name);
}
if (param.Has("axis")) {
return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
@@ -214,7 +235,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
}
if (param.Has("button")) {
- return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name);
+ return QObject::tr("%1%2%3Button %4").arg(turbo, toggle, inverted, button_name);
}
return QObject::tr("[unknown]");
@@ -375,6 +396,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
button_map[button_id]->setText(ButtonToText(param));
emulated_controller->SetButtonParam(button_id, param);
});
+ context_menu.addAction(tr("Turbo button"), [&] {
+ const bool turbo_value = !param.Get("turbo", false);
+ param.Set("turbo", turbo_value);
+ button_map[button_id]->setText(ButtonToText(param));
+ emulated_controller->SetButtonParam(button_id, param);
+ });
}
if (param.Has("axis")) {
context_menu.addAction(tr("Invert axis"), [&] {
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index 11390fec0..c287220fc 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -81,7 +81,6 @@ void PlayerControlPreview::UpdateColors() {
colors.outline = QColor(0, 0, 0);
colors.primary = QColor(225, 225, 225);
colors.button = QColor(109, 111, 114);
- colors.button2 = QColor(109, 111, 114);
colors.button2 = QColor(77, 80, 84);
colors.slider_arrow = QColor(65, 68, 73);
colors.font2 = QColor(0, 0, 0);
@@ -100,12 +99,17 @@ void PlayerControlPreview::UpdateColors() {
colors.led_off = QColor(170, 238, 255);
colors.indicator2 = QColor(59, 165, 93);
colors.charging = QColor(250, 168, 26);
+ colors.button_turbo = QColor(217, 158, 4);
colors.left = colors.primary;
colors.right = colors.primary;
- // Possible alternative to set colors from settings
- // colors.left = QColor(controller->GetColors().left.body);
- // colors.right = QColor(controller->GetColors().right.body);
+
+ const auto color_left = controller->GetColorsValues()[0].body;
+ const auto color_right = controller->GetColorsValues()[1].body;
+ if (color_left != 0 && color_right != 0) {
+ colors.left = QColor(color_left);
+ colors.right = QColor(color_right);
+ }
}
void PlayerControlPreview::ResetInputs() {
@@ -2465,7 +2469,6 @@ void PlayerControlPreview::DrawJoystickDot(QPainter& p, const QPointF center,
void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
const Common::Input::ButtonStatus& pressed, float width,
float height, Direction direction, float radius) {
- p.setBrush(button_color);
if (pressed.value) {
switch (direction) {
case Direction::Left:
@@ -2483,16 +2486,16 @@ void PlayerControlPreview::DrawRoundButton(QPainter& p, QPointF center,
case Direction::None:
break;
}
- p.setBrush(colors.highlight);
}
QRectF rect = {center.x() - width, center.y() - height, width * 2.0f, height * 2.0f};
+ p.setBrush(GetButtonColor(button_color, pressed.value, pressed.turbo));
p.drawRoundedRect(rect, radius, radius);
}
void PlayerControlPreview::DrawMinusButton(QPainter& p, const QPointF center,
const Common::Input::ButtonStatus& pressed,
int button_size) {
p.setPen(colors.outline);
- p.setBrush(pressed.value ? colors.highlight : colors.button);
+ p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawRectangle(p, center, button_size, button_size / 3.0f);
}
void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
@@ -2500,7 +2503,7 @@ void PlayerControlPreview::DrawPlusButton(QPainter& p, const QPointF center,
int button_size) {
// Draw outer line
p.setPen(colors.outline);
- p.setBrush(pressed.value ? colors.highlight : colors.button);
+ p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawRectangle(p, center, button_size, button_size / 3.0f);
DrawRectangle(p, center, button_size / 3.0f, button_size);
@@ -2522,7 +2525,7 @@ void PlayerControlPreview::DrawGCButtonX(QPainter& p, const QPointF center,
}
p.setPen(colors.outline);
- p.setBrush(pressed.value ? colors.highlight : colors.button);
+ p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, button_x);
}
@@ -2535,7 +2538,7 @@ void PlayerControlPreview::DrawGCButtonY(QPainter& p, const QPointF center,
}
p.setPen(colors.outline);
- p.setBrush(pressed.value ? colors.highlight : colors.button);
+ p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, button_x);
}
@@ -2549,17 +2552,15 @@ void PlayerControlPreview::DrawGCButtonZ(QPainter& p, const QPointF center,
}
p.setPen(colors.outline);
- p.setBrush(pressed.value ? colors.highlight : colors.button2);
+ p.setBrush(GetButtonColor(colors.button2, pressed.value, pressed.turbo));
DrawPolygon(p, button_x);
}
void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center,
const Common::Input::ButtonStatus& pressed,
float button_size) {
- p.setBrush(button_color);
- if (pressed.value) {
- p.setBrush(colors.highlight);
- }
+
+ p.setBrush(GetButtonColor(button_color, pressed.value, pressed.turbo));
p.drawEllipse(center, button_size, button_size);
}
@@ -2616,7 +2617,7 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center,
// Draw arrow button
p.setPen(pressed.value ? colors.highlight : colors.button);
- p.setBrush(pressed.value ? colors.highlight : colors.button);
+ p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, arrow_button);
switch (direction) {
@@ -2668,10 +2669,20 @@ void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center,
// Draw arrow button
p.setPen(colors.outline);
- p.setBrush(pressed.value ? colors.highlight : colors.button);
+ p.setBrush(GetButtonColor(colors.button, pressed.value, pressed.turbo));
DrawPolygon(p, qtrigger_button);
}
+QColor PlayerControlPreview::GetButtonColor(QColor default_color, bool is_pressed, bool turbo) {
+ if (is_pressed && turbo) {
+ return colors.button_turbo;
+ }
+ if (is_pressed) {
+ return colors.highlight;
+ }
+ return default_color;
+}
+
void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center,
Common::Input::BatteryLevel battery) {
if (battery == Common::Input::BatteryLevel::None) {
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index b258c6d77..0e9e95e85 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -81,6 +81,7 @@ private:
QColor right{};
QColor button{};
QColor button2{};
+ QColor button_turbo{};
QColor font{};
QColor font2{};
QColor highlight{};
@@ -183,6 +184,7 @@ private:
const Common::Input::ButtonStatus& pressed, float size = 1.0f);
void DrawTriggerButton(QPainter& p, QPointF center, Direction direction,
const Common::Input::ButtonStatus& pressed);
+ QColor GetButtonColor(QColor default_color, bool is_pressed, bool turbo);
// Draw battery functions
void DrawBattery(QPainter& p, QPointF center, Common::Input::BatteryLevel battery);
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index d1b870c72..fb1292f07 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -89,7 +89,6 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent,
"using-a-controller-or-android-phone-for-motion-or-touch-input'><span "
"style=\"text-decoration: underline; color:#039be5;\">Learn More</span></a>"));
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
SetConfiguration();
UpdateUiDisplay();
ConnectEvents();
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 93db47cfd..7e757eafd 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -66,8 +66,6 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
setFocusPolicy(Qt::ClickFocus);
setWindowTitle(tr("Properties"));
- // remove Help question mark button from the title bar
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
addons_tab->SetTitleId(title_id);
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp
index 688c2dd38..1275f10c8 100644
--- a/src/yuzu/configuration/configure_ringcon.cpp
+++ b/src/yuzu/configuration/configure_ringcon.cpp
@@ -4,9 +4,11 @@
#include <memory>
#include <QKeyEvent>
#include <QMenu>
+#include <QMessageBox>
#include <QTimer>
+#include <fmt/format.h>
-#include "core/hid/emulated_devices.h"
+#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
@@ -126,9 +128,16 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
ui->buttonRingAnalogPush,
};
- emulated_device = hid_core_.GetEmulatedDevices();
- emulated_device->SaveCurrentConfig();
- emulated_device->EnableConfiguration();
+ emulated_controller = hid_core_.GetEmulatedController(Core::HID::NpadIdType::Player1);
+ emulated_controller->SaveCurrentConfig();
+ emulated_controller->EnableConfiguration();
+
+ Core::HID::ControllerUpdateCallback engine_callback{
+ .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
+ .is_npad_service = false,
+ };
+ callback_key = emulated_controller->SetCallback(engine_callback);
+ is_controller_set = true;
LoadConfiguration();
@@ -143,9 +152,9 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
HandleClick(
analog_map_buttons[sub_button_id],
[=, this](const Common::ParamPackage& params) {
- Common::ParamPackage param = emulated_device->GetRingParam();
+ Common::ParamPackage param = emulated_controller->GetRingParam();
SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
- emulated_device->SetRingParam(param);
+ emulated_controller->SetRingParam(param);
},
InputCommon::Polling::InputType::Stick);
});
@@ -155,16 +164,16 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
connect(analog_button, &QPushButton::customContextMenuRequested,
[=, this](const QPoint& menu_location) {
QMenu context_menu;
- Common::ParamPackage param = emulated_device->GetRingParam();
+ Common::ParamPackage param = emulated_controller->GetRingParam();
context_menu.addAction(tr("Clear"), [&] {
- emulated_device->SetRingParam({});
+ emulated_controller->SetRingParam(param);
analog_map_buttons[sub_button_id]->setText(tr("[not set]"));
});
context_menu.addAction(tr("Invert axis"), [&] {
const bool invert_value = param.Get("invert_x", "+") == "-";
const std::string invert_str = invert_value ? "+" : "-";
param.Set("invert_x", invert_str);
- emulated_device->SetRingParam(param);
+ emulated_controller->SetRingParam(param);
for (int sub_button_id2 = 0; sub_button_id2 < ANALOG_SUB_BUTTONS_NUM;
++sub_button_id2) {
analog_map_buttons[sub_button_id2]->setText(
@@ -177,16 +186,19 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
}
connect(ui->sliderRingAnalogDeadzone, &QSlider::valueChanged, [=, this] {
- Common::ParamPackage param = emulated_device->GetRingParam();
+ Common::ParamPackage param = emulated_controller->GetRingParam();
const auto slider_value = ui->sliderRingAnalogDeadzone->value();
ui->labelRingAnalogDeadzone->setText(tr("Deadzone: %1%").arg(slider_value));
param.Set("deadzone", slider_value / 100.0f);
- emulated_device->SetRingParam(param);
+ emulated_controller->SetRingParam(param);
});
connect(ui->restore_defaults_button, &QPushButton::clicked, this,
&ConfigureRingController::RestoreDefaults);
+ connect(ui->enable_ring_controller_button, &QPushButton::clicked, this,
+ &ConfigureRingController::EnableRingController);
+
timeout_timer->setSingleShot(true);
connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
@@ -202,7 +214,14 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
}
ConfigureRingController::~ConfigureRingController() {
- emulated_device->DisableConfiguration();
+ emulated_controller->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
+ Common::Input::PollingMode::Active);
+ emulated_controller->DisableConfiguration();
+
+ if (is_controller_set) {
+ emulated_controller->DeleteCallback(callback_key);
+ is_controller_set = false;
+ }
};
void ConfigureRingController::changeEvent(QEvent* event) {
@@ -219,7 +238,7 @@ void ConfigureRingController::RetranslateUI() {
void ConfigureRingController::UpdateUI() {
RetranslateUI();
- const Common::ParamPackage param = emulated_device->GetRingParam();
+ const Common::ParamPackage param = emulated_controller->GetRingParam();
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
auto* const analog_button = analog_map_buttons[sub_button_id];
@@ -240,9 +259,9 @@ void ConfigureRingController::UpdateUI() {
}
void ConfigureRingController::ApplyConfiguration() {
- emulated_device->DisableConfiguration();
- emulated_device->SaveCurrentConfig();
- emulated_device->EnableConfiguration();
+ emulated_controller->DisableConfiguration();
+ emulated_controller->SaveCurrentConfig();
+ emulated_controller->EnableConfiguration();
}
void ConfigureRingController::LoadConfiguration() {
@@ -252,10 +271,62 @@ void ConfigureRingController::LoadConfiguration() {
void ConfigureRingController::RestoreDefaults() {
const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys(
0, 0, Config::default_ringcon_analogs[0], Config::default_ringcon_analogs[1], 0, 0.05f);
- emulated_device->SetRingParam(Common::ParamPackage(default_ring_string));
+ emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string));
UpdateUI();
}
+void ConfigureRingController::EnableRingController() {
+ const auto dialog_title = tr("Error enabling ring input");
+
+ is_ring_enabled = false;
+ ui->ring_controller_sensor_value->setText(tr("Not connected"));
+
+ if (!Settings::values.enable_joycon_driver) {
+ QMessageBox::warning(this, dialog_title, tr("Direct Joycon driver is not enabled"));
+ return;
+ }
+
+ ui->enable_ring_controller_button->setEnabled(false);
+ ui->enable_ring_controller_button->setText(tr("Configuring"));
+ // SetPollingMode is blocking. Allow to update the button status before calling the command
+ repaint();
+
+ const auto result = emulated_controller->SetPollingMode(
+ Core::HID::EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Ring);
+ switch (result) {
+ case Common::Input::DriverResult::Success:
+ is_ring_enabled = true;
+ break;
+ case Common::Input::DriverResult::NotSupported:
+ QMessageBox::warning(this, dialog_title,
+ tr("The current mapped device doesn't support the ring controller"));
+ break;
+ case Common::Input::DriverResult::NoDeviceDetected:
+ QMessageBox::warning(this, dialog_title,
+ tr("The current mapped device doesn't have a ring attached"));
+ break;
+ default:
+ QMessageBox::warning(this, dialog_title,
+ tr("Unexpected driver result %1").arg(static_cast<int>(result)));
+ break;
+ }
+ ui->enable_ring_controller_button->setEnabled(true);
+ ui->enable_ring_controller_button->setText(tr("Enable"));
+}
+
+void ConfigureRingController::ControllerUpdate(Core::HID::ControllerTriggerType type) {
+ if (!is_ring_enabled) {
+ return;
+ }
+ if (type != Core::HID::ControllerTriggerType::RingController) {
+ return;
+ }
+
+ const auto value = emulated_controller->GetRingSensorValues();
+ const auto tex_value = QString::fromStdString(fmt::format("{:.3f}", value.raw_value));
+ ui->ring_controller_sensor_value->setText(tex_value);
+}
+
void ConfigureRingController::HandleClick(
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
InputCommon::Polling::InputType type) {
diff --git a/src/yuzu/configuration/configure_ringcon.h b/src/yuzu/configuration/configure_ringcon.h
index 38a9cb716..b23c27906 100644
--- a/src/yuzu/configuration/configure_ringcon.h
+++ b/src/yuzu/configuration/configure_ringcon.h
@@ -13,7 +13,7 @@ class InputSubsystem;
namespace Core::HID {
class HIDCore;
-class EmulatedDevices;
+class EmulatedController;
} // namespace Core::HID
namespace Ui {
@@ -42,6 +42,12 @@ private:
/// Restore all buttons to their default values.
void RestoreDefaults();
+ /// Sets current polling mode to ring input
+ void EnableRingController();
+
+ // Handles emulated controller events
+ void ControllerUpdate(Core::HID::ControllerTriggerType type);
+
/// Called when the button was pressed.
void HandleClick(QPushButton* button,
std::function<void(const Common::ParamPackage&)> new_input_setter,
@@ -78,7 +84,11 @@ private:
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
InputCommon::InputSubsystem* input_subsystem;
- Core::HID::EmulatedDevices* emulated_device;
+ Core::HID::EmulatedController* emulated_controller;
+
+ bool is_ring_enabled{};
+ bool is_controller_set{};
+ int callback_key;
std::unique_ptr<Ui::ConfigureRingController> ui;
};
diff --git a/src/yuzu/configuration/configure_ringcon.ui b/src/yuzu/configuration/configure_ringcon.ui
index 9ec634dd4..514dff372 100644
--- a/src/yuzu/configuration/configure_ringcon.ui
+++ b/src/yuzu/configuration/configure_ringcon.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>298</width>
- <height>339</height>
+ <width>315</width>
+ <height>400</height>
</rect>
</property>
<property name="windowTitle">
@@ -46,187 +46,283 @@
</property>
</spacer>
</item>
- <item>
- <widget class="QGroupBox" name="RingAnalog">
- <property name="title">
- <string>Ring Sensor Parameters</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>6</number>
- </property>
- <property name="rightMargin">
- <number>3</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <layout class="QHBoxLayout" name="buttonRingAnalogPullHorizontaLayout">
+ <item>
+ <widget class="QGroupBox" name="RingAnalog">
+ <property name="title">
+ <string>Virtual Ring Sensor Parameters</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_1">
<property name="spacing">
- <number>3</number>
+ <number>0</number>
</property>
- <item alignment="Qt::AlignHCenter">
- <widget class="QGroupBox" name="buttonRingAnalogPullGroup">
- <property name="title">
- <string>Pull</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="buttonRingAnalogPullHorizontaLayout">
+ <property name="spacing">
+ <number>3</number>
</property>
- <layout class="QVBoxLayout" name="buttonRingAnalogPullVerticalLayout">
- <property name="spacing">
- <number>3</number>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonRingAnalogPullGroup">
+ <property name="title">
+ <string>Pull</string>
</property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>3</number>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
</property>
- <property name="rightMargin">
- <number>3</number>
+ <layout class="QVBoxLayout" name="buttonRingAnalogPullVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonRingAnalogPull">
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>Pull</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonRingAnalogPushGroup">
+ <property name="title">
+ <string>Push</string>
</property>
- <property name="bottomMargin">
- <number>3</number>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
</property>
- <item>
- <widget class="QPushButton" name="buttonRingAnalogPull">
- <property name="minimumSize">
- <size>
- <width>68</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>68</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">min-width: 68px;</string>
- </property>
- <property name="text">
- <string>Pull</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
+ <layout class="QVBoxLayout" name="buttonRingAnalogPushVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonRingAnalogPush">
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>Push</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
</item>
- <item alignment="Qt::AlignHCenter">
- <widget class="QGroupBox" name="buttonRingAnalogPushGroup">
- <property name="title">
- <string>Push</string>
+ <item>
+ <layout class="QVBoxLayout" name="sliderRingAnalogDeadzoneVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
</property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
</property>
- <layout class="QVBoxLayout" name="buttonRingAnalogPushVerticalLayout">
- <property name="spacing">
- <number>3</number>
- </property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>3</number>
- </property>
- <property name="rightMargin">
- <number>3</number>
- </property>
- <property name="bottomMargin">
- <number>3</number>
- </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>10</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="sliderRingAnalogDeadzoneHorizontalLayout">
<item>
- <widget class="QPushButton" name="buttonRingAnalogPush">
- <property name="minimumSize">
- <size>
- <width>68</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>68</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="styleSheet">
- <string notr="true">min-width: 68px;</string>
- </property>
+ <widget class="QLabel" name="labelRingAnalogDeadzone">
<property name="text">
- <string>Push</string>
+ <string>Deadzone: 0%</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter</set>
</property>
- </widget>
+ </widget>
</item>
- </layout>
- </widget>
+ </layout>
+ </item>
+ <item>
+ <widget class="QSlider" name="sliderRingAnalogDeadzone">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
</item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="sliderRingAnalogDeadzoneVerticalLayout">
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="RingDriver">
+ <property name="title">
+ <string>Direct Joycon Driver</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
- <number>3</number>
+ <number>0</number>
</property>
<property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
+ <enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
- <number>0</number>
+ <number>3</number>
</property>
<property name="topMargin">
- <number>10</number>
+ <number>6</number>
</property>
<property name="rightMargin">
- <number>0</number>
+ <number>3</number>
</property>
<property name="bottomMargin">
- <number>3</number>
+ <number>10</number>
</property>
<item>
- <layout class="QHBoxLayout" name="sliderRingAnalogDeadzoneHorizontalLayout">
- <item>
- <widget class="QLabel" name="labelRingAnalogDeadzone">
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>10</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>10</number>
+ </property>
+ <property name="bottomMargin">
+ <number>10</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>10</number>
+ </property>
+ <item row="0" column="1">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>76</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="enable_ring_controller_label">
+ <property name="text">
+ <string>Enable Ring Input</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="enable_ring_controller_button">
<property name="text">
- <string>Deadzone: 0%</string>
+ <string>Enable</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="ring_controller_sensor_label">
+ <property name="text">
+ <string>Ring Sensor Value</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="ring_controller_sensor_value">
+ <property name="text">
+ <string>Not connected</string>
</property>
<property name="alignment">
- <set>Qt::AlignHCenter</set>
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
- </widget>
+ </widget>
</item>
- </layout>
- </item>
- <item>
- <widget class="QSlider" name="sliderRingAnalogDeadzone">
- <property name="maximum">
- <number>100</number>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- </widget>
+ </layout>
</item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
+ </layout>
+ </widget>
+ </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@@ -273,6 +369,6 @@
<signal>rejected()</signal>
<receiver>ConfigureRingController</receiver>
<slot>reject()</slot>
- </connection>
+ </connection>
</connections>
</ui>
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 94049f2f4..9ea4c02da 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -31,6 +31,9 @@ constexpr std::array<u32, 7> LOCALE_BLOCKLIST{
};
static bool IsValidLocale(u32 region_index, u32 language_index) {
+ if (region_index >= LOCALE_BLOCKLIST.size()) {
+ return false;
+ }
return ((LOCALE_BLOCKLIST.at(region_index) >> language_index) & 1) == 0;
}
@@ -55,8 +58,11 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
});
const auto locale_check = [this](int index) {
- const bool valid_locale =
- IsValidLocale(ui->combo_region->currentIndex(), ui->combo_language->currentIndex());
+ const auto region_index = ConfigurationShared::GetComboboxIndex(
+ Settings::values.region_index.GetValue(true), ui->combo_region);
+ const auto language_index = ConfigurationShared::GetComboboxIndex(
+ Settings::values.language_index.GetValue(true), ui->combo_language);
+ const bool valid_locale = IsValidLocale(region_index, language_index);
ui->label_warn_invalid_locale->setVisible(!valid_locale);
if (!valid_locale) {
ui->label_warn_invalid_locale->setText(
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index 8f02880a7..a7f086258 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -42,13 +42,7 @@ private:
std::unique_ptr<Ui::ConfigureSystem> ui;
bool enabled = false;
- int language_index = 0;
- int region_index = 0;
- int time_zone_index = 0;
- int sound_index = 0;
-
ConfigurationShared::CheckState use_rng_seed;
- ConfigurationShared::CheckState use_custom_rtc;
Core::System& system;
};
diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp
index 1edc5f1f3..5a545aa70 100644
--- a/src/yuzu/configuration/configure_tas.cpp
+++ b/src/yuzu/configuration/configure_tas.cpp
@@ -17,7 +17,6 @@ ConfigureTasDialog::ConfigureTasDialog(QWidget* parent)
setFocusPolicy(Qt::ClickFocus);
setWindowTitle(tr("TAS Configuration"));
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(ui->tas_path_button, &QToolButton::pressed, this,
[this] { SetDirectory(DirectoryTarget::TAS, ui->tas_path_edit); });
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp
index 9bb69cab1..41ef4250a 100644
--- a/src/yuzu/configuration/input_profiles.cpp
+++ b/src/yuzu/configuration/input_profiles.cpp
@@ -58,13 +58,16 @@ std::vector<std::string> InputProfiles::GetInputProfileNames() {
std::vector<std::string> profile_names;
profile_names.reserve(map_profiles.size());
- for (const auto& [profile_name, config] : map_profiles) {
+ auto it = map_profiles.cbegin();
+ while (it != map_profiles.cend()) {
+ const auto& [profile_name, config] = *it;
if (!ProfileExistsInFilesystem(profile_name)) {
- DeleteProfile(profile_name);
+ it = map_profiles.erase(it);
continue;
}
profile_names.push_back(profile_name);
+ ++it;
}
std::stable_sort(profile_names.begin(), profile_names.end());
diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp
index 19f3775a3..e2f55ebae 100644
--- a/src/yuzu/debugger/controller.cpp
+++ b/src/yuzu/debugger/controller.cpp
@@ -20,9 +20,8 @@ ControllerDialog::ControllerDialog(Core::HID::HIDCore& hid_core_,
setWindowTitle(tr("Controller P1"));
resize(500, 350);
setMinimumSize(500, 350);
- // Remove the "?" button from the titlebar and enable the maximize button
- setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) |
- Qt::WindowMaximizeButtonHint);
+ // Enable the maximize button
+ setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
widget = new PlayerControlPreview(this);
refreshConfiguration();
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp
index d3e2d3c12..493ee0b17 100644
--- a/src/yuzu/debugger/profiler.cpp
+++ b/src/yuzu/debugger/profiler.cpp
@@ -49,9 +49,8 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Di
setObjectName(QStringLiteral("MicroProfile"));
setWindowTitle(tr("&MicroProfile"));
resize(1000, 600);
- // Remove the "?" button from the titlebar and enable the maximize button
- setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) |
- Qt::WindowMaximizeButtonHint);
+ // Enable the maximize button
+ setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
#if MICROPROFILE_ENABLED
diff --git a/src/yuzu/discord_impl.cpp b/src/yuzu/discord_impl.cpp
index c351e9b83..de0c307d4 100644
--- a/src/yuzu/discord_impl.cpp
+++ b/src/yuzu/discord_impl.cpp
@@ -4,7 +4,10 @@
#include <chrono>
#include <string>
#include <discord_rpc.h>
+#include <fmt/format.h>
+#include <httplib.h>
#include "common/common_types.h"
+#include "common/string_util.h"
#include "core/core.h"
#include "core/loader/loader.h"
#include "yuzu/discord_impl.h"
@@ -14,7 +17,6 @@ namespace DiscordRPC {
DiscordImpl::DiscordImpl(Core::System& system_) : system{system_} {
DiscordEventHandlers handlers{};
-
// The number is the client ID for yuzu, it's used for images and the
// application name
Discord_Initialize("712465656758665259", &handlers, 1, nullptr);
@@ -29,23 +31,74 @@ void DiscordImpl::Pause() {
Discord_ClearPresence();
}
+static std::string GetGameString(const std::string& title) {
+ // Convert to lowercase
+ std::string icon_name = Common::ToLower(title);
+
+ // Replace spaces with dashes
+ std::replace(icon_name.begin(), icon_name.end(), ' ', '-');
+
+ // Remove non-alphanumeric characters but keep dashes
+ std::erase_if(icon_name, [](char c) { return !std::isalnum(c) && c != '-'; });
+
+ // Remove dashes from the start and end of the string
+ icon_name.erase(icon_name.begin(), std::find_if(icon_name.begin(), icon_name.end(),
+ [](int ch) { return ch != '-'; }));
+ icon_name.erase(
+ std::find_if(icon_name.rbegin(), icon_name.rend(), [](int ch) { return ch != '-'; }).base(),
+ icon_name.end());
+
+ // Remove double dashes
+ icon_name.erase(std::unique(icon_name.begin(), icon_name.end(),
+ [](char a, char b) { return a == '-' && b == '-'; }),
+ icon_name.end());
+
+ return icon_name;
+}
+
void DiscordImpl::Update() {
s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
+ const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
+ const std::string default_image = "yuzu_logo";
+ std::string game_cover_url = "https://yuzu-emu.org";
std::string title;
- if (system.IsPoweredOn()) {
- system.GetAppLoader().ReadTitle(title);
- }
+
DiscordRichPresence presence{};
- presence.largeImageKey = "yuzu_logo";
- presence.largeImageText = "yuzu is an emulator for the Nintendo Switch";
+
if (system.IsPoweredOn()) {
+ system.GetAppLoader().ReadTitle(title);
+
+ // Used to format Icon URL for yuzu website game compatibility page
+ std::string icon_name = GetGameString(title);
+
+ // New Check for game cover
+ httplib::Client cli(game_cover_url);
+
+ if (auto res = cli.Head(fmt::format("/images/game/boxart/{}.png", icon_name).c_str())) {
+ if (res->status == 200) {
+ game_cover_url += fmt::format("/images/game/boxart/{}.png", icon_name);
+ } else {
+ game_cover_url = "yuzu_logo";
+ }
+ } else {
+ game_cover_url = "yuzu_logo";
+ }
+
+ presence.largeImageKey = game_cover_url.c_str();
+ presence.largeImageText = title.c_str();
+
+ presence.smallImageKey = default_image.c_str();
+ presence.smallImageText = default_text.c_str();
presence.state = title.c_str();
presence.details = "Currently in game";
} else {
- presence.details = "Not in game";
+ presence.largeImageKey = default_image.c_str();
+ presence.largeImageText = default_text.c_str();
+ presence.details = "Currently not in game";
}
+
presence.startTimestamp = start_time;
Discord_UpdatePresence(&presence);
}
diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp
index 13723f6e5..6530186c1 100644
--- a/src/yuzu/hotkeys.cpp
+++ b/src/yuzu/hotkeys.cpp
@@ -21,7 +21,7 @@ void HotkeyRegistry::SaveHotkeys() {
{hotkey.first, group.first,
UISettings::ContextualShortcut({hotkey.second.keyseq.toString(),
hotkey.second.controller_keyseq,
- hotkey.second.context})});
+ hotkey.second.context, hotkey.second.repeat})});
}
}
}
@@ -47,6 +47,7 @@ void HotkeyRegistry::LoadHotkeys() {
hk.controller_shortcut->disconnect();
hk.controller_shortcut->SetKey(hk.controller_keyseq);
}
+ hk.repeat = shortcut.shortcut.repeat;
}
}
@@ -57,8 +58,7 @@ QShortcut* HotkeyRegistry::GetHotkey(const QString& group, const QString& action
hk.shortcut = new QShortcut(hk.keyseq, widget, nullptr, nullptr, hk.context);
}
- hk.shortcut->setAutoRepeat(false);
-
+ hk.shortcut->setAutoRepeat(hk.repeat);
return hk.shortcut;
}
diff --git a/src/yuzu/hotkeys.h b/src/yuzu/hotkeys.h
index dc5b7f628..848239c35 100644
--- a/src/yuzu/hotkeys.h
+++ b/src/yuzu/hotkeys.h
@@ -115,6 +115,7 @@ private:
QShortcut* shortcut = nullptr;
ControllerShortcut* controller_shortcut = nullptr;
Qt::ShortcutContext context = Qt::WindowShortcut;
+ bool repeat;
};
using HotkeyMap = std::map<QString, Hotkey>;
diff --git a/src/yuzu/install_dialog.cpp b/src/yuzu/install_dialog.cpp
index 84ec4fe13..673bbaa83 100644
--- a/src/yuzu/install_dialog.cpp
+++ b/src/yuzu/install_dialog.cpp
@@ -46,7 +46,6 @@ InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialo
vbox_layout->addLayout(hbox_layout);
setLayout(vbox_layout);
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setWindowTitle(tr("Install Files to NAND"));
}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index c278620ab..f5e6e0f58 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1015,11 +1015,6 @@ void GMainWindow::InitializeWidgets() {
filter_status_button->setFocusPolicy(Qt::NoFocus);
connect(filter_status_button, &QPushButton::clicked, this,
&GMainWindow::OnToggleAdaptingFilter);
- auto filter = Settings::values.scaling_filter.GetValue();
- if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
- filter == Settings::ScalingFilter::Fsr) {
- Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor);
- }
UpdateFilterText();
filter_status_button->setCheckable(true);
filter_status_button->setChecked(true);
@@ -2769,8 +2764,7 @@ void GMainWindow::OnMenuInstallToNAND() {
ui->action_Install_File_NAND->setEnabled(false);
install_progress = new QProgressDialog(QString{}, tr("Cancel"), 0, total_size, this);
- install_progress->setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint &
- ~Qt::WindowMaximizeButtonHint);
+ install_progress->setWindowFlags(windowFlags() & ~Qt::WindowMaximizeButtonHint);
install_progress->setAttribute(Qt::WA_DeleteOnClose, true);
install_progress->setFixedWidth(installDialog.GetMinimumWidth() + 40);
install_progress->show();
@@ -3513,10 +3507,6 @@ void GMainWindow::OnToggleAdaptingFilter() {
} else {
filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1);
}
- if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&
- filter == Settings::ScalingFilter::Fsr) {
- filter = Settings::ScalingFilter::NearestNeighbor;
- }
Settings::values.scaling_filter.SetValue(filter);
filter_status_button->setChecked(true);
UpdateFilterText();
@@ -4513,6 +4503,11 @@ int main(int argc, char* argv[]) {
}
#endif
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ // Disables the "?" button on all dialogs. Disabled by default on Qt6.
+ QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
+#endif
+
// Enables the core to make the qt created contexts current on std::threads
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
QApplication app(argc, argv);
diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp
index cbd52da85..d71cc23a7 100644
--- a/src/yuzu/multiplayer/direct_connect.cpp
+++ b/src/yuzu/multiplayer/direct_connect.cpp
@@ -81,20 +81,13 @@ void DirectConnectWindow::Connect() {
}
}
}
- switch (static_cast<ConnectionType>(ui->connection_type->currentIndex())) {
- case ConnectionType::TraversalServer:
- break;
- case ConnectionType::IP:
- if (!ui->ip->hasAcceptableInput()) {
- NetworkMessage::ErrorManager::ShowError(
- NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID);
- return;
- }
- if (!ui->port->hasAcceptableInput()) {
- NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::PORT_NOT_VALID);
- return;
- }
- break;
+ if (!ui->ip->hasAcceptableInput()) {
+ NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::IP_ADDRESS_NOT_VALID);
+ return;
+ }
+ if (!ui->port->hasAcceptableInput()) {
+ NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::PORT_NOT_VALID);
+ return;
}
// Store settings
diff --git a/src/yuzu/multiplayer/direct_connect.ui b/src/yuzu/multiplayer/direct_connect.ui
index 57d6ec25a..0dd4e6829 100644
--- a/src/yuzu/multiplayer/direct_connect.ui
+++ b/src/yuzu/multiplayer/direct_connect.ui
@@ -27,19 +27,10 @@
<number>0</number>
</property>
<item>
- <widget class="QComboBox" name="connection_type">
- <item>
- <property name="text">
- <string>IP Address</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
<widget class="QWidget" name="ip_container" native="true">
<layout class="QHBoxLayout" name="ip_layout">
<property name="leftMargin">
- <number>5</number>
+ <number>0</number>
</property>
<property name="topMargin">
<number>0</number>
@@ -53,17 +44,17 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
- <string>IP</string>
+ <string>Server Address</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="ip">
<property name="toolTip">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;IPv4 address of the host&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Server address of the host&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maxLength">
- <number>16</number>
+ <number>253</number>
</property>
</widget>
</item>
@@ -85,6 +76,12 @@
<property name="placeholderText">
<string notr="true" extracomment="placeholder string that tells user default port">24872</string>
</property>
+ <property name="maximumSize">
+ <size>
+ <width>65</width>
+ <height>50</height>
+ </size>
+ </property>
</widget>
</item>
</layout>
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp
index 08c275696..6c93e3511 100644
--- a/src/yuzu/multiplayer/lobby.cpp
+++ b/src/yuzu/multiplayer/lobby.cpp
@@ -77,6 +77,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
// UI Buttons
connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby);
connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned);
+ connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty);
connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull);
connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch);
connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom);
@@ -329,6 +330,16 @@ bool LobbyFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s
return true;
}
+ // filter by empty rooms
+ if (filter_empty) {
+ QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent);
+ int player_count =
+ sourceModel()->data(member_list, LobbyItemMemberList::MemberListRole).toList().size();
+ if (player_count == 0) {
+ return false;
+ }
+ }
+
// filter by filled rooms
if (filter_full) {
QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent);
@@ -399,6 +410,11 @@ void LobbyFilterProxyModel::SetFilterOwned(bool filter) {
invalidate();
}
+void LobbyFilterProxyModel::SetFilterEmpty(bool filter) {
+ filter_empty = filter;
+ invalidate();
+}
+
void LobbyFilterProxyModel::SetFilterFull(bool filter) {
filter_full = filter;
invalidate();
diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h
index 300dad13e..2674ae7c3 100644
--- a/src/yuzu/multiplayer/lobby.h
+++ b/src/yuzu/multiplayer/lobby.h
@@ -130,12 +130,14 @@ public:
public slots:
void SetFilterOwned(bool);
+ void SetFilterEmpty(bool);
void SetFilterFull(bool);
void SetFilterSearch(const QString&);
private:
QStandardItemModel* game_list;
bool filter_owned = false;
+ bool filter_empty = false;
bool filter_full = false;
QString filter_search;
};
diff --git a/src/yuzu/multiplayer/lobby.ui b/src/yuzu/multiplayer/lobby.ui
index 4c9901c9a..0ef0ef762 100644
--- a/src/yuzu/multiplayer/lobby.ui
+++ b/src/yuzu/multiplayer/lobby.ui
@@ -78,6 +78,13 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="hide_empty">
+ <property name="text">
+ <string>Hide Empty Rooms</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QCheckBox" name="hide_full">
<property name="text">
<string>Hide Full Rooms</string>
diff --git a/src/yuzu/multiplayer/validation.h b/src/yuzu/multiplayer/validation.h
index dd25af280..cbbe6757b 100644
--- a/src/yuzu/multiplayer/validation.h
+++ b/src/yuzu/multiplayer/validation.h
@@ -38,11 +38,28 @@ private:
QRegularExpression(QStringLiteral("^[a-zA-Z0-9._ -]{4,20}"));
QRegularExpressionValidator nickname;
- /// ipv4 address only
- // TODO remove this when we support hostnames in direct connect
+ /// ipv4 / ipv6 / hostnames
QRegularExpression ip_regex = QRegularExpression(QStringLiteral(
- "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|"
- "2[0-4][0-9]|25[0-5])"));
+ // IPv4 regex
+ "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|"
+ // IPv6 regex
+ "^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|"
+ "(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-"
+ "5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|"
+ "(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)"
+ "(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|"
+ "(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]"
+ "\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2["
+ "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2["
+ "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2["
+ "0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|"
+ "(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?"
+ "\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?$|"
+ // Hostname regex
+ "^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\\.)+[a-zA-Z]{2,}$"));
QRegularExpressionValidator ip;
/// port must be between 0 and 65535
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 2006b883e..db43b7033 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -22,6 +22,7 @@ struct ContextualShortcut {
QString keyseq;
QString controller_keyseq;
int context;
+ bool repeat;
};
struct Shortcut {
diff --git a/src/yuzu/util/limitable_input_dialog.cpp b/src/yuzu/util/limitable_input_dialog.cpp
index bbb370595..5f6a9c193 100644
--- a/src/yuzu/util/limitable_input_dialog.cpp
+++ b/src/yuzu/util/limitable_input_dialog.cpp
@@ -16,8 +16,6 @@ LimitableInputDialog::LimitableInputDialog(QWidget* parent) : QDialog{parent} {
LimitableInputDialog::~LimitableInputDialog() = default;
void LimitableInputDialog::CreateUI() {
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
-
text_label = new QLabel(this);
text_entry = new QLineEdit(this);
text_label_invalid = new QLabel(this);
diff --git a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
index 4b10fa517..1670aa596 100644
--- a/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
+++ b/src/yuzu/util/sequence_dialog/sequence_dialog.cpp
@@ -8,7 +8,6 @@
SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) {
setWindowTitle(tr("Enter a hotkey"));
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
key_sequence = new QKeySequenceEdit;