mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
Fix a particular type of race condition in file dialog requests
It seems to be possible for a user to back out of a screen before receiving the "dialog completed" callback on Android, in which case things pointed to by the callback might be gone. In this case, it's better to simply not call the callback, rather than crashing. This is accomplished by assigning "Tokens" to screens that cause requests, and in ~Screen, invalidate any pending requests belonging to that token.
This commit is contained in:
parent
b4122ef1f4
commit
1304d04161
@ -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<std::mutex> 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<std::mutex> guard(callbackMutex_);
|
||||
auto iter = callbackMap_.find(requestId);
|
||||
@ -82,7 +100,7 @@ void RequestManager::PostSystemFailure(int requestId) {
|
||||
|
||||
std::lock_guard<std::mutex> 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);
|
||||
}
|
||||
|
@ -12,6 +12,10 @@ class Path;
|
||||
typedef std::function<void(const char *responseString, int responseValue)> RequestCallback;
|
||||
typedef std::function<void()> 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 @@ public:
|
||||
// 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 @@ public:
|
||||
// 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<int, CallbackPair> callbackMap_;
|
||||
@ -58,7 +64,7 @@ private:
|
||||
};
|
||||
|
||||
struct PendingFailure {
|
||||
RequestFailedCallback callback;
|
||||
RequestFailedCallback failedCallback;
|
||||
};
|
||||
|
||||
// Let's start at 10 to get a recognizably valid ID in logs.
|
||||
@ -66,6 +72,8 @@ private:
|
||||
std::vector<PendingSuccess> pendingSuccesses_;
|
||||
std::vector<PendingFailure> 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
|
||||
|
@ -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{};
|
||||
|
@ -360,7 +360,7 @@ private:
|
||||
// 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 @@ protected:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
private:
|
||||
std::string *value_;
|
||||
BrowseFileType fileType_;
|
||||
RequesterToken token_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace UI
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 @@ public:
|
||||
|
||||
virtual TouchInput transformTouch(const TouchInput &touch) { return touch; }
|
||||
|
||||
protected:
|
||||
int GetRequesterToken();
|
||||
|
||||
private:
|
||||
ScreenManager *screenManager_;
|
||||
int token_ = -1;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Screen);
|
||||
};
|
||||
|
||||
|
@ -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<std::mutex> guard(nativeMutex_);
|
||||
|
@ -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;
|
||||
|
@ -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 @@ private:
|
||||
int chatChangeID_ = 0;
|
||||
bool toBottom_ = true;
|
||||
bool promptInput_ = false;
|
||||
int token_;
|
||||
};
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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 @@ private:
|
||||
float lastScale_ = 1.0f;
|
||||
bool lastLayoutWasGrid_ = true;
|
||||
ScreenManager *screenManager_;
|
||||
int token_;
|
||||
};
|
||||
|
||||
class RemoteISOBrowseScreen;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<std::string> 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" };
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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;
|
||||
|
@ -2,12 +2,14 @@
|
||||
|
||||
#include "Common/CommonWindows.h"
|
||||
#include <Windowsx.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -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<void(bool, const std::string &)> 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'; }
|
||||
|
@ -1750,7 +1750,6 @@ std::vector<std::string> System_GetCameraDeviceList() { return std::vector<std::
|
||||
bool System_AudioRecordingIsAvailable() { return false; }
|
||||
bool System_AudioRecordingState() { return false; }
|
||||
|
||||
void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function<void(bool, const std::string &)> cb) { cb(false, ""); }
|
||||
#endif
|
||||
|
||||
// TODO: To avoid having to define these here, these should probably be turned into system "requests".
|
||||
|
Loading…
Reference in New Issue
Block a user