From b47f3ef39770d3cef48852e38cc0354336489750 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 20 Feb 2023 13:19:59 -0600 Subject: [PATCH] Remove input batching to replace with common-c implementation --- app/src/main/java/com/limelight/Game.java | 10 +- .../com/limelight/nvstream/NvConnection.java | 94 +------------------ 2 files changed, 6 insertions(+), 98 deletions(-) diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index c8556875..e1d6c647 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -247,7 +247,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, View backgroundTouchView = findViewById(R.id.backgroundTouchView); backgroundTouchView.setOnTouchListener(this); - boolean needsInputBatching = false; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // Request unbuffered input event dispatching for all input classes we handle here. // Without this, input events are buffered to be delivered in lock-step with VBlank, @@ -266,10 +265,6 @@ public class Game extends Activity implements SurfaceHolder.Callback, InputDevice.SOURCE_CLASS_POSITION | // Touchpads InputDevice.SOURCE_CLASS_TRACKBALL // Mice (pointer capture) ); - - // Since the OS isn't going to batch for us, we have to batch mouse events to - // avoid triggering a bug in GeForce Experience that can lead to massive latency. - needsInputBatching = true; } notificationOverlayView = findViewById(R.id.notificationOverlay); @@ -481,8 +476,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, conn = new NvConnection(getApplicationContext(), new ComputerDetails.AddressTuple(host, port), httpsPort, uniqueId, config, - PlatformBinding.getCryptoProvider(this), serverCert, - needsInputBatching); + PlatformBinding.getCryptoProvider(this), serverCert); controllerHandler = new ControllerHandler(this, conn, this, prefConfig); keyboardTranslator = new KeyboardTranslator(); @@ -1816,7 +1810,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View view, MotionEvent event) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // Tell the OS not to buffer input events for us // diff --git a/app/src/main/java/com/limelight/nvstream/NvConnection.java b/app/src/main/java/com/limelight/nvstream/NvConnection.java index 99fcee89..cc084bde 100644 --- a/app/src/main/java/com/limelight/nvstream/NvConnection.java +++ b/app/src/main/java/com/limelight/nvstream/NvConnection.java @@ -47,21 +47,13 @@ public class NvConnection { private ConnectionContext context; private static Semaphore connectionAllowed = new Semaphore(1); private final boolean isMonkey; - private final boolean batchMouseInput; private final Context appContext; - private static final int MOUSE_BATCH_PERIOD_MS = 5; - private Timer mouseInputTimer; - private final Object mouseInputLock = new Object(); - private short relMouseX, relMouseY, relMouseWidth, relMouseHeight; - private short absMouseX, absMouseY, absMouseWidth, absMouseHeight; - - public NvConnection(Context appContext, ComputerDetails.AddressTuple host, int httpsPort, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert, boolean batchMouseInput) + public NvConnection(Context appContext, ComputerDetails.AddressTuple host, int httpsPort, String uniqueId, StreamConfiguration config, LimelightCryptoProvider cryptoProvider, X509Certificate serverCert) { this.appContext = appContext; this.cryptoProvider = cryptoProvider; this.uniqueId = uniqueId; - this.batchMouseInput = batchMouseInput; this.context = new ConnectionContext(); this.context.serverAddress = host; @@ -95,11 +87,6 @@ public class NvConnection { } public void stop() { - // Stop sending additional input - if (mouseInputTimer != null) { - mouseInputTimer.cancel(); - } - // Interrupt any pending connection. This is thread-safe. MoonBridge.interruptConnection(); @@ -114,24 +101,6 @@ public class NvConnection { connectionAllowed.release(); } - private void flushMousePosition() { - synchronized (mouseInputLock) { - if (relMouseX != 0 || relMouseY != 0) { - if (relMouseWidth != 0 || relMouseHeight != 0) { - MoonBridge.sendMouseMoveAsMousePosition(relMouseX, relMouseY, relMouseWidth, relMouseHeight); - } - else { - MoonBridge.sendMouseMove(relMouseX, relMouseY); - } - relMouseX = relMouseY = relMouseWidth = relMouseHeight = 0; - } - if (absMouseX != 0 || absMouseY != 0 || absMouseWidth != 0 || absMouseHeight != 0) { - MoonBridge.sendMousePosition(absMouseX, absMouseY, absMouseWidth, absMouseHeight); - absMouseX = absMouseY = absMouseWidth = absMouseHeight = 0; - } - } - } - private InetAddress resolveServerAddress() throws IOException { // Try to find an address that works for this host InetAddress[] addrs = InetAddress.getAllByName(context.serverAddress.address); @@ -473,20 +442,6 @@ public class NvConnection { connectionAllowed.release(); return; } - - if (batchMouseInput) { - // High polling rate mice can cause GeForce Experience's input queue to get backed up, - // causing massive input latency. We counter this by limiting our mouse events to 200 Hz - // which appears to avoid triggering the issue on all known configurations. - mouseInputTimer = new Timer("MouseInput", true); - mouseInputTimer.schedule(new TimerTask() { - @Override - public void run() { - // Flush the mouse position every 5 ms - flushMousePosition(); - } - }, MOUSE_BATCH_PERIOD_MS, MOUSE_BATCH_PERIOD_MS); - } } } }).start(); @@ -495,65 +450,27 @@ public class NvConnection { public void sendMouseMove(final short deltaX, final short deltaY) { if (!isMonkey) { - synchronized (mouseInputLock) { - relMouseX += deltaX; - relMouseY += deltaY; - - // Reset these to ensure we don't send this as a position update - relMouseWidth = 0; - relMouseHeight = 0; - } - - if (!batchMouseInput) { - flushMousePosition(); - } + MoonBridge.sendMouseMove(deltaX, deltaY); } } public void sendMousePosition(short x, short y, short referenceWidth, short referenceHeight) { if (!isMonkey) { - synchronized (mouseInputLock) { - absMouseX = x; - absMouseY = y; - absMouseWidth = referenceWidth; - absMouseHeight = referenceHeight; - } - - if (!batchMouseInput) { - flushMousePosition(); - } + MoonBridge.sendMousePosition(x, y, referenceWidth, referenceHeight); } } public void sendMouseMoveAsMousePosition(short deltaX, short deltaY, short referenceWidth, short referenceHeight) { if (!isMonkey) { - synchronized (mouseInputLock) { - // Only accumulate the delta if the reference size is the same - if (relMouseWidth == referenceWidth && relMouseHeight == referenceHeight) { - relMouseX += deltaX; - relMouseY += deltaY; - } - else { - relMouseX = deltaX; - relMouseY = deltaY; - } - - relMouseWidth = referenceWidth; - relMouseHeight = referenceHeight; - } - - if (!batchMouseInput) { - flushMousePosition(); - } + MoonBridge.sendMouseMoveAsMousePosition(deltaX, deltaY, referenceWidth, referenceHeight); } } public void sendMouseButtonDown(final byte mouseButton) { if (!isMonkey) { - flushMousePosition(); MoonBridge.sendMouseButton(MouseButtonPacket.PRESS_EVENT, mouseButton); } } @@ -561,7 +478,6 @@ public class NvConnection { public void sendMouseButtonUp(final byte mouseButton) { if (!isMonkey) { - flushMousePosition(); MoonBridge.sendMouseButton(MouseButtonPacket.RELEASE_EVENT, mouseButton); } } @@ -597,14 +513,12 @@ public class NvConnection { public void sendMouseScroll(final byte scrollClicks) { if (!isMonkey) { - flushMousePosition(); MoonBridge.sendMouseScroll(scrollClicks); } } public void sendMouseHighResScroll(final short scrollAmount) { if (!isMonkey) { - flushMousePosition(); MoonBridge.sendMouseHighResScroll(scrollAmount); } }