Skip to content

Fix absolute mouse position on multi-monitor targets + touch input - #1519

Open
imcynic wants to merge 2 commits into
jetkvm:devfrom
imcynic:fix/ipad-mouse-offset
Open

Fix absolute mouse position on multi-monitor targets + touch input#1519
imcynic wants to merge 2 commits into
jetkvm:devfrom
imcynic:fix/ipad-mouse-offset

Conversation

@imcynic

@imcynic imcynic commented Jul 6, 2026

Copy link
Copy Markdown

Summary

Two related absolute-mouse positioning fixes:

1. Multi-monitor coordinate mapping (fixes #1446). The USB HID absolute pointer (0..32767) is interpreted by the target OS across the bounding box of the entire multi-monitor desktop, while JetKVM captures a single screen — so on multi-monitor targets, clicks land far away from where you click on the video (measured 1700–3000 px off on a 3-monitor Linux target). This adds an optional device-side remap of absolute coordinates onto the captured screen's rectangle within the full desktop:

  • AbsMouseMappingConfig in the device config (disabled by default, nil-safe, validated: positivity, rect-fits-in-desktop with overflow-safe arithmetic, sane upper bound)
  • Applied at the single rpcAbsMouseReport choke point, covering both the HID-RPC datachannel path and the legacy JSON-RPC path; invalid/absent config falls back to identity (stock behavior)
  • getAbsMouseMapping / setAbsMouseMapping JSON-RPC methods + authenticated GET/POST /mouse-mapping HTTP endpoints (the latter lets host-side automation keep the mapping in sync when the target's display layout changes, without a WebRTC session)
  • New "Multi-Monitor Mapping" section under Settings → Mouse
  • Set failures roll back in-memory state; updates are serialized; persistence errors return 500, validation errors 400

2. Touch-input handling in absolute mode (iPad/tablets). Relative mode needs pointer lock, which doesn't exist on iPadOS — absolute is the only usable mode there, and it had a position offset plus no drag support:

  • Use clientX/clientY against getBoundingClientRect() instead of e.offsetX/offsetY — offsetX/Y is unreliable for touch-synthesized events on iPadOS/WebKit and caused a large offset for touch clients
  • Absolute mode now listens to pointermove (relative mode keeps mousemove for pointer lock), and the video element gets touch-action: none, so touch drags move the remote mouse instead of scrolling the page
  • Non-primary touches are ignored; pointercancel releases buttons; setPointerCapture on pointerdown so a release outside the video element isn't lost (touch already captures implicitly; this covers mouse/pen)
  • Fixed a fullscreenchange listener that was added without cleanup

Test plan

  • Unit tests (mouse_mapping_test.go) for validation, the remap math, and clamping — table-driven, incl. identity/disabled/invalid fallback, boundary (0 / 32767), screen==desktop, overflow and bound cases; run on a physical JetKVM (linux/arm)
  • Closed-loop hardware verification on a 3-monitor Linux (KDE/Wayland) target: browser input → JetKVM USB HID → measured host cursor position. 9-point grid across the video: 0 px max error with mapping enabled (was 1700–3000 px off before); mapping disabled reproduces existing behavior exactly
  • Touch verification with trusted touch events: tap coordinates byte-exact at the target's evdev layer; drags deliver continuous moves with the button held, clean press/release
  • ui lint + tsc clean; frontend + release builds green
  • make test_e2e not run (requires a resettable test device)

Notes: new UI strings are currently in en.json only — happy to run the machine-translate pass or adjust wording per your conventions. Also happy to drop the HTTP endpoints if you'd prefer the RPC surface only.

imcynic added 2 commits July 6, 2026 18:17
…ts and touch clients

Absolute mouse coordinates (0..32767) are interpreted by the target OS
across the bounding box of the entire desktop, while JetKVM captures a
single screen — on multi-monitor targets every click landed far from
the video position (jetkvm#1446). Adds an optional device-side mapping
(config + getAbsMouseMapping/setAbsMouseMapping RPCs + authenticated
/mouse-mapping HTTP endpoints) that remaps coordinates onto the
captured screen's rectangle, applied at the single rpcAbsMouseReport
choke point, plus a Mouse settings section to configure it.

Touch clients (iPadOS Safari): absolute handler now uses
clientX/clientY against getBoundingClientRect instead of offsetX/Y
(unreliable for touch-synthesized events on WebKit), listens to
pointermove instead of mousemove in absolute mode, marks the video
touch-action:none so drags emit pointer events instead of scrolling,
ignores non-primary touches, and releases buttons on pointercancel.
- Serialize mapping updates and guard the config pointer with a dedicated
  RWMutex; roll back in-memory state when persisting fails
- Bound mapping dimensions (1<<20) against overflow and float precision loss
- Return 500 for persistence failures, 400 only for invalid mappings
- Capture the pointer on pointerdown in absolute mode so button releases
  outside the video element are not lost
- Clean up the fullscreenchange listener; guard NaN in mapping form inputs
- Add on-device unit tests for validate/apply/clamp incl. overflow and
  boundary cases
@CLAassistant

CLAassistant commented Jul 6, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@imcynic

imcynic commented Jul 7, 2026

Copy link
Copy Markdown
Author

CLA assistant check Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.

Bryan seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Not signing a CLA, you're welcome to reference and rewrite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Absolute Mouse Position in Multi-Screen Setup

2 participants