From b2dd5b6d70a746e546ed2bdff18613a54ca18bfd Mon Sep 17 00:00:00 2001 From: phobos665 Date: Mon, 18 May 2026 13:45:15 +0100 Subject: [PATCH 1/3] feat(): Pre-allocate the SDL byte array rather than initializing it on every frame. Should see a tiny performance improvement. --- app/src/main/java/com/winlator/winhandler/WinHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/winlator/winhandler/WinHandler.java b/app/src/main/java/com/winlator/winhandler/WinHandler.java index df97ade100..ec14c17ff6 100644 --- a/app/src/main/java/com/winlator/winhandler/WinHandler.java +++ b/app/src/main/java/com/winlator/winhandler/WinHandler.java @@ -74,6 +74,7 @@ public class WinHandler { private final ArrayList xinputProcesses; private final XServer xServer; private final XServerView xServerView; + private byte[] sdlButtons = new byte[15]; private InputControlsView inputControlsView; private Thread rumblePollerThread; @@ -811,7 +812,7 @@ private void sendMemoryFileState(ExternalController controller, MappedByteBuffer buffer.putShort((short)lAxis); buffer.putShort((short)rAxis); // --- Buttons and D-Pad are perfect. No changes here. --- - byte[] sdlButtons = new byte[15]; + sdlButtons[0] = state.isPressed(0) ? (byte)1 : (byte)0; // A sdlButtons[1] = state.isPressed(1) ? (byte)1 : (byte)0; // B sdlButtons[2] = state.isPressed(2) ? (byte)1 : (byte)0; // X From 39bb8a3989f4a6defe61cb45064732debfb55e18 Mon Sep 17 00:00:00 2001 From: phobos665 Date: Mon, 18 May 2026 13:52:40 +0100 Subject: [PATCH 2/3] feat(): Adjust sendVirtualGamepadState to also use the instance's sdlButtons. Note: these changes are only for the single-controller support. Later we should update this file to do proper multi-controller support. --- .../com/winlator/winhandler/WinHandler.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/winlator/winhandler/WinHandler.java b/app/src/main/java/com/winlator/winhandler/WinHandler.java index ec14c17ff6..992395693a 100644 --- a/app/src/main/java/com/winlator/winhandler/WinHandler.java +++ b/app/src/main/java/com/winlator/winhandler/WinHandler.java @@ -852,21 +852,21 @@ public void sendVirtualGamepadState(GamepadState state) { gamepadBuffer.putShort((short)rAxis); // Buttons & D-Pad - byte[] sdlButtons = new byte[15]; - sdlButtons[0] = state.isPressed(0) ? (byte)1 : (byte)0; // A - sdlButtons[1] = state.isPressed(1) ? (byte)1 : (byte)0; // B - sdlButtons[2] = state.isPressed(2) ? (byte)1 : (byte)0; // X - sdlButtons[3] = state.isPressed(3) ? (byte)1 : (byte)0; // Y - sdlButtons[9] = state.isPressed(4) ? (byte)1 : (byte)0; // Left Bumper - sdlButtons[10] = state.isPressed(5) ? (byte)1 : (byte)0; // Right Bumper - sdlButtons[4] = state.isPressed(6) ? (byte)1 : (byte)0; // Select/Back - sdlButtons[6] = state.isPressed(7) ? (byte)1 : (byte)0; // Start - sdlButtons[7] = state.isPressed(8) ? (byte)1 : (byte)0; // Left Stick - sdlButtons[8] = state.isPressed(9) ? (byte)1 : (byte)0; // Right Stick - sdlButtons[11] = state.dpad[0] ? (byte)1 : (byte)0; // DPAD_UP - sdlButtons[12] = state.dpad[2] ? (byte)1 : (byte)0; // DPAD_DOWN - sdlButtons[13] = state.dpad[3] ? (byte)1 : (byte)0; // DPAD_LEFT - sdlButtons[14] = state.dpad[1] ? (byte)1 : (byte)0; // DPAD_RIGHT + + this.sdlButtons[0] = state.isPressed(0) ? (byte)1 : (byte)0; // A + this.sdlButtons[1] = state.isPressed(1) ? (byte)1 : (byte)0; // B + this.sdlButtons[2] = state.isPressed(2) ? (byte)1 : (byte)0; // X + this.sdlButtons[3] = state.isPressed(3) ? (byte)1 : (byte)0; // Y + this.sdlButtons[9] = state.isPressed(4) ? (byte)1 : (byte)0; // Left Bumper + this.sdlButtons[10] = state.isPressed(5) ? (byte)1 : (byte)0; // Right Bumper + this.sdlButtons[4] = state.isPressed(6) ? (byte)1 : (byte)0; // Select/Back + this.sdlButtons[6] = state.isPressed(7) ? (byte)1 : (byte)0; // Start + this.sdlButtons[7] = state.isPressed(8) ? (byte)1 : (byte)0; // Left Stick + this.sdlButtons[8] = state.isPressed(9) ? (byte)1 : (byte)0; // Right Stick + this.sdlButtons[11] = state.dpad[0] ? (byte)1 : (byte)0; // DPAD_UP + this.sdlButtons[12] = state.dpad[2] ? (byte)1 : (byte)0; // DPAD_DOWN + this.sdlButtons[13] = state.dpad[3] ? (byte)1 : (byte)0; // DPAD_LEFT + this.sdlButtons[14] = state.dpad[1] ? (byte)1 : (byte)0; // DPAD_RIGHT gamepadBuffer.put(sdlButtons); gamepadBuffer.put((byte)0); // Ignored HAT value } From 9f32503981ae18ec47f9ff56f68f8e9909ca2a9c Mon Sep 17 00:00:00 2001 From: phobos665 Date: Mon, 18 May 2026 14:02:56 +0100 Subject: [PATCH 3/3] feat(): fix an issue with potentially a duplicate polling thread for the same input listening. Checks for the running thread, and will run it if not already running. --- .../java/com/winlator/winhandler/WinHandler.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/winlator/winhandler/WinHandler.java b/app/src/main/java/com/winlator/winhandler/WinHandler.java index 992395693a..bb0dcc29af 100644 --- a/app/src/main/java/com/winlator/winhandler/WinHandler.java +++ b/app/src/main/java/com/winlator/winhandler/WinHandler.java @@ -547,8 +547,12 @@ public void start() { } catch (UnknownHostException e2) { } } - this.running = true; - startSendThread(); + + if(!this.running) { + this.running = true; + startSendThread(); + } + Executors.newSingleThreadExecutor().execute(() -> { try { DatagramSocket datagramSocket = new DatagramSocket((SocketAddress) null); @@ -568,8 +572,10 @@ public void start() { }); startRumblePoller(); - running = true; - startSendThread(); + if(!running) { + running = true; + startSendThread(); + } } private void startRumblePoller() {