diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index 1635152a24f2..2ad6f27e10b8 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -31,13 +31,21 @@ const char *RequestTypeAsString(SystemRequestType type) { } } -bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, RequestFailedCallback failedCallback, const std::string ¶m1, const std::string ¶m2, int param3) { +bool RequestManager::MakeSystemRequest(SystemRequestType type, RequesterToken token, RequestCallback callback, RequestFailedCallback failedCallback, const std::string ¶m1, const std::string ¶m2, int param3) { + if (token == NO_REQUESTER_TOKEN) { + _dbg_assert_(!callback); + _dbg_assert_(!failedCallback); + } + if (callback || failedCallback) { + _dbg_assert_(token != NO_REQUESTER_TOKEN); + } + int requestId = idCounter_++; // NOTE: We need to register immediately, in order to support synchronous implementations. if (callback || failedCallback) { std::lock_guard guard(callbackMutex_); - callbackMap_[requestId] = { callback, failedCallback }; + callbackMap_[requestId] = { callback, failedCallback, token }; } VERBOSE_LOG(SYSTEM, "Making system request %s: id %d", RequestTypeAsString(type), requestId); @@ -52,6 +60,16 @@ bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback c return true; } +void RequestManager::ForgetRequestsWithToken(RequesterToken token) { + for (auto &iter : callbackMap_) { + if (iter.second.token == token) { + INFO_LOG(SYSTEM, "Forgetting about requester with token %d", token); + iter.second.callback = nullptr; + iter.second.failedCallback = nullptr; + } + } +} + void RequestManager::PostSystemSuccess(int requestId, const char *responseString, int responseValue) { std::lock_guard guard(callbackMutex_); auto iter = callbackMap_.find(requestId); @@ -82,7 +100,7 @@ void RequestManager::PostSystemFailure(int requestId) { std::lock_guard responseGuard(responseMutex_); PendingFailure response; - response.callback = iter->second.failedCallback; + response.failedCallback = iter->second.failedCallback; pendingFailures_.push_back(response); callbackMap_.erase(iter); } @@ -96,8 +114,8 @@ void RequestManager::ProcessRequests() { } pendingSuccesses_.clear(); for (auto &iter : pendingFailures_) { - if (iter.callback) { - iter.callback(); + if (iter.failedCallback) { + iter.failedCallback(); } } pendingFailures_.clear(); @@ -113,9 +131,9 @@ void RequestManager::Clear() { } void System_CreateGameShortcut(const Path &path, const std::string &title) { - g_requestManager.MakeSystemRequest(SystemRequestType::CREATE_GAME_SHORTCUT, nullptr, nullptr, path.ToString(), title, 0); + g_requestManager.MakeSystemRequest(SystemRequestType::CREATE_GAME_SHORTCUT, NO_REQUESTER_TOKEN, nullptr, nullptr, path.ToString(), title, 0); } void System_ShowFileInFolder(const Path &path) { - g_requestManager.MakeSystemRequest(SystemRequestType::SHOW_FILE_IN_FOLDER, nullptr, nullptr, path.ToString(), "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::SHOW_FILE_IN_FOLDER, NO_REQUESTER_TOKEN, nullptr, nullptr, path.ToString(), "", 0); } diff --git a/Common/System/Request.h b/Common/System/Request.h index 314dd7f88a03..3cd4f2a3be2f 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -12,6 +12,10 @@ class Path; typedef std::function RequestCallback; typedef std::function RequestFailedCallback; +typedef int RequesterToken; +#define NO_REQUESTER_TOKEN -1 +#define NON_EPHEMERAL_TOKEN -2 + // Platforms often have to process requests asynchronously, on wildly different threads, // and then somehow pass a response back to the main thread (especially Android...) // This acts as bridge and buffer. @@ -23,7 +27,7 @@ class RequestManager { // The callback you pass in will be called on the main thread later. // Params are at the end since it's the part most likely to recieve additions in the future, // now that we have both callbacks. - bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, RequestFailedCallback failedCallback, const std::string ¶m1, const std::string ¶m2, int param3); + bool MakeSystemRequest(SystemRequestType type, RequesterToken token, RequestCallback callback, RequestFailedCallback failedCallback, const std::string ¶m1, const std::string ¶m2, int param3); // Called by the platform implementation, when it's finished with a request. void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0); @@ -33,19 +37,21 @@ class RequestManager { // This will call the callback of any finished requests. void ProcessRequests(); + RequesterToken GenerateRequesterToken() { + int token = tokenGen_++; + return token; + } + + void ForgetRequestsWithToken(RequesterToken token); + // Unclear if we need this... void Clear(); private: - struct PendingRequest { - SystemRequestType type; - RequestCallback callback; - RequestFailedCallback failedCallback; - }; - struct CallbackPair { RequestCallback callback; RequestFailedCallback failedCallback; + RequesterToken token; }; std::map callbackMap_; @@ -58,7 +64,7 @@ class RequestManager { }; struct PendingFailure { - RequestFailedCallback callback; + RequestFailedCallback failedCallback; }; // Let's start at 10 to get a recognizably valid ID in logs. @@ -66,6 +72,8 @@ class RequestManager { std::vector pendingSuccesses_; std::vector pendingFailures_; std::mutex responseMutex_; + + RequesterToken tokenGen_ = 20000; }; const char *RequestTypeAsString(SystemRequestType type); @@ -75,14 +83,14 @@ extern RequestManager g_requestManager; // Wrappers for easy requests. // NOTE: Semantics have changed - this no longer calls the callback on cancellation, instead you // can specify a different callback for that. -inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { - g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, failedCallback, title, defaultValue, 0); +inline void System_InputBoxGetString(RequesterToken token, const std::string &title, const std::string &defaultValue, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { + g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, token, callback, failedCallback, title, defaultValue, 0); } // This one will pop up a special image browser if available. You can also pick // images with the file browser below. -inline void System_BrowseForImage(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { - g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, failedCallback, title, "", 0); +inline void System_BrowseForImage(RequesterToken token, const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { + g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, token, callback, failedCallback, title, "", 0); } enum class BrowseFileType { @@ -95,78 +103,78 @@ enum class BrowseFileType { ANY, }; -inline void System_BrowseForFile(const std::string &title, BrowseFileType type, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { - g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE, callback, failedCallback, title, "", (int)type); +inline void System_BrowseForFile(RequesterToken token, const std::string &title, BrowseFileType type, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { + g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE, token, callback, failedCallback, title, "", (int)type); } -inline void System_BrowseForFolder(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { - g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, failedCallback, title, "", 0); +inline void System_BrowseForFolder(RequesterToken token, const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { + g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, token, callback, failedCallback, title, "", 0); } // The returned string is username + '\n' + password. -inline void System_AskUsernamePassword(const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { - g_requestManager.MakeSystemRequest(SystemRequestType::ASK_USERNAME_PASSWORD, callback, failedCallback, title, "", 0); +inline void System_AskUsernamePassword(RequesterToken token, const std::string &title, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) { + g_requestManager.MakeSystemRequest(SystemRequestType::ASK_USERNAME_PASSWORD, token, callback, failedCallback, title, "", 0); } inline void System_CopyStringToClipboard(const std::string &string) { - g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, nullptr, string, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, NO_REQUESTER_TOKEN, nullptr, nullptr, string, "", 0); } inline void System_ExitApp() { - g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, nullptr, nullptr, "", "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, NO_REQUESTER_TOKEN, nullptr, nullptr, "", "", 0); } inline void System_RestartApp(const std::string ¶ms) { - g_requestManager.MakeSystemRequest(SystemRequestType::RESTART_APP, nullptr, nullptr, params, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::RESTART_APP, NO_REQUESTER_TOKEN, nullptr, nullptr, params, "", 0); } inline void System_RecreateActivity() { - g_requestManager.MakeSystemRequest(SystemRequestType::RECREATE_ACTIVITY, nullptr, nullptr, "", "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::RECREATE_ACTIVITY, NO_REQUESTER_TOKEN, nullptr, nullptr, "", "", 0); } // The design is a little weird, just a holdover from the old message. Can either toggle or set to on or off. inline void System_ToggleFullscreenState(const std::string ¶m) { - g_requestManager.MakeSystemRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, nullptr, nullptr, param, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, NO_REQUESTER_TOKEN, nullptr, nullptr, param, "", 0); } inline void System_GraphicsBackendFailedAlert(const std::string ¶m) { - g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, nullptr, nullptr, param, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, NO_REQUESTER_TOKEN, nullptr, nullptr, param, "", 0); } inline void System_CameraCommand(const std::string &command) { - g_requestManager.MakeSystemRequest(SystemRequestType::CAMERA_COMMAND, nullptr, nullptr, command, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::CAMERA_COMMAND, NO_REQUESTER_TOKEN, nullptr, nullptr, command, "", 0); } inline void System_GPSCommand(const std::string &command) { - g_requestManager.MakeSystemRequest(SystemRequestType::GPS_COMMAND, nullptr, nullptr, command, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::GPS_COMMAND, NO_REQUESTER_TOKEN, nullptr, nullptr, command, "", 0); } inline void System_InfraredCommand(const std::string &command) { - g_requestManager.MakeSystemRequest(SystemRequestType::INFRARED_COMMAND, nullptr, nullptr, command, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::INFRARED_COMMAND, NO_REQUESTER_TOKEN, nullptr, nullptr, command, "", 0); } inline void System_MicrophoneCommand(const std::string &command) { - g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, nullptr, nullptr, command, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, NO_REQUESTER_TOKEN, nullptr, nullptr, command, "", 0); } inline void System_ShareText(const std::string &text) { - g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, nullptr, nullptr, text, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, NO_REQUESTER_TOKEN, nullptr, nullptr, text, "", 0); } inline void System_NotifyUIState(const std::string &state) { - g_requestManager.MakeSystemRequest(SystemRequestType::NOTIFY_UI_STATE, nullptr, nullptr, state, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::NOTIFY_UI_STATE, NO_REQUESTER_TOKEN, nullptr, nullptr, state, "", 0); } inline void System_SetWindowTitle(const std::string ¶m) { - g_requestManager.MakeSystemRequest(SystemRequestType::SET_WINDOW_TITLE, nullptr, nullptr, param, "", 0); + g_requestManager.MakeSystemRequest(SystemRequestType::SET_WINDOW_TITLE, NO_REQUESTER_TOKEN, nullptr, nullptr, param, "", 0); } inline bool System_SendDebugOutput(const std::string &string) { - return g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_OUTPUT, nullptr, nullptr, string, "", 0); + return g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_OUTPUT, NO_REQUESTER_TOKEN, nullptr, nullptr, string, "", 0); } inline void System_SendDebugScreenshot(const std::string &data, int height) { - g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_SCREENSHOT, nullptr, nullptr, data, "", height); + g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_SCREENSHOT, NO_REQUESTER_TOKEN, nullptr, nullptr, data, "", height); } // Non-inline to avoid including Path.h diff --git a/Common/UI/PopupScreens.cpp b/Common/UI/PopupScreens.cpp index d586d7c931a9..f4110d9d7df9 100644 --- a/Common/UI/PopupScreens.cpp +++ b/Common/UI/PopupScreens.cpp @@ -500,8 +500,8 @@ void SliderFloatPopupScreen::OnCompleted(DialogResult result) { } } -PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams) - : AbstractChoiceWithValueDisplay(title, layoutParams), screenManager_(screenManager), value_(value), placeHolder_(placeholder), maxLen_(maxLen) { +PopupTextInputChoice::PopupTextInputChoice(RequesterToken token, std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams) + : AbstractChoiceWithValueDisplay(title, layoutParams), screenManager_(screenManager), value_(value), placeHolder_(placeholder), maxLen_(maxLen), token_(token) { OnClick.Handle(this, &PopupTextInputChoice::HandleClick); } @@ -510,7 +510,7 @@ EventReturn PopupTextInputChoice::HandleClick(EventParams &e) { // Choose method depending on platform capabilities. if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { - System_InputBoxGetString(text_, *value_ , [=](const std::string &enteredValue, int) { + System_InputBoxGetString(token_, text_, *value_ , [=](const std::string &enteredValue, int) { *value_ = StripSpaces(enteredValue); EventParams params{}; OnChange.Trigger(params); @@ -668,10 +668,10 @@ std::string ChoiceWithValueDisplay::ValueText() const { return valueText.str(); } -FileChooserChoice::FileChooserChoice(std::string *value, const std::string &text, BrowseFileType fileType, LayoutParams *layoutParams) - : AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), fileType_(fileType) { +FileChooserChoice::FileChooserChoice(RequesterToken token, std::string *value, const std::string &text, BrowseFileType fileType, LayoutParams *layoutParams) + : AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), fileType_(fileType), token_(token) { OnClick.Add([=](UI::EventParams &) { - System_BrowseForFile(text_, fileType, [=](const std::string &returnValue, int) { + System_BrowseForFile(token, text_, fileType, [=](const std::string &returnValue, int) { if (*value_ != returnValue) { *value = returnValue; UI::EventParams e{}; @@ -692,10 +692,10 @@ std::string FileChooserChoice::ValueText() const { return path.GetFilename(); } -FolderChooserChoice::FolderChooserChoice(std::string *value, const std::string &text, LayoutParams *layoutParams) - : AbstractChoiceWithValueDisplay(text, layoutParams), value_(value) { +FolderChooserChoice::FolderChooserChoice(RequesterToken token, std::string *value, const std::string &text, LayoutParams *layoutParams) + : AbstractChoiceWithValueDisplay(text, layoutParams), value_(value), token_(token) { OnClick.Add([=](UI::EventParams &) { - System_BrowseForFolder(text_, [=](const std::string &returnValue, int) { + System_BrowseForFolder(token_, text_, [=](const std::string &returnValue, int) { if (*value_ != returnValue) { *value = returnValue; UI::EventParams e{}; diff --git a/Common/UI/PopupScreens.h b/Common/UI/PopupScreens.h index 213206b6bc35..ee5a36272ff6 100644 --- a/Common/UI/PopupScreens.h +++ b/Common/UI/PopupScreens.h @@ -360,7 +360,7 @@ class PopupSliderChoiceFloat : public AbstractChoiceWithValueDisplay { // NOTE: This one will defer to a system-native dialog if possible. class PopupTextInputChoice : public AbstractChoiceWithValueDisplay { public: - PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams = 0); + PopupTextInputChoice(RequesterToken token, std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams = 0); Event OnChange; @@ -370,6 +370,7 @@ class PopupTextInputChoice : public AbstractChoiceWithValueDisplay { private: EventReturn HandleClick(EventParams &e); EventReturn HandleChange(EventParams &e); + RequesterToken token_; ScreenManager *screenManager_; std::string *value_; std::string placeHolder_; @@ -405,7 +406,7 @@ enum class FileChooserFileType { class FileChooserChoice : public AbstractChoiceWithValueDisplay { public: - FileChooserChoice(std::string *value, const std::string &title, BrowseFileType fileType, LayoutParams *layoutParams = nullptr); + FileChooserChoice(RequesterToken token, std::string *value, const std::string &title, BrowseFileType fileType, LayoutParams *layoutParams = nullptr); std::string ValueText() const override; Event OnChange; @@ -413,11 +414,12 @@ class FileChooserChoice : public AbstractChoiceWithValueDisplay { private: std::string *value_; BrowseFileType fileType_; + RequesterToken token_; }; class FolderChooserChoice : public AbstractChoiceWithValueDisplay { public: - FolderChooserChoice(std::string *value, const std::string &title, LayoutParams *layoutParams = nullptr); + FolderChooserChoice(RequesterToken token, std::string *value, const std::string &title, LayoutParams *layoutParams = nullptr); std::string ValueText() const override; Event OnChange; @@ -425,7 +427,7 @@ class FolderChooserChoice : public AbstractChoiceWithValueDisplay { private: std::string *value_; BrowseFileType fileType_; + RequesterToken token_; }; - } // namespace UI diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index 657aaddcca5b..12c360d6f5f5 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -1,4 +1,5 @@ #include "Common/System/Display.h" +#include "Common/System/Request.h" #include "Common/Input/InputState.h" #include "Common/UI/Root.h" #include "Common/UI/Screen.h" @@ -21,6 +22,21 @@ void Screen::focusChanged(ScreenFocusChange focusChange) { DEBUG_LOG(SYSTEM, "Screen %s got %s", this->tag(), eventName); } +int Screen::GetRequesterToken() { + if (token_ < 0) { + token_ = g_requestManager.GenerateRequesterToken(); + } + return token_; +} + +Screen::~Screen() { + screenManager_ = nullptr; + if (token_ >= 0) { + // To avoid expired callbacks getting called. + g_requestManager.ForgetRequestsWithToken(token_); + } +} + ScreenManager::~ScreenManager() { shutdown(); } diff --git a/Common/UI/Screen.h b/Common/UI/Screen.h index e1f7bf8298cb..de40bae6848c 100644 --- a/Common/UI/Screen.h +++ b/Common/UI/Screen.h @@ -64,9 +64,7 @@ ENUM_CLASS_BITOPS(ScreenRenderFlags); class Screen { public: Screen() : screenManager_(nullptr) { } - virtual ~Screen() { - screenManager_ = nullptr; - } + virtual ~Screen(); virtual void onFinish(DialogResult reason) {} virtual void update() {} @@ -100,8 +98,13 @@ class Screen { virtual TouchInput transformTouch(const TouchInput &touch) { return touch; } +protected: + int GetRequesterToken(); + private: ScreenManager *screenManager_; + int token_ = -1; + DISALLOW_COPY_AND_ASSIGN(Screen); }; diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 555d638320bd..025d701d05cc 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -897,7 +897,7 @@ int PSPOskDialog::NativeKeyboard() { defaultText.assign(u"VALUE"); // There's already ConvertUCS2ToUTF8 in this file. Should we use that instead of the global ones? - System_InputBoxGetString(::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), + System_InputBoxGetString(NON_EPHEMERAL_TOKEN, ::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), [&](const std::string &value, int) { // Success callback std::lock_guard guard(nativeMutex_); diff --git a/UI/ChatScreen.cpp b/UI/ChatScreen.cpp index 4d4faa882a36..1a79eaee06bb 100644 --- a/UI/ChatScreen.cpp +++ b/UI/ChatScreen.cpp @@ -97,7 +97,7 @@ UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) { sendChat(chat); #elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("Chat"), "", [](const std::string &value, int) { + System_InputBoxGetString(token_, n->T("Chat"), "", [](const std::string &value, int) { sendChat(value); }); #endif @@ -180,7 +180,7 @@ void ChatMenu::Update() { // Could remove the fullscreen check here, it works now. auto n = GetI18NCategory(I18NCat::NETWORKING); if (promptInput_ && g_Config.bBypassOSKWithKeyboard && !g_Config.UseFullScreen()) { - System_InputBoxGetString(n->T("Chat"), n->T("Chat Here"), [](const std::string &value, int) { + System_InputBoxGetString(token_, n->T("Chat"), n->T("Chat Here"), [](const std::string &value, int) { sendChat(value); }); promptInput_ = false; diff --git a/UI/ChatScreen.h b/UI/ChatScreen.h index b068ddb1f075..5c2bee05324e 100644 --- a/UI/ChatScreen.h +++ b/UI/ChatScreen.h @@ -5,7 +5,8 @@ class ChatMenu : public UI::AnchorLayout { public: - ChatMenu(const Bounds &screenBounds, UI::LayoutParams *lp = nullptr): UI::AnchorLayout(lp) { + ChatMenu(int token, const Bounds &screenBounds, UI::LayoutParams *lp = nullptr) + : UI::AnchorLayout(lp), token_(token) { CreateSubviews(screenBounds); } void Update() override; @@ -41,4 +42,5 @@ class ChatMenu : public UI::AnchorLayout { int chatChangeID_ = 0; bool toBottom_ = true; bool promptInput_ = false; + int token_; }; diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index 1b63895c95ac..0fe6eb040759 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -206,7 +206,7 @@ static char *GetLineNoNewline(char *temp, int sz, FILE *fp) { } UI::EventReturn CwCheatScreen::OnImportBrowse(UI::EventParams ¶ms) { - System_BrowseForFile("Open cheat DB file", BrowseFileType::DB, [&](const std::string &value, int) { + System_BrowseForFile(GetRequesterToken(), "Open cheat DB file", BrowseFileType::DB, [&](const std::string &value, int) { Path path(value); INFO_LOG(SYSTEM, "Attempting to load cheats from: '%s'", path.ToVisualString().c_str()); if (ImportCheats(path)) { diff --git a/UI/DriverManagerScreen.cpp b/UI/DriverManagerScreen.cpp index 67a0148a344c..e2f037cdbd89 100644 --- a/UI/DriverManagerScreen.cpp +++ b/UI/DriverManagerScreen.cpp @@ -212,7 +212,7 @@ UI::EventReturn DriverManagerScreen::OnCustomDriverUninstall(UI::EventParams &e) UI::EventReturn DriverManagerScreen::OnCustomDriverInstall(UI::EventParams &e) { auto gr = GetI18NCategory(I18NCat::GRAPHICS); - System_BrowseForFile(gr->T("Install custom driver..."), BrowseFileType::ZIP, [this](const std::string &value, int) { + System_BrowseForFile(GetRequesterToken(), gr->T("Install custom driver..."), BrowseFileType::ZIP, [this](const std::string &value, int) { if (value.empty()) { return; } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 6541c1dbe43d..f4e58c513e65 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1039,7 +1039,7 @@ void EmuScreen::CreateViews() { root_->Add(btn)->OnClick.Handle(this, &EmuScreen::OnChat); chatButton_ = btn; } - chatMenu_ = root_->Add(new ChatMenu(screenManager()->getUIContext()->GetBounds(), new LayoutParams(FILL_PARENT, FILL_PARENT))); + chatMenu_ = root_->Add(new ChatMenu(GetRequesterToken(), screenManager()->getUIContext()->GetBounds(), new LayoutParams(FILL_PARENT, FILL_PARENT))); chatMenu_->SetVisibility(UI::V_GONE); } else { chatButton_ = nullptr; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 5593b57c5816..a206b091cca0 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -805,12 +805,12 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) // Compound view just like the audio file choosers class MacAddressChooser : public UI::LinearLayout { public: - MacAddressChooser(Path gamePath, std::string *value, const std::string &title, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr); + MacAddressChooser(RequesterToken token, Path gamePath, std::string *value, const std::string &title, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr); }; static constexpr UI::Size ITEM_HEIGHT = 64.f; -MacAddressChooser::MacAddressChooser(Path gamePath_, std::string *value, const std::string &title, ScreenManager *screenManager, UI::LayoutParams *layoutParams) : UI::LinearLayout(UI::ORIENT_HORIZONTAL, layoutParams) { +MacAddressChooser::MacAddressChooser(RequesterToken token, Path gamePath_, std::string *value, const std::string &title, ScreenManager *screenManager, UI::LayoutParams *layoutParams) : UI::LinearLayout(UI::ORIENT_HORIZONTAL, layoutParams) { using namespace UI; SetSpacing(5.0f); if (!layoutParams) { @@ -820,7 +820,7 @@ MacAddressChooser::MacAddressChooser(Path gamePath_, std::string *value, const s auto n = GetI18NCategory(I18NCat::NETWORKING); std::string initialValue = *value; - Add(new PopupTextInputChoice(value, title, g_Config.sMACAddress, 17, screenManager, new LinearLayoutParams(1.0f)))->OnChange.Add([=](UI::EventParams &e) { + Add(new PopupTextInputChoice(token, value, title, g_Config.sMACAddress, 17, screenManager, new LinearLayoutParams(1.0f)))->OnChange.Add([=](UI::EventParams &e) { // Validate the chosen address, and restore to initialValue if bad. if (g_Config.sMACAddress.size() != 17) { // TODO: Alert the user @@ -860,7 +860,7 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti networkingSettings->Add(new Choice(n->T("Open PPSSPP Multiplayer Wiki Page")))->OnClick.Handle(this, &GameSettingsScreen::OnAdhocGuides); networkingSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)"))); - networkingSettings->Add(new MacAddressChooser(gamePath_, &g_Config.sMACAddress, n->T("Change Mac Address"), screenManager())); + networkingSettings->Add(new MacAddressChooser(GetRequesterToken(), gamePath_, &g_Config.sMACAddress, n->T("Change Mac Address"), screenManager())); static const char* wlanChannels[] = { "Auto", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11" }; auto wlanChannelChoice = networkingSettings->Add(new PopupMultiChoice(&g_Config.iWlanAdhocChannel, n->T("WLAN Channel"), wlanChannels, 0, ARRAY_SIZE(wlanChannels), I18NCat::NETWORKING, screenManager())); for (int i = 0; i < 4; i++) { @@ -897,11 +897,11 @@ void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSetti #endif #if !defined(MOBILE_DEVICE) && !defined(USING_QT_UI) // TODO: Add all platforms where KEY_CHAR support is added - PopupTextInputChoice *qc1 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat0, n->T("Quick Chat 1"), "", 32, screenManager())); - PopupTextInputChoice *qc2 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat1, n->T("Quick Chat 2"), "", 32, screenManager())); - PopupTextInputChoice *qc3 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat2, n->T("Quick Chat 3"), "", 32, screenManager())); - PopupTextInputChoice *qc4 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat3, n->T("Quick Chat 4"), "", 32, screenManager())); - PopupTextInputChoice *qc5 = networkingSettings->Add(new PopupTextInputChoice(&g_Config.sQuickChat4, n->T("Quick Chat 5"), "", 32, screenManager())); + PopupTextInputChoice *qc1 = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sQuickChat0, n->T("Quick Chat 1"), "", 32, screenManager())); + PopupTextInputChoice *qc2 = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sQuickChat1, n->T("Quick Chat 2"), "", 32, screenManager())); + PopupTextInputChoice *qc3 = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sQuickChat2, n->T("Quick Chat 3"), "", 32, screenManager())); + PopupTextInputChoice *qc4 = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sQuickChat3, n->T("Quick Chat 4"), "", 32, screenManager())); + PopupTextInputChoice *qc5 = networkingSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sQuickChat4, n->T("Quick Chat 5"), "", 32, screenManager())); #elif defined(USING_QT_UI) Choice *qc1 = networkingSettings->Add(new Choice(n->T("Quick Chat 1"))); Choice *qc2 = networkingSettings->Add(new Choice(n->T("Quick Chat 2"))); @@ -1201,7 +1201,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { systemSettings->Add(new PopupMultiChoice(&g_Config.iLanguage, psps->T("Game language"), defaultLanguages, -1, ARRAY_SIZE(defaultLanguages), I18NCat::PSPSETTINGS, screenManager())); static const char *models[] = { "PSP-1000", "PSP-2000/3000" }; systemSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), I18NCat::SYSTEM, screenManager()))->SetEnabled(!PSP_IsInited()); - systemSettings->Add(new PopupTextInputChoice(&g_Config.sNickName, sy->T("Change Nickname"), "", 32, screenManager())); + systemSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &g_Config.sNickName, sy->T("Change Nickname"), "", 32, screenManager())); systemSettings->Add(new CheckBox(&g_Config.bScreenshotsAsPNG, sy->T("Screenshots as PNG"))); #if defined(_WIN32) || (defined(USING_QT_UI) && !defined(MOBILE_DEVICE)) @@ -1294,7 +1294,7 @@ UI::EventReturn GameSettingsScreen::OnJitAffectingSetting(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeMemStickDir(UI::EventParams &e) { #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - System_BrowseForFolder("", [](const std::string &value, int) { + System_BrowseForFolder(GetRequesterToken(), "", [](const std::string &value, int) { DarwinFileSystemServices::setUserPreferredMemoryStickDirectory(Path(value)); }); #else @@ -1374,7 +1374,7 @@ UI::EventReturn GameSettingsScreen::OnChangeBackground(UI::EventParams &e) { RecreateViews(); } else { auto sy = GetI18NCategory(I18NCat::SYSTEM); - System_BrowseForImage(sy->T("Set UI background..."), [=](const std::string &value, int) { + System_BrowseForImage(GetRequesterToken(), sy->T("Set UI background..."), [=](const std::string &value, int) { if (!value.empty()) { Path dest = GetSysDirectory(DIRECTORY_SYSTEM) / (endsWithNoCase(value, ".jpg") ? "background.jpg" : "background.png"); File::Copy(Path(value), dest); @@ -1565,7 +1565,7 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](const std::string &value, int) { g_Config.sQuickChat0 = value; }); #endif @@ -1575,7 +1575,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](const std::string &value, int) { g_Config.sQuickChat1 = value; }); #endif @@ -1585,7 +1585,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](const std::string &value, int) { g_Config.sQuickChat2 = value; }); #endif @@ -1595,7 +1595,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](const std::string &value, int) { g_Config.sQuickChat3 = value; }); #endif @@ -1605,7 +1605,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](const std::string &value, int) { g_Config.sQuickChat4 = value; }); #endif @@ -1615,7 +1615,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("Enter a new PSP nickname"), g_Config.sNickName, [](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), n->T("Enter a new PSP nickname"), g_Config.sNickName, [](const std::string &value, int) { g_Config.sNickName = StripSpaces(value); }); #endif @@ -2077,7 +2077,7 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) { UI::EventReturn HostnameSelectScreen::OnEditClick(UI::EventParams& e) { auto n = GetI18NCategory(I18NCat::NETWORKING); - System_InputBoxGetString(n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) { + System_InputBoxGetString(GetRequesterToken(), n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) { addrView_->SetText(value); }); return UI::EVENT_DONE; diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index ce86f87b483e..ae01a4d04b50 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -510,8 +510,8 @@ void DirButton::Draw(UIContext &dc) { } } -GameBrowser::GameBrowser(const Path &path, BrowseFlags browseFlags, bool *gridStyle, ScreenManager *screenManager, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams) - : LinearLayout(UI::ORIENT_VERTICAL, layoutParams), path_(path), gridStyle_(gridStyle), browseFlags_(browseFlags), lastText_(lastText), lastLink_(lastLink), screenManager_(screenManager) { +GameBrowser::GameBrowser(int token, const Path &path, BrowseFlags browseFlags, bool *gridStyle, ScreenManager *screenManager, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams) + : LinearLayout(UI::ORIENT_VERTICAL, layoutParams), path_(path), gridStyle_(gridStyle), browseFlags_(browseFlags), lastText_(lastText), lastLink_(lastLink), screenManager_(screenManager), token_(token) { using namespace UI; path_.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION)); path_.SetRootAlias("ms:", GetSysDirectory(DIRECTORY_MEMSTICK_ROOT).ToVisualString()); @@ -604,7 +604,7 @@ UI::EventReturn GameBrowser::LastClick(UI::EventParams &e) { UI::EventReturn GameBrowser::BrowseClick(UI::EventParams &e) { auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_BrowseForFolder(mm->T("Choose folder"), [this](const std::string &filename, int) { + System_BrowseForFolder(token_, mm->T("Choose folder"), [this](const std::string &filename, int) { this->SetPath(Path(filename)); }); return UI::EVENT_DONE; @@ -781,7 +781,7 @@ void GameBrowser::Refresh() { if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_TV) { topBar->Add(new Choice(mm->T("Enter Path"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Add([=](UI::EventParams &) { auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_InputBoxGetString(mm->T("Enter Path"), path_.GetPath().ToString(), [=](const char *responseString, int responseValue) { + System_InputBoxGetString(token_, mm->T("Enter Path"), path_.GetPath().ToString(), [=](const char *responseString, int responseValue) { this->SetPath(Path(responseString)); }); return UI::EVENT_DONE; @@ -1098,7 +1098,7 @@ void MainScreen::CreateViews() { if (showRecent) { ScrollView *scrollRecentGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); scrollRecentGames->SetTag("MainScreenRecentGames"); - GameBrowser *tabRecentGames = new GameBrowser( + GameBrowser *tabRecentGames = new GameBrowser(GetRequesterToken(), Path("!RECENT"), BrowseFlags::NONE, &g_Config.bGridView1, screenManager(), "", "", new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); scrollRecentGames->Add(tabRecentGames); @@ -1118,10 +1118,10 @@ void MainScreen::CreateViews() { scrollHomebrew->SetTag("MainScreenHomebrew"); - GameBrowser *tabAllGames = new GameBrowser(Path(g_Config.currentDirectory), BrowseFlags::STANDARD, &g_Config.bGridView2, screenManager(), + GameBrowser *tabAllGames = new GameBrowser(GetRequesterToken(), Path(g_Config.currentDirectory), BrowseFlags::STANDARD, &g_Config.bGridView2, screenManager(), mm->T("How to get games"), "https://www.ppsspp.org/getgames", new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); - GameBrowser *tabHomebrew = new GameBrowser(GetSysDirectory(DIRECTORY_GAME), BrowseFlags::HOMEBREW_STORE, &g_Config.bGridView3, screenManager(), + GameBrowser *tabHomebrew = new GameBrowser(GetRequesterToken(), GetSysDirectory(DIRECTORY_GAME), BrowseFlags::HOMEBREW_STORE, &g_Config.bGridView3, screenManager(), mm->T("How to get homebrew & demos", "How to get homebrew && demos"), "https://www.ppsspp.org/gethomebrew", new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); @@ -1151,7 +1151,7 @@ void MainScreen::CreateViews() { Path remotePath(FormatRemoteISOUrl(g_Config.sLastRemoteISOServer.c_str(), g_Config.iLastRemoteISOPort, RemoteSubdir().c_str())); - GameBrowser *tabRemote = new GameBrowser(remotePath, BrowseFlags::NAVIGATE, &g_Config.bGridView3, screenManager(), + GameBrowser *tabRemote = new GameBrowser(GetRequesterToken(), remotePath, BrowseFlags::NAVIGATE, &g_Config.bGridView3, screenManager(), ri->T("Remote disc streaming"), "https://www.ppsspp.org/docs/reference/disc-streaming", new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); tabRemote->SetHomePath(remotePath); @@ -1330,7 +1330,7 @@ bool MainScreen::key(const KeyInput &touch) { searchKeyModifier_ = true; if (touch.keyCode == NKCODE_F && searchKeyModifier_ && System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { auto se = GetI18NCategory(I18NCat::SEARCH); - System_InputBoxGetString(se->T("Search term"), searchFilter_, [&](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), se->T("Search term"), searchFilter_, [&](const std::string &value, int) { searchFilter_ = StripSpaces(value); searchChanged_ = true; }); @@ -1399,7 +1399,7 @@ void MainScreen::update() { UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) { if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) { auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_BrowseForFile(mm->T("Load"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { + System_BrowseForFile(GetRequesterToken(), mm->T("Load"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, value); }); } @@ -1609,7 +1609,7 @@ void UmdReplaceScreen::CreateViews() { if (g_Config.iMaxRecent > 0) { ScrollView *scrollRecentGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); scrollRecentGames->SetTag("UmdReplaceRecentGames"); - GameBrowser *tabRecentGames = new GameBrowser( + GameBrowser *tabRecentGames = new GameBrowser(GetRequesterToken(), Path("!RECENT"), BrowseFlags::NONE, &g_Config.bGridView1, screenManager(), "", "", new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); scrollRecentGames->Add(tabRecentGames); @@ -1620,7 +1620,7 @@ void UmdReplaceScreen::CreateViews() { ScrollView *scrollAllGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); scrollAllGames->SetTag("UmdReplaceAllGames"); - GameBrowser *tabAllGames = new GameBrowser(Path(g_Config.currentDirectory), BrowseFlags::STANDARD, &g_Config.bGridView2, screenManager(), + GameBrowser *tabAllGames = new GameBrowser(GetRequesterToken(), Path(g_Config.currentDirectory), BrowseFlags::STANDARD, &g_Config.bGridView2, screenManager(), mm->T("How to get games"), "https://www.ppsspp.org/getgames.html", new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); @@ -1635,7 +1635,7 @@ void UmdReplaceScreen::CreateViews() { if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) { rightColumnItems->Add(new Choice(mm->T("Load", "Load...")))->OnClick.Add([&](UI::EventParams &e) { auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_BrowseForFile(mm->T("Load"), BrowseFileType::BOOTABLE, [&](const std::string &value, int) { + System_BrowseForFile(GetRequesterToken(), mm->T("Load"), BrowseFileType::BOOTABLE, [&](const std::string &value, int) { __UmdReplace(Path(value)); TriggerFinish(DR_OK); }); diff --git a/UI/MainScreen.h b/UI/MainScreen.h index 994cb82ba2a4..1e8d98521f3b 100644 --- a/UI/MainScreen.h +++ b/UI/MainScreen.h @@ -44,7 +44,7 @@ bool LaunchFile(ScreenManager *screenManager, const Path &path); class GameBrowser : public UI::LinearLayout { public: - GameBrowser(const Path &path, BrowseFlags browseFlags, bool *gridStyle, ScreenManager *screenManager, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams = nullptr); + GameBrowser(int token, const Path &path, BrowseFlags browseFlags, bool *gridStyle, ScreenManager *screenManager, std::string lastText, std::string lastLink, UI::LayoutParams *layoutParams = nullptr); UI::Event OnChoice; UI::Event OnHoldChoice; @@ -109,6 +109,7 @@ class GameBrowser : public UI::LinearLayout { float lastScale_ = 1.0f; bool lastLayoutWasGrid_ = true; ScreenManager *screenManager_; + int token_; }; class RemoteISOBrowseScreen; diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 41d733201261..03b7f6fbe3d9 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -356,7 +356,7 @@ UI::EventReturn MemStickScreen::SetFolderManually(UI::EventParams ¶ms) { // The old way, from before scoped storage. #if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) auto sy = GetI18NCategory(I18NCat::SYSTEM); - System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](const std::string &value, int) { + System_InputBoxGetString(GetRequesterToken(), sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](const std::string &value, int) { auto sy = GetI18NCategory(I18NCat::SYSTEM); auto di = GetI18NCategory(I18NCat::DIALOG); @@ -469,7 +469,7 @@ UI::EventReturn MemStickScreen::UseStorageRoot(UI::EventParams ¶ms) { UI::EventReturn MemStickScreen::Browse(UI::EventParams ¶ms) { auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_BrowseForFolder(mm->T("Choose folder"), [=](const std::string &value, int) { + System_BrowseForFolder(GetRequesterToken(), mm->T("Choose folder"), [=](const std::string &value, int) { Path pendingMemStickFolder = Path(value); INFO_LOG(SYSTEM, "Got folder: '%s'", pendingMemStickFolder.c_str()); // Browse finished. Let's pop up the confirmation dialog. diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index 0a170d60cb60..8ed622622ee7 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -530,7 +530,7 @@ void RemoteISOBrowseScreen::CreateViews() { ScrollView *scrollRecentGames = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)); scrollRecentGames->SetTag("RemoteGamesTab"); - GameBrowser *tabRemoteGames = new GameBrowser( + GameBrowser *tabRemoteGames = new GameBrowser(GetRequesterToken(), Path(url_), BrowseFlags::NAVIGATE, &g_Config.bGridView1, screenManager(), "", "", new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); tabRemoteGames->SetHomePath(Path(url_)); @@ -601,7 +601,7 @@ void RemoteISOSettingsScreen::CreateViews() { if (System_GetPropertyBool(SYSPROP_HAS_FOLDER_BROWSER)) { static const char *shareTypes[] = { "Recent files", "Choose directory" }; remoteisoSettings->Add(new PopupMultiChoice(&g_Config.iRemoteISOShareType, ri->T("Files to share"), shareTypes, 0, ARRAY_SIZE(shareTypes), I18NCat::REMOTEISO, screenManager())); - FolderChooserChoice *folderChooser = remoteisoSettings->Add(new FolderChooserChoice(&g_Config.sRemoteISOSharedDir, ri->T("Files to share"))); + FolderChooserChoice *folderChooser = remoteisoSettings->Add(new FolderChooserChoice(GetRequesterToken(), &g_Config.sRemoteISOSharedDir, ri->T("Files to share"))); folderChooser->SetEnabledFunc([=]() { return g_Config.iRemoteISOShareType == (int)RemoteISOShareType::LOCAL_FOLDER; }); @@ -610,7 +610,7 @@ void RemoteISOSettingsScreen::CreateViews() { g_Config.iRemoteISOShareType = (int)RemoteISOShareType::RECENT; } - UI::Choice *remoteServer = new PopupTextInputChoice(&g_Config.sLastRemoteISOServer, ri->T("Remote Server"), "", 255, screenManager()); + UI::Choice *remoteServer = new PopupTextInputChoice(GetRequesterToken(), &g_Config.sLastRemoteISOServer, ri->T("Remote Server"), "", 255, screenManager()); remoteisoSettings->Add(remoteServer); remoteServer->SetEnabledPtr(&g_Config.bRemoteISOManual); @@ -619,7 +619,7 @@ void RemoteISOSettingsScreen::CreateViews() { UI::Choice *remoteSubdir; { - PopupTextInputChoice *remoteSubdirInput = new PopupTextInputChoice(&g_Config.sRemoteISOSubdir, ri->T("Remote Subdirectory"), "", 255, screenManager()); + PopupTextInputChoice *remoteSubdirInput = new PopupTextInputChoice(GetRequesterToken(), &g_Config.sRemoteISOSubdir, ri->T("Remote Subdirectory"), "", 255, screenManager()); remoteSubdirInput->OnChange.Handle(this, &RemoteISOSettingsScreen::OnChangeRemoteISOSubdir); remoteSubdir = remoteSubdirInput; } diff --git a/UI/RetroAchievementScreens.cpp b/UI/RetroAchievementScreens.cpp index 2e09550f20d5..203a074b58ef 100644 --- a/UI/RetroAchievementScreens.cpp +++ b/UI/RetroAchievementScreens.cpp @@ -20,14 +20,14 @@ static inline const char *DeNull(const char *ptr) { // Compound view, creating a FileChooserChoice inside. class AudioFileChooser : public UI::LinearLayout { public: - AudioFileChooser(std::string *value, const std::string &title, UI::UISound sound, UI::LayoutParams *layoutParams = nullptr); + AudioFileChooser(RequesterToken token, std::string *value, const std::string &title, UI::UISound sound, UI::LayoutParams *layoutParams = nullptr); UI::UISound sound_; }; static constexpr UI::Size ITEM_HEIGHT = 64.f; -AudioFileChooser::AudioFileChooser(std::string *value, const std::string &title, UI::UISound sound, UI::LayoutParams *layoutParams) : UI::LinearLayout(UI::ORIENT_HORIZONTAL, layoutParams), sound_(sound) { +AudioFileChooser::AudioFileChooser(RequesterToken token, std::string *value, const std::string &title, UI::UISound sound, UI::LayoutParams *layoutParams) : UI::LinearLayout(UI::ORIENT_HORIZONTAL, layoutParams), sound_(sound) { using namespace UI; SetSpacing(2.0f); if (!layoutParams) { @@ -38,7 +38,7 @@ AudioFileChooser::AudioFileChooser(std::string *value, const std::string &title, g_BackgroundAudio.SFX().Play(sound_, 0.6f); return UI::EVENT_DONE; }); - Add(new FileChooserChoice(value, title, BrowseFileType::SOUND_EFFECT, new LinearLayoutParams(1.0f)))->OnChange.Add([=](UI::EventParams &e) { + Add(new FileChooserChoice(token, value, title, BrowseFileType::SOUND_EFFECT, new LinearLayoutParams(1.0f)))->OnChange.Add([=](UI::EventParams &e) { std::string path = e.s; Sample *sample = Sample::Load(path); if (sample) { @@ -299,7 +299,7 @@ void RetroAchievementsSettingsScreen::CreateAccountTab(UI::ViewGroup *viewGroup) }); } else if (System_GetPropertyBool(SYSPROP_HAS_LOGIN_DIALOG)) { viewGroup->Add(new Choice(di->T("Log in")))->OnClick.Add([=](UI::EventParams &) -> UI::EventReturn { - System_AskUsernamePassword(StringFromFormat("RetroAchievements: %s", di->T("Log in")), [](const std::string &value, int) { + System_AskUsernamePassword(GetRequesterToken(), StringFromFormat("RetroAchievements: %s", di->T("Log in")), [](const std::string &value, int) { std::vector parts; SplitString(value, '\n', parts); if (parts.size() == 2 && !parts[0].empty() && !parts[1].empty()) { @@ -310,8 +310,8 @@ void RetroAchievementsSettingsScreen::CreateAccountTab(UI::ViewGroup *viewGroup) }); } else { // Hack up a temporary quick login-form-ish-thing - viewGroup->Add(new PopupTextInputChoice(&username_, di->T("Username"), "", 128, screenManager())); - viewGroup->Add(new PopupTextInputChoice(&password_, di->T("Password"), "", 128, screenManager()))->SetPasswordDisplay(); + viewGroup->Add(new PopupTextInputChoice(GetRequesterToken(), &username_, di->T("Username"), "", 128, screenManager())); + viewGroup->Add(new PopupTextInputChoice(GetRequesterToken(), &password_, di->T("Password"), "", 128, screenManager()))->SetPasswordDisplay(); Choice *loginButton = viewGroup->Add(new Choice(di->T("Log in"))); loginButton->OnClick.Add([=](UI::EventParams &) -> UI::EventReturn { if (!username_.empty() && !password_.empty()) { @@ -357,8 +357,8 @@ void RetroAchievementsSettingsScreen::CreateCustomizeTab(UI::ViewGroup *viewGrou using namespace UI; viewGroup->Add(new ItemHeader(ac->T("Sound Effects"))); - viewGroup->Add(new AudioFileChooser(&g_Config.sAchievementsUnlockAudioFile, ac->T("Achievement unlocked"), UISound::ACHIEVEMENT_UNLOCKED)); - viewGroup->Add(new AudioFileChooser(&g_Config.sAchievementsLeaderboardSubmitAudioFile, ac->T("Leaderboard score submission"), UISound::LEADERBOARD_SUBMITTED)); + viewGroup->Add(new AudioFileChooser(GetRequesterToken(), &g_Config.sAchievementsUnlockAudioFile, ac->T("Achievement unlocked"), UISound::ACHIEVEMENT_UNLOCKED)); + viewGroup->Add(new AudioFileChooser(GetRequesterToken(), &g_Config.sAchievementsLeaderboardSubmitAudioFile, ac->T("Leaderboard score submission"), UISound::LEADERBOARD_SUBMITTED)); static const char *positions[] = { "None", "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right" }; diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index c39428204b3e..9b384db1003c 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -674,7 +674,7 @@ UI::EventReturn SavedataScreen::OnSortClick(UI::EventParams &e) { UI::EventReturn SavedataScreen::OnSearch(UI::EventParams &e) { if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { auto di = GetI18NCategory(I18NCat::DIALOG); - System_InputBoxGetString(di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) { + System_InputBoxGetString(GetRequesterToken(), di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) { System_PostUIMessage(UIMessage::SAVEDATA_SEARCH, value); }); } diff --git a/UI/TabbedDialogScreen.cpp b/UI/TabbedDialogScreen.cpp index 7c570b0655ec..88a7fe8afe96 100644 --- a/UI/TabbedDialogScreen.cpp +++ b/UI/TabbedDialogScreen.cpp @@ -84,7 +84,7 @@ void TabbedUIDialogScreenWithGameBackground::CreateViews() { LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true); searchSettings->Add(new ItemHeader(se->T("Find settings"))); - searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Add([=](UI::EventParams &e) { + searchSettings->Add(new PopupTextInputChoice(GetRequesterToken(), &searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Add([=](UI::EventParams &e) { System_PostUIMessage(UIMessage::GAMESETTINGS_SEARCH, StripSpaces(searchFilter_)); return UI::EVENT_DONE; }); diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index b4c4d1c9ba83..3682f736abc4 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -321,7 +321,7 @@ namespace MainWindow { void BrowseAndBootDone(std::string filename); - void BrowseAndBoot(std::string defaultPath, bool browseDirectory) { + void BrowseAndBoot(RequesterToken token, std::string defaultPath, bool browseDirectory) { browsePauseAfter = false; if (GetUIState() == UISTATE_INGAME) { browsePauseAfter = Core_IsStepping(); @@ -333,11 +333,11 @@ namespace MainWindow { W32Util::MakeTopMost(GetHWND(), false); if (browseDirectory) { - System_BrowseForFolder(mm->T("Load"), [](const std::string &value, int) { + System_BrowseForFolder(token, mm->T("Load"), [](const std::string &value, int) { BrowseAndBootDone(value); }); } else { - System_BrowseForFile(mm->T("Load"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { + System_BrowseForFile(token, mm->T("Load"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { BrowseAndBootDone(value); }); } @@ -352,9 +352,9 @@ namespace MainWindow { W32Util::MakeTopMost(GetHWND(), g_Config.bTopMost); } - static void UmdSwitchAction() { + static void UmdSwitchAction(RequesterToken token) { auto mm = GetI18NCategory(I18NCat::MAINMENU); - System_BrowseForFile(mm->T("Switch UMD"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { + System_BrowseForFile(token, mm->T("Switch UMD"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { __UmdReplace(Path(value)); }); } @@ -441,15 +441,15 @@ namespace MainWindow { // Parse the menu selections: switch (wmId) { case ID_FILE_LOAD: - BrowseAndBoot("", false); + BrowseAndBoot(NON_EPHEMERAL_TOKEN, "", false); break; case ID_FILE_LOAD_DIR: - BrowseAndBoot("", true); + BrowseAndBoot(NON_EPHEMERAL_TOKEN, "", true); break; case ID_FILE_LOAD_MEMSTICK: - BrowseAndBoot(GetSysDirectory(DIRECTORY_GAME).ToString()); + BrowseAndBoot(NON_EPHEMERAL_TOKEN, GetSysDirectory(DIRECTORY_GAME).ToString()); break; case ID_FILE_OPEN_NEW_INSTANCE: @@ -500,7 +500,7 @@ namespace MainWindow { break; case ID_EMULATION_SWITCH_UMD: - UmdSwitchAction(); + UmdSwitchAction(NON_EPHEMERAL_TOKEN); break; case ID_EMULATION_ROTATION_H: g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; break; diff --git a/Windows/MainWindowMenu.h b/Windows/MainWindowMenu.h index fe34643718a4..5a15f9950dcc 100644 --- a/Windows/MainWindowMenu.h +++ b/Windows/MainWindowMenu.h @@ -2,12 +2,14 @@ #include "Common/CommonWindows.h" #include + +#include "Common/System/Request.h" #include "Core/System.h" namespace MainWindow { void MainWindowMenu_Process(HWND hWnd, WPARAM wParam); void TranslateMenus(HWND hWnd, HMENU menu); - void BrowseAndBoot(std::string defaultPath, bool browseDirectory = false); + void BrowseAndBoot(RequesterToken token, std::string defaultPath, bool browseDirectory = false); void setTexScalingMultiplier(int level); void SetIngameMenuItemStates(HMENU menu, const GlobalUIState state); } diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 6503191361f3..815d1d622ed3 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -135,7 +135,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string return false; } } -void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\0'; } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index e890a9ba0cb5..88615489bd2e 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1750,7 +1750,6 @@ std::vector System_GetCameraDeviceList() { return std::vector cb) { cb(false, ""); } #endif // TODO: To avoid having to define these here, these should probably be turned into system "requests".