feat(desktop): optional pointer capture (Pointer Lock) with Esc-to-release hint #60

Merged
Claude-Run merged 1 commit from feat/VAPP-49-desktop-pointer-capture into main 2026-06-29 15:10:46 +02:00
Member

Add a default-off "Capture mouse" toggle to the remote-desktop pane toolbar. When armed, the first click on the canvas calls requestPointerLock(); the browser shows its native lock notice and a floating in-app "Mouse captured - press Esc to release" notice appears (a fixed-position div appended to document.body, shown/hidden on pointerlockchange and removed on teardown). Esc, the toggle going Off (which calls exitPointerLock), or any pointerlockchange to unlocked releases capture and clears the hint.

While captured the browser hides the OS cursor and delivers relative movementX/movementY deltas, so the driver accumulates them into a virtual cursor clamped to the remote dims (new clamp_cursor helper, host-tested) and maps that to the existing absolute-coordinate wire format, so no protocol change is needed (the minimal path from the issue). Clicks and wheel use the virtual cursor while locked; keyboard keeps working because the canvas is refocused on lock. The virtual cursor is seeded to the screen centre when the lock engages.

The toggle is a per-session Dioxus signal (not persisted) pushed to the wasm session via DesktopHandle::set_capture; the wasm session owns the lock and the hint so no Dioxus signal is written from a raw JS event callback. Listener now records its own EventTarget so the document-level pointerlock listeners are removed from document (not the canvas) on teardown. Adds the web-sys "Node" feature for the hint's appendChild/textContent.

Relative-motion input was not pursued (the accumulate-to-absolute path is sufficient for the first pass), so no dependent issue is filed.

#VAPP-49

Add a default-off "Capture mouse" toggle to the remote-desktop pane toolbar. When armed, the first click on the canvas calls requestPointerLock(); the browser shows its native lock notice and a floating in-app "Mouse captured - press Esc to release" notice appears (a fixed-position div appended to document.body, shown/hidden on pointerlockchange and removed on teardown). Esc, the toggle going Off (which calls exitPointerLock), or any pointerlockchange to unlocked releases capture and clears the hint. While captured the browser hides the OS cursor and delivers relative movementX/movementY deltas, so the driver accumulates them into a virtual cursor clamped to the remote dims (new clamp_cursor helper, host-tested) and maps that to the existing absolute-coordinate wire format, so no protocol change is needed (the minimal path from the issue). Clicks and wheel use the virtual cursor while locked; keyboard keeps working because the canvas is refocused on lock. The virtual cursor is seeded to the screen centre when the lock engages. The toggle is a per-session Dioxus signal (not persisted) pushed to the wasm session via DesktopHandle::set_capture; the wasm session owns the lock and the hint so no Dioxus signal is written from a raw JS event callback. Listener now records its own EventTarget so the document-level pointerlock listeners are removed from document (not the canvas) on teardown. Adds the web-sys "Node" feature for the hint's appendChild/textContent. Relative-motion input was not pursued (the accumulate-to-absolute path is sufficient for the first pass), so no dependent issue is filed. #VAPP-49
feat(desktop): optional pointer capture (Pointer Lock) with Esc-to-release hint
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 1m18s
Create release / Create release from merged PR (pull_request) Has been skipped
6d64ee2e10
Add a default-off "Capture mouse" toggle to the remote-desktop pane toolbar. When armed, the first click on the canvas calls requestPointerLock(); the browser shows its native lock notice and a floating in-app "Mouse captured - press Esc to release" notice appears (a fixed-position div appended to document.body, shown/hidden on pointerlockchange and removed on teardown). Esc, the toggle going Off (which calls exitPointerLock), or any pointerlockchange to unlocked releases capture and clears the hint.

While captured the browser hides the OS cursor and delivers relative movementX/movementY deltas, so the driver accumulates them into a virtual cursor clamped to the remote dims (new clamp_cursor helper, host-tested) and maps that to the existing absolute-coordinate wire format, so no protocol change is needed (the minimal path from the issue). Clicks and wheel use the virtual cursor while locked; keyboard keeps working because the canvas is refocused on lock. The virtual cursor is seeded to the screen centre when the lock engages.

The toggle is a per-session Dioxus signal (not persisted) pushed to the wasm session via DesktopHandle::set_capture; the wasm session owns the lock and the hint so no Dioxus signal is written from a raw JS event callback. Listener now records its own EventTarget so the document-level pointerlock listeners are removed from document (not the canvas) on teardown. Adds the web-sys "Node" feature for the hint's appendChild/textContent.

Relative-motion input was not pursued (the accumulate-to-absolute path is sufficient for the first pass), so no dependent issue is filed.

#VAPP-49
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-apps!60
No description provided.