fix: hide + freeze the local cursor while streaming
ci / rust (push) Has been cancelled

The host renders its own cursor from our raw deltas, so the local macOS cursor both
stays visible and drifts away from the remote one — and it can wander out of the window,
where a click focuses another app. While the stream has focus, do what Moonlight does:
warp the cursor mid-view, disconnect it from mouse movement
(CGAssociateMouseAndMouseCursorPosition(false) — GCMouse still delivers raw HID deltas),
and hide it. Released on app deactivation (Cmd+Tab is the escape hatch), view teardown,
and disconnect; re-captured when the stream regains focus. The HUD's Disconnect gains ⌘D
since a hidden, frozen cursor can't click it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 15:38:03 +02:00
parent bfd64ce871
commit 9aa2d71f49
3 changed files with 71 additions and 4 deletions
+6 -3
View File
@@ -103,9 +103,12 @@ PUNKTFUNK_AUTOCONNECT=<box-ip> PUNKTFUNK_MODE=1280x720x60 swift run PunktfunkCli
doesn't persist fingerprints yet — add it alongside the "add host" UX.
8. **Input capture caveats** (stage 1): GC handlers only fire while the app has focus —
on focus loss `InputCapture` auto-releases everything still held (keys + buttons) so
nothing sticks down host-side. Local shortcuts (⌘-anything) still also reach the host;
a capture toggle is a small follow-up. One live capture per process (the GC mouse/
keyboard singletons have a single handler slot — ownership is tracked so a stale
nothing sticks down host-side. While the stream has focus the LOCAL cursor is hidden
and frozen mid-view (`CursorCapture` in StreamView.swift — the host renders its own
cursor; the local one diverges from it and a stray click would focus another app);
Cmd+Tab frees it, ⌘D disconnects. Local shortcuts (⌘-anything) still also reach the
host; a capture toggle is a small follow-up. One live capture per process (the GC
mouse/keyboard singletons have a single handler slot — ownership is tracked so a stale
capture's stop() can't clobber a newer one).
9. **iOS**: same package (`BUILD_IOS=1` for the xcframework slice); `StreamView` needs the
`UIViewRepresentable` twin and touch→input mapping.