Make a little system to replace the InputBox message queue with something more generic

This commit is contained in:
Henrik Rydgård committed 2023-03-22 11:35:57 +01:00
1 parent 94debfbf36
commit 3852d4f698
6 files changed
+143

No files matched your search

+2
View File
@@ -550,6 +550,7 @@
<ClInclude Include="Swap.h" />
<ClInclude Include="SysError.h" />
<ClInclude Include="System\Display.h" />
<ClInclude Include="System\Message.h" />
<ClInclude Include="System\NativeApp.h" />
<ClInclude Include="System\System.h" />
<ClInclude Include="Thread\Barrier.h" />
@@ -1005,6 +1006,7 @@
<ClCompile Include="OSVersion.cpp" />
<ClCompile Include="StringUtils.cpp" />
<ClCompile Include="System\Display.cpp" />
<ClCompile Include="System\Message.cpp" />
<ClCompile Include="Thread\ParallelLoop.cpp" />
<ClCompile Include="Thread\ThreadManager.cpp" />
<ClCompile Include="Thread\ThreadUtil.cpp" />
+6
View File
@@ -494,6 +494,9 @@
<ClInclude Include="..\ext\basis_universal\basisu_transcoder_uastc.h">
<Filter>ext\basis_universal</Filter>
</ClInclude>
<ClInclude Include="System\Message.h">
<Filter>System</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ABI.cpp" />
@@ -920,6 +923,9 @@
<ClCompile Include="..\ext\basis_universal\basisu_transcoder.cpp">
<Filter>ext\basis_universal</Filter>
</ClCompile>
<ClCompile Include="System\Message.cpp">
<Filter>System</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="Crypto">
+55
View File
@@ -0,0 +1,55 @@
#include "Common/System/Message.h"
#include "Common/System/System.h"
#include "Common/Log.h"
RequestManager g_RequestManager;
const char *RequestTypeAsString(SystemRequestType type) {
switch (type) {
case SystemRequestType::INPUT_TEXT_MODAL: return "INPUT_TEXT_MODAL";
default: return "N/A";
}
}
bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const char *param1, const char *param2) {
int requestId = idCounter_++;
if (!System_MakeRequest(type, requestId, param1, param2)) {
return false;
}
if (!callback) {
// We don't expect a response, this is a one-directional request. We're thus done.
return true;
}
std::lock_guard<std::mutex> guard(callbackMutex_);
callbackMap_[requestId] = callback;
return true;
}
void RequestManager::PostSystemResponse(int requestId, const char *responseString, int responseValue) {
std::lock_guard<std::mutex> 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);
return;
}
std::lock_guard<std::mutex> responseGuard(responseMutex_);
PendingResponse response;
response.callback = iter->second;
response.responseString = responseString;
response.responseValue = responseValue;
pendingResponses_.push_back(response);
}
void RequestManager::ProcessRequests() {
std::lock_guard<std::mutex> guard(responseMutex_);
for (auto &iter : pendingResponses_) {
if (iter.callback) {
iter.callback(iter.responseString.c_str(), iter.responseValue);
}
}
pendingResponses_.clear();
}
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include <vector>
#include <mutex>
#include <map>
#include <functional>
#include "Common/System/System.h"
typedef std::function<void(const char *responseString, int responseValue)> RequestCallback;
// Platforms often have to process requests asynchronously, on wildly different threads.
// (Especially Android...)
// This acts as bridge and buffer.
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);
// Called by the platform implementation, when it's finished with a request.
void PostSystemResponse(int requestId, const char *responseString, int responseValue);
// This must be called every frame from the beginning of NativeUpdate().
// This will call the callback of any finished requests.
void ProcessRequests();
private:
struct PendingRequest {
SystemRequestType type;
RequestCallback callback;
};
std::map<int, RequestCallback> callbackMap_;
std::mutex callbackMutex_;
struct PendingResponse {
std::string responseString;
int responseValue;
RequestCallback callback;
};
int idCounter_ = 0;
std::vector<PendingResponse> pendingResponses_;
std::mutex responseMutex_;
};
const char *RequestTypeAsString(SystemRequestType type);
extern RequestManager g_RequestManager;
+10
View File
@@ -146,6 +146,16 @@ 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<std::string> System_GetPropertyStringVec(SystemProperty prop);
int System_GetPropertyInt(SystemProperty prop);
+20
View File
@@ -513,6 +513,26 @@ void System_InputBoxGetString(const std::string &title, const std::string &defau
});
}
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);