Skip to content

Commit

Permalink
Avoid unnecessary reinitialization of PS4/PS5 gamepads during stream …
Browse files Browse the repository at this point in the history
…exit

onInputDeviceChanged() is triggered by starting/stopping pointer capture, so we should
unregister our callbacks before that happens to avoid triggering several gamepad context
reinitializations right as the stream is exiting
  • Loading branch information
cgutman committed Oct 29, 2023
1 parent fc77322 commit c356862
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
22 changes: 19 additions & 3 deletions app/src/main/java/com/limelight/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,6 @@ public void notifyCrash(Exception e) {
keyboardTranslator = new KeyboardTranslator();

InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
inputManager.registerInputDeviceListener(controllerHandler, null);
inputManager.registerInputDeviceListener(keyboardTranslator, null);

// Initialize touch contexts
Expand Down Expand Up @@ -1079,12 +1078,11 @@ public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
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);
}

Expand All @@ -1104,6 +1102,21 @@ protected void onDestroy() {
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();
Expand Down Expand Up @@ -2310,6 +2323,9 @@ public void run() {
// 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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -134,6 +135,7 @@ public ControllerHandler(Activity activityContext, NvConnection conn, GameGestur
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
Expand Down Expand Up @@ -205,6 +207,9 @@ public ControllerHandler(Activity activityContext, NvConnection conn, GameGestur
// 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) {
Expand Down Expand Up @@ -260,9 +265,16 @@ public void onInputDeviceChanged(int deviceId) {
}

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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ private boolean hasCaptureCompatibleInputDevice() {
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();
}
Expand Down

0 comments on commit c356862

Please sign in to comment.