mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #12691 from unknownbrackets/inputbox
Android: Process input prompts more clearly
This commit is contained in:
commit
4501045224
14 changed files with 204 additions and 208 deletions
|
@ -15,9 +15,10 @@
|
|||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <algorithm>
|
||||
#include "i18n/i18n.h"
|
||||
#include "math/math_util.h"
|
||||
#include <algorithm>
|
||||
#include "util/text/utf8.h"
|
||||
|
||||
#include "Core/Dialog/PSPOskDialog.h"
|
||||
#include "Core/Util/PPGeDraw.h"
|
||||
|
@ -853,14 +854,19 @@ int PSPOskDialog::NativeKeyboard() {
|
|||
if (defaultText.empty())
|
||||
defaultText.assign(L"VALUE");
|
||||
|
||||
if (System_InputBoxGetWString(titleText.c_str(), defaultText, inputChars)) {
|
||||
u32 maxLength = FieldMaxLength();
|
||||
if (inputChars.length() > maxLength) {
|
||||
ERROR_LOG(SCEUTILITY, "NativeKeyboard: input text too long(%d characters/glyphs max), truncating to game-requested length.", maxLength);
|
||||
inputChars.erase(maxLength, std::string::npos);
|
||||
// TODO: This is USING_WIN_UI only, so we rely on it being synchronous...
|
||||
// But we should really have this set some state that is checked each time NativeKeyboard is called.
|
||||
System_InputBoxGetString(ConvertWStringToUTF8(titleText), ConvertWStringToUTF8(defaultText), [&](bool result, const std::string &value) {
|
||||
if (result) {
|
||||
inputChars = ConvertUTF8ToWString(value);
|
||||
u32 maxLength = FieldMaxLength();
|
||||
if (inputChars.length() > maxLength) {
|
||||
ERROR_LOG(SCEUTILITY, "NativeKeyboard: input text too long(%d characters/glyphs max), truncating to game-requested length.", maxLength);
|
||||
inputChars.erase(maxLength, std::string::npos);
|
||||
}
|
||||
}
|
||||
}
|
||||
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
|
||||
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
|
||||
});
|
||||
|
||||
u16_le *outText = oskParams->fields[0].outtext;
|
||||
|
||||
|
|
|
@ -227,13 +227,13 @@ void System_SendMessage(const char *command, const char *parameter) {
|
|||
void System_AskForPermission(SystemPermission permission) {}
|
||||
PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; }
|
||||
|
||||
bool System_InputBoxGetString(const char *title, const char *defaultValue, char *outValue, size_t outLength)
|
||||
{
|
||||
QString text = emugl->InputBoxGetQString(QString(title), QString(defaultValue));
|
||||
if (text.isEmpty())
|
||||
return false;
|
||||
strcpy(outValue, text.toStdString().c_str());
|
||||
return true;
|
||||
void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function<void(bool, const std::string &)> cb) {
|
||||
QString text = emugl->InputBoxGetQString(QString::fromStdString(title), QString::fromStdString(defaultValue));
|
||||
if (text.isEmpty()) {
|
||||
cb(false, "");
|
||||
} else {
|
||||
cb(true, text.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
void Vibrate(int length_ms) {
|
||||
|
|
|
@ -26,13 +26,11 @@ void ChatMenu::CreatePopupContents(UI::ViewGroup *parent) {
|
|||
#if defined(USING_WIN_UI)
|
||||
//freeze the ui when using ctrl + C hotkey need workaround
|
||||
if (g_Config.bBypassOSKWithKeyboard && !g_Config.bFullScreen) {
|
||||
std::wstring titleText = ConvertUTF8ToWString(n->T("Chat"));
|
||||
std::wstring defaultText = ConvertUTF8ToWString(n->T("Chat Here"));
|
||||
std::wstring inputChars;
|
||||
if (System_InputBoxGetWString(titleText.c_str(), defaultText, inputChars)) {
|
||||
//chatEdit_->SetText(ConvertWStringToUTF8(inputChars));
|
||||
sendChat(ConvertWStringToUTF8(inputChars));
|
||||
}
|
||||
System_InputBoxGetString(n->T("Chat"), n->T("Chat Here"), [](bool result, const std::string &value) {
|
||||
if (result) {
|
||||
sendChat(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
chatEdit_->OnEnter.Handle(this, &ChatMenu::OnSubmit);
|
||||
|
@ -123,7 +121,10 @@ UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) {
|
|||
chatEdit_->SetFocus();
|
||||
sendChat(chat);
|
||||
#elif PPSSPP_PLATFORM(ANDROID)
|
||||
System_SendMessage("inputbox", "Chat:");
|
||||
auto n = GetI18NCategory("Networking");
|
||||
System_InputBoxGetString(n->T("Chat"), "", [](bool result, const std::string &value) {
|
||||
sendChat(value);
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
|
|
@ -265,13 +265,6 @@ void GameSettingsScreen::CreateViews() {
|
|||
softwareGPU->SetEnabled(false);
|
||||
}
|
||||
|
||||
std::vector<std::string> cameraList = Camera::getDeviceList();
|
||||
if (cameraList.size() >= 1) {
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Camera")));
|
||||
PopupMultiChoiceDynamic *cameraChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sCameraDevice, gr->T("Camera Device"), cameraList, nullptr, screenManager()));
|
||||
cameraChoice->OnChoice.Handle(this, &GameSettingsScreen::OnCameraDeviceChange);
|
||||
}
|
||||
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Frame Rate Control")));
|
||||
static const char *frameSkip[] = {"Off", "1", "2", "3", "4", "5", "6", "7", "8"};
|
||||
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iFrameSkip, gr->T("Frame Skipping"), frameSkip, 0, ARRAY_SIZE(frameSkip), gr->GetName(), screenManager()));
|
||||
|
@ -472,6 +465,13 @@ void GameSettingsScreen::CreateViews() {
|
|||
cardboardYShift->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
||||
#endif
|
||||
|
||||
std::vector<std::string> cameraList = Camera::getDeviceList();
|
||||
if (cameraList.size() >= 1) {
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Camera")));
|
||||
PopupMultiChoiceDynamic *cameraChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sCameraDevice, gr->T("Camera Device"), cameraList, nullptr, screenManager()));
|
||||
cameraChoice->OnChoice.Handle(this, &GameSettingsScreen::OnCameraDeviceChange);
|
||||
}
|
||||
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Hack Settings", "Hack Settings (these WILL cause glitches)")));
|
||||
|
||||
static const char *bloomHackOptions[] = { "Off", "Safe", "Balanced", "Aggressive" };
|
||||
|
@ -982,7 +982,32 @@ UI::EventReturn GameSettingsScreen::OnJitAffectingSetting(UI::EventParams &e) {
|
|||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeMemStickDir(UI::EventParams &e) {
|
||||
auto sy = GetI18NCategory("System");
|
||||
System_SendMessage("inputbox", (std::string(sy->T("Memory Stick Folder")) + ":" + g_Config.memStickDirectory).c_str());
|
||||
System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory, [&](bool result, const std::string &value) {
|
||||
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);
|
||||
}
|
||||
|
||||
pendingMemstickFolder_ = newPath;
|
||||
std::string promptMessage = sy->T("ChangingMemstickPath", "Save games, save states, and other data will not be copied to this folder.\n\nChange the Memory Stick folder?");
|
||||
if (!File::Exists(newPath)) {
|
||||
promptMessage = sy->T("ChangingMemstickPathNotExists", "That folder doesn't exist yet.\n\nSave games, save states, and other data will not be copied to this folder.\n\nCreate a new Memory Stick folder?");
|
||||
}
|
||||
// Add the path for clarity and proper confirmation.
|
||||
promptMessage += "\n\n" + newPath + "/";
|
||||
screenManager()->push(new PromptScreen(promptMessage, di->T("Yes"), di->T("No"), std::bind(&GameSettingsScreen::CallbackMemstickFolder, this, std::placeholders::_1)));
|
||||
}
|
||||
});
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
|
@ -1139,43 +1164,6 @@ void GameSettingsScreen::onFinish(DialogResult result) {
|
|||
NativeMessageReceived("gpu_clearCache", "");
|
||||
}
|
||||
|
||||
void GameSettingsScreen::sendMessage(const char *message, const char *value) {
|
||||
UIDialogScreenWithGameBackground::sendMessage(message, value);
|
||||
|
||||
auto sy = GetI18NCategory("System");
|
||||
auto di = GetI18NCategory("Dialog");
|
||||
|
||||
if (!strcmp(message, "inputbox_completed")) {
|
||||
std::vector<std::string> inputboxValue;
|
||||
SplitString(value, ':', inputboxValue);
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
if (inputboxValue.size() >= 2 && inputboxValue[0] == sy->T("Memory Stick Folder")) {
|
||||
// Allow colons in the path.
|
||||
std::string newPath = std::string(value).substr(inputboxValue[0].size() + 1);
|
||||
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);
|
||||
}
|
||||
|
||||
pendingMemstickFolder_ = newPath;
|
||||
std::string promptMessage = sy->T("ChangingMemstickPath", "Save games, save states, and other data will not be copied to this folder.\n\nChange the Memory Stick folder?");
|
||||
if (!File::Exists(newPath)) {
|
||||
promptMessage = sy->T("ChangingMemstickPathNotExists", "That folder doesn't exist yet.\n\nSave games, save states, and other data will not be copied to this folder.\n\nCreate a new Memory Stick folder?");
|
||||
}
|
||||
// Add the path for clarity and proper confirmation.
|
||||
promptMessage += "\n\n" + newPath + "/";
|
||||
screenManager()->push(new PromptScreen(promptMessage, di->T("Yes"), di->T("No"), std::bind(&GameSettingsScreen::CallbackMemstickFolder, this, std::placeholders::_1)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
void GameSettingsScreen::CallbackMemstickFolder(bool yes) {
|
||||
auto sy = GetI18NCategory("System");
|
||||
|
@ -1289,98 +1277,73 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) {
|
|||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
|
||||
const size_t chat_len = 64;
|
||||
|
||||
char chat[chat_len];
|
||||
memset(chat, 0, sizeof(chat));
|
||||
|
||||
if (System_InputBoxGetString("Enter Quick Chat 1", g_Config.sQuickChat0.c_str(), chat, chat_len)) {
|
||||
g_Config.sQuickChat0 = chat;
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
System_SendMessage("inputbox", ("quickchat0:" + g_Config.sQuickChat0).c_str());
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__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;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
|
||||
const size_t chat_len = 64;
|
||||
|
||||
char chat[chat_len];
|
||||
memset(chat, 0, sizeof(chat));
|
||||
|
||||
if (System_InputBoxGetString("Enter Quick Chat 2", g_Config.sQuickChat1.c_str(), chat, chat_len)) {
|
||||
g_Config.sQuickChat1 = chat;
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
System_SendMessage("inputbox", ("quickchat1:" + g_Config.sQuickChat1).c_str());
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__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;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
|
||||
const size_t chat_len = 64;
|
||||
|
||||
char chat[chat_len];
|
||||
memset(chat, 0, sizeof(chat));
|
||||
|
||||
if (System_InputBoxGetString("Enter Quick Chat 3", g_Config.sQuickChat2.c_str(), chat, chat_len)) {
|
||||
g_Config.sQuickChat2 = chat;
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
System_SendMessage("inputbox", ("quickchat2:" + g_Config.sQuickChat2).c_str());
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__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;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
|
||||
const size_t chat_len = 64;
|
||||
|
||||
char chat[chat_len];
|
||||
memset(chat, 0, sizeof(chat));
|
||||
|
||||
if (System_InputBoxGetString("Enter Quick Chat 4", g_Config.sQuickChat3.c_str(), chat, chat_len)) {
|
||||
g_Config.sQuickChat3 = chat;
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
System_SendMessage("inputbox", ("quickchat3:" + g_Config.sQuickChat3).c_str());
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__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;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
|
||||
const size_t chat_len = 64;
|
||||
|
||||
char chat[chat_len];
|
||||
memset(chat, 0, sizeof(chat));
|
||||
|
||||
if (System_InputBoxGetString("Enter Quick Chat 5", g_Config.sQuickChat4.c_str(), chat, chat_len)) {
|
||||
g_Config.sQuickChat4 = chat;
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
System_SendMessage("inputbox", ("quickchat4:" + g_Config.sQuickChat4).c_str());
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__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;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
|
||||
const size_t name_len = 256;
|
||||
|
||||
char name[name_len];
|
||||
memset(name, 0, sizeof(name));
|
||||
|
||||
if (System_InputBoxGetString("Enter a new PSP nickname", g_Config.sNickName.c_str(), name, name_len)) {
|
||||
g_Config.sNickName = StripSpaces(name);
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
// TODO: The return value is handled in NativeApp::inputbox_completed. This is horrific.
|
||||
System_SendMessage("inputbox", ("nickname:" + g_Config.sNickName).c_str());
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__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);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
@ -1389,7 +1352,12 @@ UI::EventReturn GameSettingsScreen::OnChangeproAdhocServerAddress(UI::EventParam
|
|||
auto sy = GetI18NCategory("System");
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
System_SendMessage("inputbox", ("IP:" + g_Config.proAdhocServer).c_str());
|
||||
auto n = GetI18NCategory("Networking");
|
||||
System_InputBoxGetString(n->T("IP"), g_Config.proAdhocServer, [](bool result, const std::string &value) {
|
||||
if (result) {
|
||||
g_Config.proAdhocServer = value;
|
||||
}
|
||||
});
|
||||
#else
|
||||
screenManager()->push(new HostnameSelectScreen(&g_Config.proAdhocServer, sy->T("proAdhocServer Address:")));
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,6 @@ public:
|
|||
|
||||
void update() override;
|
||||
void onFinish(DialogResult result) override;
|
||||
void sendMessage(const char *message, const char *value) override;
|
||||
std::string tag() const override { return "settings"; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -159,13 +159,19 @@ struct PendingMessage {
|
|||
std::string value;
|
||||
};
|
||||
|
||||
struct PendingInputBox {
|
||||
std::function<void(bool, const std::string &)> cb;
|
||||
bool result;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
static std::mutex pendingMutex;
|
||||
static std::vector<PendingMessage> pendingMessages;
|
||||
static std::vector<PendingInputBox> pendingInputBoxes;
|
||||
static Draw::DrawContext *g_draw;
|
||||
static Draw::Pipeline *colorPipeline;
|
||||
static Draw::Pipeline *texColorPipeline;
|
||||
static UIContext *uiContext;
|
||||
static std::vector<std::string> inputboxValue;
|
||||
|
||||
#ifdef _WIN32
|
||||
WindowsAudioBackend *winAudioBackend;
|
||||
|
@ -445,6 +451,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();
|
||||
#ifdef IOS
|
||||
user_data_path += "/";
|
||||
#endif
|
||||
|
@ -1094,42 +1101,6 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) {
|
|||
if (msg == "inputDeviceConnected") {
|
||||
KeyMap::NotifyPadConnected(value);
|
||||
}
|
||||
if (msg == "inputbox_completed") {
|
||||
SplitString(value, ':', inputboxValue);
|
||||
std::string setString = inputboxValue.size() > 1 ? inputboxValue[1] : "";
|
||||
if (inputboxValue[0] == "IP")
|
||||
g_Config.proAdhocServer = setString;
|
||||
else if (inputboxValue[0] == "nickname")
|
||||
g_Config.sNickName = setString;
|
||||
else if (inputboxValue[0] == "remoteiso_subdir")
|
||||
g_Config.sRemoteISOSubdir = setString;
|
||||
else if (inputboxValue[0] == "remoteiso_server")
|
||||
g_Config.sLastRemoteISOServer = setString;
|
||||
|
||||
if (inputboxValue[0] == "quickchat0")
|
||||
g_Config.sQuickChat0 = setString;
|
||||
if (inputboxValue[0] == "quickchat1")
|
||||
g_Config.sQuickChat1 = setString;
|
||||
if (inputboxValue[0] == "quickchat2")
|
||||
g_Config.sQuickChat2 = setString;
|
||||
if (inputboxValue[0] == "quickchat3")
|
||||
g_Config.sQuickChat3 = setString;
|
||||
if (inputboxValue[0] == "quickchat4")
|
||||
g_Config.sQuickChat4 = setString;
|
||||
if (inputboxValue[0] == "nickname")
|
||||
g_Config.sNickName = setString;
|
||||
if (inputboxValue[0] == "Chat") {
|
||||
if (inputboxValue.size() > 2)
|
||||
{
|
||||
std::string chatString = value;
|
||||
chatString.erase(0, 5);
|
||||
sendChat(chatString);
|
||||
} else {
|
||||
sendChat(setString);
|
||||
}
|
||||
}
|
||||
inputboxValue.clear();
|
||||
}
|
||||
if (msg == "bgImage_updated") {
|
||||
if (!value.empty()) {
|
||||
std::string dest = GetSysDirectory(DIRECTORY_SYSTEM) + (endsWithNoCase(value, ".jpg") ? "background.jpg" : "background.png");
|
||||
|
@ -1184,15 +1155,21 @@ void NativeUpdate() {
|
|||
PROFILE_END_FRAME();
|
||||
|
||||
std::vector<PendingMessage> toProcess;
|
||||
std::vector<PendingInputBox> inputToProcess;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(pendingMutex);
|
||||
toProcess = std::move(pendingMessages);
|
||||
inputToProcess = std::move(pendingInputBoxes);
|
||||
pendingMessages.clear();
|
||||
pendingInputBoxes.clear();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < toProcess.size(); i++) {
|
||||
HandleGlobalMessage(toProcess[i].msg, toProcess[i].value);
|
||||
screenManager->sendMessage(toProcess[i].msg.c_str(), toProcess[i].value.c_str());
|
||||
for (const auto &item : toProcess) {
|
||||
HandleGlobalMessage(item.msg, item.value);
|
||||
screenManager->sendMessage(item.msg.c_str(), item.value.c_str());
|
||||
}
|
||||
for (const auto &item : inputToProcess) {
|
||||
item.cb(item.result, item.value);
|
||||
}
|
||||
|
||||
g_DownloadManager.Update();
|
||||
|
@ -1339,6 +1316,15 @@ void NativeMessageReceived(const char *message, const char *value) {
|
|||
pendingMessages.push_back(pendingMessage);
|
||||
}
|
||||
|
||||
void NativeInputBoxReceived(std::function<void(bool, const std::string &)> cb, bool result, const std::string &value) {
|
||||
std::lock_guard<std::mutex> 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.
|
||||
ILOG("NativeResized - setting flag");
|
||||
|
|
|
@ -520,12 +520,22 @@ void RemoteISOSettingsScreen::CreateViews() {
|
|||
}
|
||||
|
||||
UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteServer(UI::EventParams &e) {
|
||||
System_SendMessage("inputbox", ("remoteiso_server:" + g_Config.sLastRemoteISOServer).c_str());
|
||||
#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) {
|
||||
g_Config.sLastRemoteISOServer = value;
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteISOSubdir(UI::EventParams &e) {
|
||||
System_SendMessage("inputbox", ("remoteiso_subdir:" + g_Config.sRemoteISOSubdir).c_str());
|
||||
#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) {
|
||||
g_Config.sRemoteISOSubdir = value;
|
||||
});
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "stdafx.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
#include "Common/CommonWindows.h"
|
||||
#include "Common/OSVersion.h"
|
||||
|
@ -337,23 +338,12 @@ void EnableCrashingOnCrashes() {
|
|||
FreeLibrary(kernel32);
|
||||
}
|
||||
|
||||
bool System_InputBoxGetString(const char *title, const char *defaultValue, char *outValue, size_t outLength)
|
||||
{
|
||||
void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function<void(bool, const std::string &)> cb) {
|
||||
std::string out;
|
||||
if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) {
|
||||
strcpy(outValue, out.c_str());
|
||||
return true;
|
||||
cb(true, out);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue)
|
||||
{
|
||||
if (InputBox_GetWString(MainWindow::GetHInstance(), MainWindow::GetHWND(), title, defaultvalue, outvalue)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
cb(false, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,8 @@ static jmethodID postCommand;
|
|||
static jobject nativeActivity;
|
||||
static volatile bool exitRenderLoop;
|
||||
static bool renderLoopRunning;
|
||||
static int inputBoxSequence = 1;
|
||||
std::map<int, std::function<void(bool, const std::string &)>> inputBoxCallbacks;
|
||||
|
||||
static float dp_xscale = 1.0f;
|
||||
static float dp_yscale = 1.0f;
|
||||
|
@ -572,6 +574,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
|
|||
ILOG("Not shutting down renderer - not initialized");
|
||||
}
|
||||
|
||||
inputBoxCallbacks.clear();
|
||||
NativeShutdown();
|
||||
VFSShutdown();
|
||||
while (frameCommands.size())
|
||||
|
@ -667,6 +670,33 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv
|
|||
}
|
||||
}
|
||||
|
||||
void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function<void(bool, const std::string &)> 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());
|
||||
}
|
||||
|
||||
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendInputBox(JNIEnv *env, jclass, jstring jseqID, jboolean result, jstring jvalue) {
|
||||
std::string seqID = GetJavaString(env, jseqID);
|
||||
std::string value = GetJavaString(env, jvalue);
|
||||
|
||||
int seq = 0;
|
||||
if (!TryParse(seqID, &seq)) {
|
||||
ELOG("Invalid inputbox seqID value: %s", seqID.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto entry = inputBoxCallbacks.find(seq);
|
||||
if (entry == inputBoxCallbacks.end()) {
|
||||
ELOG("Did not find inputbox callback for %s, shutdown?", seqID.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
NativeInputBoxReceived(entry->second, result, value);
|
||||
}
|
||||
|
||||
void UpdateRunLoopAndroid(JNIEnv *env) {
|
||||
NativeUpdate();
|
||||
|
||||
|
|
|
@ -1169,8 +1169,8 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C
|
|||
return bld;
|
||||
}
|
||||
|
||||
// The return value is sent elsewhere. TODO in java, in SendMessage in C++.
|
||||
public void inputBox(final String title, String defaultText, String defaultAction) {
|
||||
// The return value is sent to C++ via seqID.
|
||||
public void inputBox(final String seqID, final String title, String defaultText, String defaultAction) {
|
||||
final FrameLayout fl = new FrameLayout(this);
|
||||
final EditText input = new EditText(this);
|
||||
input.setGravity(Gravity.CENTER);
|
||||
|
@ -1202,14 +1202,14 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C
|
|||
.setPositiveButton(defaultAction, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface d, int which) {
|
||||
NativeApp.sendMessage("inputbox_completed", title + ":" + input.getText().toString());
|
||||
NativeApp.sendInputBox(seqID, true, input.getText().toString());
|
||||
d.dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface d, int which) {
|
||||
NativeApp.sendMessage("inputbox_failed", "");
|
||||
NativeApp.sendInputBox(seqID, false, "");
|
||||
d.cancel();
|
||||
}
|
||||
})
|
||||
|
@ -1311,15 +1311,17 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C
|
|||
inputMethodManager.toggleSoftInputFromWindow(surfView.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0);
|
||||
return true;
|
||||
} else if (command.equals("inputbox")) {
|
||||
String seqID = "";
|
||||
String title = "Input";
|
||||
String defString = "";
|
||||
String[] param = params.split(":");
|
||||
if (param[0].length() > 0)
|
||||
title = param[0];
|
||||
if (param.length > 1)
|
||||
defString = param[1];
|
||||
Log.i(TAG, "Launching inputbox: " + title + " " + defString);
|
||||
inputBox(title, defString, "OK");
|
||||
String[] param = params.split(":@:", 3);
|
||||
seqID = param[0];
|
||||
if (param.length > 1 && param[1].length() > 0)
|
||||
title = param[1];
|
||||
if (param.length > 2)
|
||||
defString = param[2];
|
||||
Log.i(TAG, "Launching inputbox: #" + seqID + " " + title + " " + defString);
|
||||
inputBox(seqID, title, defString, "OK");
|
||||
return true;
|
||||
} else if (command.equals("vibrate")) {
|
||||
int milliseconds = -1;
|
||||
|
|
|
@ -48,6 +48,7 @@ public class NativeApp {
|
|||
public static native boolean accelerometer(float x, float y, float z);
|
||||
|
||||
public static native void sendMessage(String msg, String arg);
|
||||
public static native void sendInputBox(String seqID, boolean result, String value);
|
||||
|
||||
public static native String queryConfig(String queryName);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -34,6 +35,9 @@ 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<void(bool, const std::string &)> 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.
|
||||
|
@ -119,8 +123,7 @@ void OpenDirectory(const char *path);
|
|||
void LaunchBrowser(const char *url);
|
||||
void LaunchMarket(const char *url);
|
||||
void LaunchEmail(const char *email_address);
|
||||
bool System_InputBoxGetString(const char *title, const char *defaultValue, char *outValue, size_t outlength);
|
||||
bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultValue, std::wstring &outValue);
|
||||
void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function<void(bool, const std::string &)> cb);
|
||||
void System_SendMessage(const char *command, const char *parameter);
|
||||
PermissionStatus System_GetPermissionStatus(SystemPermission permission);
|
||||
void System_AskForPermission(SystemPermission permission);
|
||||
|
|
|
@ -81,7 +81,7 @@ bool System_GetPropertyBool(SystemProperty prop) {
|
|||
return false;
|
||||
}
|
||||
void System_SendMessage(const char *command, const char *parameter) {}
|
||||
bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) { 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; }
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ void NativeRender(GraphicsContext *graphicsContext) { }
|
|||
void NativeResized() { }
|
||||
|
||||
void System_SendMessage(const char *command, const char *parameter) {}
|
||||
bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) { 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; }
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue