From 7e2afe82b58a9005dff4b645c56a5288f37127fb Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 14 Dec 2023 16:07:57 +1000 Subject: [PATCH] FullscreenUI: Fix opening while paused --- src/core/fullscreen_ui.cpp | 63 +++++++++++++++++------- src/core/system.cpp | 11 +++++ src/core/system.h | 3 ++ src/duckstation-nogui/nogui_host.cpp | 4 ++ src/duckstation-qt/qthost.cpp | 10 ++-- src/duckstation-regtest/regtest_host.cpp | 5 ++ 6 files changed, 73 insertions(+), 23 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 28cd35cc2..3324e4fbf 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -229,6 +229,7 @@ static void ExitFullscreenAndOpenURL(const std::string_view& url); static void CopyTextToClipboard(std::string title, const std::string_view& text); static void DrawAboutWindow(); static void OpenAboutWindow(); +static void FixStateIfPaused(); static MainWindowType s_current_main_window = MainWindowType::None; static PauseSubMenu s_current_pause_submenu = PauseSubMenu::None; @@ -595,6 +596,9 @@ bool FullscreenUI::Initialize() if (!System::IsValid()) SwitchToLanding(); + if (!System::IsRunning()) + Host::OnIdleStateChanged(); + return true; } @@ -697,6 +701,26 @@ void FullscreenUI::OpenPauseMenu() s_current_main_window = MainWindowType::PauseMenu; s_current_pause_submenu = PauseSubMenu::None; QueueResetFocus(); + FixStateIfPaused(); +} + +void FullscreenUI::FixStateIfPaused() +{ + if (!System::IsValid() || System::IsRunning()) + return; + + // When we're paused, we won't have trickled the key up event for escape yet. Do it now. + ImGui::UpdateInputEvents(false); + + Host::OnIdleStateChanged(); + Host::RunOnCPUThread([]() { + if (System::IsValid()) + { + // Why twice? To clear the "wants keyboard input" flag. + System::InvalidateDisplay(); + System::InvalidateDisplay(); + } + }); } void FullscreenUI::ClosePauseMenu() @@ -711,6 +735,7 @@ void FullscreenUI::ClosePauseMenu() s_current_pause_submenu = PauseSubMenu::None; s_pause_menu_was_open = false; QueueResetFocus(); + FixStateIfPaused(); } void FullscreenUI::OpenPauseSubMenu(PauseSubMenu submenu) @@ -837,6 +862,7 @@ void FullscreenUI::ReturnToMainWindow() { ClosePauseMenu(); s_current_main_window = System::IsValid() ? MainWindowType::None : MainWindowType::Landing; + FixStateIfPaused(); } bool FullscreenUI::LoadResources() @@ -1556,7 +1582,7 @@ void FullscreenUI::DrawInputBindingWindow() ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoInputs)) { ImGui::TextWrapped("%s", SmallString::from_format(FSUI_FSTR("Setting {} binding {}."), s_input_binding_section, - s_input_binding_display_name) + s_input_binding_display_name) .c_str()); ImGui::TextUnformatted(FSUI_CSTR("Push a controller button or axis now.")); ImGui::NewLine(); @@ -2887,7 +2913,7 @@ void FullscreenUI::DrawBIOSSettingsPage() if (MenuButtonWithValue(title, SmallString::from_format(FSUI_FSTR("BIOS to use when emulating {} consoles."), - Settings::GetConsoleRegionDisplayName(region)), + Settings::GetConsoleRegionDisplayName(region)), filename.has_value() ? (filename->empty() ? FSUI_CSTR("Auto-Detect") : filename->c_str()) : FSUI_CSTR("Use Global Setting"))) { @@ -3362,12 +3388,13 @@ void FullscreenUI::DrawControllerSettingsPage() if (mtap_enabled[mtap_port]) { - MenuHeading(TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}{}")), mtap_port + 1, - mtap_slot_names[mtap_slot])); + MenuHeading(TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}{}")), + mtap_port + 1, mtap_slot_names[mtap_slot])); } else { - MenuHeading(TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}")), mtap_port + 1)); + MenuHeading( + TinyString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}")), mtap_port + 1)); } const TinyString section = TinyString::from_format("Pad{}", global_slot + 1); @@ -3416,12 +3443,12 @@ void FullscreenUI::DrawControllerSettingsPage() if (mtap_enabled[mtap_port]) { MenuHeading(SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {}{} Macros")), - mtap_port + 1, mtap_slot_names[mtap_slot])); + mtap_port + 1, mtap_slot_names[mtap_slot])); } else { MenuHeading(SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {} Macros")), - mtap_port + 1)); + mtap_port + 1)); } for (u32 macro_index = 0; macro_index < InputManager::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++) @@ -3564,12 +3591,12 @@ void FullscreenUI::DrawControllerSettingsPage() { MenuHeading( SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {}{} Settings")), - mtap_port + 1, mtap_slot_names[mtap_slot])); + mtap_port + 1, mtap_slot_names[mtap_slot])); } else { - MenuHeading(SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {} Settings")), - mtap_port + 1)); + MenuHeading(SmallString::from_format( + fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {} Settings")), mtap_port + 1)); } for (const SettingInfo& si : ci->settings) @@ -4245,7 +4272,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage() { tstr.format(ICON_FA_RULER_VERTICAL "{}##{}", opt.ui_name, opt.name); str.format(FSUI_FSTR("Value: {} | Default: {} | Minimum: {} | Maximum: {}"), opt.value[0].float_value, - opt.default_value[0].float_value, opt.min_value[0].float_value, opt.max_value[0].float_value); + opt.default_value[0].float_value, opt.min_value[0].float_value, opt.max_value[0].float_value); if (MenuButton(tstr, str)) ImGui::OpenPopup(tstr); @@ -4344,7 +4371,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage() { tstr.format(ICON_FA_RULER_VERTICAL "{}##{}", opt.ui_name, opt.name); str.format(FSUI_FSTR("Value: {} | Default: {} | Minimum: {} | Maximum: {}"), opt.value[0].int_value, - opt.default_value[0].int_value, opt.min_value[0].int_value, opt.max_value[0].int_value); + opt.default_value[0].int_value, opt.min_value[0].int_value, opt.max_value[0].int_value); if (MenuButton(tstr, str)) ImGui::OpenPopup(tstr); @@ -4609,7 +4636,7 @@ void FullscreenUI::DrawAchievementsSettingsPage() { ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]); ActiveButton(SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_USER, "Username: {}")), - bsi->GetStringValue("Cheevos", "Username")), + bsi->GetStringValue("Cheevos", "Username")), false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); TinyString ts_string; @@ -4642,7 +4669,7 @@ void FullscreenUI::DrawAchievementsSettingsPage() ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]); ActiveButton(SmallString::from_format(fmt::runtime(FSUI_ICONSTR(ICON_FA_BOOKMARK, "Game: {} ({})")), - Achievements::GetGameID(), Achievements::GetGameTitle()), + Achievements::GetGameID(), Achievements::GetGameTitle()), false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); const std::string& rich_presence_string = Achievements::GetRichPresenceString(); @@ -5083,9 +5110,9 @@ void FullscreenUI::PopulateSaveStateScreenshot(SaveStateListEntry* li, const Ext li->preview_texture.reset(); if (ssi && !ssi->screenshot_data.empty()) { - li->preview_texture = g_gpu_device->FetchTexture( - ssi->screenshot_width, ssi->screenshot_height, 1, 1, 1, GPUTexture::Type::Texture, GPUTexture::Format::RGBA8, - ssi->screenshot_data.data(), sizeof(u32) * ssi->screenshot_width); + li->preview_texture = g_gpu_device->FetchTexture(ssi->screenshot_width, ssi->screenshot_height, 1, 1, 1, + GPUTexture::Type::Texture, GPUTexture::Format::RGBA8, + ssi->screenshot_data.data(), sizeof(u32) * ssi->screenshot_width); } else { @@ -6523,6 +6550,7 @@ void FullscreenUI::OpenAchievementsWindow() s_current_main_window = MainWindowType::Achievements; QueueResetFocus(); + FixStateIfPaused(); } bool FullscreenUI::IsAchievementsWindowOpen() @@ -6553,6 +6581,7 @@ void FullscreenUI::OpenLeaderboardsWindow() s_current_main_window = MainWindowType::Leaderboards; QueueResetFocus(); + FixStateIfPaused(); } bool FullscreenUI::IsLeaderboardsWindowOpen() diff --git a/src/core/system.cpp b/src/core/system.cpp index ab92e2a56..8e680ef8e 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -1108,6 +1108,7 @@ void System::PauseSystem(bool paused) PlatformMisc::ResumeScreensaver(); Host::OnSystemPaused(); + Host::OnIdleStateChanged(); InvalidateDisplay(); } else @@ -1122,6 +1123,7 @@ void System::PauseSystem(bool paused) UpdateDisplaySync(); Host::OnSystemResumed(); + Host::OnIdleStateChanged(); ResetPerformanceCounters(); ResetThrottler(); @@ -1285,6 +1287,7 @@ bool System::BootSystem(SystemBootParameters parameters) Path::GetFileName(parameters.filename), error.GetDescription())); s_state = State::Shutdown; Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); return false; } @@ -1324,6 +1327,7 @@ bool System::BootSystem(SystemBootParameters parameters) parameters.filename, error.GetDescription())); s_state = State::Shutdown; Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); return false; } @@ -1338,6 +1342,7 @@ bool System::BootSystem(SystemBootParameters parameters) parameters.override_exe.c_str()); s_state = State::Shutdown; Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); return false; } @@ -1351,6 +1356,7 @@ bool System::BootSystem(SystemBootParameters parameters) s_state = State::Shutdown; ClearRunningGame(); Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); return false; } @@ -1382,6 +1388,7 @@ bool System::BootSystem(SystemBootParameters parameters) s_state = State::Shutdown; ClearRunningGame(); Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); return false; } } @@ -1392,6 +1399,7 @@ bool System::BootSystem(SystemBootParameters parameters) s_state = State::Shutdown; ClearRunningGame(); Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); return false; } @@ -1401,6 +1409,7 @@ bool System::BootSystem(SystemBootParameters parameters) s_state = State::Shutdown; ClearRunningGame(); Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); return false; } @@ -1453,6 +1462,7 @@ bool System::BootSystem(SystemBootParameters parameters) PlatformMisc::SuspendScreensaver(); Host::OnSystemStarted(); + Host::OnIdleStateChanged(); // try to load the state, if it fails, bail out if (!parameters.save_state.empty()) @@ -1692,6 +1702,7 @@ void System::DestroySystem() s_state = State::Shutdown; Host::OnSystemDestroyed(); + Host::OnIdleStateChanged(); } void System::ClearRunningGame() diff --git a/src/core/system.h b/src/core/system.h index 39f5ee39f..c8fe75e2e 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -518,6 +518,9 @@ void OnSystemPaused(); /// Called when the VM is resumed after being paused. void OnSystemResumed(); +/// Called when the pause state changes, or fullscreen UI opens. +void OnIdleStateChanged(); + /// Called when performance metrics are updated, approximately once a second. void OnPerformanceCountersUpdated(); diff --git a/src/duckstation-nogui/nogui_host.cpp b/src/duckstation-nogui/nogui_host.cpp index 15ce8ae5f..ec251fa27 100644 --- a/src/duckstation-nogui/nogui_host.cpp +++ b/src/duckstation-nogui/nogui_host.cpp @@ -738,6 +738,10 @@ void Host::OnSystemDestroyed() { } +void Host::OnIdleStateChanged() +{ +} + void Host::BeginPresentFrame() { } diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 33280e7f4..d6f644b72 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -485,7 +485,6 @@ void EmuThread::startFullscreenUI() // poll more frequently so we don't lose events stopBackgroundControllerPollTimer(); startBackgroundControllerPollTimer(); - wakeThread(); } void EmuThread::stopFullscreenUI() @@ -731,7 +730,6 @@ void Host::OnSystemStarting() void Host::OnSystemStarted() { - g_emu_thread->wakeThread(); g_emu_thread->stopBackgroundControllerPollTimer(); emit g_emu_thread->systemStarted(); @@ -751,7 +749,6 @@ void Host::OnSystemResumed() emit g_emu_thread->systemResumed(); - g_emu_thread->wakeThread(); g_emu_thread->stopBackgroundControllerPollTimer(); } @@ -760,10 +757,11 @@ void Host::OnSystemDestroyed() g_emu_thread->resetPerformanceCounters(); g_emu_thread->startBackgroundControllerPollTimer(); emit g_emu_thread->systemDestroyed(); +} - // re-wake thread when we're running fsui, otherwise it won't draw - if (g_emu_thread->isRunningFullscreenUI()) - g_emu_thread->wakeThread(); +void Host::OnIdleStateChanged() +{ + g_emu_thread->wakeThread(); } void EmuThread::reloadInputSources() diff --git a/src/duckstation-regtest/regtest_host.cpp b/src/duckstation-regtest/regtest_host.cpp index 8c117aa5d..4333143e3 100644 --- a/src/duckstation-regtest/regtest_host.cpp +++ b/src/duckstation-regtest/regtest_host.cpp @@ -243,6 +243,11 @@ void Host::OnSystemResumed() // } +void Host::OnIdleStateChanged() +{ + // +} + void Host::OnPerformanceCountersUpdated() { //