diff --git a/CMakeLists.txt b/CMakeLists.txt
index 36dbf12c73..a6f2ea7c7e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -712,6 +712,10 @@ add_library(Common STATIC
Common/Render/Text/draw_text_uwp.h
Common/System/Display.cpp
Common/System/Display.h
+ Common/System/System.h
+ Common/System/NativeApp.h
+ Common/System/Request.cpp
+ Common/System/Request.h
Common/Thread/Channel.h
Common/Thread/ParallelLoop.cpp
Common/Thread/ParallelLoop.h
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index a28696099b..3fabaafa64 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -550,7 +550,7 @@
-
+
@@ -1006,7 +1006,7 @@
-
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 23b138fb39..879e3495b8 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -494,7 +494,7 @@
ext\basis_universal
-
+
System
@@ -923,7 +923,7 @@
ext\basis_universal
-
+
System
diff --git a/Common/System/NativeApp.h b/Common/System/NativeApp.h
index 6788642eb4..bb0c7af962 100644
--- a/Common/System/NativeApp.h
+++ b/Common/System/NativeApp.h
@@ -23,9 +23,6 @@ void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, boo
// Generic host->C++ messaging, used for functionality like system-native popup input boxes.
void NativeMessageReceived(const char *message, const char *value);
-// This is used to communicate back and thread requested input box strings.
-void NativeInputBoxReceived(std::function cb, bool result, const std::string &value);
-
// Easy way for the Java side to ask the C++ side for configuration options, such as
// the rotation lock which must be controlled from Java on Android.
// It is currently not called on non-Android platforms.
diff --git a/Common/System/Message.cpp b/Common/System/Request.cpp
similarity index 59%
rename from Common/System/Message.cpp
rename to Common/System/Request.cpp
index 8a09fc3a04..883514d8da 100644
--- a/Common/System/Message.cpp
+++ b/Common/System/Request.cpp
@@ -1,8 +1,8 @@
-#include "Common/System/Message.h"
+#include "Common/System/Request.h"
#include "Common/System/System.h"
#include "Common/Log.h"
-RequestManager g_RequestManager;
+RequestManager g_requestManager;
const char *RequestTypeAsString(SystemRequestType type) {
switch (type) {
@@ -11,7 +11,7 @@ const char *RequestTypeAsString(SystemRequestType type) {
}
}
-bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const char *param1, const char *param2) {
+bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2) {
int requestId = idCounter_++;
if (!System_MakeRequest(type, requestId, param1, param2)) {
return false;
@@ -27,12 +27,11 @@ bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback c
return true;
}
-void RequestManager::PostSystemResponse(int requestId, const char *responseString, int responseValue) {
+void RequestManager::PostSystemSuccess(int requestId, const char *responseString, int responseValue) {
std::lock_guard guard(callbackMutex_);
auto iter = callbackMap_.find(requestId);
if (iter == callbackMap_.end()) {
- // Unexpected!
- ERROR_LOG(SYSTEM, "PostSystemResponse: Unexpected request ID %d for %s (responseString=%s)", requestId, responseString);
+ ERROR_LOG(SYSTEM, "PostSystemSuccess: Unexpected request ID %d (responseString=%s)", requestId, responseString);
return;
}
@@ -44,6 +43,16 @@ void RequestManager::PostSystemResponse(int requestId, const char *responseStrin
pendingResponses_.push_back(response);
}
+void RequestManager::PostSystemFailure(int requestId) {
+ std::lock_guard guard(callbackMutex_);
+ auto iter = callbackMap_.find(requestId);
+ if (iter == callbackMap_.end()) {
+ ERROR_LOG(SYSTEM, "PostSystemFailure: Unexpected request ID %d", requestId);
+ return;
+ }
+ callbackMap_.erase(iter);
+}
+
void RequestManager::ProcessRequests() {
std::lock_guard guard(responseMutex_);
for (auto &iter : pendingResponses_) {
@@ -53,3 +62,11 @@ void RequestManager::ProcessRequests() {
}
pendingResponses_.clear();
}
+
+void RequestManager::Clear() {
+ std::lock_guard guard(callbackMutex_);
+ std::lock_guard responseGuard(responseMutex_);
+
+ pendingResponses_.clear();
+ callbackMap_.clear();
+}
diff --git a/Common/System/Message.h b/Common/System/Request.h
similarity index 66%
rename from Common/System/Message.h
rename to Common/System/Request.h
index 88cd58df41..19afe99721 100644
--- a/Common/System/Message.h
+++ b/Common/System/Request.h
@@ -16,15 +16,19 @@ class RequestManager {
public:
// These requests are to be handled by platform implementations.
// The callback you pass in will be called on the main thread later.
- bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const char *param1, const char *param2);
+ bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2);
// Called by the platform implementation, when it's finished with a request.
- void PostSystemResponse(int requestId, const char *responseString, int responseValue);
+ void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0);
+ void PostSystemFailure(int requestId);
// This must be called every frame from the beginning of NativeUpdate().
// This will call the callback of any finished requests.
void ProcessRequests();
+ // Unclear if we need this...
+ void Clear();
+
private:
struct PendingRequest {
SystemRequestType type;
@@ -47,4 +51,10 @@ private:
const char *RequestTypeAsString(SystemRequestType type);
-extern RequestManager g_RequestManager;
+extern RequestManager g_requestManager;
+
+// Wrappers for easy requests.
+// NOTE: Semantics have changed - this no longer calls the callback on cancellation.
+inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback) {
+ g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, title, defaultValue);
+}
diff --git a/Common/System/System.h b/Common/System/System.h
index c33bac6ed0..b0222aeea0 100644
--- a/Common/System/System.h
+++ b/Common/System/System.h
@@ -50,8 +50,20 @@ enum class LaunchUrlType {
void System_Vibrate(int length_ms);
void System_ShowFileInFolder(const char *path);
void System_LaunchUrl(LaunchUrlType urlType, const char *url);
-void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb);
+
+enum class SystemRequestType {
+ INPUT_TEXT_MODAL,
+};
+
+// Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h).
+// This is not to be used directly by applications, instead use the g_RequestManager to make the requests.
+// This can return false if it's known that the platform doesn't support the request, the app is supposed to handle
+// or ignore that cleanly.
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2);
+
+// TODO: To be separated into requests, see Request.h, and a way to post "UI messages".
void System_SendMessage(const char *command, const char *parameter);
+
PermissionStatus System_GetPermissionStatus(SystemPermission permission);
void System_AskForPermission(SystemPermission permission);
@@ -146,16 +158,6 @@ enum class SystemNotification {
SWITCH_UMD_UPDATED,
};
-enum class SystemRequestType {
- INPUT_TEXT_MODAL,
-};
-
-// Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h).
-// This is not to be used directly by applications, instead use the g_RequestManager to make the requests.
-// This can return false if it's known that the platform doesn't support the request, the app is supposed to handle
-// or ignore that cleanly.
-bool System_MakeRequest(SystemRequestType type, int requestId, const char *param1, const char *param2);
-
std::string System_GetProperty(SystemProperty prop);
std::vector System_GetPropertyStringVec(SystemProperty prop);
int System_GetPropertyInt(SystemProperty prop);
diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp
index e6e1ccafc4..bfbc545f67 100755
--- a/Core/Dialog/PSPOskDialog.cpp
+++ b/Core/Dialog/PSPOskDialog.cpp
@@ -22,7 +22,7 @@
#include "Common/Math/math_util.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/Serialize/SerializeFuncs.h"
-#include "Common/System/System.h"
+#include "Common/System/Request.h"
#include "Common/Serialize/Serializer.h"
#include "Core/Dialog/PSPOskDialog.h"
@@ -892,14 +892,14 @@ 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), [&](bool result, const std::string &value) {
+ System_InputBoxGetString(::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), [&](const std::string &value, int iValue) {
std::lock_guard guard(nativeMutex_);
if (nativeStatus_ != PSPOskNativeStatus::WAITING) {
return;
}
nativeValue_ = value;
- nativeStatus_ = result ? PSPOskNativeStatus::SUCCESS : PSPOskNativeStatus::FAILURE;
+ nativeStatus_ = iValue ? PSPOskNativeStatus::SUCCESS : PSPOskNativeStatus::FAILURE;
});
} else if (nativeStatus_ == PSPOskNativeStatus::SUCCESS) {
inputChars = ConvertUTF8ToUCS2(nativeValue_);
diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp
index 3571c615ca..65498db322 100644
--- a/Qt/QtMain.cpp
+++ b/Qt/QtMain.cpp
@@ -273,6 +273,8 @@ void System_Notify(SystemNotification notification) {
}
}
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; }
+
void System_SendMessage(const char *command, const char *parameter) {
if (!strcmp(command, "finish")) {
qApp->exit(0);
diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp
index f59a2dd22a..3bda836e98 100644
--- a/SDL/SDLMain.cpp
+++ b/SDL/SDLMain.cpp
@@ -166,6 +166,8 @@ void System_Vibrate(int length_ms) {
// Ignore on PC
}
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; }
+
void System_SendMessage(const char *command, const char *parameter) {
if (!strcmp(command, "toggle_fullscreen")) {
g_ToggleFullScreenNextFrame = true;
diff --git a/UI/ChatScreen.cpp b/UI/ChatScreen.cpp
index 277185b3e5..d62470666e 100644
--- a/UI/ChatScreen.cpp
+++ b/UI/ChatScreen.cpp
@@ -10,7 +10,7 @@
#include "Common/Data/Text/I18n.h"
#include "Common/Data/Encoding/Utf8.h"
-#include "Common/System/System.h"
+#include "Common/System/Request.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "Core/HLE/proAdhoc.h"
@@ -97,7 +97,7 @@ UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) {
sendChat(chat);
#elif PPSSPP_PLATFORM(ANDROID)
auto n = GetI18NCategory("Networking");
- System_InputBoxGetString(n->T("Chat"), "", [](bool result, const std::string &value) {
+ System_InputBoxGetString(n->T("Chat"), "", [](const std::string &value, int) {
sendChat(value);
});
#endif
@@ -181,10 +181,8 @@ void ChatMenu::Update() {
#if defined(USING_WIN_UI)
// Could remove the fullscreen check here, it works now.
if (promptInput_ && g_Config.bBypassOSKWithKeyboard && !g_Config.UseFullScreen()) {
- System_InputBoxGetString(n->T("Chat"), n->T("Chat Here"), [](bool result, const std::string &value) {
- if (result) {
- sendChat(value);
- }
+ System_InputBoxGetString(n->T("Chat"), n->T("Chat Here"), [](const std::string &value, int) {
+ sendChat(value);
});
promptInput_ = false;
}
diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp
index ded0d26d52..43f7ed44a5 100644
--- a/UI/GameSettingsScreen.cpp
+++ b/UI/GameSettingsScreen.cpp
@@ -30,7 +30,7 @@
#include "Common/VR/PPSSPPVR.h"
#include "Common/System/Display.h" // Only to check screen aspect ratio with pixel_yres/pixel_xres
-#include "Common/System/System.h"
+#include "Common/System/Request.h"
#include "Common/Battery/Battery.h"
#include "Common/System/NativeApp.h"
#include "Common/Data/Color/RGBAUtil.h"
@@ -1564,10 +1564,8 @@ 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)
auto n = GetI18NCategory("Networking");
- System_InputBoxGetString(n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](bool result, const std::string &value) {
- if (result) {
- g_Config.sQuickChat0 = value;
- }
+ System_InputBoxGetString(n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](const std::string &value, int) {
+ g_Config.sQuickChat0 = value;
});
#endif
return UI::EVENT_DONE;
@@ -1576,10 +1574,8 @@ 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)
auto n = GetI18NCategory("Networking");
- System_InputBoxGetString(n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](bool result, const std::string &value) {
- if (result) {
- g_Config.sQuickChat1 = value;
- }
+ System_InputBoxGetString(n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](const std::string &value, int) {
+ g_Config.sQuickChat1 = value;
});
#endif
return UI::EVENT_DONE;
@@ -1588,10 +1584,8 @@ 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)
auto n = GetI18NCategory("Networking");
- System_InputBoxGetString(n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](bool result, const std::string &value) {
- if (result) {
- g_Config.sQuickChat2 = value;
- }
+ System_InputBoxGetString(n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](const std::string &value, int) {
+ g_Config.sQuickChat2 = value;
});
#endif
return UI::EVENT_DONE;
@@ -1600,10 +1594,8 @@ 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)
auto n = GetI18NCategory("Networking");
- System_InputBoxGetString(n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](bool result, const std::string &value) {
- if (result) {
- g_Config.sQuickChat3 = value;
- }
+ System_InputBoxGetString(n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](const std::string &value, int) {
+ g_Config.sQuickChat3 = value;
});
#endif
return UI::EVENT_DONE;
@@ -1612,10 +1604,8 @@ 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)
auto n = GetI18NCategory("Networking");
- System_InputBoxGetString(n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](bool result, const std::string &value) {
- if (result) {
- g_Config.sQuickChat4 = value;
- }
+ System_InputBoxGetString(n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](const std::string &value, int) {
+ g_Config.sQuickChat4 = value;
});
#endif
return UI::EVENT_DONE;
@@ -1624,10 +1614,8 @@ 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)
auto n = GetI18NCategory("Networking");
- System_InputBoxGetString(n->T("Enter a new PSP nickname"), g_Config.sNickName, [](bool result, const std::string &value) {
- if (result) {
- g_Config.sNickName = StripSpaces(value);
- }
+ System_InputBoxGetString(n->T("Enter a new PSP nickname"), g_Config.sNickName, [](const std::string &value, int) {
+ g_Config.sNickName = StripSpaces(value);
});
#endif
return UI::EVENT_DONE;
@@ -1723,10 +1711,8 @@ UI::EventReturn GameSettingsScreen::OnSysInfo(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeSearchFilter(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__)
auto se = GetI18NCategory("Search");
- System_InputBoxGetString(se->T("Search term"), searchFilter_, [](bool result, const std::string &value) {
- if (result) {
- NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str());
- }
+ System_InputBoxGetString(se->T("Search term"), searchFilter_, [](const std::string &value, int) {
+ NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str());
});
#else
if (!System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
@@ -2098,10 +2084,8 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) {
UI::EventReturn HostnameSelectScreen::OnEditClick(UI::EventParams& e) {
auto n = GetI18NCategory("Networking");
#if PPSSPP_PLATFORM(ANDROID)
- System_InputBoxGetString(n->T("proAdhocServer Address:"), addrView_->GetText(), [this](bool result, const std::string& value) {
- if (result) {
- addrView_->SetText(value);
- }
+ System_InputBoxGetString(n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) {
+ addrView_->SetText(value);
});
#endif
return UI::EVENT_DONE;
diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp
index 265be6bf68..5bf8c83d6f 100644
--- a/UI/MemStickScreen.cpp
+++ b/UI/MemStickScreen.cpp
@@ -26,6 +26,7 @@
#include "Common/StringUtils.h"
#include "Common/System/System.h"
+#include "Common/System/Request.h"
#include "Common/System/NativeApp.h"
#include "Common/System/Display.h"
#include "Common/Data/Text/I18n.h"
@@ -336,64 +337,62 @@ UI::EventReturn MemStickScreen::SetFolderManually(UI::EventParams ¶ms) {
// The old way, from before scoped storage.
#if PPSSPP_PLATFORM(ANDROID)
auto sy = GetI18NCategory("System");
- System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](bool result, const std::string &value) {
+ System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](const std::string &value, int) {
auto sy = GetI18NCategory("System");
auto di = GetI18NCategory("Dialog");
- if (result) {
- std::string newPath = value;
- size_t pos = newPath.find_last_not_of("/");
- // Gotta have at least something but a /, and also needs to start with a /.
- if (newPath.empty() || pos == newPath.npos || newPath[0] != '/') {
- settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr);
- return;
- }
- if (pos != newPath.size() - 1) {
- newPath = newPath.substr(0, pos + 1);
- }
+ std::string newPath = value;
+ size_t pos = newPath.find_last_not_of("/");
+ // Gotta have at least something but a /, and also needs to start with a /.
+ if (newPath.empty() || pos == newPath.npos || newPath[0] != '/') {
+ settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr);
+ return;
+ }
+ if (pos != newPath.size() - 1) {
+ newPath = newPath.substr(0, pos + 1);
+ }
- if (newPath.empty()) {
- // Reuse below message instead of adding yet another string.
- System_Toast(sy->T("Path does not exist!"));
- return;
- }
+ if (newPath.empty()) {
+ // Reuse below message instead of adding yet another string.
+ System_Toast(sy->T("Path does not exist!"));
+ return;
+ }
- Path pendingMemStickFolder(newPath);
+ Path pendingMemStickFolder(newPath);
- if (!File::Exists(pendingMemStickFolder)) {
- // Try to fix the path string, apparently some users got used to leaving out the /.
- if (newPath[0] != '/') {
- newPath = "/" + newPath;
- }
+ if (!File::Exists(pendingMemStickFolder)) {
+ // Try to fix the path string, apparently some users got used to leaving out the /.
+ if (newPath[0] != '/') {
+ newPath = "/" + newPath;
+ }
- pendingMemStickFolder = Path(newPath);
- }
+ pendingMemStickFolder = Path(newPath);
+ }
- if (!File::Exists(pendingMemStickFolder) && pendingMemStickFolder.Type() == PathType::NATIVE) {
- // Still no path? Try to automatically fix the case.
- std::string oldNewPath = newPath;
- FixPathCase(Path(""), newPath, FixPathCaseBehavior::FPC_FILE_MUST_EXIST);
- if (oldNewPath != newPath) {
- NOTICE_LOG(IO, "Fixed path case: %s -> %s", oldNewPath.c_str(), newPath.c_str());
- pendingMemStickFolder = Path(newPath);
- } else {
- NOTICE_LOG(IO, "Failed to fix case of path %s (result: %s)", newPath.c_str(), oldNewPath.c_str());
- }
- }
+ if (!File::Exists(pendingMemStickFolder) && pendingMemStickFolder.Type() == PathType::NATIVE) {
+ // Still no path? Try to automatically fix the case.
+ std::string oldNewPath = newPath;
+ FixPathCase(Path(""), newPath, FixPathCaseBehavior::FPC_FILE_MUST_EXIST);
+ if (oldNewPath != newPath) {
+ NOTICE_LOG(IO, "Fixed path case: %s -> %s", oldNewPath.c_str(), newPath.c_str());
+ pendingMemStickFolder = Path(newPath);
+ } else {
+ NOTICE_LOG(IO, "Failed to fix case of path %s (result: %s)", newPath.c_str(), oldNewPath.c_str());
+ }
+ }
- if (pendingMemStickFolder == g_Config.memStickDirectory) {
- // Same directory as before - all good. Nothing to do.
- TriggerFinish(DialogResult::DR_OK);
- return;
- }
+ if (pendingMemStickFolder == g_Config.memStickDirectory) {
+ // Same directory as before - all good. Nothing to do.
+ TriggerFinish(DialogResult::DR_OK);
+ return;
+ }
- if (!File::Exists(pendingMemStickFolder)) {
- System_Toast(sy->T("Path does not exist!"));
- return;
- }
+ if (!File::Exists(pendingMemStickFolder)) {
+ System_Toast(sy->T("Path does not exist!"));
+ return;
+ }
- screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false));
- }
+ screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false));
});
#endif
return UI::EVENT_DONE;
diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp
index 75ab082de1..35503efce0 100644
--- a/UI/NativeApp.cpp
+++ b/UI/NativeApp.cpp
@@ -58,8 +58,10 @@
#include "android/jni/app-android.h"
#include "Common/System/Display.h"
+#include "Common/System/Request.h"
#include "Common/System/System.h"
#include "Common/System/NativeApp.h"
+
#include "Common/Data/Text/I18n.h"
#include "Common/Input/InputState.h"
#include "Common/Math/math_util.h"
@@ -164,15 +166,8 @@ struct PendingMessage {
std::string value;
};
-struct PendingInputBox {
- std::function cb;
- bool result;
- std::string value;
-};
-
static std::mutex pendingMutex;
static std::vector pendingMessages;
-static std::vector pendingInputBoxes;
static Draw::DrawContext *g_draw;
static Draw::Pipeline *colorPipeline;
static Draw::Pipeline *texColorPipeline;
@@ -443,7 +438,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
setlocale( LC_ALL, "C" );
std::string user_data_path = savegame_dir;
pendingMessages.clear();
- pendingInputBoxes.clear();
+ g_requestManager.Clear();
// external_dir has all kinds of meanings depending on platform.
// on iOS it's even the path to bundled app assets. It's a mess.
@@ -1248,22 +1243,18 @@ void NativeUpdate() {
PROFILE_END_FRAME();
std::vector toProcess;
- std::vector inputToProcess;
{
std::lock_guard lock(pendingMutex);
toProcess = std::move(pendingMessages);
- inputToProcess = std::move(pendingInputBoxes);
pendingMessages.clear();
- pendingInputBoxes.clear();
}
for (const auto &item : toProcess) {
HandleGlobalMessage(item.msg, item.value);
g_screenManager->sendMessage(item.msg.c_str(), item.value.c_str());
}
- for (const auto &item : inputToProcess) {
- item.cb(item.result, item.value);
- }
+
+ g_requestManager.ProcessRequests();
g_DownloadManager.Update();
g_screenManager->update();
@@ -1396,15 +1387,6 @@ void NativeMessageReceived(const char *message, const char *value) {
pendingMessages.push_back(pendingMessage);
}
-void NativeInputBoxReceived(std::function cb, bool result, const std::string &value) {
- std::lock_guard lock(pendingMutex);
- PendingInputBox pendingMessage;
- pendingMessage.cb = cb;
- pendingMessage.result = result;
- pendingMessage.value = value;
- pendingInputBoxes.push_back(pendingMessage);
-}
-
void NativeResized() {
// NativeResized can come from any thread so we just set a flag, then process it later.
VERBOSE_LOG(G3D, "NativeResized - setting flag");
diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp
index 98cea5ea85..d14c9999d4 100644
--- a/UI/RemoteISOScreen.cpp
+++ b/UI/RemoteISOScreen.cpp
@@ -31,6 +31,7 @@
#include "Common/Net/Resolve.h"
#include "Common/Net/URL.h"
#include "Common/Thread/ThreadUtil.h"
+#include "Common/System/Request.h"
#include "Common/File/PathBrowser.h"
#include "Common/Data/Format/JSONReader.h"
@@ -38,7 +39,6 @@
#include "Common/Common.h"
#include "Common/Log.h"
#include "Common/StringUtils.h"
-#include "Common/System/System.h"
#include "Common/TimeUtil.h"
#include "Core/Config.h"
#include "Core/System.h"
@@ -643,7 +643,7 @@ void RemoteISOSettingsScreen::CreateViews() {
UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteServer(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__)
auto ri = GetI18NCategory("RemoteISO");
- System_InputBoxGetString(ri->T("Remote Server"), g_Config.sLastRemoteISOServer, [](bool result, const std::string &value) {
+ System_InputBoxGetString(ri->T("Remote Server"), g_Config.sLastRemoteISOServer, [](const std::string &value, int) {
g_Config.sLastRemoteISOServer = value;
});
#endif
@@ -663,7 +663,7 @@ static void CleanupRemoteISOSubdir() {
UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteISOSubdir(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__)
auto ri = GetI18NCategory("RemoteISO");
- System_InputBoxGetString(ri->T("Remote Subdirectory"), g_Config.sRemoteISOSubdir, [](bool result, const std::string &value) {
+ System_InputBoxGetString(ri->T("Remote Subdirectory"), g_Config.sRemoteISOSubdir, [](const std::string &value, int) {
g_Config.sRemoteISOSubdir = value;
// Apply the cleanup logic, too.
CleanupRemoteISOSubdir();
diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp
index 0d04ac02b9..c7ab4b7136 100644
--- a/UI/SavedataScreen.cpp
+++ b/UI/SavedataScreen.cpp
@@ -24,7 +24,7 @@
#include "Common/Data/Text/I18n.h"
#include "Common/Math/curves.h"
#include "Common/System/NativeApp.h"
-#include "Common/System/System.h"
+#include "Common/System/Request.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/UI/Context.h"
#include "Common/UI/View.h"
@@ -674,8 +674,8 @@ UI::EventReturn SavedataScreen::OnSortClick(UI::EventParams &e) {
UI::EventReturn SavedataScreen::OnSearch(UI::EventParams &e) {
auto di = GetI18NCategory("Dialog");
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__)
- System_InputBoxGetString(di->T("Filter"), searchFilter_, [](bool result, const std::string &value) {
- if (result) {
+ System_InputBoxGetString(di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) {
+ if (ivalue) {
NativeMessageReceived("savedatascreen_search", value.c_str());
}
});
diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp
index 1529a18887..39e27cbf56 100644
--- a/UWP/PPSSPP_UWPMain.cpp
+++ b/UWP/PPSSPP_UWPMain.cpp
@@ -443,6 +443,8 @@ void System_Notify(SystemNotification notification) {
}
}
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; }
+
void System_SendMessage(const char *command, const char *parameter) {
using namespace concurrency;
diff --git a/Windows/main.cpp b/Windows/main.cpp
index 7db15f7b81..15fd6891d0 100644
--- a/Windows/main.cpp
+++ b/Windows/main.cpp
@@ -34,6 +34,7 @@
#include "Common/System/Display.h"
#include "Common/System/NativeApp.h"
#include "Common/System/System.h"
+#include "Common/System/Request.h"
#include "Common/File/FileUtil.h"
#include "Common/File/VFS/VFS.h"
#include "Common/File/VFS/DirectoryReader.h"
@@ -109,8 +110,8 @@ static std::string restartArgs;
int g_activeWindow = 0;
-static std::thread inputBoxThread;
-static bool inputBoxRunning = false;
+static std::thread g_inputBoxThread;
+static bool g_inputBoxRunning = false;
int g_lastNumInstances = 0;
void System_ShowFileInFolder(const char *path) {
@@ -376,12 +377,13 @@ static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, L
return PostMessage(dialog->GetDlgHandle(), message, wParam, lParam);
}
+// This can come from any thread, so this mostly uses PostMessage. Can't access most data directly.
void System_Notify(SystemNotification notification) {
switch (notification) {
case SystemNotification::BOOT_DONE:
{
if (g_symbolMap)
- g_symbolMap->SortSymbols();
+ g_symbolMap->SortSymbols(); // internal locking is performed here
PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0);
if (disasmWindow)
@@ -413,7 +415,7 @@ void System_Notify(SystemNotification notification) {
case SystemNotification::SYMBOL_MAP_UPDATED:
if (g_symbolMap)
- g_symbolMap->SortSymbols();
+ g_symbolMap->SortSymbols(); // internal locking is performed here
PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0);
break;
@@ -428,6 +430,28 @@ void System_Notify(SystemNotification notification) {
}
}
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) {
+ switch (type) {
+ case SystemRequestType::INPUT_TEXT_MODAL:
+ if (g_inputBoxRunning) {
+ g_inputBoxThread.join();
+ }
+
+ g_inputBoxRunning = true;
+ g_inputBoxThread = std::thread([=] {
+ std::string out;
+ if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), param2, out)) {
+ g_requestManager.PostSystemSuccess(requestId, out.c_str());
+ } else {
+ g_requestManager.PostSystemFailure(requestId);
+ }
+ });
+ return true;
+ default:
+ return false;
+ }
+}
+
void System_SendMessage(const char *command, const char *parameter) {
if (!strcmp(command, "finish")) {
if (!NativeIsRestarting()) {
@@ -497,42 +521,6 @@ void EnableCrashingOnCrashes() {
FreeLibrary(kernel32);
}
-void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) {
- if (inputBoxRunning) {
- inputBoxThread.join();
- }
-
- inputBoxRunning = true;
- inputBoxThread = std::thread([=] {
- std::string out;
- if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) {
- NativeInputBoxReceived(cb, true, out);
- } else {
- NativeInputBoxReceived(cb, false, "");
- }
- });
-}
-
-bool System_PerformRequest(SystemRequestType type, int requestId, const char *param1, const char *param2) {
- switch (type) {
- case SystemRequestType::INPUT_TEXT_MODAL:
- if (inputBoxRunning) {
- inputBoxThread.join();
- }
-
- inputBoxRunning = true;
- inputBoxThread = std::thread([=] {
- std::string out;
- if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) {
- NativeInputBoxReceived(cb, true, out);
- } else {
- NativeInputBoxReceived(cb, false, "");
- }
- });
- }
-}
-
-
void System_Toast(const char *text) {
// Not-very-good implementation. Will normally not be used on Windows anyway.
std::wstring str = ConvertUTF8ToWString(text);
@@ -639,9 +627,9 @@ static void WinMainInit() {
}
static void WinMainCleanup() {
- if (inputBoxRunning) {
- inputBoxThread.join();
- inputBoxRunning = false;
+ if (g_inputBoxRunning) {
+ g_inputBoxThread.join();
+ g_inputBoxRunning = false;
}
net::Shutdown();
CoUninitialize();
diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp
index 65a483e519..6a9e42a829 100644
--- a/android/jni/app-android.cpp
+++ b/android/jni/app-android.cpp
@@ -61,6 +61,7 @@ struct JNIEnv {};
#include "Common/System/Display.h"
#include "Common/System/NativeApp.h"
#include "Common/System/System.h"
+#include "Common/System/Request.h"
#include "Common/Thread/ThreadUtil.h"
#include "Common/File/Path.h"
#include "Common/File/DirListing.h"
@@ -175,9 +176,6 @@ static std::atomic renderLoopRunning;
static bool renderer_inited = false;
static std::mutex renderLock;
-static int inputBoxSequence = 1;
-static std::map> inputBoxCallbacks;
-
static bool sustainedPerfSupported = false;
static std::map permissions;
@@ -909,7 +907,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
{
std::lock_guard guard(renderLock);
- inputBoxCallbacks.clear();
NativeShutdown();
g_VFS.Clear();
}
@@ -1032,12 +1029,17 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv
}
}
-void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) {
- int seq = inputBoxSequence++;
- inputBoxCallbacks[seq] = cb;
-
- std::string serialized = StringFromFormat("%d:@:%s:@:%s", seq, title.c_str(), defaultValue.c_str());
- System_SendMessage("inputbox", serialized.c_str());
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) {
+ switch (type) {
+ case SystemRequestType::INPUT_TEXT_MODAL:
+ {
+ std::string serialized = StringFromFormat("%d:@:%s:@:%s", requestId, param1.c_str(), param2.c_str());
+ PushCommand("inputbox", serialized.c_str());
+ return true;
+ }
+ default:
+ return false;
+ }
}
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendInputBox(JNIEnv *env, jclass, jstring jseqID, jboolean result, jstring jvalue) {
@@ -1058,13 +1060,11 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendInputBox(JNIEnv *en
return;
}
- auto entry = inputBoxCallbacks.find(seq);
- if (entry == inputBoxCallbacks.end()) {
- ERROR_LOG(SYSTEM, "Did not find inputbox callback for %s, shutdown?", seqID.c_str());
- return;
+ if (result) {
+ g_requestManager.PostSystemSuccess(seq, value.c_str());
+ } else {
+ g_requestManager.PostSystemFailure(seq);
}
-
- NativeInputBoxReceived(entry->second, result, value);
}
void LockedNativeUpdateRender() {
diff --git a/headless/Headless.cpp b/headless/Headless.cpp
index 27e0508e64..8d6ae20519 100644
--- a/headless/Headless.cpp
+++ b/headless/Headless.cpp
@@ -116,6 +116,7 @@ bool System_GetPropertyBool(SystemProperty prop) {
}
void System_Notify(SystemNotification notification) {}
void System_SendMessage(const char *command, const char *parameter) {}
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { 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; }
diff --git a/ios/main.mm b/ios/main.mm
index 155bf79995..3caaf93e26 100644
--- a/ios/main.mm
+++ b/ios/main.mm
@@ -219,6 +219,10 @@ void System_SendMessage(const char *command, const char *parameter) {
}
}
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) {
+ return false;
+}
+
void System_Toast(const char *text) {}
void System_AskForPermission(SystemPermission permission) {}
diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp
index 05b13dcdbf..cdb699bb56 100644
--- a/libretro/libretro.cpp
+++ b/libretro/libretro.cpp
@@ -1874,7 +1874,7 @@ void System_Notify(SystemNotification notification) {
break;
}
}
-
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; }
void System_SendMessage(const char *command, const char *parameter) {}
void NativeUpdate() {}
void NativeRender(GraphicsContext *graphicsContext) {}
diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp
index ebbcdefa39..f730cc44d6 100644
--- a/unittest/JitHarness.cpp
+++ b/unittest/JitHarness.cpp
@@ -42,6 +42,7 @@ void NativeRender(GraphicsContext *graphicsContext) { }
void NativeResized() { }
void System_SendMessage(const char *command, const char *parameter) {}
+bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { 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; }