diff options
Diffstat (limited to 'docs/macos.md')
| -rw-r--r-- | docs/macos.md | 78 |
1 files changed, 17 insertions, 61 deletions
diff --git a/docs/macos.md b/docs/macos.md index 0ce29bf9..2d9fb1cc 100644 --- a/docs/macos.md +++ b/docs/macos.md @@ -430,59 +430,17 @@ without a Force Touch trackpad and when the user has feedback switched off, so a check here would only be a second place to be wrong — and it would be wrong the moment an external trackpad is plugged in mid-session. -## libproc, twice +## Shell directories and nested Look -Two features on this backend want to know something about a process that is not -us, and on Linux both answers live in `/proc`. Darwin's equivalent is libproc, -and it answers both. +`host_io.shellCwd` reads a shell's working directory using +`proc_pidinfo(PROC_PIDVNODEPATHINFO)`; Linux uses `/proc/<pid>/cwd`. +The macOS host refreshes directories for panes that produced output, so idle +frames do not poll every shell. `test/macos-snapshots/cwd.snap` covers the tag +after `cd` and after an idle tick. -**A pane's cwd** (`look.shellCwd`) is `readlink("/proc/<pid>/cwd")` there and -`proc_pidinfo(PROC_PIDVNODEPATHINFO)` here. The tag shows it and a relative -`Look` resolves against it, so it has to follow the shell rather than stay -where the pane was spawned. - -*When* it is read differs from the other three shells, and deliberately. The -tty, SDL and detached-daemon hosts poll every pane every frame — inline in the -tty loop's frame path (`src/tty/tty.zig:1228-1231`), `pollCwds` in the SDL -shell (`src/gui/gui.zig:4048`) and `pollFrame` in the daemon -(`src/detached/server.zig:889`); here the drain has just finished -saying exactly which shells produced bytes, and nothing else can have moved -one — a `cd` is a command, and a shell that ran a command writes at least its -next prompt. So `refreshCwds` reads only for panes flagged by that tick's -output and an idle session costs no syscalls at all. `test/macos-snapshots/ -cwd.snap` holds the gating to it: the tag must be right after a `cd` and must -survive a tick with nothing in it. - -**A pardes inside a pardes** (`src/nested.zig`) walks the ancestor chain -looking for our own executable, and hands the file over rather than stacking a -second full-screen UI inside a pane. `readlink("/proc/<pid>/exe")` becomes -`proc_pidpath`, and the `PPid:` line of `/proc/<pid>/status` becomes -`proc_bsdinfo.pbi_ppid`. That struct is hand-written, which is a thing to get -silently wrong: a field ordering that puts something else where `ppid` should -be still returns a plausible number, so a unit test compares `parentOf(getpid())` -against `getppid()`. - -The socket half needed real portability work rather than a second spelling. -Darwin has no `SOCK_CLOEXEC` and no `accept4`, so the flag is set with an -`fcntl` after the fact — a race only against a fork on another thread, and -every caller is past that (`src/nested.zig:81-93` names all three). -`sun_path` is 104 bytes here against 108 there, so no -buffer in the file spells a number any more; they are all sized from the field -itself, and an address that does not fit is refused rather than truncated into -a path pointing somewhere else. - -Identity gained a third sibling. `bin/pardes`, `bin/pardes-gui` and -`pardes.app/Contents/MacOS/pardes` are three installed frontends of one -program, so `samePardesExecutable` (`src/nested.zig:142`) compares BASENAMES -and ignores the paths entirely — the GUI may be system-wide while the tty -frontend sits in the user's own bin directory. `familyTail` strips a leading -`pardes-gui` or `pardes` and requires what is left to be either empty or a -valid `-os-arch` pair, which is what keeps `pardes-snap` and `pardes-perf` out -of the family; `sameFamily` then accepts two names whose tails agree, or either -of which has no tail at all. The bundle's copy always has none, because -`CFBundleExecutable` is a fixed string: the bundled `pardes-macos-aarch64` is -called `pardes` and nothing in the name records what it was. So `pardes -src/foo.zig` inside the app's own shell opens a pane in the app. +Nested launches use the same inherited 9P address and pane serial as other +native hosts. They do not inspect ancestor processes or executable names. +See [the control filesystem](fs.md) for paths and transports. ## Fonts and zoom @@ -672,8 +630,7 @@ stacked filters. Their canonical macOS source is `shaders/crt.ci.metal`, which the build installs as `pardes.app/Contents/Resources/crt.ci.metal`. The Swift shell loads that exact asset with `CIKernel.kernels(withMetalString:)` and runs it through a `CIContext` created from the system Metal device. The source is -also a Zig build import, so `EffectCode` can print what the app executes when -the source checkout is absent. +also archived by the Zig build; `EffectCode` links to it without a checkout. The ordinary CoreText/attachment/cursor pass is one function. With any scene bit or panel track it targets a retained, backing-scale bitmap; kernels then @@ -726,8 +683,8 @@ panes move and dissolve together. Scene CRT/ripple/glitch runs once after the panel composition. With no scene bit and no panel track the retained bitmap, Core Image context, -and Metal passes are bypassed. `EffectCode Panel*` embeds this actual Metal -file plus its direct Swift owner, the same files the app executes. +and Metal passes are bypassed. `EffectCode Panel*` links to this Metal +file and its Swift owner in the virtual filesystem. ### Transparent themes @@ -870,7 +827,7 @@ already do (`install_app_bin`, `install_plist`, `install_scene_kernel`, `CIKernel.kernels(withMetalString:)`. The same file is also an anonymous module import named `effect-source-crt.ci.metal`, added by `build.zig`'s per-shell module wiring under `if (shell == .macos)`, which is what lets - `EffectCode` print the exact source the app executes. + `EffectCode` link to the exact source the app executes. Its three entry points are `extern "C" [[stitchable]]`: the runtime compiler looks for stitchable functions and rejects the WHOLE source with "cannot find a valid stitchable Metal function in the source" when there are none, which @@ -981,12 +938,11 @@ prohibited) `NSWindow`, over a real core with real ptys: ```sh zig build macos-e2e -Dplatform=macos # run it zig build macos-e2e -Dplatform=macos -- --update # regenerate the goldens +zig build macos-e2e -Dplatform=macos -- test/macos-snapshots/rotate.snap ``` -The step always hands the harness the whole `test/macos-snapshots` directory, -so naming one script after `--` runs it IN ADDITION to the suite rather than -instead of it. To run a single script, invoke -`zig-out/bin/pardes-macos-e2e test/macos-snapshots/rotate.snap` directly. +With no paths, the harness runs `test/macos-snapshots`. Paths after `--` +select scripts or directories instead. The executable stays in the build cache. `test/macos_e2e.swift` links the same Swift sources the app does, minus `main.swift`, into a second binary — test scaffolding does not ship inside the @@ -1098,7 +1054,7 @@ used for the table and is not folded into the direct-path claim. - **Detached sessions.** `Attach` (`SPC s a`) and `Detach` (`SPC s D`) exist on every hosted platform, this one included, because `Builtin.enabled` is `pardes.hosted`. Neither works here. `Detach` emits `Effect.detach`, this - host fills in no `push_detach`, and `Pardes.perform` therefore reports + host fills in no `detach`, and `Pardes.perform` therefore reports `error.NotAttached` on the pane's message row (`src/pardes.zig:6837`). `Attach` emits `Effect.attach`, which `perform` turns into an `attach_req` the shell is supposed to consume from OUTSIDE `pump` with `takeAttach` — and |
