Skip to content

Support async Bluetooth pointer movement commands #166

@enaboapps

Description

@enaboapps

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:

  1. Parse/authenticate command exactly as today.
  2. If command is mouse.move and response mode is no-response:
    • enqueue/coalesce movement for async execution.
    • do not call sendResponse(...).
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions