From 2bbcbc81c644bd79a675a9c759af89b545d7bf73 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Wed, 22 Jul 2026 11:20:46 +0200 Subject: [PATCH] =?UTF-8?q?fix(apple/cursor):=20disable=20M3=20visibility-?= =?UTF-8?q?based=20auto-flip=20=E2=80=94=20it=20broke=20desktop=20drags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On-glass (Mac ↔ Windows M2c host): the host cursor's VISIBILITY is not a usable 'a game grabbed the mouse' signal — Windows hides the pointer for ordinary desktop activity (clicking, typing). The per-frame forwarder turned those transients into relative_hint=true, so the client flipped desktop→capture→desktop, which (a) warped the cursor to view-centre and (b) flushed held buttons via releaseAll — a spurious mouse-up ~200 ms into every press that broke window dragging/resizing. Disable the auto-flip; the mouse model stays user-driven (⌃⌥⇧M). The hint still rides the wire, unused, for a future M3 that keys off a REAL pointer-lock signal (host-side ClipCursor/raw-input detection) instead of visibility. Co-Authored-By: Claude Fable 5 --- .../PunktfunkKit/Views/StreamView.swift | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/clients/apple/Sources/PunktfunkKit/Views/StreamView.swift b/clients/apple/Sources/PunktfunkKit/Views/StreamView.swift index afa72c40..9c727e6d 100644 --- a/clients/apple/Sources/PunktfunkKit/Views/StreamView.swift +++ b/clients/apple/Sources/PunktfunkKit/Views/StreamView.swift @@ -567,17 +567,14 @@ public final class StreamLayerView: NSView { if prev?.visible != ev.visible || prev?.serial != ev.serial { window?.invalidateCursorRects(for: self) } - // M3 — host-driven mode flip, edge-triggered (a fresh host intent clears a manual - // override): hint ⇒ captured relative; clear ⇒ absolute, reappearing at the host's - // last pointer position. - if lastHint != ev.relativeHint { - lastHint = ev.relativeHint - hintOverride = false - } - if !hintOverride, captured, desktopMouse == ev.relativeHint { - setDesktopMouse(!ev.relativeHint, reappearAt: ev.relativeHint ? nil : (ev.x, ev.y)) - streamInputLog.info("host cursor hint: mouse model flipped to \(self.desktopMouse ? "desktop" : "capture", privacy: .public)") - } + // M3 host-driven auto-flip is DISABLED: `relative_hint` is derived from host cursor + // VISIBILITY, and Windows hides the pointer for ordinary desktop activity (clicking, + // typing) — not just when a game grabs it. Acting on those transients flipped + // desktop→capture→desktop, which warped the cursor to view-centre and flushed held + // buttons (a spurious button-up ~200 ms into every press → broke window drags). Until + // the host exposes a real pointer-LOCK signal (ClipCursor/raw-input, not visibility), + // the mouse model is user-driven only (⌃⌥⇧M). The hint still rides the wire, unused. + _ = (lastHint, hintOverride) } /// Build an `NSCursor` from a forwarded straight-alpha RGBA shape.