diff --git a/Core/Config.cpp b/Core/Config.cpp index 5076c7069f..dd14d9bf9d 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -937,6 +937,7 @@ void TouchControlConfig::ResetLayout() { fDpadSpacing = 1.0f; reset(&touchStartKey); reset(&touchSelectKey); + reset(&touchHomeKey); reset(&touchFastForwardKey); reset(&touchLKey); reset(&touchRKey); @@ -1006,6 +1007,7 @@ static constexpr ConfigSetting touchControlSettings[] = { ConfigSetting("DPadSpacing", SETTING(g_Config.touchControlsLandscape, fDpadSpacing), 1.0f, CfgFlag::PER_GAME), ConfigSetting("StartKeyX", "StartKeyY", "StartKeyScale", "ShowTouchStart", SETTING(g_Config.touchControlsLandscape, touchStartKey), defaultTouchPosShow, CfgFlag::PER_GAME), ConfigSetting("SelectKeyX", "SelectKeyY", "SelectKeyScale", "ShowTouchSelect", SETTING(g_Config.touchControlsLandscape, touchSelectKey), defaultTouchPosShow, CfgFlag::PER_GAME), + ConfigSetting("HomeKeyX", "HomeKeyY", "HomeKeyScale", "ShowTouchHome", SETTING(g_Config.touchControlsLandscape, touchHomeKey), defaultTouchPosHide, CfgFlag::PER_GAME), ConfigSetting("UnthrottleKeyX", "UnthrottleKeyY", "UnthrottleKeyScale", "ShowTouchUnthrottle", SETTING(g_Config.touchControlsLandscape, touchFastForwardKey), defaultTouchPosShow, CfgFlag::PER_GAME), ConfigSetting("LKeyX", "LKeyY", "LKeyScale", "ShowTouchLTrigger", SETTING(g_Config.touchControlsLandscape, touchLKey), defaultTouchPosShow, CfgFlag::PER_GAME), ConfigSetting("RKeyX", "RKeyY", "RKeyScale", "ShowTouchRTrigger", SETTING(g_Config.touchControlsLandscape, touchRKey), defaultTouchPosShow, CfgFlag::PER_GAME), diff --git a/Core/Config.h b/Core/Config.h index 675b3be1ee..9c43205bae 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -104,6 +104,7 @@ struct TouchControlConfig : public ConfigBlock { constexpr TouchControlConfig() { // Hide all extras and custom buttons by default. touchRightAnalogStick.show = false; + touchHomeKey.show = false; for (size_t i = 0; i < CUSTOM_BUTTON_COUNT; i++) { touchCustom[i].show = false; } @@ -119,6 +120,7 @@ struct TouchControlConfig : public ConfigBlock { ConfigTouchPos touchStartKey; ConfigTouchPos touchSelectKey; + ConfigTouchPos touchHomeKey; ConfigTouchPos touchFastForwardKey; ConfigTouchPos touchLKey; ConfigTouchPos touchRKey; diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index 16f8c4ff80..b21cdac9e5 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -471,6 +471,7 @@ const KeyMap_IntStrPair psp_button_names[] = { {CTRL_SELECT, "Select"}, {CTRL_LTRIGGER, "L"}, {CTRL_RTRIGGER, "R"}, + {CTRL_HOME, "Home"}, {VIRTKEY_AXIS_Y_MAX, "An.Up"}, {VIRTKEY_AXIS_Y_MIN, "An.Down"}, @@ -538,7 +539,6 @@ const KeyMap_IntStrPair psp_button_names[] = { {VIRTKEY_AXIS_RIGHT_X_MIN, "RightAn.Left"}, {VIRTKEY_AXIS_RIGHT_X_MAX, "RightAn.Right"}, - {CTRL_HOME, "Home"}, {CTRL_HOLD, "Hold"}, {CTRL_WLAN, "Wlan"}, {CTRL_REMOTE_HOLD, "Remote hold"}, diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 80d9bcd55b..4207f59168 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -91,6 +91,7 @@ void SingleControlMapper::Refresh() { { "Triangle", ImageID("I_TRIANGLE") }, { "Start", ImageID("I_START") }, { "Select", ImageID("I_SELECT") }, + { "Home", ImageID("I_HOME") }, { "L", ImageID("I_L") }, { "R", ImageID("I_R") } }; diff --git a/UI/GameBrowser.cpp b/UI/GameBrowser.cpp index 045e019147..f4b946db26 100644 --- a/UI/GameBrowser.cpp +++ b/UI/GameBrowser.cpp @@ -1043,7 +1043,7 @@ void GameBrowser::Refresh() { topBar->Add(new Spacer(2.0f)); topBar->Add(new TextView(pathStr, ALIGN_VCENTER | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f))); } - Choice *homeChoice = topBar->Add(new Choice(ImageID("I_HOME"), new LayoutParams(WRAP_CONTENT, 64.0f))); + Choice *homeChoice = topBar->Add(new Choice(ImageID("I_HOME_ICON"), new LayoutParams(WRAP_CONTENT, 64.0f))); homeChoice->SetRoundCorners(RoundCorners::All); homeChoice->OnClick.Handle(this, &GameBrowser::OnHomeClick); if (System_GetPropertyBool(SYSPROP_HAS_ADDITIONAL_STORAGE)) { diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index 79833e70d4..8e481b2e5d 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -940,6 +940,10 @@ void InitPadLayout(TouchControlConfig *config, DeviceOrientation orientation, fl int fast_forward_key_X = halfW; int fast_forward_key_Y = screenBottom - bottom_button_Y * scale - 100; initTouchPos(&config->touchFastForwardKey, fast_forward_key_X, fast_forward_key_Y); + + int home_key_X = halfW; + int home_key_Y = screenBottom - bottom_button_Y * scale - 150; + initTouchPos(&config->touchHomeKey, home_key_X, home_key_Y); } else { int start_key_X = halfW + bottom_key_spacing * scale; int start_key_Y = screenBottom - bottom_button_Y * scale; @@ -949,6 +953,11 @@ void InitPadLayout(TouchControlConfig *config, DeviceOrientation orientation, fl int select_key_Y = screenBottom - bottom_button_Y * scale; initTouchPos(&config->touchSelectKey, select_key_X, select_key_Y); + // Above select. + int home_key_X = halfW; + int home_key_Y = select_key_Y - 50; + initTouchPos(&config->touchHomeKey, home_key_X, home_key_Y); + int fast_forward_key_X = halfW - bottom_key_spacing * scale; int fast_forward_key_Y = screenBottom - bottom_button_Y * scale; initTouchPos(&config->touchFastForwardKey, fast_forward_key_X, fast_forward_key_Y); @@ -1076,6 +1085,7 @@ GamepadEmuView::GamepadEmuView(const TouchControlConfig &config, float xres, flo addPSPButton(CTRL_START, "Start button", rectImage, ImageID("I_RECT"), ImageID("I_START"), config.touchStartKey); addPSPButton(CTRL_SELECT, "Select button", rectImage, ImageID("I_RECT"), ImageID("I_SELECT"), config.touchSelectKey); + addPSPButton(CTRL_HOME, "Home button", rectImage, ImageID("I_RECT"), ImageID("I_HOME"), config.touchHomeKey); BoolButton *fastForward = addBoolButton(&PSP_CoreParameter().fastForward, "Fast-forward button", rectImage, ImageID("I_RECT"), ImageID("I_FAST_FORWARD_LINE"), config.touchFastForwardKey); if (fastForward) { diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index ce8463c100..64598bfe72 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -364,6 +364,7 @@ namespace CustomKeyData { { ImageID::invalid(), VIRTKEY_TOGGLE_DEBUGGER }, { ImageID::invalid(), VIRTKEY_PAUSE_NO_MENU }, { ImageID::invalid(), VIRTKEY_TOGGLE_TILT }, + { ImageID("I_HOME"), CTRL_HOME }, // IMPORTANT: Only add at the end! }; static_assert(ARRAY_SIZE(g_customKeyList) <= 64, "Too many key for a uint64_t bit mask"); @@ -421,6 +422,7 @@ namespace GestureKey { VIRTKEY_AXIS_RIGHT_Y_MAX, VIRTKEY_TOGGLE_DEBUGGER, VIRTKEY_TOGGLE_TILT, + CTRL_HOME, }; } diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 435915ff62..861395d6f7 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -2656,6 +2656,10 @@ ImDebugger::ImDebugger() { } ImDebugger::~ImDebugger() { + SaveConfig(); +} + +void ImDebugger::SaveConfig() { cfg_.SaveConfig(ConfigPath()); } diff --git a/UI/ImDebugger/ImDebugger.h b/UI/ImDebugger/ImDebugger.h index b79209b509..caf982a6b9 100644 --- a/UI/ImDebugger/ImDebugger.h +++ b/UI/ImDebugger/ImDebugger.h @@ -190,6 +190,7 @@ public: externalCommand_ = cmd; } void DeviceLost(); + void SaveConfig(); private: Path ConfigPath(); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index bbbf6cf386..6c3f2a73cb 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -436,6 +436,7 @@ void runImDebugger(Draw::DrawContext *draw) { // Convert to drawlists. ImGui::Render(); + ImGui_ImplPlatform_SaveIni(false); wantTextInput = io.WantTextInput; } else { uiContext->SetOverrideScreenFrame(nullptr); @@ -1128,19 +1129,13 @@ void NativeShutdownGraphics(GraphicsContext *graphicsContext) { gpu->DeviceLost(); } + // The imgui context and the debugger outlive the graphics, so that their state survives Android + // switching away from the app. Save now anyway, since the app may be killed in the background. if (imguiInited_) { - if (imDebugger_) { - imDebugger_->DeviceLost(); - } + imDebugger_->DeviceLost(); + imDebugger_->SaveConfig(); + ImGui_ImplPlatform_SaveIni(true); ImGui_ImplThin3d_DestroyDeviceObjects(); - ImGui_ImplThin3d_Shutdown(); - // Destroy the debugger here, while the things it refers to are still alive. If left to - // static destruction, ~ImDisasmView runs after Core's globals are gone and its - // g_disassemblyManager.clear() walks a destroyed map (and locks a destroyed mutex). - imDebugger_.reset(); - ImGui::DestroyContext(ctx_); - ctx_ = nullptr; - imguiInited_ = false; } #if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) @@ -1979,6 +1974,19 @@ void NativeShutdown() { g_screenManager = nullptr; } + if (imguiInited_) { + ImGui_ImplPlatform_SaveIni(true); + // The device objects went with NativeShutdownGraphics. + ImGui_ImplThin3d_Shutdown(); + // Destroy the debugger here, while the things it refers to are still alive. If left to + // static destruction, ~ImDisasmView runs after Core's globals are gone and its + // g_disassemblyManager.clear() walks a destroyed map (and locks a destroyed mutex). + imDebugger_.reset(); + ImGui::DestroyContext(ctx_); + ctx_ = nullptr; + imguiInited_ = false; + } + System_Notify(SystemNotification::BEFORE_CONFIG_SAVE_ON_EXIT); g_Config.Save("NativeShutdown"); diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index b50ad96733..c4b778f865 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -510,6 +510,7 @@ void ControlLayoutView::CreateViews() { addDragDropButton(touch.touchSelectKey, "Select button", rectImage, ImageID("I_SELECT")); addDragDropButton(touch.touchStartKey, "Start button", rectImage, ImageID("I_START")); + addDragDropButton(touch.touchHomeKey, "Home button", rectImage, ImageID("I_HOME")); addDragDropButton(touch.touchFastForwardKey, "Fast-forward button", rectImage, ImageID("I_FAST_FORWARD_LINE")); addDragDropButton(touch.touchLKey, "Left shoulder button", shoulderImage, ImageID("I_L")); diff --git a/UI/TouchControlVisibilityScreen.cpp b/UI/TouchControlVisibilityScreen.cpp index fd9a5c4d0c..5a5d79c853 100644 --- a/UI/TouchControlVisibilityScreen.cpp +++ b/UI/TouchControlVisibilityScreen.cpp @@ -92,6 +92,7 @@ void TouchControlVisibilityScreen::CreateDialogViews(UI::ViewGroup *parent) { toggles_.push_back({ "R", &touch.touchRKey.show, ImageID("I_R"), nullptr }); toggles_.push_back({ "Start", &touch.touchStartKey.show, ImageID("I_START"), nullptr }); toggles_.push_back({ "Select", &touch.touchSelectKey.show, ImageID("I_SELECT"), nullptr }); + toggles_.push_back({ "Home", &touch.touchHomeKey.show, ImageID("I_HOME"), nullptr }); toggles_.push_back({ "Dpad", &touch.touchDpad.show, ImageID::invalid(), nullptr }); toggles_.push_back({ "Analog Stick", &touch.touchAnalogStick.show, ImageID::invalid(), nullptr }); toggles_.push_back({ "Right Analog Stick", &touch.touchRightAnalogStick.show, ImageID::invalid(), [=](EventParams &e) { diff --git a/UI/UIAtlas.cpp b/UI/UIAtlas.cpp index 75075085e1..e936252d76 100644 --- a/UI/UIAtlas.cpp +++ b/UI/UIAtlas.cpp @@ -57,6 +57,7 @@ static const ImageMeta g_uiImageIDs[] = { {"I_TRIANGLE", true}, {"I_SELECT", true}, {"I_START", true}, + {"I_HOME", true}, {"I_ARROW", false}, {"I_ROUND", false}, {"I_ROUND_LINE", true}, @@ -105,7 +106,7 @@ static const ImageMeta g_uiImageIDs[] = { {"I_FULLSCREEN", false}, {"I_RESTORE", false}, {"I_SDCARD", false}, - {"I_HOME", false}, + {"I_HOME_ICON", false}, {"I_A", true}, {"I_B", true}, {"I_C", true}, diff --git a/assets/ui_images/buttons.svg b/assets/ui_images/buttons.svg index 09d60fab56..51e7c805c3 100644 --- a/assets/ui_images/buttons.svg +++ b/assets/ui_images/buttons.svg @@ -7,7 +7,7 @@ viewBox="0 0 158.74998 68.791658" version="1.1" id="svg1" - inkscape:version="1.4.2 (f4327f4, 2025-05-13)" + inkscape:version="1.4.4 (dcaf3e7, 2026-05-05)" sodipodi:docname="buttons.svg" xml:space="preserve" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" @@ -25,13 +25,13 @@ inkscape:pagecheckerboard="true" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" - inkscape:zoom="1" - inkscape:cx="177" - inkscape:cy="333.5" - inkscape:window-width="1920" - inkscape:window-height="1129" - inkscape:window-x="-8" - inkscape:window-y="-8" + inkscape:zoom="11.313708" + inkscape:cx="40.65864" + inkscape:cy="91.437746" + inkscape:window-width="3840" + inkscape:window-height="2071" + inkscape:window-x="-9" + inkscape:window-y="-9" inkscape:window-maximized="1" inkscape:current-layer="layer1" showgrid="false" @@ -618,7 +618,11 @@ d="m 27.680138,73.304133 v 1.108926 h 6.03687 v -1.108926 z m 0,2.174666 v 1.064811 h 6.03687 v -1.064811 z m 0,2.160271 v 1.079207 h 6.03687 V 77.63907 Z" />