summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar flodavid2023-07-25 22:31:39 +0200
committerGravatar flodavid2023-10-12 01:51:52 +0200
commita34565727b6eba66cf20d32f3ec2ad073f29f9e1 (patch)
tree9263279b90c2241c2f28d54051f95c05e3ec1f24 /src
parentMerge pull request #11720 from lat9nq/dbg-syms (diff)
downloadyuzu-a34565727b6eba66cf20d32f3ec2ad073f29f9e1.tar.gz
yuzu-a34565727b6eba66cf20d32f3ec2ad073f29f9e1.tar.xz
yuzu-a34565727b6eba66cf20d32f3ec2ad073f29f9e1.zip
yuzu: Enable to use controller to close a game
- Add General setting to choose if a confirm dialog is shown when stopping - Show the right confirm dialog if wanted - Reuse dialog window that ask to close the game - Add "L + Plus + Minus" default shortcut to Stop emulation - Create generic question dialog based on TAS dialog - It allows controller interaction on most dialogs
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/shared_translation.cpp1
-rw-r--r--src/yuzu/main.cpp86
-rw-r--r--src/yuzu/main.h13
-rw-r--r--src/yuzu/uisettings.h5
5 files changed, 75 insertions, 32 deletions
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 1de093447..bc47d1688 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -129,7 +129,7 @@ const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{
129 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut, false}}, 129 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+O"), QStringLiteral(""), Qt::WidgetWithChildrenShortcut, false}},
130 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, 130 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F2"), QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
131 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral(""), Qt::WindowShortcut, false}}, 131 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"), QStringLiteral(""), Qt::WindowShortcut, false}},
132 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral(""), Qt::WindowShortcut, false}}, 132 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"), QStringLiteral("L+Plus+Minus"), Qt::WindowShortcut, false}},
133 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, 133 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
134 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, 134 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Reset")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
135 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut, false}}, 135 {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp
index a4e8af1b4..9e65525ca 100644
--- a/src/yuzu/configuration/shared_translation.cpp
+++ b/src/yuzu/configuration/shared_translation.cpp
@@ -157,6 +157,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
157 INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", ""); 157 INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", "");
158 INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", ""); 158 INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", "");
159 INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", ""); 159 INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", "");
160 INSERT(UISettings, confirm_before_stopping, "Confirm stopping emulation", "");
160 INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", ""); 161 INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", "");
161 INSERT(UISettings, controller_applet_disabled, "Disable controller applet", ""); 162 INSERT(UISettings, controller_applet_disabled, "Disable controller applet", "");
162 163
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 5427758c1..26fa3e191 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -209,7 +209,7 @@ void GMainWindow::ShowTelemetryCallout() {
209 tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'>Anonymous " 209 tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'>Anonymous "
210 "data is collected</a> to help improve yuzu. " 210 "data is collected</a> to help improve yuzu. "
211 "<br/><br/>Would you like to share your usage data with us?"); 211 "<br/><br/>Would you like to share your usage data with us?");
212 if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) { 212 if (!question(this, tr("Telemetry"), telemetry_message)) {
213 Settings::values.enable_telemetry = false; 213 Settings::values.enable_telemetry = false;
214 system->ApplySettings(); 214 system->ApplySettings();
215 } 215 }
@@ -2418,9 +2418,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT
2418 } 2418 }
2419 }(); 2419 }();
2420 2420
2421 if (QMessageBox::question(this, tr("Remove Entry"), entry_question, 2421 if (!question(this, tr("Remove Entry"), entry_question, QMessageBox::Yes | QMessageBox::No,
2422 QMessageBox::Yes | QMessageBox::No, 2422 QMessageBox::No)) {
2423 QMessageBox::No) != QMessageBox::Yes) {
2424 return; 2423 return;
2425 } 2424 }
2426 2425
@@ -2519,8 +2518,8 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ
2519 } 2518 }
2520 }(); 2519 }();
2521 2520
2522 if (QMessageBox::question(this, tr("Remove File"), question, QMessageBox::Yes | QMessageBox::No, 2521 if (!GMainWindow::question(this, tr("Remove File"), question,
2523 QMessageBox::No) != QMessageBox::Yes) { 2522 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) {
2524 return; 2523 return;
2525 } 2524 }
2526 2525
@@ -3426,8 +3425,25 @@ void GMainWindow::OnPauseContinueGame() {
3426} 3425}
3427 3426
3428void GMainWindow::OnStopGame() { 3427void GMainWindow::OnStopGame() {
3429 if (system->GetExitLocked() && !ConfirmForceLockedExit()) { 3428 // Open (or not) the right confirm dialog based on current setting and game exit lock
3430 return; 3429 if (UISettings::values.confirm_before_stopping.GetValue() == UISettings::AskStopIndex::Always) {
3430 if (system->GetExitLocked()) {
3431 if (!ConfirmForceLockedExit()) {
3432 return;
3433 }
3434 } else {
3435 if (!ConfirmChangeGame()) {
3436 return;
3437 }
3438 }
3439 } else {
3440 if (UISettings::values.confirm_before_stopping.GetValue() ==
3441 UISettings::AskStopIndex::Game &&
3442 system->GetExitLocked()) {
3443 if (!ConfirmForceLockedExit()) {
3444 return;
3445 }
3446 }
3431 } 3447 }
3432 3448
3433 play_time_manager->Stop(); 3449 play_time_manager->Stop();
@@ -3817,22 +3833,11 @@ void GMainWindow::OnTasRecord() {
3817 const bool is_recording = input_subsystem->GetTas()->Record(); 3833 const bool is_recording = input_subsystem->GetTas()->Record();
3818 if (!is_recording) { 3834 if (!is_recording) {
3819 is_tas_recording_dialog_active = true; 3835 is_tas_recording_dialog_active = true;
3820 ControllerNavigation* controller_navigation = 3836
3821 new ControllerNavigation(system->HIDCore(), this); 3837 bool answer = question(this, tr("TAS Recording"), tr("Overwrite file of player 1?"),
3822 // Use QMessageBox instead of question so we can link controller navigation 3838 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
3823 QMessageBox* box_dialog = new QMessageBox(); 3839
3824 box_dialog->setWindowTitle(tr("TAS Recording")); 3840 input_subsystem->GetTas()->SaveRecording(answer);
3825 box_dialog->setText(tr("Overwrite file of player 1?"));
3826 box_dialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
3827 box_dialog->setDefaultButton(QMessageBox::Yes);
3828 connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
3829 [box_dialog](Qt::Key key) {
3830 QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
3831 QCoreApplication::postEvent(box_dialog, event);
3832 });
3833 int res = box_dialog->exec();
3834 controller_navigation->UnloadController();
3835 input_subsystem->GetTas()->SaveRecording(res == QMessageBox::Yes);
3836 is_tas_recording_dialog_active = false; 3841 is_tas_recording_dialog_active = false;
3837 } 3842 }
3838 OnTasStateChanged(); 3843 OnTasStateChanged();
@@ -4073,6 +4078,27 @@ void GMainWindow::OnLoadAmiibo() {
4073 LoadAmiibo(filename); 4078 LoadAmiibo(filename);
4074} 4079}
4075 4080
4081bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text,
4082 QMessageBox::StandardButtons buttons,
4083 QMessageBox::StandardButton defaultButton) {
4084 ControllerNavigation* controller_navigation = new ControllerNavigation(system->HIDCore(), this);
4085
4086 QMessageBox* box_dialog = new QMessageBox(parent);
4087 box_dialog->setWindowTitle(title);
4088 box_dialog->setText(text);
4089 box_dialog->setStandardButtons(buttons);
4090 box_dialog->setDefaultButton(defaultButton);
4091 connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
4092 [box_dialog](Qt::Key key) {
4093 QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
4094 QCoreApplication::postEvent(box_dialog, event);
4095 });
4096 int res = box_dialog->exec();
4097
4098 controller_navigation->UnloadController();
4099 return res == QMessageBox::Yes;
4100}
4101
4076void GMainWindow::LoadAmiibo(const QString& filename) { 4102void GMainWindow::LoadAmiibo(const QString& filename) {
4077 auto* virtual_amiibo = input_subsystem->GetVirtualAmiibo(); 4103 auto* virtual_amiibo = input_subsystem->GetVirtualAmiibo();
4078 const QString title = tr("Error loading Amiibo data"); 4104 const QString title = tr("Error loading Amiibo data");
@@ -4806,8 +4832,7 @@ bool GMainWindow::ConfirmClose() {
4806 return true; 4832 return true;
4807 } 4833 }
4808 const auto text = tr("Are you sure you want to close yuzu?"); 4834 const auto text = tr("Are you sure you want to close yuzu?");
4809 const auto answer = QMessageBox::question(this, tr("yuzu"), text); 4835 return question(this, tr("yuzu"), text);
4810 return answer != QMessageBox::No;
4811} 4836}
4812 4837
4813void GMainWindow::closeEvent(QCloseEvent* event) { 4838void GMainWindow::closeEvent(QCloseEvent* event) {
@@ -4900,11 +4925,11 @@ bool GMainWindow::ConfirmChangeGame() {
4900 if (emu_thread == nullptr) 4925 if (emu_thread == nullptr)
4901 return true; 4926 return true;
4902 4927
4903 const auto answer = QMessageBox::question( 4928 // Use custom question to link controller navigation
4929 return question(
4904 this, tr("yuzu"), 4930 this, tr("yuzu"),
4905 tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."), 4931 tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."),
4906 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); 4932 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
4907 return answer != QMessageBox::No;
4908} 4933}
4909 4934
4910bool GMainWindow::ConfirmForceLockedExit() { 4935bool GMainWindow::ConfirmForceLockedExit() {
@@ -4914,8 +4939,7 @@ bool GMainWindow::ConfirmForceLockedExit() {
4914 const auto text = tr("The currently running application has requested yuzu to not exit.\n\n" 4939 const auto text = tr("The currently running application has requested yuzu to not exit.\n\n"
4915 "Would you like to bypass this and exit anyway?"); 4940 "Would you like to bypass this and exit anyway?");
4916 4941
4917 const auto answer = QMessageBox::question(this, tr("yuzu"), text); 4942 return question(this, tr("yuzu"), text);
4918 return answer != QMessageBox::No;
4919} 4943}
4920 4944
4921void GMainWindow::RequestGameExit() { 4945void GMainWindow::RequestGameExit() {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 2346eb3bd..711c53a32 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -7,6 +7,7 @@
7#include <optional> 7#include <optional>
8 8
9#include <QMainWindow> 9#include <QMainWindow>
10#include <QMessageBox>
10#include <QTimer> 11#include <QTimer>
11#include <QTranslator> 12#include <QTranslator>
12 13
@@ -15,6 +16,7 @@
15#include "input_common/drivers/tas_input.h" 16#include "input_common/drivers/tas_input.h"
16#include "yuzu/compatibility_list.h" 17#include "yuzu/compatibility_list.h"
17#include "yuzu/hotkeys.h" 18#include "yuzu/hotkeys.h"
19#include "yuzu/util/controller_navigation.h"
18 20
19#ifdef __unix__ 21#ifdef __unix__
20#include <QVariant> 22#include <QVariant>
@@ -431,6 +433,17 @@ private:
431 const std::string& command, const std::string& arguments, 433 const std::string& command, const std::string& arguments,
432 const std::string& categories, const std::string& keywords); 434 const std::string& categories, const std::string& keywords);
433 435
436 /**
437 * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog
438 * The only difference is that it returns a boolean.
439 *
440 * @returns true if buttons contains QMessageBox::Yes and the user clicks on the "Yes" button.
441 */
442 bool question(QWidget* parent, const QString& title, const QString& text,
443 QMessageBox::StandardButtons buttons =
444 QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
445 QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
446
434 std::unique_ptr<Ui::MainWindow> ui; 447 std::unique_ptr<Ui::MainWindow> ui;
435 448
436 std::unique_ptr<Core::System> system; 449 std::unique_ptr<Core::System> system;
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 975008159..1216c4efa 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -56,6 +56,8 @@ enum class Theme {
56 MidnightBlueColorful, 56 MidnightBlueColorful,
57}; 57};
58 58
59enum AskStopIndex : int { Always, Game, Never };
60
59using Themes = std::array<std::pair<const char*, const char*>, 6>; 61using Themes = std::array<std::pair<const char*, const char*>, 6>;
60extern const Themes themes; 62extern const Themes themes;
61 63
@@ -94,6 +96,9 @@ struct Values {
94 Setting<bool> confirm_before_closing{ 96 Setting<bool> confirm_before_closing{
95 linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default, 97 linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default,
96 true, true}; 98 true, true};
99 Setting<bool> confirm_before_stopping{
100 linkage, true, "confirmStop", Category::UiGeneral, Settings::Specialization::Default,
101 true, true};
97 Setting<bool> first_start{linkage, true, "firstStart", Category::Ui}; 102 Setting<bool> first_start{linkage, true, "firstStart", Category::Ui};
98 Setting<bool> pause_when_in_background{linkage, 103 Setting<bool> pause_when_in_background{linkage,
99 false, 104 false,