mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 18:54:14 +01:00 
			
		
		
		
	Merge pull request #11159 from flodavid/master_bis
Enable to use controller to close a game
This commit is contained in:
		
						commit
						18672e6a78
					
				| @ -45,6 +45,7 @@ SWITCHABLE(CpuAccuracy, true); | ||||
| SWITCHABLE(FullscreenMode, true); | ||||
| SWITCHABLE(GpuAccuracy, true); | ||||
| SWITCHABLE(Language, true); | ||||
| SWITCHABLE(MemoryLayout, true); | ||||
| SWITCHABLE(NvdecEmulation, false); | ||||
| SWITCHABLE(Region, true); | ||||
| SWITCHABLE(RendererBackend, true); | ||||
| @ -61,6 +62,10 @@ SWITCHABLE(u32, false); | ||||
| SWITCHABLE(u8, false); | ||||
| SWITCHABLE(u8, true); | ||||
| 
 | ||||
| // Used in UISettings
 | ||||
| // TODO see if we can move this to uisettings.cpp
 | ||||
| SWITCHABLE(ConfirmStop, true); | ||||
| 
 | ||||
| #undef SETTING | ||||
| #undef SWITCHABLE | ||||
| #endif | ||||
|  | ||||
| @ -67,6 +67,7 @@ SWITCHABLE(CpuAccuracy, true); | ||||
| SWITCHABLE(FullscreenMode, true); | ||||
| SWITCHABLE(GpuAccuracy, true); | ||||
| SWITCHABLE(Language, true); | ||||
| SWITCHABLE(MemoryLayout, true); | ||||
| SWITCHABLE(NvdecEmulation, false); | ||||
| SWITCHABLE(Region, true); | ||||
| SWITCHABLE(RendererBackend, true); | ||||
| @ -83,6 +84,10 @@ SWITCHABLE(u32, false); | ||||
| SWITCHABLE(u8, false); | ||||
| SWITCHABLE(u8, true); | ||||
| 
 | ||||
| // Used in UISettings
 | ||||
| // TODO see if we can move this to uisettings.h
 | ||||
| SWITCHABLE(ConfirmStop, true); | ||||
| 
 | ||||
| #undef SETTING | ||||
| #undef SWITCHABLE | ||||
| #endif | ||||
|  | ||||
| @ -133,6 +133,8 @@ ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid); | ||||
| 
 | ||||
| ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb); | ||||
| 
 | ||||
| ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); | ||||
| 
 | ||||
| ENUM(FullscreenMode, Borderless, Exclusive); | ||||
| 
 | ||||
| ENUM(NvdecEmulation, Off, Cpu, Gpu); | ||||
|  | ||||
| @ -128,8 +128,8 @@ const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{ | ||||
|     {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", "Restart Emulation")),        QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F6"),      QStringLiteral("R+Plus+Minus"), Qt::WindowShortcut, false}}, | ||||
|     {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")),           QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F5"),      QStringLiteral("L+Plus+Minus"), 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}}, | ||||
|  | ||||
| @ -157,6 +157,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) { | ||||
|     INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", ""); | ||||
|     INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", ""); | ||||
|     INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", ""); | ||||
|     INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", ""); | ||||
|     INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", ""); | ||||
|     INSERT(UISettings, controller_applet_disabled, "Disable controller applet", ""); | ||||
| 
 | ||||
| @ -383,6 +384,13 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QWidget* parent) { | ||||
|     translations->insert( | ||||
|         {Settings::EnumMetadata<Settings::ConsoleMode>::Index(), | ||||
|          {PAIR(ConsoleMode, Docked, "Docked"), PAIR(ConsoleMode, Handheld, "Handheld")}}); | ||||
|     translations->insert( | ||||
|         {Settings::EnumMetadata<Settings::ConfirmStop>::Index(), | ||||
|          { | ||||
|              PAIR(ConfirmStop, Ask_Always, "Always ask (Default)"), | ||||
|              PAIR(ConfirmStop, Ask_Based_On_Game, "Only if game specifies not to stop"), | ||||
|              PAIR(ConfirmStop, Ask_Never, "Never ask"), | ||||
|          }}); | ||||
| 
 | ||||
| #undef PAIR | ||||
| #undef CTX_PAIR | ||||
|  | ||||
| @ -211,7 +211,7 @@ void GMainWindow::ShowTelemetryCallout() { | ||||
|         tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'>Anonymous " | ||||
|            "data is collected</a> to help improve yuzu. " | ||||
|            "<br/><br/>Would you like to share your usage data with us?"); | ||||
|     if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) { | ||||
|     if (!question(this, tr("Telemetry"), telemetry_message)) { | ||||
|         Settings::values.enable_telemetry = false; | ||||
|         system->ApplySettings(); | ||||
|     } | ||||
| @ -2420,9 +2420,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT | ||||
|         } | ||||
|     }(); | ||||
| 
 | ||||
|     if (QMessageBox::question(this, tr("Remove Entry"), entry_question, | ||||
|                               QMessageBox::Yes | QMessageBox::No, | ||||
|                               QMessageBox::No) != QMessageBox::Yes) { | ||||
|     if (!question(this, tr("Remove Entry"), entry_question, QMessageBox::Yes | QMessageBox::No, | ||||
|                   QMessageBox::No)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| @ -2521,8 +2520,8 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ | ||||
|         } | ||||
|     }(); | ||||
| 
 | ||||
|     if (QMessageBox::question(this, tr("Remove File"), question, QMessageBox::Yes | QMessageBox::No, | ||||
|                               QMessageBox::No) != QMessageBox::Yes) { | ||||
|     if (!GMainWindow::question(this, tr("Remove File"), question, | ||||
|                                QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| @ -3409,10 +3408,13 @@ void GMainWindow::OnRestartGame() { | ||||
|     if (!system->IsPoweredOn()) { | ||||
|         return; | ||||
|     } | ||||
|     // Make a copy since ShutdownGame edits game_path
 | ||||
|     const auto current_game = QString(current_game_path); | ||||
|     ShutdownGame(); | ||||
|     BootGame(current_game); | ||||
| 
 | ||||
|     if (ConfirmShutdownGame()) { | ||||
|         // Make a copy since ShutdownGame edits game_path
 | ||||
|         const auto current_game = QString(current_game_path); | ||||
|         ShutdownGame(); | ||||
|         BootGame(current_game); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnPauseGame() { | ||||
| @ -3434,18 +3436,39 @@ void GMainWindow::OnPauseContinueGame() { | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnStopGame() { | ||||
|     if (system->GetExitLocked() && !ConfirmForceLockedExit()) { | ||||
|         return; | ||||
|     if (ConfirmShutdownGame()) { | ||||
|         play_time_manager->Stop(); | ||||
|         // Update game list to show new play time
 | ||||
|         game_list->PopulateAsync(UISettings::values.game_dirs); | ||||
|         if (OnShutdownBegin()) { | ||||
|             OnShutdownBeginDialog(); | ||||
|         } else { | ||||
|             OnEmulationStopped(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     play_time_manager->Stop(); | ||||
|     // Update game list to show new play time
 | ||||
|     game_list->PopulateAsync(UISettings::values.game_dirs); | ||||
|     if (OnShutdownBegin()) { | ||||
|         OnShutdownBeginDialog(); | ||||
| bool GMainWindow::ConfirmShutdownGame() { | ||||
|     if (UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Always) { | ||||
|         if (system->GetExitLocked()) { | ||||
|             if (!ConfirmForceLockedExit()) { | ||||
|                 return false; | ||||
|             } | ||||
|         } else { | ||||
|             if (!ConfirmChangeGame()) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         OnEmulationStopped(); | ||||
|         if (UISettings::values.confirm_before_stopping.GetValue() == | ||||
|                 ConfirmStop::Ask_Based_On_Game && | ||||
|             system->GetExitLocked()) { | ||||
|             if (!ConfirmForceLockedExit()) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnLoadComplete() { | ||||
| @ -3825,22 +3848,11 @@ void GMainWindow::OnTasRecord() { | ||||
|     const bool is_recording = input_subsystem->GetTas()->Record(); | ||||
|     if (!is_recording) { | ||||
|         is_tas_recording_dialog_active = true; | ||||
|         ControllerNavigation* controller_navigation = | ||||
|             new ControllerNavigation(system->HIDCore(), this); | ||||
|         // Use QMessageBox instead of question so we can link controller navigation
 | ||||
|         QMessageBox* box_dialog = new QMessageBox(); | ||||
|         box_dialog->setWindowTitle(tr("TAS Recording")); | ||||
|         box_dialog->setText(tr("Overwrite file of player 1?")); | ||||
|         box_dialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No); | ||||
|         box_dialog->setDefaultButton(QMessageBox::Yes); | ||||
|         connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent, | ||||
|                 [box_dialog](Qt::Key key) { | ||||
|                     QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); | ||||
|                     QCoreApplication::postEvent(box_dialog, event); | ||||
|                 }); | ||||
|         int res = box_dialog->exec(); | ||||
|         controller_navigation->UnloadController(); | ||||
|         input_subsystem->GetTas()->SaveRecording(res == QMessageBox::Yes); | ||||
| 
 | ||||
|         bool answer = question(this, tr("TAS Recording"), tr("Overwrite file of player 1?"), | ||||
|                                QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); | ||||
| 
 | ||||
|         input_subsystem->GetTas()->SaveRecording(answer); | ||||
|         is_tas_recording_dialog_active = false; | ||||
|     } | ||||
|     OnTasStateChanged(); | ||||
| @ -4081,6 +4093,29 @@ void GMainWindow::OnLoadAmiibo() { | ||||
|     LoadAmiibo(filename); | ||||
| } | ||||
| 
 | ||||
| bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text, | ||||
|                            QMessageBox::StandardButtons buttons, | ||||
|                            QMessageBox::StandardButton defaultButton) { | ||||
| 
 | ||||
|     QMessageBox* box_dialog = new QMessageBox(parent); | ||||
|     box_dialog->setWindowTitle(title); | ||||
|     box_dialog->setText(text); | ||||
|     box_dialog->setStandardButtons(buttons); | ||||
|     box_dialog->setDefaultButton(defaultButton); | ||||
| 
 | ||||
|     ControllerNavigation* controller_navigation = | ||||
|         new ControllerNavigation(system->HIDCore(), box_dialog); | ||||
|     connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent, | ||||
|             [box_dialog](Qt::Key key) { | ||||
|                 QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); | ||||
|                 QCoreApplication::postEvent(box_dialog, event); | ||||
|             }); | ||||
|     int res = box_dialog->exec(); | ||||
| 
 | ||||
|     controller_navigation->UnloadController(); | ||||
|     return res == QMessageBox::Yes; | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::LoadAmiibo(const QString& filename) { | ||||
|     auto* virtual_amiibo = input_subsystem->GetVirtualAmiibo(); | ||||
|     const QString title = tr("Error loading Amiibo data"); | ||||
| @ -4814,8 +4849,7 @@ bool GMainWindow::ConfirmClose() { | ||||
|         return true; | ||||
|     } | ||||
|     const auto text = tr("Are you sure you want to close yuzu?"); | ||||
|     const auto answer = QMessageBox::question(this, tr("yuzu"), text); | ||||
|     return answer != QMessageBox::No; | ||||
|     return question(this, tr("yuzu"), text); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::closeEvent(QCloseEvent* event) { | ||||
| @ -4908,11 +4942,11 @@ bool GMainWindow::ConfirmChangeGame() { | ||||
|     if (emu_thread == nullptr) | ||||
|         return true; | ||||
| 
 | ||||
|     const auto answer = QMessageBox::question( | ||||
|     // Use custom question to link controller navigation
 | ||||
|     return question( | ||||
|         this, tr("yuzu"), | ||||
|         tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."), | ||||
|         QMessageBox::Yes | QMessageBox::No, QMessageBox::No); | ||||
|     return answer != QMessageBox::No; | ||||
|         QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); | ||||
| } | ||||
| 
 | ||||
| bool GMainWindow::ConfirmForceLockedExit() { | ||||
| @ -4922,8 +4956,7 @@ bool GMainWindow::ConfirmForceLockedExit() { | ||||
|     const auto text = tr("The currently running application has requested yuzu to not exit.\n\n" | ||||
|                          "Would you like to bypass this and exit anyway?"); | ||||
| 
 | ||||
|     const auto answer = QMessageBox::question(this, tr("yuzu"), text); | ||||
|     return answer != QMessageBox::No; | ||||
|     return question(this, tr("yuzu"), text); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::RequestGameExit() { | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| #include <optional> | ||||
| 
 | ||||
| #include <QMainWindow> | ||||
| #include <QMessageBox> | ||||
| #include <QTimer> | ||||
| #include <QTranslator> | ||||
| 
 | ||||
| @ -15,6 +16,7 @@ | ||||
| #include "input_common/drivers/tas_input.h" | ||||
| #include "yuzu/compatibility_list.h" | ||||
| #include "yuzu/hotkeys.h" | ||||
| #include "yuzu/util/controller_navigation.h" | ||||
| 
 | ||||
| #ifdef __unix__ | ||||
| #include <QVariant> | ||||
| @ -424,6 +426,11 @@ private: | ||||
|     bool CheckSystemArchiveDecryption(); | ||||
|     bool CheckFirmwarePresence(); | ||||
|     void ConfigureFilesystemProvider(const std::string& filepath); | ||||
|     /**
 | ||||
|      * Open (or not) the right confirm dialog based on current setting and game exit lock | ||||
|      * @returns true if the player confirmed or the settings do no require it | ||||
|      */ | ||||
|     bool ConfirmShutdownGame(); | ||||
| 
 | ||||
|     QString GetTasStateDescription() const; | ||||
|     bool CreateShortcut(const std::string& shortcut_path, const std::string& title, | ||||
| @ -431,6 +438,17 @@ private: | ||||
|                         const std::string& command, const std::string& arguments, | ||||
|                         const std::string& categories, const std::string& keywords); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog | ||||
|      * The only difference is that it returns a boolean. | ||||
|      * | ||||
|      * @returns true if buttons contains QMessageBox::Yes and the user clicks on the "Yes" button. | ||||
|      */ | ||||
|     bool question(QWidget* parent, const QString& title, const QString& text, | ||||
|                   QMessageBox::StandardButtons buttons = | ||||
|                       QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No), | ||||
|                   QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); | ||||
| 
 | ||||
|     std::unique_ptr<Ui::MainWindow> ui; | ||||
| 
 | ||||
|     std::unique_ptr<Core::System> system; | ||||
|  | ||||
| @ -16,7 +16,9 @@ | ||||
| #include "common/settings_enums.h" | ||||
| 
 | ||||
| using Settings::Category; | ||||
| using Settings::ConfirmStop; | ||||
| using Settings::Setting; | ||||
| using Settings::SwitchableSetting; | ||||
| 
 | ||||
| #ifndef CANNOT_EXPLICITLY_INSTANTIATE | ||||
| namespace Settings { | ||||
| @ -94,6 +96,15 @@ struct Values { | ||||
|     Setting<bool> confirm_before_closing{ | ||||
|         linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default, | ||||
|         true,    true}; | ||||
| 
 | ||||
|     SwitchableSetting<ConfirmStop> confirm_before_stopping{linkage, | ||||
|                                                            ConfirmStop::Ask_Always, | ||||
|                                                            "confirmStop", | ||||
|                                                            Category::UiGeneral, | ||||
|                                                            Settings::Specialization::Default, | ||||
|                                                            true, | ||||
|                                                            true}; | ||||
| 
 | ||||
|     Setting<bool> first_start{linkage, true, "firstStart", Category::Ui}; | ||||
|     Setting<bool> pause_when_in_background{linkage, | ||||
|                                            false, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user