diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index 3560eedf..232b6474 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -495,7 +495,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, keyboardTranslator = new KeyboardTranslator(); InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE); - inputManager.registerInputDeviceListener(controllerHandler, null); inputManager.registerInputDeviceListener(keyboardTranslator, null); // Initialize touch contexts @@ -1079,12 +1078,11 @@ public class Game extends Activity implements SurfaceHolder.Callback, protected void onDestroy() { super.onDestroy(); - InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE); if (controllerHandler != null) { - inputManager.unregisterInputDeviceListener(controllerHandler); controllerHandler.destroy(); } if (keyboardTranslator != null) { + InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE); inputManager.unregisterInputDeviceListener(keyboardTranslator); } @@ -1104,6 +1102,21 @@ public class Game extends Activity implements SurfaceHolder.Callback, inputCaptureProvider.destroy(); } + @Override + protected void onPause() { + if (isFinishing()) { + // Stop any further input device notifications before we lose focus (and pointer capture) + if (controllerHandler != null) { + controllerHandler.stop(); + } + + // Ungrab input to prevent further input device notifications + setInputGrabState(false); + } + + super.onPause(); + } + @Override protected void onStop() { super.onStop(); @@ -2310,6 +2323,9 @@ public class Game extends Activity implements SurfaceHolder.Callback, // Let the display go to sleep now getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + // Stop processing controller input + controllerHandler.stop(); + // Ungrab input setInputGrabState(false); diff --git a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java index c75a8b52..96088c43 100644 --- a/app/src/main/java/com/limelight/binding/input/ControllerHandler.java +++ b/app/src/main/java/com/limelight/binding/input/ControllerHandler.java @@ -114,6 +114,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD private final double stickDeadzone; private final InputDeviceContext defaultContext = new InputDeviceContext(); private final GameGestures gestures; + private final InputManager inputManager; private final Vibrator deviceVibrator; private final VibratorManager deviceVibratorManager; private final SensorManager deviceSensorManager; @@ -134,6 +135,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD this.prefConfig = prefConfig; this.deviceVibrator = (Vibrator) activityContext.getSystemService(Context.VIBRATOR_SERVICE); this.deviceSensorManager = (SensorManager) activityContext.getSystemService(Context.SENSOR_SERVICE); + this.inputManager = (InputManager) activityContext.getSystemService(Context.INPUT_SERVICE); this.mainThreadHandler = new Handler(Looper.getMainLooper()); // Create a HandlerThread to process battery state updates. These can be slow enough @@ -205,6 +207,9 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD // currentControllers set which will allow them to properly unplug // if they are removed. initialControllers = getAttachedControllerMask(activityContext); + + // Register ourselves for input device notifications + inputManager.registerInputDeviceListener(this, null); } private static InputDevice.MotionRange getMotionRangeForJoystickAxis(InputDevice dev, int axis) { @@ -260,9 +265,16 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD } public void stop() { + if (stopped) { + return; + } + // Stop new device contexts from being created or used stopped = true; + // Unregister our input device callbacks + inputManager.unregisterInputDeviceListener(this); + for (int i = 0; i < inputDeviceContexts.size(); i++) { InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i); deviceContext.destroy(); diff --git a/app/src/main/java/com/limelight/binding/input/capture/AndroidNativePointerCaptureProvider.java b/app/src/main/java/com/limelight/binding/input/capture/AndroidNativePointerCaptureProvider.java index 3109dcc2..589f4137 100644 --- a/app/src/main/java/com/limelight/binding/input/capture/AndroidNativePointerCaptureProvider.java +++ b/app/src/main/java/com/limelight/binding/input/capture/AndroidNativePointerCaptureProvider.java @@ -65,6 +65,9 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu public void showCursor() { super.showCursor(); + // It is important to unregister the listener *before* releasing pointer capture, + // because releasing pointer capture can cause an onInputDeviceChanged() callback + // for devices with a touchpad (like a DS4 controller). inputManager.unregisterInputDeviceListener(this); targetView.releasePointerCapture(); }