From 08649f0f154491e066b20897b59fe94e09bbfadd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Oct 2026 16:21:10 +0200 Subject: [PATCH] UI: Make switchScreen replace the whole screen stack It only replaced the top screen, but most callers switch from a dialog: Play on the game screen, the store, the installers, the framedump launcher. The screens under it stayed alive, so launching a game from the game screen and exiting it left [MainScreen, MainScreen], one more each time. Co-Authored-By: Claude Opus 5.5 --- Common/UI/ScreenManager.cpp | 21 +++++++++++---------- Common/UI/ScreenManager.h | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Common/UI/ScreenManager.cpp b/Common/UI/ScreenManager.cpp index ff7aa55c43..f6c65750bb 100644 --- a/Common/UI/ScreenManager.cpp +++ b/Common/UI/ScreenManager.cpp @@ -24,10 +24,6 @@ void ScreenManager::switchScreen(Screen *screen) { return; } - // Note that if a dialog is found, this will be a silent background switch that - // will only become apparent if the dialog is closed. The previous screen will stick around - // until that switch. - // TODO: is this still true? if (!nextStack_.empty()) { for (int i = 0; i < nextStack_.size(); i++) { INFO_LOG(Log::UI, "NextStack contents[%d].screen->tag(): '%s'", i, nextStack_[i].screen->tag()); @@ -150,17 +146,22 @@ void ScreenManager::Update() { void ScreenManager::switchToNext() { if (nextStack_.empty()) { ERROR_LOG(Log::System, "switchToNext: No nextStack_!"); + return; } - Layer temp = {nullptr, 0}; - if (!stack_.empty()) { - temp = stack_.back(); - temp.screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); - stack_.pop_back(); + // Replaces the whole stack. Most callers switch from a dialog (Play on the game screen, the store, + // installers), and replacing only the top left the screens below alive, like one more MainScreen + // under every game launched that way. + std::vector old = std::move(stack_); + stack_.clear(); + if (!old.empty()) { + old.back().screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); } stack_.push_back(nextStack_.front()); nextStack_.front().screen->focusChanged(ScreenFocusChange::FOCUS_BECAME_TOP); - delete temp.screen; + for (auto iter = old.rbegin(); iter != old.rend(); ++iter) { + delete iter->screen; + } UI::SetFocusedView(nullptr, UI::FocusFlags::CAUSE_SCREEN_CHANGE); // When will this ever happen? Should handle focus here too? diff --git a/Common/UI/ScreenManager.h b/Common/UI/ScreenManager.h index e815c834c1..3881d2bf5a 100644 --- a/Common/UI/ScreenManager.h +++ b/Common/UI/ScreenManager.h @@ -34,6 +34,7 @@ class ScreenManager { public: virtual ~ScreenManager(); + // Replaces the whole stack with the screen, at the start of the next frame. void switchScreen(Screen *screen); void ProcessScreenSwitches(); void ProcessInputEvent(const QueuedEvent &event);