Summary
Make high-frequency Bluetooth pointer movement commands asynchronous on Switchify PC so Android can send movement without waiting for a command completion acknowledgement for every packet.
This is the PC-side companion to the Android sender change. The first target should be mouse.move only. Keep clicks, drag boundaries, keyboard, text, media, window, pairing, ping, profile, and disconnect-intent commands on the existing request/response path.
Current behavior
Relevant PC code:
src/main/bluetooth/bluetooth-transport.ts
- reassembles BLE frames and awaits
controlService.handleRemoteMessage(...).
src/main/control/control-service.ts
- forwards remote messages to
RemoteSessionManager.
src/main/transport/remote-session-manager.ts
- validates/authenticates each message.
- executes normal commands via
executeCommand(...).
- sends
ack only after successful execution.
src/main/input/command-executor.ts
- queues pointer actions through
pointerActionQueue.
- executes mouse movement through the desktop input adapter.
Today the Bluetooth ack for normal commands means validated and executed, not merely received. That creates a BLE round-trip for every movement command.
Android behavior this must support
The Android app currently waits for an ack for every command:
SwitchifyPcBleClient.sendExpected(...) waits for a matching response id.
- live
sendCommand(...) is serialized by a sendMutex.
PcBleGattClient.sendAndReceive(...) writes all frames, then waits for one response notification.
PcMouseControlViewModel sets isBusy and drops new commands while waiting for ack.
The paired Android issue should introduce a send-only path for movement. This PC issue should provide the matching server behavior.
Target behavior
- Authenticated
mouse.move commands can be sent as no-response/fire-and-forget commands.
- PC still validates and authenticates the message before executing movement.
- PC does not send an ack for no-response movement commands.
- PC coalesces queued movement deltas so stale movement does not accumulate if Android sends faster than Windows input can consume.
- Existing ack/result behavior remains unchanged for all non-movement commands.
- Invalid auth/malformed payload handling for normal request/response commands remains unchanged.
Implementation notes
Suggested protocol shape:
- Add an optional request field such as
responseMode: 'none' | 'ack' or equivalent.
- Default missing value to the current ack behavior for backward compatibility.
- Only allow no-response mode for explicitly supported pointer commands, initially
mouse.move.
Suggested PC flow:
- Parse/authenticate command exactly as today.
- If command is
mouse.move and response mode is no-response:
- enqueue/coalesce movement for async execution.
- do not call
sendResponse(...).
- For all other commands:
- preserve current execute-then-ack behavior.
Tests
Add or update PC tests to cover:
- no-response
mouse.move is authenticated and executed without sending an ack.
- unsupported no-response command types fall back to error or acked behavior as designed.
- normal
mouse.move without no-response still sends ack for backward compatibility.
- coalescing prevents stale movement backlog.
- invalid auth is still rejected safely.
Acceptance criteria
- PC supports an authenticated no-response path for
mouse.move.
- PC does not send ack for no-response movement packets.
- PC coalesces movement so latency does not grow under high input rate.
- Existing request/response behavior remains for all other commands.
- Existing Android clients that still expect movement acks remain compatible.
- Tests cover the new movement path.
Summary
Make high-frequency Bluetooth pointer movement commands asynchronous on Switchify PC so Android can send movement without waiting for a command completion acknowledgement for every packet.
This is the PC-side companion to the Android sender change. The first target should be
mouse.moveonly. Keep clicks, drag boundaries, keyboard, text, media, window, pairing, ping, profile, and disconnect-intent commands on the existing request/response path.Current behavior
Relevant PC code:
src/main/bluetooth/bluetooth-transport.tscontrolService.handleRemoteMessage(...).src/main/control/control-service.tsRemoteSessionManager.src/main/transport/remote-session-manager.tsexecuteCommand(...).ackonly after successful execution.src/main/input/command-executor.tspointerActionQueue.Today the Bluetooth ack for normal commands means validated and executed, not merely received. That creates a BLE round-trip for every movement command.
Android behavior this must support
The Android app currently waits for an ack for every command:
SwitchifyPcBleClient.sendExpected(...)waits for a matching response id.sendCommand(...)is serialized by asendMutex.PcBleGattClient.sendAndReceive(...)writes all frames, then waits for one response notification.PcMouseControlViewModelsetsisBusyand drops new commands while waiting for ack.The paired Android issue should introduce a send-only path for movement. This PC issue should provide the matching server behavior.
Target behavior
mouse.movecommands can be sent as no-response/fire-and-forget commands.Implementation notes
Suggested protocol shape:
responseMode: 'none' | 'ack'or equivalent.mouse.move.Suggested PC flow:
mouse.moveand response mode is no-response:sendResponse(...).Tests
Add or update PC tests to cover:
mouse.moveis authenticated and executed without sending an ack.mouse.movewithout no-response still sends ack for backward compatibility.Acceptance criteria
mouse.move.