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:
@@ -31,15 +31,18 @@ extension ClickModifier {
|
||||
/// SwiftUI's `TapGesture` hands its handler nothing about the event.
|
||||
///
|
||||
/// **This is how a surface without a drag source gets a double-click meaning** (the 2026-08-06
|
||||
/// click-latency fix). A second tap recogniser is never the way: a sequential
|
||||
/// `.onTapGesture(count: 2)` makes every single click on its subtree wait out the system
|
||||
/// double-click interval — and on macOS even a *simultaneous* two-tap recogniser holds primary
|
||||
/// clicks on views that carry no `.onDrag`. (A drag source forces immediate event delivery, which
|
||||
/// is why the card faces, the lane header and the trash rows — `CardFaceView`'s simultaneous
|
||||
/// arrangement — stay instant; `LaneView`'s empty-space layer measurably does not.) A single
|
||||
/// `.onTapGesture` fires once per click of a run, so branching on this count expresses
|
||||
/// "first click selects, second creates" — Finder's cadence — with exactly one recogniser and
|
||||
/// nothing to disambiguate.
|
||||
/// click-latency fix). A second tap recogniser is never the way: a *multi-click* recogniser on a
|
||||
/// dragless subtree — a sequential `.onTapGesture(count: 2)` or even a simultaneous two-tap —
|
||||
/// makes macOS hold every primary click on that subtree pending disambiguation for the system
|
||||
/// double-click interval. (A real `.onDrag` forces immediate delivery, which is why the card
|
||||
/// faces, the lane header and the trash rows — `CardFaceView`'s simultaneous arrangement — can
|
||||
/// carry one and stay instant. A lone count-1 tap needs no such help: measured on real events
|
||||
/// 2026-08-07, `LaneView`'s dragless empty-space layer fires in ~1–3 ms — there is nothing to
|
||||
/// disambiguate. And an `.onDrag` must never be added there *for* delivery: even an
|
||||
/// empty-provider drag source claims drags outright and kills the rubber band's simultaneous
|
||||
/// `DragGesture`.) A single `.onTapGesture` fires once per click of a run, so branching on this
|
||||
/// count expresses "first click selects, second creates" — Finder's cadence — with exactly one
|
||||
/// recogniser and nothing to disambiguate.
|
||||
enum PointerClick {
|
||||
|
||||
/// The `clickCount` of the click being handled: 1 for a lone click or a run's first, 2 for
|
||||
|
||||
Reference in New Issue
Block a user