From 13a37418e6cb4596f74fcfa1b38276c14d125e1e Mon Sep 17 00:00:00 2001 From: Stenzek Date: Tue, 13 Aug 2024 17:48:31 +1000 Subject: [PATCH] FullscreenUI: Fix popup close resetting window scroll --- src/core/fullscreen_ui.cpp | 55 ++++++++++++++++++----------------- src/util/imgui_fullscreen.cpp | 39 ++++++++++++++----------- src/util/imgui_fullscreen.h | 11 ++++++- 3 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 408845eb3..d4b5f5eee 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -71,6 +71,7 @@ public: #define FSUI_FSTR(str) fmt::runtime(Host::TranslateToStringView(TR_CONTEXT, str)) #define FSUI_NSTR(str) str +using ImGuiFullscreen::FocusResetType; using ImGuiFullscreen::g_large_font; using ImGuiFullscreen::g_layout_padding_left; using ImGuiFullscreen::g_layout_padding_top; @@ -125,6 +126,7 @@ using ImGuiFullscreen::ForceKeyNavEnabled; using ImGuiFullscreen::GetCachedTexture; using ImGuiFullscreen::GetCachedTextureAsync; using ImGuiFullscreen::GetPlaceholderTexture; +using ImGuiFullscreen::GetQueuedFocusResetType; using ImGuiFullscreen::HorizontalMenuItem; using ImGuiFullscreen::IsFocusResetQueued; using ImGuiFullscreen::IsGamepadInputSource; @@ -636,7 +638,7 @@ void FullscreenUI::OnSystemStarted() return; s_current_main_window = MainWindowType::None; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } void FullscreenUI::OnSystemPaused() @@ -695,7 +697,7 @@ void FullscreenUI::OpenPauseMenu() PauseForMenuOpen(true); s_current_main_window = MainWindowType::PauseMenu; s_current_pause_submenu = PauseSubMenu::None; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); ForceKeyNavEnabled(); FixStateIfPaused(); } @@ -730,7 +732,7 @@ void FullscreenUI::ClosePauseMenu() s_current_main_window = MainWindowType::None; s_current_pause_submenu = PauseSubMenu::None; s_pause_menu_was_open = false; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); FixStateIfPaused(); } @@ -738,7 +740,7 @@ void FullscreenUI::OpenPauseSubMenu(PauseSubMenu submenu) { s_current_main_window = MainWindowType::PauseMenu; s_current_pause_submenu = submenu; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } void FullscreenUI::Shutdown() @@ -876,7 +878,7 @@ void FullscreenUI::ReturnToPreviousWindow() if (System::IsValid() && s_pause_menu_was_open) { s_current_main_window = MainWindowType::PauseMenu; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } else { @@ -976,7 +978,6 @@ void FullscreenUI::DoStartFile() if (!path.empty()) DoStartPath(path); - QueueResetFocus(); CloseFileSelector(); }; @@ -1040,7 +1041,6 @@ void FullscreenUI::DoStartDisc() DoStartDisc(std::move(paths[index])); CloseChoiceDialog(); - QueueResetFocus(); }); } @@ -1117,7 +1117,6 @@ void FullscreenUI::DoChangeDiscFromFile() } } - QueueResetFocus(); CloseFileSelector(); ReturnToPreviousWindow(); }; @@ -1153,7 +1152,6 @@ void FullscreenUI::DoChangeDisc() System::SwitchMediaSubImage(static_cast(index - 1)); } - QueueResetFocus(); CloseChoiceDialog(); ReturnToPreviousWindow(); }; @@ -1195,7 +1193,6 @@ void FullscreenUI::DoChangeDisc() System::InsertMedia(paths[index - 1].c_str()); } - QueueResetFocus(); CloseChoiceDialog(); ReturnToMainWindow(); }; @@ -1299,7 +1296,7 @@ void FullscreenUI::DoToggleFullscreen() void FullscreenUI::SwitchToLanding() { s_current_main_window = MainWindowType::Landing; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size) @@ -1396,7 +1393,7 @@ void FullscreenUI::DrawLandingWindow() FSUI_CSTR("Launch a game from a file, disc, or starts the console without any disc inserted."))) { s_current_main_window = MainWindowType::StartGame; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } if (HorizontalMenuItem(GetCachedTexture("fullscreenui/applications-system.png"), FSUI_CSTR("Settings"), @@ -1410,7 +1407,7 @@ void FullscreenUI::DrawLandingWindow() (!AreAnyDialogsOpen() && WantsToCloseMenu())) { s_current_main_window = MainWindowType::Exit; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } } EndHorizontalMenu(); @@ -1481,7 +1478,7 @@ void FullscreenUI::DrawStartGameWindow() (!AreAnyDialogsOpen() && WantsToCloseMenu())) { s_current_main_window = MainWindowType::Landing; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } } EndHorizontalMenu(); @@ -1527,7 +1524,7 @@ void FullscreenUI::DrawExitWindow() WantsToCloseMenu()) { s_current_main_window = MainWindowType::Landing; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } if (HorizontalMenuItem(GetCachedTexture("fullscreenui/exit.png"), FSUI_CSTR("Exit DuckStation"), @@ -2742,7 +2739,7 @@ void FullscreenUI::SwitchToGameSettingsForSerial(std::string_view serial) s_game_settings_interface->Load(); s_current_main_window = MainWindowType::Settings; s_settings_page = SettingsPage::Summary; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } void FullscreenUI::SwitchToGameSettings() @@ -2884,7 +2881,7 @@ void FullscreenUI::DrawSettingsWindow() { index = (index == 0) ? (count - 1) : (index - 1); s_settings_page = pages[index]; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } else if (ImGui::IsKeyPressed(ImGuiKey_GamepadDpadRight, true) || ImGui::IsKeyPressed(ImGuiKey_NavGamepadTweakFast, true) || @@ -2892,7 +2889,7 @@ void FullscreenUI::DrawSettingsWindow() { index = (index + 1) % count; s_settings_page = pages[index]; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } } @@ -2911,6 +2908,7 @@ void FullscreenUI::DrawSettingsWindow() if (NavButton(icons[i], i == index, true, ITEM_WIDTH, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY)) { s_settings_page = pages[i]; + QueueResetFocus(FocusResetType::WindowChanged); } } @@ -2920,8 +2918,13 @@ void FullscreenUI::DrawSettingsWindow() EndFullscreenWindow(); // we have to do this here, because otherwise it uses target, and jumps a frame later. - if (IsFocusResetQueued()) + // don't do it for popups opening/closing, otherwise we lose our position + if (FocusResetType focus_reset = GetQueuedFocusResetType(); focus_reset != FocusResetType::None && + focus_reset != FocusResetType::PopupOpened && + focus_reset != FocusResetType::PopupClosed) + { ImGui::SetNextWindowScroll(ImVec2(0.0f, 0.0f)); + } if (BeginFullscreenWindow( ImVec2(0.0f, heading_size.y), @@ -5836,7 +5839,7 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading) { s_save_state_selector_submenu_index = -1; if (!closed) - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } ImGui::PopStyleColor(3); @@ -6280,7 +6283,7 @@ void FullscreenUI::DrawGameListWindow() else if (ImGui::IsKeyPressed(ImGuiKey_GamepadStart, false) || ImGui::IsKeyPressed(ImGuiKey_F2)) { s_current_main_window = MainWindowType::GameListSettings; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } switch (s_game_list_view) @@ -6785,7 +6788,7 @@ void FullscreenUI::DrawGameListSettingsWindow() if (NavButton(ICON_FA_BACKWARD, true, true)) { s_current_main_window = MainWindowType::GameList; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } NavTitle(FSUI_CSTR("Game List Settings")); @@ -6806,7 +6809,7 @@ void FullscreenUI::DrawGameListSettingsWindow() if (ImGui::IsWindowFocused() && WantsToCloseMenu()) { s_current_main_window = MainWindowType::GameList; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } auto lock = Host::GetSettingsLock(); @@ -6960,7 +6963,7 @@ void FullscreenUI::SwitchToGameList() auto lock = Host::GetSettingsLock(); PopulateGameListDirectoryCache(Host::Internal::GetBaseSettingsLayer()); } - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); } GPUTexture* FullscreenUI::GetGameListCover(const GameList::Entry* entry) @@ -7114,7 +7117,7 @@ void FullscreenUI::OpenAchievementsWindow() } s_current_main_window = MainWindowType::Achievements; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); FixStateIfPaused(); } @@ -7148,7 +7151,7 @@ void FullscreenUI::OpenLeaderboardsWindow() } s_current_main_window = MainWindowType::Leaderboards; - QueueResetFocus(); + QueueResetFocus(FocusResetType::WindowChanged); FixStateIfPaused(); } diff --git a/src/util/imgui_fullscreen.cpp b/src/util/imgui_fullscreen.cpp index 762bddb64..2f8629f46 100644 --- a/src/util/imgui_fullscreen.cpp +++ b/src/util/imgui_fullscreen.cpp @@ -90,7 +90,7 @@ ImVec4 UISecondaryTextColor; static u32 s_menu_button_index = 0; static u32 s_close_button_state = 0; -static bool s_focus_reset_queued = false; +static FocusResetType s_focus_reset_queued = FocusResetType::None; static bool s_light_theme = false; static LRUCache> s_texture_cache(128, true); @@ -213,7 +213,7 @@ void ImGuiFullscreen::SetFonts(ImFont* standard_font, ImFont* medium_font, ImFon bool ImGuiFullscreen::Initialize(const char* placeholder_image_path) { - s_focus_reset_queued = true; + s_focus_reset_queued = FocusResetType::WindowChanged; s_close_button_state = 0; s_placeholder_texture = LoadTexture(placeholder_image_path); @@ -579,22 +579,22 @@ void ImGuiFullscreen::PopResetLayout() ImGui::PopStyleVar(12); } -void ImGuiFullscreen::QueueResetFocus() +void ImGuiFullscreen::QueueResetFocus(FocusResetType type) { - s_focus_reset_queued = true; + s_focus_reset_queued = type; s_close_button_state = 0; } bool ImGuiFullscreen::ResetFocusHere() { - if (!s_focus_reset_queued) + if (s_focus_reset_queued == FocusResetType::None) return false; // don't take focus from dialogs if (ImGui::FindBlockingModal(ImGui::GetCurrentWindow())) return false; - s_focus_reset_queued = false; + s_focus_reset_queued = FocusResetType::None; ImGui::SetWindowFocus(); // only do the active selection magic when we're using keyboard/gamepad @@ -602,6 +602,11 @@ bool ImGuiFullscreen::ResetFocusHere() } bool ImGuiFullscreen::IsFocusResetQueued() +{ + return (s_focus_reset_queued != FocusResetType::None); +} + +ImGuiFullscreen::FocusResetType ImGuiFullscreen::GetQueuedFocusResetType() { return s_focus_reset_queued; } @@ -2127,7 +2132,7 @@ void ImGuiFullscreen::OpenFileSelector(std::string_view title, bool select_direc s_file_selector_filters = std::move(filters); SetFileSelectorDirectory(std::move(initial_directory)); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupOpened); } void ImGuiFullscreen::CloseFileSelector() @@ -2143,7 +2148,7 @@ void ImGuiFullscreen::CloseFileSelector() std::string().swap(s_file_selector_current_directory); s_file_selector_items.clear(); ImGui::CloseCurrentPopup(); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupClosed); } void ImGuiFullscreen::DrawFileSelector() @@ -2222,7 +2227,7 @@ void ImGuiFullscreen::DrawFileSelector() else { SetFileSelectorDirectory(std::move(selected->full_path)); - QueueResetFocus(); + QueueResetFocus(FocusResetType::Other); } } else if (directory_selected) @@ -2243,7 +2248,7 @@ void ImGuiFullscreen::DrawFileSelector() " ") { SetFileSelectorDirectory(std::move(s_file_selector_items.front().full_path)); - QueueResetFocus(); + QueueResetFocus(FocusResetType::Other); } } } @@ -2265,7 +2270,7 @@ void ImGuiFullscreen::OpenChoiceDialog(std::string_view title, bool checkable, C s_choice_dialog_title = fmt::format("{}##choice_dialog", title); s_choice_dialog_options = std::move(options); s_choice_dialog_callback = std::move(callback); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupOpened); } void ImGuiFullscreen::CloseChoiceDialog() @@ -2278,7 +2283,7 @@ void ImGuiFullscreen::CloseChoiceDialog() std::string().swap(s_choice_dialog_title); ChoiceDialogOptions().swap(s_choice_dialog_options); ChoiceDialogCallback().swap(s_choice_dialog_callback); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupClosed); } void ImGuiFullscreen::DrawChoiceDialog() @@ -2398,7 +2403,7 @@ void ImGuiFullscreen::OpenInputStringDialog(std::string title, std::string messa s_input_dialog_caption = std::move(caption); s_input_dialog_ok_text = std::move(ok_button_text); s_input_dialog_callback = std::move(callback); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupOpened); } void ImGuiFullscreen::DrawInputDialog() @@ -2510,7 +2515,7 @@ void ImGuiFullscreen::OpenConfirmMessageDialog(std::string title, std::string me s_message_dialog_callback = std::move(callback); s_message_dialog_buttons[0] = std::move(yes_button_text); s_message_dialog_buttons[1] = std::move(no_button_text); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupOpened); } void ImGuiFullscreen::OpenInfoMessageDialog(std::string title, std::string message, InfoMessageDialogCallback callback, @@ -2523,7 +2528,7 @@ void ImGuiFullscreen::OpenInfoMessageDialog(std::string title, std::string messa s_message_dialog_message = std::move(message); s_message_dialog_callback = std::move(callback); s_message_dialog_buttons[0] = std::move(button_text); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupOpened); } void ImGuiFullscreen::OpenMessageDialog(std::string title, std::string message, MessageDialogCallback callback, @@ -2539,7 +2544,7 @@ void ImGuiFullscreen::OpenMessageDialog(std::string title, std::string message, s_message_dialog_buttons[0] = std::move(first_button_text); s_message_dialog_buttons[1] = std::move(second_button_text); s_message_dialog_buttons[2] = std::move(third_button_text); - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupOpened); } void ImGuiFullscreen::CloseMessageDialog() @@ -2552,7 +2557,7 @@ void ImGuiFullscreen::CloseMessageDialog() s_message_dialog_message = {}; s_message_dialog_buttons = {}; s_message_dialog_callback = {}; - QueueResetFocus(); + QueueResetFocus(FocusResetType::PopupClosed); } void ImGuiFullscreen::DrawMessageDialog() diff --git a/src/util/imgui_fullscreen.h b/src/util/imgui_fullscreen.h index 4c5ea2f2f..7653d8055 100644 --- a/src/util/imgui_fullscreen.h +++ b/src/util/imgui_fullscreen.h @@ -142,9 +142,18 @@ void EndLayout(); void PushResetLayout(); void PopResetLayout(); -void QueueResetFocus(); +enum class FocusResetType : u8 +{ + None, + PopupOpened, + PopupClosed, + WindowChanged, + Other, +}; +void QueueResetFocus(FocusResetType type); bool ResetFocusHere(); bool IsFocusResetQueued(); +FocusResetType GetQueuedFocusResetType(); void ForceKeyNavEnabled(); bool WantsToCloseMenu();