diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index 044618e46..dad8ed123 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -2358,6 +2358,7 @@ void Achievements::DrawAchievementsWindow() const ImVec4 heading_background = ImGuiFullscreen::ModAlpha(ImGuiFullscreen::UIBackgroundColor, heading_alpha); const ImVec2 display_size = ImGui::GetIO().DisplaySize; const float heading_height = ImGuiFullscreen::LayoutScale(heading_height_unscaled); + bool close_window = false; if (ImGuiFullscreen::BeginFullscreenWindow( ImVec2(), ImVec2(display_size.x, heading_height), "achievements_heading", heading_background, 0.0f, ImVec2(), @@ -2393,12 +2394,9 @@ void Achievements::DrawAchievementsWindow() SmallString text; ImVec2 text_size; - if (ImGuiFullscreen::FloatingButton(ICON_FA_WINDOW_CLOSE, 10.0f, 10.0f, -1.0f, -1.0f, 1.0f, 0.0f, true, - g_large_font) || - ImGuiFullscreen::WantsToCloseMenu()) - { - FullscreenUI::ReturnToPreviousWindow(); - } + close_window = (ImGuiFullscreen::FloatingButton(ICON_FA_WINDOW_CLOSE, 10.0f, 10.0f, -1.0f, -1.0f, 1.0f, 0.0f, + true, g_large_font) || + ImGuiFullscreen::WantsToCloseMenu()); const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize)); text.assign(s_game_title); @@ -2518,6 +2516,9 @@ void Achievements::DrawAchievementsWindow() ImGuiFullscreen::EndFullscreenWindow(); FullscreenUI::SetStandardSelectionFooterText(true); + + if (close_window) + FullscreenUI::ReturnToPreviousWindow(); } void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo) @@ -2854,8 +2855,10 @@ void Achievements::DrawLeaderboardsWindow() const float tab_width = (ImGui::GetWindowWidth() / ImGuiFullscreen::g_layout_scale) * 0.5f; ImGui::SetCursorPos(ImVec2(0.0f, top + spacing_small)); - if (ImGui::IsKeyPressed(ImGuiKey_NavGamepadTweakSlow, false) || - ImGui::IsKeyPressed(ImGuiKey_NavGamepadTweakFast, false)) + if (ImGui::IsKeyPressed(ImGuiKey_GamepadDpadLeft, false) || + ImGui::IsKeyPressed(ImGuiKey_NavGamepadTweakSlow, false) || + ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false) || ImGui::IsKeyPressed(ImGuiKey_GamepadDpadRight, false) || + ImGui::IsKeyPressed(ImGuiKey_NavGamepadTweakFast, false) || ImGui::IsKeyPressed(ImGuiKey_RightArrow, false)) { s_is_showing_all_leaderboard_entries = !s_is_showing_all_leaderboard_entries; ImGuiFullscreen::QueueResetFocus(ImGuiFullscreen::FocusResetType::Other); diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index c47de0361..7da559095 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -111,6 +111,7 @@ using ImGuiFullscreen::CenterImage; using ImGuiFullscreen::CloseChoiceDialog; using ImGuiFullscreen::CloseFileSelector; using ImGuiFullscreen::CreateTextureFromImage; +using ImGuiFullscreen::DefaultActiveButton; using ImGuiFullscreen::DrawShadowedText; using ImGuiFullscreen::EndFullscreenColumns; using ImGuiFullscreen::EndFullscreenColumnWindow; @@ -125,8 +126,8 @@ using ImGuiFullscreen::GetCachedTexture; using ImGuiFullscreen::GetCachedTextureAsync; using ImGuiFullscreen::GetPlaceholderTexture; using ImGuiFullscreen::HorizontalMenuItem; -using ImGuiFullscreen::IsFocusResetQueued; using ImGuiFullscreen::IsFocusResetFromWindowChange; +using ImGuiFullscreen::IsFocusResetQueued; using ImGuiFullscreen::IsGamepadInputSource; using ImGuiFullscreen::LayoutScale; using ImGuiFullscreen::LoadTexture; @@ -636,7 +637,7 @@ void FullscreenUI::OnSystemStarted() return; s_current_main_window = MainWindowType::None; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } void FullscreenUI::OnSystemPaused() @@ -695,7 +696,7 @@ void FullscreenUI::OpenPauseMenu() PauseForMenuOpen(true); s_current_main_window = MainWindowType::PauseMenu; s_current_pause_submenu = PauseSubMenu::None; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); ForceKeyNavEnabled(); FixStateIfPaused(); } @@ -730,7 +731,7 @@ void FullscreenUI::ClosePauseMenu() s_current_main_window = MainWindowType::None; s_current_pause_submenu = PauseSubMenu::None; s_pause_menu_was_open = false; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); FixStateIfPaused(); } @@ -738,7 +739,7 @@ void FullscreenUI::OpenPauseSubMenu(PauseSubMenu submenu) { s_current_main_window = MainWindowType::PauseMenu; s_current_pause_submenu = submenu; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } void FullscreenUI::Shutdown() @@ -876,7 +877,7 @@ void FullscreenUI::ReturnToPreviousWindow() if (System::IsValid() && s_pause_menu_was_open) { s_current_main_window = MainWindowType::PauseMenu; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } else { @@ -1294,7 +1295,7 @@ void FullscreenUI::DoToggleFullscreen() void FullscreenUI::SwitchToLanding() { s_current_main_window = MainWindowType::Landing; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size) @@ -1391,7 +1392,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(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } if (HorizontalMenuItem(GetCachedTexture("fullscreenui/applications-system.png"), FSUI_CSTR("Settings"), @@ -1405,7 +1406,7 @@ void FullscreenUI::DrawLandingWindow() (!AreAnyDialogsOpen() && WantsToCloseMenu())) { s_current_main_window = MainWindowType::Exit; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } } EndHorizontalMenu(); @@ -1476,7 +1477,7 @@ void FullscreenUI::DrawStartGameWindow() (!AreAnyDialogsOpen() && WantsToCloseMenu())) { s_current_main_window = MainWindowType::Landing; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } } EndHorizontalMenu(); @@ -1522,7 +1523,7 @@ void FullscreenUI::DrawExitWindow() WantsToCloseMenu()) { s_current_main_window = MainWindowType::Landing; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } if (HorizontalMenuItem(GetCachedTexture("fullscreenui/exit.png"), FSUI_CSTR("Exit DuckStation"), @@ -2737,7 +2738,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(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } void FullscreenUI::SwitchToGameSettings() @@ -2879,7 +2880,7 @@ void FullscreenUI::DrawSettingsWindow() { index = (index == 0) ? (count - 1) : (index - 1); s_settings_page = pages[index]; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::Other); } else if (ImGui::IsKeyPressed(ImGuiKey_GamepadDpadRight, true) || ImGui::IsKeyPressed(ImGuiKey_NavGamepadTweakFast, true) || @@ -2887,7 +2888,7 @@ void FullscreenUI::DrawSettingsWindow() { index = (index + 1) % count; s_settings_page = pages[index]; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::Other); } } @@ -2906,7 +2907,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); + QueueResetFocus(FocusResetType::Other); } } @@ -5344,10 +5345,10 @@ void FullscreenUI::DrawPauseMenu() 3, // Achievements }; - const bool just_focused = ResetFocusHere(); BeginMenuButtons(submenu_item_count[static_cast(s_current_pause_submenu)], 1.0f, ImGuiFullscreen::LAYOUT_MENU_BUTTON_X_PADDING, ImGuiFullscreen::LAYOUT_MENU_BUTTON_Y_PADDING, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); + ResetFocusHere(); switch (s_current_pause_submenu) { @@ -5356,10 +5357,7 @@ void FullscreenUI::DrawPauseMenu() // NOTE: Menu close must come first, because otherwise VM destruction options will race. const bool has_game = System::IsValid() && !System::GetGameSerial().empty(); - if (just_focused) - ImGui::SetFocusID(ImGui::GetID(FSUI_ICONSTR(ICON_FA_PLAY, "Resume Game")), ImGui::GetCurrentWindow()); - - if (ActiveButton(FSUI_ICONSTR(ICON_FA_PLAY, "Resume Game"), false) || WantsToCloseMenu()) + if (DefaultActiveButton(FSUI_ICONSTR(ICON_FA_PLAY, "Resume Game"), false) || WantsToCloseMenu()) ClosePauseMenu(); if (ActiveButton(FSUI_ICONSTR(ICON_FA_FAST_FORWARD, "Toggle Fast Forward"), false)) @@ -5436,12 +5434,6 @@ void FullscreenUI::DrawPauseMenu() case PauseSubMenu::Exit: { - if (just_focused) - { - ImGui::SetFocusID(ImGui::GetID(FSUI_ICONSTR(ICON_FA_POWER_OFF, "Exit Without Saving")), - ImGui::GetCurrentWindow()); - } - if (ActiveButton(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu"), false) || WantsToCloseMenu()) OpenPauseSubMenu(PauseSubMenu::None); @@ -5454,23 +5446,17 @@ void FullscreenUI::DrawPauseMenu() if (ActiveButton(FSUI_ICONSTR(ICON_FA_SAVE, "Exit And Save State"), false)) RequestShutdown(true); - if (ActiveButton(FSUI_ICONSTR(ICON_FA_POWER_OFF, "Exit Without Saving"), false)) + if (DefaultActiveButton(FSUI_ICONSTR(ICON_FA_POWER_OFF, "Exit Without Saving"), false)) RequestShutdown(false); } break; case PauseSubMenu::Achievements: { - if (just_focused) - { - ImGui::SetFocusID(ImGui::GetID(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu")), - ImGui::GetCurrentWindow()); - } - if (ActiveButton(FSUI_ICONSTR(ICON_FA_BACKWARD, "Back To Pause Menu"), false) || WantsToCloseMenu()) OpenPauseSubMenu(PauseSubMenu::None); - if (ActiveButton(FSUI_ICONSTR(ICON_FA_TROPHY, "Achievements"), false)) + if (DefaultActiveButton(FSUI_ICONSTR(ICON_FA_TROPHY, "Achievements"), false)) OpenAchievementsWindow(); if (ActiveButton(FSUI_ICONSTR(ICON_FA_STOPWATCH, "Leaderboards"), false)) @@ -5833,7 +5819,7 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading) { s_save_state_selector_submenu_index = -1; if (!closed) - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } ImGui::PopStyleColor(3); @@ -6277,7 +6263,7 @@ void FullscreenUI::DrawGameListWindow() else if (ImGui::IsKeyPressed(ImGuiKey_GamepadStart, false) || ImGui::IsKeyPressed(ImGuiKey_F2)) { s_current_main_window = MainWindowType::GameListSettings; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } switch (s_game_list_view) @@ -6782,7 +6768,7 @@ void FullscreenUI::DrawGameListSettingsWindow() if (NavButton(ICON_FA_BACKWARD, true, true)) { s_current_main_window = MainWindowType::GameList; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::Other); } NavTitle(FSUI_CSTR("Game List Settings")); @@ -6803,7 +6789,7 @@ void FullscreenUI::DrawGameListSettingsWindow() if (ImGui::IsWindowFocused() && WantsToCloseMenu()) { s_current_main_window = MainWindowType::GameList; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } auto lock = Host::GetSettingsLock(); @@ -6957,7 +6943,7 @@ void FullscreenUI::SwitchToGameList() auto lock = Host::GetSettingsLock(); PopulateGameListDirectoryCache(Host::Internal::GetBaseSettingsLayer()); } - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); } GPUTexture* FullscreenUI::GetGameListCover(const GameList::Entry* entry) @@ -7111,7 +7097,7 @@ void FullscreenUI::OpenAchievementsWindow() } s_current_main_window = MainWindowType::Achievements; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); FixStateIfPaused(); } @@ -7145,7 +7131,7 @@ void FullscreenUI::OpenLeaderboardsWindow() } s_current_main_window = MainWindowType::Leaderboards; - QueueResetFocus(FocusResetType::WindowChanged); + QueueResetFocus(FocusResetType::ViewChanged); FixStateIfPaused(); } diff --git a/src/util/imgui_fullscreen.cpp b/src/util/imgui_fullscreen.cpp index 50188dcd0..d0fb08a7e 100644 --- a/src/util/imgui_fullscreen.cpp +++ b/src/util/imgui_fullscreen.cpp @@ -211,7 +211,7 @@ void ImGuiFullscreen::SetFonts(ImFont* standard_font, ImFont* medium_font, ImFon bool ImGuiFullscreen::Initialize(const char* placeholder_image_path) { - s_focus_reset_queued = FocusResetType::WindowChanged; + s_focus_reset_queued = FocusResetType::ViewChanged; s_close_button_state = 0; s_placeholder_texture = LoadTexture(placeholder_image_path); @@ -589,11 +589,18 @@ bool ImGuiFullscreen::ResetFocusHere() return false; // don't take focus from dialogs - if (ImGui::FindBlockingModal(ImGui::GetCurrentWindow())) + ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (ImGui::FindBlockingModal(window)) return false; + // Only fully reset the window on window change, that way setting page changes don't spend a frame without focus. + if (s_focus_reset_queued == FocusResetType::ViewChanged) + window->LastFrameActive = 0; + s_focus_reset_queued = FocusResetType::None; + ImGui::SetWindowFocus(); + ImGui::NavInitWindow(window, true); // only do the active selection magic when we're using keyboard/gamepad return (GImGui->NavInputSource == ImGuiInputSource_Keyboard || GImGui->NavInputSource == ImGuiInputSource_Gamepad); @@ -1130,6 +1137,15 @@ bool ImGuiFullscreen::ActiveButton(const char* title, bool is_active, bool enabl return ActiveButtonWithRightText(title, nullptr, is_active, enabled, height, font); } +bool ImGuiFullscreen::DefaultActiveButton(const char* title, bool is_active, bool enabled /* = true */, + float height /* = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY */, + ImFont* font /* = g_large_font */) +{ + const bool result = ActiveButtonWithRightText(title, nullptr, is_active, enabled, height, font); + ImGui::SetItemDefaultFocus(); + return result; +} + bool ImGuiFullscreen::ActiveButtonWithRightText(const char* title, const char* right_title, bool is_active, bool enabled, float height, ImFont* font) { diff --git a/src/util/imgui_fullscreen.h b/src/util/imgui_fullscreen.h index bfdae42c6..fce248138 100644 --- a/src/util/imgui_fullscreen.h +++ b/src/util/imgui_fullscreen.h @@ -147,7 +147,7 @@ enum class FocusResetType : u8 None, PopupOpened, PopupClosed, - WindowChanged, + ViewChanged, Other, }; void QueueResetFocus(FocusResetType type); @@ -201,6 +201,8 @@ void MenuHeading(const char* title, bool draw_line = true); bool MenuHeadingButton(const char* title, const char* value = nullptr, bool enabled = true, bool draw_line = true); bool ActiveButton(const char* title, bool is_active, bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font); +bool DefaultActiveButton(const char* title, bool is_active, bool enabled = true, + float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font); bool ActiveButtonWithRightText(const char* title, const char* right_title, bool is_active, bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font); bool MenuButton(const char* title, const char* summary, bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,