diff --git a/Common/System/Request.h b/Common/System/Request.h index 856fbb9e41..9972ee4205 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -79,3 +79,44 @@ inline void System_BrowseForFile(const std::string &title, BrowseFileType type, inline void System_BrowseForFolder(const std::string &title, RequestCallback callback) { g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, title, "", 0); } + +inline void System_CopyStringToClipboard(const std::string &string) { + g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, string, "", 0); +} + +inline void System_ExitApp() { + g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, nullptr, "", "", 0); +} + +inline void System_RestartApp(const std::string ¶ms) { + g_requestManager.MakeSystemRequest(SystemRequestType::RESTART_APP, nullptr, params, "", 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, param, "", 0); +} + +inline void System_GraphicsBackendFailedAlert(const std::string ¶m) { + g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, nullptr, param, "", 0); +} + +inline void System_CameraCommand(const std::string &command) { + g_requestManager.MakeSystemRequest(SystemRequestType::CAMERA_COMMAND, nullptr, command, "", 0); +} + +inline void System_GPSCommand(const std::string &command) { + g_requestManager.MakeSystemRequest(SystemRequestType::GPS_COMMAND, nullptr, command, "", 0); +} + +inline void System_MicrophoneCommand(const std::string &command) { + g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, nullptr, command, "", 0); +} + +inline void System_ShareText(const std::string &text) { + g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, nullptr, text, "", 0); +} + +inline void System_NotifyUIState(const std::string &state) { + g_requestManager.MakeSystemRequest(SystemRequestType::NOTIFY_UI_STATE, nullptr, state, "", 0); +} diff --git a/Common/System/System.h b/Common/System/System.h index 1b05cf4960..795493ae44 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -51,22 +51,38 @@ void System_Vibrate(int length_ms); void System_ShowFileInFolder(const char *path); void System_LaunchUrl(LaunchUrlType urlType, const char *url); +// It's sometimes a little unclear what should be a request, and what should be a separate function. +// Going forward, "optional" things (PPSSPP will still function alright without it) will be requests, +// to make implementations simpler in the default case. + enum class SystemRequestType { INPUT_TEXT_MODAL, BROWSE_FOR_IMAGE, BROWSE_FOR_FILE, BROWSE_FOR_FOLDER, + + EXIT_APP, + RESTART_APP, // For graphics backend changes + COPY_TO_CLIPBOARD, + TOGGLE_FULLSCREEN_STATE, + GRAPHICS_BACKEND_FAILED_ALERT, + + // High-level hardware control + CAMERA_COMMAND, + GPS_COMMAND, + MICROPHONE_COMMAND, + + SHARE_TEXT, + NOTIFY_UI_STATE, // Used on Android only. Not a SystemNotification since it takes a parameter. }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). // This is not to be used directly by applications, instead use the g_RequestManager to make the requests. // This can return false if it's known that the platform doesn't support the request, the app is supposed to handle // or ignore that cleanly. +// Some requests don't use responses. bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3); -// TODO: To be separated into requests, see Request.h, and a way to post "UI messages". -void System_SendMessage(const char *command, const char *parameter); - PermissionStatus System_GetPermissionStatus(SystemPermission permission); void System_AskForPermission(SystemPermission permission); @@ -159,6 +175,11 @@ enum class SystemNotification { BOOT_DONE, // this is sent from EMU thread! Make sure that Host handles it properly! SYMBOL_MAP_UPDATED, SWITCH_UMD_UPDATED, + ROTATE_UPDATED, + FORCE_RECREATE_ACTIVITY, + IMMERSIVE_MODE_CHANGE, + AUDIO_RESET_DEVICE, + SUSTAINED_PERF_CHANGE, }; std::string System_GetProperty(SystemProperty prop); diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index c48e7eca16..5a3f53c68f 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -13,6 +13,7 @@ #include "Common/UI/Tween.h" #include "Common/UI/Root.h" #include "Common/GPU/thin3d.h" +#include "Common/System/Request.h" #include "Common/System/System.h" #include "Common/TimeUtil.h" #include "Common/StringUtils.h" @@ -1195,7 +1196,7 @@ bool TextEdit::Key(const KeyInput &input) { switch (input.keyCode) { case NKCODE_C: // Just copy the entire text contents, until we get selection support. - System_SendMessage("setclipboardtext", text_.c_str()); + System_CopyStringToClipboard(text_.c_str()); break; case NKCODE_V: { diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index 571f846545..512bcfe15d 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -21,6 +21,7 @@ #include "ppsspp_config.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Core/HLE/HLE.h" @@ -360,7 +361,7 @@ int Camera::startCapture() { #elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) || defined(USING_QT_UI) char command[40] = {0}; snprintf(command, sizeof(command), "startVideo_%dx%d", width, height); - System_SendMessage("camera_command", command); + System_CameraCommand(command); #elif PPSSPP_PLATFORM(LINUX) __v4l_startCapture(width, height); #else @@ -376,7 +377,7 @@ int Camera::stopCapture() { winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr }); } #elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) || defined(USING_QT_UI) - System_SendMessage("camera_command", "stopVideo"); + System_CameraCommand("stopVideo"); #elif PPSSPP_PLATFORM(LINUX) __v4l_stopCapture(); #else diff --git a/Core/HLE/sceUsbGps.cpp b/Core/HLE/sceUsbGps.cpp index 020339fe10..fe9fdf66d5 100644 --- a/Core/HLE/sceUsbGps.cpp +++ b/Core/HLE/sceUsbGps.cpp @@ -21,6 +21,7 @@ #include #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Core/HLE/HLE.h" @@ -51,7 +52,7 @@ void __UsbGpsDoState(PointerWrap &p) { void __UsbGpsShutdown() { gpsStatus = GPS_STATE_OFF; - System_SendMessage("gps_command", "close"); + System_GPSCommand("close"); }; static int sceUsbGpsGetInitDataLocation(u32 addr) { @@ -69,14 +70,14 @@ static int sceUsbGpsOpen() { ERROR_LOG(HLE, "UNIMPL sceUsbGpsOpen"); GPS::init(); gpsStatus = GPS_STATE_ON; - System_SendMessage("gps_command", "open"); + System_GPSCommand("open"); return 0; } static int sceUsbGpsClose() { ERROR_LOG(HLE, "UNIMPL sceUsbGpsClose"); gpsStatus = GPS_STATE_OFF; - System_SendMessage("gps_command", "close"); + System_GPSCommand("close"); return 0; } diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 8ab6ff23da..2d46b5e6a2 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -22,6 +22,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceKernelThread.h" @@ -328,7 +329,7 @@ int Microphone::startMic(void *param) { int sampleRate = micParam->at(0); int channels = micParam->at(1); INFO_LOG(HLE, "microphone_command : sr = %d", sampleRate); - System_SendMessage("microphone_command", ("startRecording:" + std::to_string(sampleRate)).c_str()); + System_MicrophoneCommand("startRecording:" + std::to_string(sampleRate)); #endif micState = 1; return 0; @@ -339,7 +340,7 @@ int Microphone::stopMic() { if (winMic) winMic->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr }); #elif PPSSPP_PLATFORM(ANDROID) - System_SendMessage("microphone_command", "stopRecording"); + System_MicrophoneCommand("stopRecording"); #endif micState = 0; return 0; diff --git a/Core/System.cpp b/Core/System.cpp index 71aacc931e..5a1c26b338 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -33,6 +33,7 @@ #include #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/File/Path.h" #include "Common/Math/math_util.h" #include "Common/Thread/ThreadUtil.h" @@ -134,7 +135,7 @@ void UpdateUIState(GlobalUIState newState) { case UISTATE_EXCEPTION: state = "exception"; break; } if (state) { - System_SendMessage("uistate", state); + System_NotifyUIState(state); } } } diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 28ca9d75ef..c165914bba 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -271,6 +271,10 @@ void System_Notify(SystemNotification notification) { if (g_symbolMap) g_symbolMap->SortSymbols(); break; + case SystemNotification::AUDIO_RESET_DEVICE: + StopSDLAudioDevice(); + InitSDLAudioDevice(); + break; default: break; } @@ -331,6 +335,16 @@ bool MainUI::HandleCustomEvent(QEvent *e) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + qApp->exit(0); + return true; + case SystemRequestType::RESTART_APP: + // Should find a way to properly restart the app. + qApp->exit(0); + return true; + case SystemRequestType::COPY_TO_CLIPBOARD: + QApplication::clipboard()->setText(param1.c_str()); + return true; case SystemRequestType::INPUT_TEXT_MODAL: { g_requestId = requestId; @@ -356,34 +370,20 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string g_param2 = param2; QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFolderEvent)); return true; + case SystemRequestType::CAMERA_COMMAND: + if (!strncmp(param1.c_str(), "startVideo", 10)) { + int width = 0, height = 0; + sscanf(param1.c_str(), "startVideo_%dx%d", &width, &height); + emit(qtcamera->onStartCamera(width, height)); + } else if (param1 == "stopVideo") { + emit(qtcamera->onStopCamera()); + } + return true; default: return false; } } -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "finish")) { - qApp->exit(0); - } else if (!strcmp(command, "graphics_restart")) { - // Should find a way to properly restart the app. - qApp->exit(0); - } else if (!strcmp(command, "camera_command")) { - if (!strncmp(parameter, "startVideo", 10)) { - int width = 0, height = 0; - sscanf(parameter, "startVideo_%dx%d", &width, &height); - emit(qtcamera->onStartCamera(width, height)); - } else if (!strcmp(parameter, "stopVideo")) { - emit(qtcamera->onStopCamera()); - } - } else if (!strcmp(command, "setclipboardtext")) { - QApplication::clipboard()->setText(parameter); -#if defined(SDL) - } else if (!strcmp(command, "audio_resetDevice")) { - StopSDLAudioDevice(); - InitSDLAudioDevice(); -#endif - } -} void System_Toast(const char *text) {} void System_AskForPermission(SystemPermission permission) {} diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index ad80509a44..8aadab0be5 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -170,6 +170,14 @@ void System_Vibrate(int length_ms) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + case SystemRequestType::RESTART_APP: // Not sure how we best do this, but do a clean exit, better than being stuck in a bad state. + // Do a clean exit + g_QuitRequested = true; + return true; + case SystemRequestType::COPY_TO_CLIPBOARD: + SDL_SetClipboardText(param1.c_str()); + return true; #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) case SystemRequestType::BROWSE_FOR_FILE: { @@ -198,33 +206,20 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string return true; } #endif - } - return false; -} - -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "toggle_fullscreen")) { + case SystemRequestType::TOGGLE_FULLSCREEN_STATE: g_ToggleFullScreenNextFrame = true; - if (strcmp(parameter, "1") == 0) { + if (param1 == "1") { g_ToggleFullScreenType = 1; - } else if (strcmp(parameter, "0") == 0) { + } else if (param1 == "0") { g_ToggleFullScreenType = 0; } else { // Just toggle. g_ToggleFullScreenType = -1; } - } else if (!strcmp(command, "finish")) { - // Do a clean exit - g_QuitRequested = true; - } else if (!strcmp(command, "graphics_restart")) { - // Not sure how we best do this, but do a clean exit, better than being stuck in a bad state. - g_QuitRequested = true; - } else if (!strcmp(command, "setclipboardtext")) { - SDL_SetClipboardText(parameter); - } else if (!strcmp(command, "audio_resetDevice")) { - StopSDLAudioDevice(); - InitSDLAudioDevice(); - } + return true; + default: + return false; + } } void System_AskForPermission(SystemPermission permission) {} @@ -467,6 +462,11 @@ bool System_GetPropertyBool(SystemProperty prop) { void System_Notify(SystemNotification notification) { switch (notification) { + case SystemNotification::AUDIO_RESET_DEVICE: + StopSDLAudioDevice(); + InitSDLAudioDevice(); + break; + default: break; } diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index bfcb9e662c..eba85e37bf 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -37,6 +37,7 @@ #include "Common/StringUtils.h" #include "Common/System/Display.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/TimeUtil.h" #include "Core/KeyMap.h" #include "Core/Host.h" @@ -717,16 +718,26 @@ void TouchTestScreen::render() { ui_context->Flush(); } -void RecreateActivity(); +void RecreateActivity() { + const int SYSTEM_JELLYBEAN = 16; + if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= SYSTEM_JELLYBEAN) { + INFO_LOG(SYSTEM, "Sending recreate"); + System_Notify(SystemNotification::FORCE_RECREATE_ACTIVITY); + INFO_LOG(SYSTEM, "Got back from recreate"); + } else { + auto gr = GetI18NCategory("Graphics"); + System_Toast(gr->T("Must Restart", "You must restart PPSSPP for this change to take effect")); + } +} UI::EventReturn TouchTestScreen::OnImmersiveModeChange(UI::EventParams &e) { - System_SendMessage("immersive", ""); + System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE); return UI::EVENT_DONE; } UI::EventReturn TouchTestScreen::OnRenderingBackend(UI::EventParams &e) { g_Config.Save("GameSettingsScreen::RenderingBackend"); - System_SendMessage("graphics_restart", "--touchscreentest"); + System_RestartApp("--touchscreentest"); return UI::EVENT_DONE; } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index e5c03ba69b..19b17a7a46 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -41,6 +41,7 @@ using namespace std::placeholders; #include "Common/System/Display.h" #include "Common/System/System.h" #include "Common/System/NativeApp.h" +#include "Common/System/Request.h" #include "Common/Profiler/Profiler.h" #include "Common/Math/curves.h" #include "Common/TimeUtil.h" @@ -210,7 +211,6 @@ bool EmuScreen::bootAllowStorage(const Path &filename) { case PERMISSION_STATUS_DENIED: stopRender_ = true; screenManager()->switchScreen(new MainScreen()); - System_SendMessage("event", "failstartgame"); return false; case PERMISSION_STATUS_PENDING: @@ -243,7 +243,6 @@ void EmuScreen::bootGame(const Path &filename) { if (invalid_) { errorMessage_ = error_string; ERROR_LOG(BOOT, "%s", errorMessage_.c_str()); - System_SendMessage("event", "failstartgame"); return; } bootComplete(); @@ -328,7 +327,6 @@ void EmuScreen::bootGame(const Path &filename) { invalid_ = true; errorMessage_ = error_string; ERROR_LOG(BOOT, "%s", errorMessage_.c_str()); - System_SendMessage("event", "failstartgame"); } if (PSP_CoreParameter().compat.flags().RequireBufferedRendering && g_Config.bSkipBufferEffects) { @@ -392,8 +390,6 @@ void EmuScreen::bootComplete() { #endif } - System_SendMessage("event", "startgame"); - saveStateSlot_ = SaveState::GetCurrentSlot(); loadingViewColor_->Divert(0x00FFFFFF, 0.2f); @@ -429,7 +425,6 @@ void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) { // DR_YES means a message sent to PauseMenu by NativeMessageReceived. if (result == DR_OK || quit_) { screenManager()->switchScreen(new MainScreen()); - System_SendMessage("event", "exitgame"); quit_ = false; } // Returning to the PauseScreen, unless we're stepping, means we should go back to controls. @@ -472,7 +467,6 @@ void EmuScreen::sendMessage(const char *message, const char *value) { ERROR_LOG(LOADER, "Error resetting: %s", resetError.c_str()); stopRender_ = true; screenManager()->switchScreen(new MainScreen()); - System_SendMessage("event", "failstartgame"); return; } } else if (!strcmp(message, "boot")) { @@ -676,7 +670,7 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) { NativeMessageReceived("savestate_displayslot", ""); break; case VIRTKEY_TOGGLE_FULLSCREEN: - System_SendMessage("toggle_fullscreen", ""); + System_ToggleFullscreenState(""); break; case VIRTKEY_SCREENSHOT: diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 470efbca15..eba83997d1 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1193,23 +1193,11 @@ UI::EventReturn GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnScreenRotation(UI::EventParams &e) { INFO_LOG(SYSTEM, "New display rotation: %d", g_Config.iScreenRotation); INFO_LOG(SYSTEM, "Sending rotate"); - System_SendMessage("rotate", ""); + System_Notify(SystemNotification::ROTATE_UPDATED); INFO_LOG(SYSTEM, "Got back from rotate"); return UI::EVENT_DONE; } -void RecreateActivity() { - const int SYSTEM_JELLYBEAN = 16; - if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= SYSTEM_JELLYBEAN) { - INFO_LOG(SYSTEM, "Sending recreate"); - System_SendMessage("recreate", ""); - INFO_LOG(SYSTEM, "Got back from recreate"); - } else { - auto gr = GetI18NCategory("Graphics"); - System_SendMessage("toast", gr->T("Must Restart", "You must restart PPSSPP for this change to take effect")); - } -} - UI::EventReturn GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) { auto n = GetI18NCategory("Networking"); System_LaunchUrl(LaunchUrlType::BROWSER_URL, n->T("MultiplayerHowToURL", "https://github.com/hrydgard/ppsspp/wiki/How-to-play-multiplayer-games-with-PPSSPP")); @@ -1217,12 +1205,12 @@ UI::EventReturn GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnImmersiveModeChange(UI::EventParams &e) { - System_SendMessage("immersive", ""); + System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE); return UI::EVENT_DONE; } UI::EventReturn GameSettingsScreen::OnSustainedPerformanceModeChange(UI::EventParams &e) { - System_SendMessage("sustainedPerfMode", ""); + System_Notify(SystemNotification::SUSTAINED_PERF_CHANGE); return UI::EVENT_DONE; } @@ -1329,12 +1317,12 @@ UI::EventReturn GameSettingsScreen::OnChangeBackground(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnFullscreenChange(UI::EventParams &e) { g_Config.iForceFullScreen = -1; - System_SendMessage("toggle_fullscreen", g_Config.UseFullScreen() ? "1" : "0"); + System_ToggleFullscreenState(g_Config.UseFullScreen() ? "1" : "0"); return UI::EVENT_DONE; } UI::EventReturn GameSettingsScreen::OnFullscreenMultiChange(UI::EventParams &e) { - System_SendMessage("toggle_fullscreen", g_Config.UseFullScreen() ? "1" : "0"); + System_ToggleFullscreenState(g_Config.UseFullScreen() ? "1" : "0"); return UI::EVENT_DONE; } @@ -1348,7 +1336,7 @@ void GameSettingsScreen::onFinish(DialogResult result) { Reporting::Enable(enableReports_, "report.ppsspp.org"); Reporting::UpdateConfig(); if (!g_Config.Save("GameSettingsScreen::onFinish")) { - System_SendMessage("toast", "Failed to save settings!\nCheck permissions, or try to restart the device."); + System_Toast("Failed to save settings!\nCheck permissions, or try to restart the device."); } if (editThenRestore_) { @@ -1477,7 +1465,7 @@ void GameSettingsScreen::TriggerRestart(const char *why) { } // Make sure the new instance is considered the first. ShutdownInstanceCounter(); - System_SendMessage("graphics_restart", param.c_str()); + System_RestartApp(param); } void GameSettingsScreen::CallbackRenderingBackend(bool yes) { @@ -1559,7 +1547,7 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) { if (g_Config.sAudioDevice == a->T("Auto")) { g_Config.sAudioDevice.clear(); } - System_SendMessage("audio_resetDevice", ""); + System_Notify(SystemNotification::AUDIO_RESET_DEVICE); return UI::EVENT_DONE; } @@ -2107,8 +2095,8 @@ UI::EventReturn HostnameSelectScreen::OnIPClick(UI::EventParams& e) { std::string text = e.v ? e.v->Tag() : ""; if (text.length() > 0) { addrView_->SetText(text); - // TODO: Copy the IP to clipboard for the host to easily share their IP through chatting apps. - System_SendMessage("setclipboardtext", text.c_str()); // Doesn't seems to be working on windows (yet?) + // Copy the IP to clipboard for the host to easily share their IP through chatting apps. + System_CopyStringToClipboard(text); } return UI::EVENT_DONE; } diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 768b3c4f21..d5baa80ef1 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -980,7 +980,6 @@ UI::EventReturn GameBrowser::OnHomebrewStore(UI::EventParams &e) { } MainScreen::MainScreen() { - System_SendMessage("event", "mainscreen"); g_BackgroundAudio.SetGame(Path()); } @@ -1287,7 +1286,7 @@ UI::EventReturn MainScreen::OnFullScreenToggle(UI::EventParams &e) { } #if !defined(MOBILE_DEVICE) g_Config.bFullScreen = !g_Config.bFullScreen; - System_SendMessage("toggle_fullscreen", ""); + System_ToggleFullscreenState(""); #endif return UI::EVENT_DONE; } @@ -1428,11 +1427,11 @@ UI::EventReturn MainScreen::OnForums(UI::EventParams &e) { UI::EventReturn MainScreen::OnExit(UI::EventParams &e) { // Let's make sure the config was saved, since it may not have been. if (!g_Config.Save("MainScreen::OnExit")) { - System_SendMessage("toast", "Failed to save settings!\nCheck permissions, or try to restart the device."); + System_Toast("Failed to save settings!\nCheck permissions, or try to restart the device."); } // Request the framework to exit cleanly. - System_SendMessage("finish", ""); + System_ExitApp(); UpdateUIState(UISTATE_EXIT); return UI::EVENT_DONE; diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 9b3def0b61..d5812885ad 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -771,7 +771,7 @@ void ConfirmMemstickMoveScreen::FinishFolderMove() { if (!initialSetup_) { // We restart the app here, to get the new settings. - System_SendMessage("graphics_restart", ""); + System_RestartApp(""); } else { // This is initial setup, we now switch to the main screen, if we were successful // (which we better have been...) diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index c99684bbe0..84dbbbe80f 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -29,6 +29,7 @@ #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Math/curves.h" #include "Common/File/VFS/VFS.h" @@ -846,11 +847,7 @@ UI::EventReturn CreditsScreen::OnSupport(UI::EventParams &e) { } UI::EventReturn CreditsScreen::OnTwitter(UI::EventParams &e) { -#ifdef __ANDROID__ - System_SendMessage("showTwitter", "PPSSPP_emu"); -#else System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://twitter.com/#!/PPSSPP_emu"); -#endif return UI::EVENT_DONE; } @@ -876,7 +873,7 @@ UI::EventReturn CreditsScreen::OnDiscord(UI::EventParams &e) { UI::EventReturn CreditsScreen::OnShare(UI::EventParams &e) { auto cr = GetI18NCategory("PSPCredits"); - System_SendMessage("sharetext", cr->T("CheckOutPPSSPP", "Check out PPSSPP, the awesome PSP emulator: https://www.ppsspp.org/")); + System_ShareText(cr->T("CheckOutPPSSPP", "Check out PPSSPP, the awesome PSP emulator: https://www.ppsspp.org/")); return UI::EVENT_DONE; } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 6ff7dd17fb..b42c9a037d 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -387,7 +387,7 @@ static void CheckFailedGPUBackends() { g_Config.iGPUBackend = g_Config.NextValidBackend(); if (lastBackend != g_Config.iGPUBackend) { std::string param = GPUBackendToString((GPUBackend)lastBackend) + " -> " + GPUBackendToString((GPUBackend)g_Config.iGPUBackend); - System_SendMessage("graphics_failedBackend", param.c_str()); + System_GraphicsBackendFailedAlert(param); WARN_LOG(LOADER, "Failed graphics backend switched from %s (%d to %d)", param.c_str(), lastBackend, g_Config.iGPUBackend); } // And then let's - for now - add the current to the failed list. @@ -640,11 +640,11 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch g_Config.bPauseMenuExitsEmulator = true; if (!strcmp(argv[i], "--fullscreen")) { g_Config.iForceFullScreen = 1; - System_SendMessage("toggle_fullscreen", "1"); + System_ToggleFullscreenState("1"); } if (!strcmp(argv[i], "--windowed")) { g_Config.iForceFullScreen = 0; - System_SendMessage("toggle_fullscreen", "0"); + System_ToggleFullscreenState("0"); } if (!strcmp(argv[i], "--touchscreentest")) gotoTouchScreenTest = true; @@ -1289,7 +1289,7 @@ bool NativeKey(const KeyInput &key) { pspKeys.clear(); if (KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &pspKeys)) { if (std::find(pspKeys.begin(), pspKeys.end(), VIRTKEY_PAUSE) != pspKeys.end()) { - System_SendMessage("finish", ""); + System_ExitApp(); return true; } } @@ -1390,8 +1390,6 @@ void NativeShutdown() { g_screenManager = nullptr; } -#if !PPSSPP_PLATFORM(UWP) -#endif g_Config.Save("NativeShutdown"); INFO_LOG(SYSTEM, "NativeShutdown called"); @@ -1404,7 +1402,9 @@ void NativeShutdown() { ShutdownWebServer(); - System_SendMessage("finish", ""); +#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) + System_ExitApp(); +#endif net::Shutdown(); @@ -1423,6 +1423,10 @@ void NativeShutdown() { g_threadManager.Teardown(); +#if !(PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS)) + System_ExitApp(); +#endif + // Previously we did exit() here on Android but that makes it hard to do things like restart on backend change. // I think we handle most globals correctly or correct-enough now. } diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 4738e425d9..f3405fdc89 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -28,6 +28,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/StringUtils.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/VR/PPSSPPVR.h" #include "Common/UI/AsyncImageFileView.h" @@ -392,7 +393,7 @@ UI::EventReturn GamePauseScreen::OnScreenshotClicked(UI::EventParams &e) { UI::EventReturn GamePauseScreen::OnExitToMenu(UI::EventParams &e) { if (g_Config.bPauseMenuExitsEmulator) { - System_SendMessage("finish", ""); + System_ExitApp(); } else { TriggerFinish(DR_OK); } diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index d174437aee..f78a8e0787 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -486,22 +486,13 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string }); return true; } - } - - return false; -} - -void System_SendMessage(const char *command, const char *parameter) { - using namespace concurrency; - - if (!strcmp(command, "finish")) { - // Not really supposed to support this under UWP. - } else if (!strcmp(command, "toggle_fullscreen")) { + case SystemRequestType::TOGGLE_FULLSCREEN_STATE: + { auto view = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView(); bool flag = !view->IsFullScreenMode; - if (strcmp(parameter, "0") == 0) { + if (param1 == "0") { flag = false; - } else if (strcmp(parameter, "1") == 0){ + } else if (param1 == "1"){ flag = true; } if (flag) { @@ -509,6 +500,10 @@ void System_SendMessage(const char *command, const char *parameter) { } else { view->ExitFullScreenMode(); } + return true; + } + default: + return false; } } diff --git a/Windows/main.cpp b/Windows/main.cpp index 59e83a0722..9b6f19df4f 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -443,6 +443,30 @@ std::wstring MakeFilter(std::wstring filter) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + if (!NativeIsRestarting()) { + PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + } + return true; + case SystemRequestType::RESTART_APP: + { + restartArgs = param1; + if (!restartArgs.empty()) + AddDebugRestartArgs(); + if (IsDebuggerPresent()) { + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0); + } else { + g_Config.bRestartRequired = true; + PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + } + return true; + } + case SystemRequestType::COPY_TO_CLIPBOARD: + { + std::wstring data = ConvertUTF8ToWString(param1); + W32Util::CopyTextToClipboard(MainWindow::GetDisplayHWND(), data); + return true; + } case SystemRequestType::INPUT_TEXT_MODAL: if (g_dialogRunning) { g_dialogThread.join(); @@ -516,43 +540,28 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } return true; } - default: - return false; - } -} - -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "finish")) { - if (!NativeIsRestarting()) { - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); - } - } else if (!strcmp(command, "graphics_restart")) { - restartArgs = parameter == nullptr ? "" : parameter; - if (!restartArgs.empty()) - AddDebugRestartArgs(); - if (IsDebuggerPresent()) { - PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0); - } else { - g_Config.bRestartRequired = true; - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); - } - } else if (!strcmp(command, "graphics_failedBackend")) { - auto err = GetI18NCategory("Error"); - const char *backendSwitchError = err->T("GenericBackendSwitchCrash", "PPSSPP crashed while starting. This usually means a graphics driver problem. Try upgrading your graphics drivers.\n\nGraphics backend has been switched:"); - std::wstring full_error = ConvertUTF8ToWString(StringFromFormat("%s %s", backendSwitchError, parameter)); - std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error")); - MessageBox(MainWindow::GetHWND(), full_error.c_str(), title.c_str(), MB_OK); - } else if (!strcmp(command, "setclipboardtext")) { - std::wstring data = ConvertUTF8ToWString(parameter); - W32Util::CopyTextToClipboard(MainWindow::GetDisplayHWND(), data); - } else if (!strcmp(command, "toggle_fullscreen")) { + case SystemRequestType::TOGGLE_FULLSCREEN_STATE: + { bool flag = !MainWindow::IsFullscreen(); - if (strcmp(parameter, "0") == 0) { + if (param1 == "0") { flag = false; - } else if (strcmp(parameter, "1") == 0) { + } else if (param1 == "1") { flag = true; } MainWindow::SendToggleFullscreen(flag); + return true; + } + case SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT: + { + auto err = GetI18NCategory("Error"); + const char *backendSwitchError = err->T("GenericBackendSwitchCrash", "PPSSPP crashed while starting. This usually means a graphics driver problem. Try upgrading your graphics drivers.\n\nGraphics backend has been switched:"); + std::wstring full_error = ConvertUTF8ToWString(StringFromFormat("%s %s", backendSwitchError, param1.c_str())); + std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error")); + MessageBox(MainWindow::GetHWND(), full_error.c_str(), title.c_str(), MB_OK); + return true; + } + default: + return false; } } diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 6d5693273e..d12832a7fe 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -85,7 +85,7 @@ bool AndroidVulkanContext::InitAPI() { INFO_LOG(G3D, "Creating Vulkan device"); if (g_Vulkan->CreateDevice() != VK_SUCCESS) { INFO_LOG(G3D, "Failed to create vulkan device: %s", g_Vulkan->InitError().c_str()); - System_SendMessage("toast", "No Vulkan driver found. Using OpenGL instead."); + System_Toast("No Vulkan driver found. Using OpenGL instead."); g_Vulkan->DestroyInstance(); delete g_Vulkan; g_Vulkan = nullptr; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index b5e8ac937f..dc114d850c 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -401,10 +401,6 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url) { } } -void System_SendMessage(const char *command, const char *parameter) { - PushCommand(command, parameter); -} - std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: @@ -538,9 +534,6 @@ bool System_GetPropertyBool(SystemProperty prop) { } } -void System_Notify(SystemNotification notification) { -} - std::string Android_GetInputDeviceDebugString() { if (!nativeActivity) { return "(N/A)"; @@ -1027,8 +1020,31 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv } } +void System_Notify(SystemNotification notification) { + switch (notification) { + case SystemNotification::ROTATE_UPDATED: + PushCommand("rotate", ""); + break; + case SystemNotification::FORCE_RECREATE_ACTIVITY: + PushCommand("recreate", ""); + break; + case SystemNotification::IMMERSIVE_MODE_CHANGE: + PushCommand("immersive", ""); + break; + case SystemNotification::SUSTAINED_PERF_CHANGE: + PushCommand("sustainedPerfMode", ""); + break; + } +} + bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + PushCommand("finish", ""); + return true; + case SystemRequestType::RESTART_APP: + PushCommand("graphics_restart", param1); + return true; case SystemRequestType::INPUT_TEXT_MODAL: { std::string serialized = StringFromFormat("%d:@:%s:@:%s", requestId, param1.c_str(), param2.c_str()); @@ -1044,6 +1060,22 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::BROWSE_FOR_FOLDER: PushCommand("browse_folder", StringFromFormat("%d", requestId)); return true; + + case SystemRequestType::CAMERA_COMMAND: + PushCommand("camera_command", param1); + return true; + case SystemRequestType::GPS_COMMAND: + PushCommand("gps_command", param1); + return true; + case SystemRequestType::MICROPHONE_COMMAND: + PushCommand("microphone_command", param1); + return true; + case SystemRequestType::SHARE_TEXT: + PushCommand("share_text", param1); + return true; + case SystemRequestType::NOTIFY_UI_STATE: + PushCommand("uistate", param1); + return true; default: return false; } @@ -1209,7 +1241,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); - // Some messages are caught by app-android. + // Some messages are caught by app-android. TODO: Should be all. if (msg == "moga") { mogaVersion = prm; } else if (msg == "permission_pending") { diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index bd6857bef4..d8e4622950 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -1319,14 +1319,31 @@ public abstract class NativeActivity extends Activity { public boolean processCommand(String command, String params) { SurfaceView surfView = javaGL ? mGLSurfaceView : mSurfaceView; if (command.equals("launchBrowser")) { - try { - Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); - startActivity(i); - return true; - } catch (Exception e) { - // No browser? - Log.e(TAG, e.toString()); - return false; + // Special case for twitter + if (params.startsWith("https://twitter.com/#!/")) { + try { + String twitter_user_name = params.replaceFirst("https://twitter.com/#!/", ""); + try { + Log.i(TAG, "Launching twitter directly: " + twitter_user_name); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + twitter_user_name))); + } catch (Exception e) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/#!/" + twitter_user_name))); + } + return true; + } catch (Exception e) { // For example, android.content.ActivityNotFoundException + Log.e(TAG, e.toString()); + return false; + } + } else { + try { + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); + startActivity(i); + return true; + } catch (Exception e) { + // No browser? + Log.e(TAG, e.toString()); + return false; + } } } else if (command.equals("launchEmail")) { try { @@ -1386,18 +1403,7 @@ public abstract class NativeActivity extends Activity { Log.e(TAG, e.toString()); return false; } - } else if (command.equals("sharejpeg")) { - try { - Intent share = new Intent(Intent.ACTION_SEND); - share.setType("image/jpeg"); - share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + params)); - startActivity(Intent.createChooser(share, "Share Picture")); - return true; - } catch (Exception e) { // For example, android.content.ActivityNotFoundException - Log.e(TAG, e.toString()); - return false; - } - } else if (command.equals("sharetext")) { + } else if (command.equals("share_text")) { try { Intent sendIntent = new Intent(); sendIntent.setType("text/plain"); @@ -1410,19 +1416,6 @@ public abstract class NativeActivity extends Activity { Log.e(TAG, e.toString()); return false; } - } else if (command.equals("showTwitter")) { - try { - String twitter_user_name = params; - try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + twitter_user_name))); - } catch (Exception e) { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/#!/" + twitter_user_name))); - } - return true; - } catch (Exception e) { // For example, android.content.ActivityNotFoundException - Log.e(TAG, e.toString()); - return false; - } } else if (command.equals("launchMarket")) { // Don't need this, can just use launchBrowser with a market: // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 137b3ae1f3..c085bab344 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -115,7 +115,6 @@ bool System_GetPropertyBool(SystemProperty prop) { } } void System_Notify(SystemNotification notification) {} -void System_SendMessage(const char *command, const char *parameter) {} bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 9c4ff956ff..49f8a011dd 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -160,15 +160,20 @@ static LocationHelper *locationHelper; }); } +extern float g_safeInsetLeft; +extern float g_safeInsetRight; +extern float g_safeInsetTop; +extern float g_safeInsetBottom; + - (void)viewSafeAreaInsetsDidChange { if (@available(iOS 11.0, *)) { [super viewSafeAreaInsetsDidChange]; char safeArea[100]; // we use 0.0f instead of safeAreaInsets.bottom because the bottom overlay isn't disturbing (for now) - snprintf(safeArea, sizeof(safeArea), "%f:%f:%f:%f", - self.view.safeAreaInsets.left, self.view.safeAreaInsets.right, - self.view.safeAreaInsets.top, 0.0f); - System_SendMessage("safe_insets", safeArea); + g_safeInsetLeft = self.view.safeAreaInsets.left; + g_safeInsetRight = self.view.safeAreaInsets.right; + g_safeInsetTop = self.view.safeAreaInsets.top; + g_safeInsetBottom = 0.0f; } } diff --git a/ios/main.mm b/ios/main.mm index c879c0793d..e90b60e8a1 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -89,10 +89,10 @@ void *exception_handler(void *argument) { return NULL; } -static float g_safeInsetLeft = 0.0; -static float g_safeInsetRight = 0.0; -static float g_safeInsetTop = 0.0; -static float g_safeInsetBottom = 0.0; +float g_safeInsetLeft = 0.0; +float g_safeInsetRight = 0.0; +float g_safeInsetTop = 0.0; +float g_safeInsetBottom = 0.0; // We no longer need to judge if jit is usable or not by according to the ios version. /* @@ -176,45 +176,16 @@ void System_Notify(SystemNotification notification) { } } -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "finish")) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { + switch (type) { + case SystemRequestType::EXIT_APP: exit(0); // The below seems right, but causes hangs. See #12140. // dispatch_async(dispatch_get_main_queue(), ^{ // [sharedViewController shutdown]; // exit(0); // }); - } else if (!strcmp(command, "sharetext")) { - NSString *text = [NSString stringWithUTF8String:parameter]; - [sharedViewController shareText:text]; - } else if (!strcmp(command, "camera_command")) { - if (!strncmp(parameter, "startVideo", 10)) { - int width = 0, height = 0; - sscanf(parameter, "startVideo_%dx%d", &width, &height); - setCameraSize(width, height); - startVideo(); - } else if (!strcmp(parameter, "stopVideo")) { - stopVideo(); - } - } else if (!strcmp(command, "gps_command")) { - if (!strcmp(parameter, "open")) { - startLocation(); - } else if (!strcmp(parameter, "close")) { - stopLocation(); - } - } else if (!strcmp(command, "safe_insets")) { - float left, right, top, bottom; - if (4 == sscanf(parameter, "%f:%f:%f:%f", &left, &right, &top, &bottom)) { - g_safeInsetLeft = left; - g_safeInsetRight = right; - g_safeInsetTop = top; - g_safeInsetBottom = bottom; - } - } -} - -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { - switch (type) { + break; case SystemRequestType::BROWSE_FOR_FILE: { DarwinDirectoryPanelCallback callback = [requestId] (bool success, Path path) { @@ -241,8 +212,32 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string services.presentDirectoryPanel(callback, /* allowFiles = */ false, /* allowDirectories = */ true); return true; } + case SystemRequestType::CAMERA_COMMAND: + if (!strncmp(param1.c_str(), "startVideo", 10)) { + int width = 0, height = 0; + sscanf(param1.c_str(), "startVideo_%dx%d", &width, &height); + setCameraSize(width, height); + startVideo(); + } else if (!strcmp(param1.c_str(), "stopVideo")) { + stopVideo(); + } + return true; + case SystemRequestType::GPS_COMMAND: + if (param1 == "open") { + startLocation(); + } else if (param1 == "close") { + stopLocation(); + } + return true; + case SystemRequestType::SHARE_TEXT: + { + NSString *text = [NSString stringWithUTF8String:param1.c_str()]; + [sharedViewController shareText:text]; + return true; + } + default: + return false; } - return false; } void System_Toast(const char *text) {} diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 2289b1fb97..dea29a92a9 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1875,7 +1875,6 @@ void System_Notify(SystemNotification notification) { } } bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } -void System_SendMessage(const char *command, const char *parameter) {} void NativeUpdate() {} void NativeRender(GraphicsContext *graphicsContext) {} void NativeResized() {} diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index d578c0af13..18518360f6 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -41,7 +41,6 @@ void NativeUpdate() { } void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } -void System_SendMessage(const char *command, const char *parameter) {} bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {}