Ports the macOS-specific Zig code behind cfg(target_os = "macos"):
- renderer: a GraphicsApi trait with generic::Renderer<G>; Metal backend
(all renderer/metal/* files, shaders.metal verbatim, runtime library
compile, IOSurface layer, CVDisplayLink), shadertoy -> MSL via naga;
OpenGL remains the backend elsewhere.
- font: CoreText face, shaper and discovery with build.rs backend
selection (coretext default; coretext-freetype / coretext-harfbuzz /
coretext-noshape features), no fontconfig/freetype/harfbuzz on Apple.
- input: KeymapDarwin via UCKeyTranslate, option-as-alt, mac keycodes.
- os: macos, mach, cf_release_thread, NSProcessInfo args and macOS
branches; config: macOS defaults, keybinds, Application Support paths.
- termio/core: login(1) wrapping, openpty/execvpe, Darwin child exit
handling, os_log logging.
Compile-checked for aarch64/x86_64-apple-darwin (clippy -D warnings
clean) using the cross setup in docs/rewrite/notes/macos-M1.md; cannot
run here. The embedded runtime/C API (embedded.zig) is the next step.
Also includes the cross-platform integration edits shared by the crash,
verification, Windows and macOS work (Cargo target-gating, thread
crash-context hooks, apprt-gtk surface/IME refactor, termio/os cfg
gates), a cfg fix so ghostty-config builds on wasm32, and an allow for
the intentional recursion in the crash overflow test.
Test Plan:
- cargo test --workspace (3224 passed)
- cargo clippy --workspace --all-targets -- -D warnings
- cargo check --target aarch64-apple-darwin -p ghostty-renderer (with
the documented cross env)
rustfmt.toml sets group_imports, imports_granularity and imports_layout,
which are nightly-only; agents formatted with stable rustfmt, which
ignored them. This is a formatting-only pass with `cargo +nightly fmt`.
Test Plan:
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace
Ports the remainder of ZIG/src/termio: Options, backend, message,
mailbox, Termio, Thread, Exec and stream_handler.
Threading model (replacing libxev): the IO thread owns Termio and runs a
single poll(2) loop over the mailbox eventfd, a stop eventfd, the child
pidfd and pty POLLOUT, driving Ghostty's timers (25 ms resize
coalescing, 1 s synchronized-output, 15 ms selection scroll, 200 ms
termios polling). A separate pty read thread locks the shared renderer
state and feeds the terminal. Renderer and surface interaction go
through RendererMailbox/SurfaceMailbox traits.
The stream handler answers all queries (DA, DSR, XTVERSION, DECRQM,
OSC color queries, XTGETTCAP, DECRQSS, ...) and forwards titles, pwd,
OSC 52, notifications, progress and bell as surface messages. Zig
unlocks the renderer mutex when a mailbox is full; here overflow goes to
an ordered outbox flushed after the locks drop.
IO1's local stand-ins are replaced with the real config types.
Open: RendererState lives in termio for now (renderer State.zig is
being ported); kitty graphics replies and tmux viewer are not hooked up;
wait-after-command lives in Surface (core); Flatpak stop path needs a
ghostty-os change.
Test Plan:
- cargo test -p ghostty-termio (102 unit + 21 end-to-end tests on a
real pty, incl. backpressure, DA1 replies, resize coalescing, exits)