mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
WipeRequesterToken() only reset the screen's token, after CreateViews() had already handed it to the new views, so nothing was ever forgotten - not even in ~Screen(), which saw a token of -1. A text input dialog open across a RecreateViews() (on the RetroAchievements screen, a slow login failing) would then write through a deleted PopupTextInputChoice, possibly into the field that took its place: #21708. Requests made while creating views now get their own token, forgotten before the views are deleted. Screen-level requests keep the screen's token. RequestManager: ForgetRequestsWithToken() now locks, and also drops responses that arrived but weren't processed yet. ProcessRequests() calls the callbacks one at a time without holding the lock, so a callback that closes a screen drops the rest of that screen's responses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
64 lines
1.5 KiB
C++
64 lines
1.5 KiB
C++
#include "Common/System/Request.h"
|
|
#include "Common/UI/Screen.h"
|
|
#include "Common/UI/UI.h"
|
|
#include "Common/Log.h"
|
|
|
|
void Screen::focusChanged(ScreenFocusChange focusChange) {
|
|
const char *eventName = "";
|
|
switch (focusChange) {
|
|
case ScreenFocusChange::FOCUS_LOST_TOP:
|
|
#if !defined(MOBILE_DEVICE)
|
|
if (WantsTextInput()) {
|
|
System_NotifyUIEvent(UIEventNotification::TEXT_LOSTFOCUS);
|
|
}
|
|
#endif
|
|
eventName = "FOCUS_LOST_TOP";
|
|
break;
|
|
case ScreenFocusChange::FOCUS_BECAME_TOP:
|
|
#if !defined(MOBILE_DEVICE)
|
|
if (WantsTextInput()) {
|
|
System_NotifyUIEvent(UIEventNotification::TEXT_GOTFOCUS);
|
|
}
|
|
#endif
|
|
eventName = "FOCUS_BECAME_TOP";
|
|
break;
|
|
}
|
|
DEBUG_LOG(Log::UI, "Screen %s got %s", this->tag(), eventName);
|
|
}
|
|
|
|
int Screen::GetRequesterToken() {
|
|
int &token = creatingViews_ ? viewsToken_ : token_;
|
|
if (token < 0) {
|
|
token = g_requestManager.GenerateRequesterToken();
|
|
}
|
|
return token;
|
|
}
|
|
|
|
void Screen::ForgetViewRequests() {
|
|
if (viewsToken_ >= 0) {
|
|
g_requestManager.ForgetRequestsWithToken(viewsToken_);
|
|
viewsToken_ = -1;
|
|
}
|
|
}
|
|
|
|
Screen::~Screen() {
|
|
screenManager_ = nullptr;
|
|
// To avoid expired callbacks getting called.
|
|
if (token_ >= 0) {
|
|
g_requestManager.ForgetRequestsWithToken(token_);
|
|
}
|
|
ForgetViewRequests();
|
|
}
|
|
|
|
const char *DialogResultToString(DialogResult result) {
|
|
switch (result) {
|
|
case DR_NONE: return "DR_NONE";
|
|
case DR_OK: return "DR_OK";
|
|
case DR_CANCEL: return "DR_CANCEL";
|
|
case DR_YES: return "DR_YES";
|
|
case DR_NO: return "DR_NO";
|
|
case DR_BACK: return "DR_BACK";
|
|
default: return "(N/A)";
|
|
}
|
|
}
|