renderer: a frame the embedder presents itself wakes no main-thread present (sync line)
Merged
LA
17h ago+268+268+012345678901234567890123456789-7-7-0123456789
Summary
- The same change as #75 (into
release/cmux-9ce9b7d0-e2), cherry-picked with-xontorelease/cmux-sync-20261104(the upstream-sync line that cmux PR manaflow-ai/cmux#35478 pins). The ghostty-next pin carries the change whichever cmux PR moves it first. - With
GHOSTTY_HOST_PRESENT_EMBEDDER, a frame of the host size kept for the embedder's present, which the layer cannot show in its bounds now, goes to no main-queue block (setSurfaceCallbackdropped it there). The skip is decided under the Core Animation lock and thenfresh.mutex, only while the kept frame is still that frame (Metal.embedderShowsKeptFrame). All other frames still go through main. See #75 for the full description, the kept-frame rule after a host change, and the four Codex rounds. - The cherry-picks applied with no conflict.
IOSurfaceLayer.zigis the same file on both lines;Metal.zig,ghostty.handNEXT.mddiffer only outside the changed parts.
Testing
- Green on this line (Zig 0.17.0; scratch branch
scratch/embedder-wake-sync-greenonly narrows the workflow's test filter tohost present:, never merged): https://github.com/manaflow-ai/ghostty-next/actions/runs/41920331766: 109/109 and lib-vt 97/97. - Red and green on the other line, and the reviews: #75.
Observed / Not run
- Observed: the run above;
zig fmt --checkandzig ast-checkwith Zig 0.17.0. - Not run: the cmux side (see #75).
Changelog
none
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Cherry-picks #75 onto release/cmux-sync-20261104 so the ghostty-next pin carries the fix whichever cmux PR moves it first. When GHOSTTY_HOST_PRESENT_EMBEDDER is on, a frame of the host size kept for the embedder's present no longer wakes the main thread: setSurfaceCallback previously dropped it after dispatching to the main queue.
- The skip is decided under the Core Animation lock then
fresh.mutex, and only while the kept frame is still that frame; a host change drops it, so a skipped frame never shows for a later equal size (A->B->A). - All other frames — first frames, frames at the shown size, frames for bounds the embedder already set, frames of a size the host no longer has — still go through main.