diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-07 14:00:29 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-07 14:10:43 -0300 |
| commit | 7545cdbf47559d4e996c7d3fc9ae8968a3342292 (patch) | |
| tree | 1344829ac67c55c2c233e813cd6c32bb8e548281 /src/macos/Sources/PardesView.swift | |
| parent | 3f2d6f43199d0e230490396deb50f8dc49c7b8b0 (diff) | |
| download | pardes-7545cdbf47559d4e996c7d3fc9ae8968a3342292.tar.gz pardes-7545cdbf47559d4e996c7d3fc9ae8968a3342292.zip | |
macos: use two-finger click for Exec and deep press for Look
Diffstat (limited to 'src/macos/Sources/PardesView.swift')
| -rw-r--r-- | src/macos/Sources/PardesView.swift | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/src/macos/Sources/PardesView.swift b/src/macos/Sources/PardesView.swift index 3f5f1346..f9afa7b1 100644 --- a/src/macos/Sources/PardesView.swift +++ b/src/macos/Sources/PardesView.swift @@ -45,25 +45,27 @@ protocol PardesViewDelegate: AnyObject { /// constructed, so this is the part of the gesture a test can reach. /// /// acme's three buttons are the whole vocabulary — 1 selects, 2 executes, -/// 3 looks — and a trackpad has one surface. Two fingers is the gesture macOS -/// itself spells "secondary", so it is Look; three is the one left over, so it -/// is Exec, the heavier verb, which is also what a deep press means. +/// 3 looks — and a trackpad has one surface. More than one finger is Exec, +/// because running something is what a hand does over and over and it gets +/// the gesture that costs nothing; Look is the deep press, one deliberate +/// push past the click for the verb that goes somewhere. /// -/// The finger count has to win over the stream, and that is not a preference. -/// macOS's secondary click is "click or tap with TWO OR MORE fingers": with it -/// on, a three-finger click is delivered as rightMouseDown exactly like a -/// two-finger one, and a view that trusts the stream cannot tell them apart — -/// three fingers silently did Look. Measured on real hardware, which is the -/// only way this was ever going to be found: `rightMouseDown: resting=3`. +/// Two and three fingers are the same verb here, and that is the hardware +/// talking rather than a shrug. macOS's secondary click is "click or tap with +/// TWO OR MORE fingers": with it on — the default — a three-finger click is +/// delivered as rightMouseDown exactly like a two-finger one, and a view that +/// trusts the stream calls both of them Look. Measured on real hardware, which +/// is the only way this was ever going to be found: +/// `rightMouseDown: resting=3`. So the count is what keeps a multi-finger +/// click off Look, and the stream cannot be trusted to do it. /// -/// So the stream is only the fallback, for when there are no fingers to count: +/// The stream is only the fallback, for when there are no fingers to count: /// a real mouse's right button is Look and its middle button is Exec, and both /// arrive with an empty touch set. enum Trackpad { static func button(stream: pardes_mouse_button_e, fingers: Int) -> pardes_mouse_button_e { switch fingers { - case 2: return PARDES_MOUSE_RIGHT - case 3...: return PARDES_MOUSE_MIDDLE + case 2...: return PARDES_MOUSE_MIDDLE // One finger, or none to count: the stream is the answer. A trackpad // single click comes in on the left stream and stays left; a real // mouse's right and middle buttons keep their acme meanings. @@ -72,9 +74,9 @@ enum Trackpad { } /// A force click is a deliberate second gesture on top of an ordinary one, - /// so it gets the verb that does something rather than the one that - /// navigates. - static let forceClickButton: pardes_mouse_button_e = PARDES_MOUSE_MIDDLE + /// so it gets the verb that goes somewhere rather than the one that runs + /// something: press harder and you Look. + static let forceClickButton: pardes_mouse_button_e = PARDES_MOUSE_RIGHT } // Matches bg_default/fg_default in src/gui/gui.zig and DEFAULT_FG/DEFAULT_BG in @@ -643,7 +645,7 @@ final class PardesView: NSView { // hardware it does not always: AppKit routes NSTouch through the four // touchesXxx callbacks, and the touch set hanging off a *mouse* event can // come back empty depending on how the click was produced. Empty reads as - // one finger, which is a two-finger Look silently degrading into a select + // one finger, which is a two-finger Exec silently degrading into a select // — the exact failure this was supposed to avoid. So the count is // maintained here and the mouse event's own set is preferred only when it // has something in it. @@ -674,7 +676,7 @@ final class PardesView: NSView { registerForDraggedTypes([.fileURL]) // Indirect touches are the trackpad's. Without this the touch set is // always empty and every click looks like one finger, which is exactly - // the bug that would make two-finger Look silently never fire. + // the bug that would make two-finger Exec silently never fire. allowedTouchTypes = [.indirect] // Without a pressure configuration the deep-press stages are the // system's business and stage 2 may never be delivered here. @@ -1737,15 +1739,17 @@ final class PardesView: NSView { /// flight. AppKit keeps sending stage-2 events while the finger stays down, /// so only the transition counts. /// - /// Whatever button is in flight is released before the middle one goes out: - /// a middle press arriving while the core holds a left select-drag is - /// acme's 1-2 chord, which is Cut. Releasing first costs a cursor move at - /// the click point — which is what clicking there would have done anyway. + /// Whatever button is in flight is released before the look one goes out: + /// a right press arriving while the core holds a left select-drag is + /// acme's 1-3 chord, which is Paste. Releasing first costs a cursor move + /// at the click point — which is what clicking there would have done + /// anyway; a multi-finger press released this way fires its own Exec, + /// which is what the fingers already asked for. /// /// Not gated on the press being a LEFT one, which is what stopped this /// working: on a Force Touch trackpad the deep press is just as likely to - /// have arrived on the right stream, and an in-flight Look upgraded by - /// pressing harder is precisely the gesture. Already-Exec is the only case + /// have arrived on the right stream, and an in-flight Exec upgraded by + /// pressing harder is precisely the gesture. Already-Look is the only case /// with nothing to do. override func pressureChange(with event: NSEvent) { trace("pressure: stage=\(event.stage) latched=\(String(describing: latchedButton?.rawValue))") @@ -1829,7 +1833,7 @@ final class PardesView: NSView { /// (secondary click, three-finger drag, force click, "look up"), none of /// which this process can read, and every one of which turns a gesture into /// a different NSEvent or into none at all. When someone reports that - /// two-finger Look does nothing, this is the only thing that can answer + /// two-finger Exec does nothing, this is the only thing that can answer /// whether AppKit saw two fingers, one, or no click at all. private func trace(_ message: @autoclosure () -> String) { guard PardesView.tracing else { return } |
