From 25d216a20ac9904188be6b2fd33c3afa158b056d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 26 Jan 2026 11:08:55 +0100 Subject: [PATCH] Release all keys and axes on game controller disconnect on Android --- Core/KeyMap.cpp | 4 ++-- .../org/ppsspp/ppsspp/InputDeviceState.java | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index 3f387e2d16..5428f17c37 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -847,8 +847,8 @@ void NotifyPadConnected(InputDeviceID deviceId, std::string_view name) { g_seenPads.insert(std::string(name)); g_padNames[deviceId] = name; - // Don't notify within the first 8 seconds, to avoid notification spam on startup. - if (time_now_d() >= 8.0) { + // Don't notify within the first 5 seconds, to avoid notification spam on startup. + if (time_now_d() >= 5.0) { auto co = GetI18NCategory(I18NCat::CONTROLS); g_OSD.Show(OSDType::MESSAGE_SUCCESS, ApplySafeSubstitutions("%1: %2", co->T("Game controller connected"), name), "", "I_CONTROLLER", 2.0f, "controller_connected"); } diff --git a/android/src/org/ppsspp/ppsspp/InputDeviceState.java b/android/src/org/ppsspp/ppsspp/InputDeviceState.java index 075e6f94bc..c42df7290c 100644 --- a/android/src/org/ppsspp/ppsspp/InputDeviceState.java +++ b/android/src/org/ppsspp/ppsspp/InputDeviceState.java @@ -5,11 +5,14 @@ import android.view.InputDevice; import android.view.InputDevice.MotionRange; import android.view.KeyEvent; import android.view.MotionEvent; +import java.util.Set; +import java.util.HashSet; + public class InputDeviceState { private static final String TAG = "InputDeviceState"; - private int deviceId; + private final int deviceId; private final InputDevice mDevice; private final int[] mAxes; @@ -21,6 +24,9 @@ public class InputDeviceState { private final int sources; + private final Set pressedKeys = new HashSet<>(); + + InputDevice getDevice() { return mDevice; } @@ -140,6 +146,15 @@ public class InputDeviceState { public void Disconnect() { NativeApp.sendMessageFromJava("inputDeviceDisconnectedID", String.valueOf(this.deviceId)); + // Also reset all the buttons and axes. + for (int value : pressedKeys) { + NativeApp.keyUp(deviceId, value); + } + pressedKeys.clear(); + for (int i = 0; i < mAxes.length; i++) { + mValues[i] = 0.0f; + } + NativeApp.joystickAxis(deviceId, mAxes, mValues, mAxes.length); } // This is called from dispatchKeyEvent. @@ -150,11 +165,13 @@ public class InputDeviceState { if (isInvalidKeyCode(keyCode) && isEventSentByNintendoSwitchLeftJoyCon(event)) { int remappedKeyCode = remapNintendoSwitchLeftJoyConKeyCodeFromScanCode(event.getScanCode()); if (remappedKeyCode != 0) { + pressedKeys.add(remappedKeyCode); // need to pass false for the repeat flag, otherwise pressing two adjacent dpad buttons simultaneously to move diagonally does not work. return NativeApp.keyDown(deviceId, remappedKeyCode, false); } } + pressedKeys.add(keyCode); return NativeApp.keyDown(deviceId, keyCode, repeat); } @@ -172,10 +189,10 @@ public class InputDeviceState { return NativeApp.keyUp(deviceId, keyCode); } - public boolean onJoystickMotion(MotionEvent event) { + public void onJoystickMotion(MotionEvent event) { if (!inputSourceIsJoystick(event.getSource())) { Log.i(TAG, "Not a joystick event: source = " + event.getSource()); - return false; + return; } int count = 0; for (int i = 0; i < mAxes.length; i++) { @@ -189,7 +206,6 @@ public class InputDeviceState { } } NativeApp.joystickAxis(deviceId, mAxisIds, mValues, count); - return true; } private boolean isInvalidKeyCode(int keyCode) {