UI: Don't recreate a screen's views while a popup is on top of it

Popups are transparent, so the screen under one still renders, and
render() ran DoRecreateViews(). A RecreateViews() on that screen (a
resize or rotation on DisplayLayoutScreen or TouchControlLayoutScreen,
MainScreen on RECENT_FILES_CHANGED from the recent-files thread, the
achievements login finishing) then deleted the choice that opened the
popup. Closing the popup wrote through it and called its handlers.

Leave the old views in place until the screen is back on top, where
update() recreates them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-12 14:32:38 +02:00
1 parent 88018255c2
commit 0754544e27
3 files changed
+16 -1

No files matched your search

+9
View File
@@ -393,6 +393,15 @@ void ScreenManager::finishDialog(Screen *dialog, DialogResult result) {
dialogResult_ = result;
}
bool ScreenManager::HasScreenAbove(const Screen *screen) const {
for (size_t i = 0; i + 1 < stack_.size(); ++i) {
if (stack_[i].screen == screen) {
return true;
}
}
return false;
}
Screen *ScreenManager::dialogParent(const Screen *dialog) const {
for (size_t i = 1; i < stack_.size(); ++i) {
if (stack_[i].screen == dialog) {
+2
View File
@@ -64,6 +64,8 @@ public:
// Pops the dialog away.
void finishDialog(Screen *dialog, DialogResult result = DR_OK);
Screen *dialogParent(const Screen *dialog) const;
// True if the screen is in the stack, with something (like a popup) on top of it.
bool HasScreenAbove(const Screen *screen) const;
void sendMessage(UIMessage message, const char *value);
+5 -1
View File
@@ -128,7 +128,11 @@ Bounds UIScreen::GetLayoutBounds(UIContext &dc) const {
}
ScreenRenderFlags UIScreen::render(ScreenRenderMode mode) {
DoRecreateViews();
// A screen rendered under a popup must keep its views: the popup's callbacks point into them (the choice
// that opened it, the value it writes to). update() recreates them once the screen is on top again.
if (!root_ || !screenManager()->HasScreenAbove(this)) {
DoRecreateViews();
}
UIContext &uiContext = *screenManager()->getUIContext();
if (root_) {