The empty provider was never load-bearing — the dragless layer frees the rubber band

Measured on real events 2026-08-07, correcting the 2026-08-06 hosted
finding: a bare count-1 tap on LaneView's empty-space layer fires in
~1-3 ms with no drag source at all — the hold that made the empty
.onDrag look necessary was the sterile NSApp.postEvent stream
over-disambiguating. And the provider was actively harmful: even an
empty drag source claims the mouse-drag at threshold, starving the
marquee's simultaneous DragGesture after one sample — the band froze
and the mouseUp never arrived. The layer goes dragless; drags from
empty space belong wholly to MarqueeControl. PointerClick's and the
layer's comments retell the corrected story. Alongside: openCard is
typed @MainActor throughout, which makes the closure Sendable and
lets CardFaceRole carry it under CardFaceView's nonisolated ==.

Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
2026-08-07 12:55:54 -04:00
parent b0ffff1aa1
commit 8aefaf23ce
9 changed files with 42 additions and 36 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ struct BoardView: View {
/// Opens a card's window 's second half (04-interactions.md Grammar). A closure from
/// `BoardWindowHost` rather than an `openWindow` call here, because building a `CardWindowRef`
/// needs the board's own window ref, which is the host's identity and not the board's.
let openCard: (ItemID) -> Void
let openCard: @MainActor (ItemID) -> Void
/// The toolbar search field's handle (`BoardSearchPresentation`), threaded down so the strip can
/// fill in `focusBoard` Escape's "in an empty field it returns focus to the board" needs the