summaryrefslogtreecommitdiff
path: root/src/macos/Sources/PardesView.swift
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-07 14:00:29 -0300
committerGabriel Schneider <[email protected]>2026-09-07 14:10:43 -0300
commit7545cdbf47559d4e996c7d3fc9ae8968a3342292 (patch)
tree1344829ac67c55c2c233e813cd6c32bb8e548281 /src/macos/Sources/PardesView.swift
parent3f2d6f43199d0e230490396deb50f8dc49c7b8b0 (diff)
downloadpardes-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.swift52
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 }