summaryrefslogtreecommitdiff
path: root/docs/macos.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/macos.md')
-rw-r--r--docs/macos.md73
1 files changed, 45 insertions, 28 deletions
diff --git a/docs/macos.md b/docs/macos.md
index 7f695000..ff19ff93 100644
--- a/docs/macos.md
+++ b/docs/macos.md
@@ -61,10 +61,12 @@ removing; it is the encoding being right.
The one real difference is IO. The browser has no ptys, so `src/web.zig`
forwards every effect out to JavaScript as a numbered code plus a byte payload,
and JavaScript performs it. macOS has `forkpty`, `read` and `write` right there,
-so effects never cross the boundary at all: `pardes_tick` drains the core's
-effect queue and performs each one in Zig, the way `drainEffects` in
-`src/tty/tty.zig` does. That is why the runtime struct is two callbacks and not
-twelve.
+so almost no effect crosses the boundary at all: `pardes_tick` drains the
+core's effect queue and performs each one in Zig, the way `drainEffects` in
+`src/tty/tty.zig` does. That is why the runtime struct is three callbacks and
+not twelve — and why two of the three are the clipboard: the pasteboard is
+AppKit's, in both directions, and is the one piece of IO the Zig side cannot
+reach for itself.
## The seam
@@ -100,13 +102,20 @@ is made of and what opens a path from argv or the Dock (`Look <path>`).
it. `pardes_resize` also carries one cell in *physical* pixels, which only the
native PDF placement path reads — pass the backing-store size, not points.
-**Runtime callbacks.** `pardes_runtime_s` is a `userdata` and two functions,
+**Runtime callbacks.** `pardes_runtime_s` is a `userdata` and three functions,
copied by value during init so the struct need not outlive the call. `wakeup`
-means "your state moved, please pump me"; `set_clipboard` fires inside a tick
-when the yank register changes, with the text borrowed for the duration of the
-call. There is no `open_url` callback because the core already opens links
-itself through `/usr/bin/open` (`src/look.zig`), and no file callbacks because
-it owns the filesystem side too.
+means "your state moved, please pump me". `set_clipboard` hands over text to put
+on the pasteboard, borrowed for the duration of the call; it fires inside a tick
+for the five `SPC` clipboard words and for the tag's own `y` chord, and for
+nothing else — an ordinary `y` or `d` writes the core's register and never
+reaches here, which is what stopped deleting a character from clobbering the
+desktop's clipboard. `read_clipboard` is that direction reversed: "give me the
+pasteboard", with no payload either way, because the host answers by calling
+`pardes_paste` — and NSPasteboard being synchronous, that usually happens inside
+the callback itself, before it returns. Both are main thread, inside
+`pardes_tick`. There is no `open_url` callback because the core already opens
+links itself through `/usr/bin/open` (`src/look.zig`), and no file callbacks
+because it owns the filesystem side too.
**Lifecycle.** `pardes_init` returns 0 or an opaque nonzero code,
`pardes_deinit` tears down, `pardes_tick` drains pty output plus the effect
@@ -195,11 +204,14 @@ already-Exec is the only case with nothing to do. The view also needs
system's business and never arrives — and the user needs "Force Click and
haptic feedback" on in System Settings, which nothing in this process can read.
-Twisting two fingers is a dial, and a dial over a list of search hits is `n`.
-`pardes_rotate` takes raw degrees and libpardes quantizes them, one search step
-per 10°, keeping the remainder — the same accumulate-and-spend shape as
-`pardes_scroll`, in Zig for the same reason: it is then unit-tested on a machine
-with no trackpad. AppKit reports counterclockwise as positive and the forward
+Twisting two fingers is a dial, and a dial over a list of look-able places is
+`n`. A notch moves the SELECTION one place along and opens nothing; Enter opens
+the one the dial stopped at, which is what makes the dial worth spinning at all
+— a stepper that opened every place it passed could not be. `pardes_rotate`
+takes raw degrees and libpardes quantizes them, one step per 10°, keeping the
+remainder — the same accumulate-and-spend shape as `pardes_scroll`, in Zig for
+the same reason: it is then unit-tested on a machine with no trackpad. AppKit
+reports counterclockwise as positive and the forward
step is clockwise, so the sign inverts here and nowhere else. The banked
remainder is deliberate hysteresis; a gesture beginning passes 0 to clear it, so
the first degree of a new twist cannot inherit a nearly-complete notch from the
@@ -244,10 +256,11 @@ asserting the machine's timer jitter.
Both halves are goldens. `rotate.snap` turns the dial at 4° per 100 ms (40°/s,
under the floor) and asserts the screen is byte-identical across the release,
then at 12° per 5 ms and asserts it is not. The list it walks is twenty-four
-hits rather than three for a reason worth keeping: `n` at the last match has
-nowhere to go, so on a short list the hardest possible flick and no flick at
-all produce the same screen — a golden that would have passed before momentum
-existed.
+places rather than three for a reason worth keeping, and `n`/`N` becoming a
+RING only sharpened it: a short ring comes round, so a hard flick can stop
+exactly where a single notch would have and the two screens agree — a golden
+that passes before momentum exists. Twenty-four is longer than the cap can
+travel (about eleven), so the fling has nowhere to hide.
## A drop is a click plus Look
@@ -306,8 +319,11 @@ the *word under the pointer* and most words resolve to nothing:
and the screen does not move. The pulse still fires — the gesture worked.
- **Exec** (three fingers) on a builtin name runs it. On ordinary prose it types
that word at a shell, which needs a terminal pane to type into.
-- **`n`/`N`** (twist) steps a results buffer. With no `/pattern`, Grep or Find
- behind it there is nothing to step.
+- **`n`/`N`** (twist) moves the SELECTION to the next look-able place and opens
+ nothing; Enter opens what it landed on. It walks a ring across panes — the
+ ones a Look came from first, then the output buffers none has — so a twist
+ with no results buffer anywhere still steps the pane in front of you. A screen
+ with no filename on it is what has nothing to step.
`PARDES_LOG=1` prints every decoded gesture to stderr — the fingers counted, the
stream it came in on, the button it resolved to, the pressure stage, the
@@ -319,12 +335,13 @@ because guessing at that from a screenshot cost an afternoon.
Every Exec and every Look taps the trackpad. The core arms a one-slot pulse in
the ONE dispatcher — `lookAt` and `execute`, the two functions a middle click, a
-right click, Enter, Tab, a tag chord, `n`/`N` stepping and the `Look`/`Exec`
-builtins all funnel into — and the host takes it once per pump with
-`pardes_take_haptic`. Exec gets `.generic`, the definite tap of something done;
-Look gets `.alignment`, the lighter detent AppKit uses when a dragged guide
-snaps. A pulse, not a queue: five Execs inside one keystroke are one thing the
-hand did.
+right click, Enter, Tab, a tag chord and the `Look`/`Exec` builtins all funnel
+into — and the host takes it once per pump with `pardes_take_haptic`. Exec gets
+`.generic`, the definite tap of something done; Look gets `.alignment`, the
+lighter detent AppKit uses when a dragged guide snaps. A pulse, not a queue:
+five Execs inside one keystroke are one thing the hand did. A twist taps nothing
+now that `n`/`N` only move the selection, and that is the honest report: the
+detent belongs to the Enter that opens, and that is where it fires.
Three details are load-bearing. `execute` arms only at `exec_depth == 0`,
because `Exec ls` re-enters as `ls` and one Tab is one gesture however many
@@ -672,7 +689,7 @@ zig build unit-test -Dplatform=macos
That covers the ABI's Zig side, the effect drain, and the two quantizers the
trackpad depends on — `takeScrollTicks` and `takeRotationNotches` are pure
-functions precisely so that "how many search steps is a 180° twist" is answerable
+functions precisely so that "how many notches is a 180° twist" is answerable
on a machine with no trackpad in it.
The header is kept honest with ghostty's trick. `build.zig` runs `translate-C`