From 02234715c5894de178241b94b63a92845b83bc9f Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 27 Jan 2025 15:17:20 +1000 Subject: [PATCH] FullscreenUI: Move UpdateRunIdleState() for system soft-fail to host That way it's always in the correct state for e.g. memory card shutdown confirmations. --- src/core/fullscreen_ui.cpp | 41 ++++++++++------------- src/core/fullscreen_ui.h | 1 + src/duckstation-qt/mainwindow.cpp | 2 +- src/duckstation-qt/qthost.cpp | 55 +++++++++++++++++++++++-------- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 67ed84036..80539dba0 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -210,7 +210,6 @@ struct PostProcessingStageInfo ////////////////////////////////////////////////////////////////////////// // Main ////////////////////////////////////////////////////////////////////////// -static void UpdateRunIdleState(); static void PauseForMenuOpen(bool set_pause_menu_open); static bool AreAnyDialogsOpen(); static void ClosePauseMenu(); @@ -1122,25 +1121,18 @@ void FullscreenUI::DoStartPath(std::string path, std::string state, std::optiona return; // This can "fail" if HC mode is enabled and the user cancels, or other startup cancel paths. - // In that case, we need to re-trigger the idle state so the user can interact with the message. - // But we can skip it if we have a system, because OnSystemStarted() fixed it up. Error error; - const bool result = System::BootSystem(std::move(params), &error); - if (result && System::IsValid()) - return; + if (!System::BootSystem(std::move(params), &error)) + { + GPUThread::RunOnThread([error_desc = error.TakeDescription()]() { + if (!IsInitialized()) + return; - GPUThread::RunOnThread([error_desc = error.TakeDescription(), result]() { - if (!IsInitialized()) - return; - - if (!result) - { OpenInfoMessageDialog(TRANSLATE_STR("System", "Error"), fmt::format(TRANSLATE_FS("System", "Failed to boot system: {}"), error_desc)); - } - - UpdateRunIdleState(); - }); + UpdateRunIdleState(); + }); + } }); } @@ -1246,21 +1238,25 @@ void FullscreenUI::ConfirmIfSavingMemoryCards(std::string action, std::function< void FullscreenUI::RequestShutdown(bool save_state) { + s_state.current_main_window = MainWindowType::None; + ConfirmIfSavingMemoryCards(FSUI_STR("shut down"), [save_state](bool result) { if (result) Host::RunOnCPUThread([save_state]() { Host::RequestSystemShutdown(false, save_state); }); - else - ClosePauseMenu(); + + ClosePauseMenu(); }); } void FullscreenUI::RequestReset() { + s_state.current_main_window = MainWindowType::None; + ConfirmIfSavingMemoryCards(FSUI_STR("reset"), [](bool result) { if (result) Host::RunOnCPUThread(System::ResetSystem); - else - ClosePauseMenu(); + + ClosePauseMenu(); }); } @@ -1297,7 +1293,7 @@ void FullscreenUI::StartChangeDiscFromFile() } } - ReturnToPreviousWindow(); + ReturnToMainWindow(); }); }; @@ -6683,10 +6679,7 @@ void FullscreenUI::DrawPauseMenu() OpenPauseSubMenu(PauseSubMenu::None); if (ActiveButton(FSUI_ICONSTR(ICON_FA_SYNC, "Reset System"), false)) - { - ClosePauseMenu(); RequestReset(); - } if (ActiveButton(FSUI_ICONSTR(ICON_FA_SAVE, "Exit And Save State"), false)) RequestShutdown(true); diff --git a/src/core/fullscreen_ui.h b/src/core/fullscreen_ui.h index f94122aa7..f76c04a85 100644 --- a/src/core/fullscreen_ui.h +++ b/src/core/fullscreen_ui.h @@ -34,6 +34,7 @@ void OpenLeaderboardsWindow(); void ReturnToMainWindow(); void ReturnToPreviousWindow(); void SetStandardSelectionFooterText(bool back_instead_of_cancel); +void UpdateRunIdleState(); #endif void Shutdown(bool clear_state); diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 0b5d053b8..8f7519fb7 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -732,7 +732,7 @@ void MainWindow::quit() // Make sure VM is gone. It really should be if we're here. if (s_system_valid) { - g_emu_thread->shutdownSystem(false, true); + g_emu_thread->shutdownSystem(false, false); QtUtils::ProcessEventsWithSleep(QEventLoop::ExcludeUserInputEvents, []() { return s_system_valid; }); } diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 260a9f221..6935a44bd 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -1990,30 +1990,51 @@ void Host::ConfirmMessageAsync(std::string_view title, std::string_view message, if (no_text.empty()) no_text = TRANSLATE_SV("QtHost", "No"); + // Ensure it always comes from the CPU thread. + if (!g_emu_thread->isCurrentThread()) + { + Host::RunOnCPUThread([title = std::string(title), message = std::string(message), callback = std::move(callback), + yes_text = std::string(yes_text), no_text = std::string(no_text)]() mutable { + ConfirmMessageAsync(title, message, std::move(callback)); + }); + return; + } + + // Pause system while dialog is up. + const bool needs_pause = System::IsValid() && !System::IsPaused(); + if (needs_pause) + System::PauseSystem(true); + // Use FSUI to display the confirmation if it is active. if (FullscreenUI::IsInitialized()) { - // This.. should not be a thing. - if (!g_emu_thread->isCurrentThread()) - { - Host::RunOnCPUThread([title = std::string(title), message = std::string(message), callback = std::move(callback), - yes_text = std::string(yes_text), no_text = std::string(no_text)]() mutable { - ConfirmMessageAsync(title, message, std::move(callback)); - }); - return; - } - GPUThread::RunOnThread([title = std::string(title), message = std::string(message), callback = std::move(callback), - yes_text = std::string(yes_text), no_text = std::string(no_text)]() mutable { + yes_text = std::string(yes_text), no_text = std::string(no_text), needs_pause]() mutable { if (!FullscreenUI::Initialize()) { callback(false); + + if (needs_pause) + { + Host::RunOnCPUThread([]() { + if (System::IsValid()) + System::PauseSystem(false); + }); + } + return; } - ImGuiFullscreen::OpenConfirmMessageDialog(std::move(title), std::move(message), std::move(callback), + // Need to reset run idle state _again_ after displaying. + auto final_callback = [callback = std::move(callback)](bool result) { + FullscreenUI::UpdateRunIdleState(); + callback(result); + }; + + ImGuiFullscreen::OpenConfirmMessageDialog(std::move(title), std::move(message), std::move(final_callback), fmt::format(ICON_FA_CHECK " {}", yes_text), fmt::format(ICON_FA_TIMES " {}", no_text)); + FullscreenUI::UpdateRunIdleState(); }); } else @@ -2021,7 +2042,7 @@ void Host::ConfirmMessageAsync(std::string_view title, std::string_view message, // Otherwise, use the desktop UI. QtHost::RunOnUIThread([title = QtUtils::StringViewToQString(title), message = QtUtils::StringViewToQString(message), callback = std::move(callback), yes_text = QtUtils::StringViewToQString(yes_text), - no_text = QtUtils::StringViewToQString(no_text)]() mutable { + no_text = QtUtils::StringViewToQString(no_text), needs_pause]() mutable { auto lock = g_main_window->pauseAndLockSystem(); bool result; @@ -2038,6 +2059,14 @@ void Host::ConfirmMessageAsync(std::string_view title, std::string_view message, } callback(result); + + if (needs_pause) + { + Host::RunOnCPUThread([]() { + if (System::IsValid()) + System::PauseSystem(false); + }); + } }); } }