Closing a busy split or confirming a tab close could freeze GTK while
unrealizing the GLArea. Both reported GDB traces show the main thread
waiting for the CPU frame-state mutex while the renderer keeps rebuilding
dense text. GTK unrealizes the display before stopping the workers, so
continuous output can keep the competing renderer active indefinitely.
Use parking_lot fair mutexes for CPU frame state and GPU draw state. A
waiting lifecycle or draw callback receives ownership instead of losing
it to the next frame update. Keep the existing lock order and resource
cleanup; no output, scrollback, or frame-rate limits are introduced. The
fair-lock handoff adds scheduling overhead when the locks are contended.
Correct the threading documentation: the CPU state is also accessed by
apprt callbacks, and the Rust-only mutex is therefore contended.
Test plan:
- Add a mock GPU regression continuously rebuilding 200x150 dense cells
while another thread unrealizes and realizes the display. It failed
its three-second deadline with the old locks and passes with fair locks.
- All 235 renderer/core tests pass, including Mesa EGL rendering tests.
- Clippy for renderer/core/GTK, all targets, passes with -D warnings.
- Nightly formatting check and release binary build pass.
- GTK/Wayland replay with font size 9 and 1 GiB scrollback runs base64
floods in two splits, confirms split and tab closes, then successfully
executes and renders a command in the surviving terminal.
Docs: docs/rewrite/ARCHITECTURE.md
Follow-up testing showed that the mailbox limit did not fix the base64
hang: moving the pointer stalled the app, and opening a tab could hang it.
Mouse link lookup copied the entire wrapped line before checking modifier
eligibility, while renderer link searches had no whole-search work budget.
Filter eligible links before traversing scrollback. Add bounded logical
line selection and skip automatic regex lookup on lines exceeding 65,536
grid cells. Keep explicit line selection and OSC8 handling unrestricted.
Skip oversized lines instead of truncating URLs into different targets.
Apply the existing terminal StringMap retry budget to renderer searches
and handle search errors without panicking. The regression triggered a
retry-limit panic through the old onig search API and now returns normally,
allowing subsequent link patterns to run.
Document the lookup limits and correct the earlier mailbox fix entry to
record that it did not resolve the reported hang on its own.
Test Plan:
- 1,513 unit/integration tests and one doctest pass across core, renderer,
and terminal with Mesa software OpenGL; one existing doctest is ignored.
- Release application build, formatting, and all-target Clippy pass.
- GTK handles 400 pointer moves, including Ctrl hover, during continuous
base64 output, opens/closes a tab, handles Ctrl+C, prints a marker, and
exits cleanly. Normal URL hover still works after a hard newline.
Reference: docs/rewrite/DEVIANT_FIXES.md (entry 41)
A freeze report from continuous newline-free base64 output exposed an
unbounded mailbox drain: producers can keep refilling the queue and prevent
one app tick from returning to the runtime for input, timers, and drawing.
Process at most 64 messages per tick and wake the runtime if work remains.
Messages retain their order and are not dropped. Document the scheduling
contract and the deliberate deviation from the upstream drain loop.
Add a finite refilling-producer regression that fails with the original
loop and verifies yielding, wakeup rearming, and eventual completion. The
reported full freeze was not consistently reproduced in headless GTK, so
this fixes a demonstrated starvation risk without claiming its root cause.
Test Plan:
- All 119 ghostty-core tests pass with Mesa software OpenGL.
- Release build, Clippy for all core targets with -D warnings, and fmt pass.
- GTK handles Ctrl+C, a follow-up command, and quit after a 15-second flood.
Reference: docs/rewrite/DEVIANT_FIXES.md (entry 40)
Relocating a Cargo-installed binary loses executable-relative resource
lookup even when themes and shell integration exist under /usr/share.
Allow packagers to set GHOSTTY_BUILD_RESOURCES_DIR when compiling.
Absolute paths are used directly; relative paths resolve against the
running executable's directory for relocatable installations. Explicit
paths do not require terminfo sentinels. A nonempty runtime override wins
in every profile when the build option is configured. Unset or empty
build options preserve existing discovery, including debug precedence.
Cargo watches the build option so changing or unsetting it recompiles
lookup. Resource files still need to be installed separately.
Document this requested upstream deviation and the build option in the
README, architecture overview, and deviation register.
Test Plan:
- Eight resource lookup unit tests pass.
- Nightly formatting and ghostty-os Clippy with -D warnings pass.
- Production build with /usr/share/ghostty succeeds; a copied executable
lists all 463 themes with no runtime override.
- Compiled probes verify absolute, relative, unset, and empty options,
Cargo rebuilds, relocation, runtime overrides, and unrelated cwd.
Deviation-Register: docs/rewrite/DEVIANT_FIXES.md
Repeated production builds recompiled build-info, GTK and their dependents
because build scripts watched missing optional files and generated outputs.
Watch packed-refs only when present and the prebuilt GTK bundle only when
consumed. Loose refs remain watched so packing them refreshes Git inputs.
Invoke glib-compile-resources directly instead of using a helper that also
watches generated XML and UI files. The existing resources directory watch
covers their source inputs. Remove the unused helper dependency and document
the build input rules.
Test Plan:
- Run cargo build --profile production three times; repeats compile nothing.
- Run cargo clippy, cargo clippy --benches and cargo clippy --tests.
- Run cargo +nightly fmt and repeat all three Clippy checks.
Documentation: docs/rewrite/ARCHITECTURE.md
- apprt-gtk: Ghostty's runtime+build-time version gating (at_least)
with cargo features adw_1_3/adw_1_4/adw_1_5/gtk_4_16 (default on) and
the fallbacks for older libraries: MessageDialog (adw < 1.5),
clipboard dialog without SwitchRow, pre-Banner debug warning and
child-exited widgets, the old about dialog, GTK 4.16 CSS error source
bytes. The minimum stays GTK 4.14 / libadwaita 1.5 (Ghostty's floor).
The root build links with -z lazy so version-gated symbols don't keep
older libraries from loading.
- ghostty-helpgen (port of helpgen.zig) generates CLI action help and
keybinding action docs from doc comments at build time, replacing the
checked-in help/*.txt; +help and +list-actions --docs stay
byte-identical to Ghostty 1.3.1.
- ghostty-bench: libc wcwidth mode and separate simd/table and
uucode/table code paths like Zig.
- ghostty-cli: Windows branches of edit-config, list-colors,
list-keybinds and boo; ssh-cache DiskCache flock locking (no-op on
Windows, as in Zig) with an exclusivity test.
Test Plan:
- cargo test --workspace
- diff <(cargo run -q -- +list-actions --docs) \
<(ghostty +list-actions --docs)
README explains what the rewrite covers, how to build, run, install and
test it. ARCHITECTURE.md gains a top-down decomposition tree (binary ->
runtime/core -> termio/terminal/renderer -> leaf crates) and an updated
crate map with the actual internal dependencies, including the crates
added during integration (apprt, inspector, onig, bench, build-data).
CHANGELOG records the rewrite under Unreleased; no version bump.
Addresses the partial ports listed in
docs/rewrite/notes/review-completeness-codex.md (details in
docs/rewrite/notes/gaps-X2.md):
- Flatpak: the exit watcher no longer consumes the host command; a
shared FlatpakSignalHandle lets closing a surface still SIGHUP the
host process group.
- Child environment is byte-preserving end to end (ghostty_os::EnvMap
of OsStrings) and Snap paths are filtered like filterSnapPaths.
- argv handling no longer panics on non-UTF-8 arguments.
- URI percent-decoding keeps raw bytes; OSC 7 pwd is passed through
without lossy conversion.
- Keybinding comparison/hashing uses full Unicode case folding from a
table generated from CaseFolding.txt (Unicode 17.0.0).
- Link regexes set Oniguruma's whole-search retry limit through the new
minimal ghostty-onig crate (one SAFETY-commented FFI call).
- OSC 9 NUL-capacity check ordering matches Zig.
- Wayland registry binds/clears globals advertised after startup.
- Custom shaders may pass sampler2D to helper functions (naga adapter).
- +list-themes preview renders OSC 8 links, styled underlines and
follows color-scheme reports.
Also includes the inspector's integration edits in shared files
(renderer state hook, termio VT recording, core/apprt-gtk wiring), X1's
config/input/cli additions for completion generation, and a fix for a
race in the termio backpressure test (it wrote before `stty raw`
applied, so the cooked line discipline dropped bytes past MAX_CANON).
Test Plan:
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings
Start of the full Rust rewrite of Ghostty 1.3.1 (reference source in
../ghostty). Sets up a workspace whose crates mirror Ghostty's Zig modules
(vt, unicode, datastruct, os, input, config, terminal, font, renderer,
termio, core, apprt-gtk) so porting work can proceed in parallel per crate.
Also adds:
- docs/rewrite/{ARCHITECTURE,PLAN,STATUS,AGENT_GUIDE}.md: crate map, core
design decisions (safe Rust, slab-based PageList, logical capacity
accounting), phased plan, progress tracker, and porting rules.
- Workspace clippy config relaxing pedantic lints that are pure noise for
low-level terminal code (casts, long functions).
- Shared vt types needed by several work packages up front: kitty
keyboard flags (kitty/key.rs) and the CSI separator bitset (SepList).
Test Plan:
- cargo test -p ghostty-vt (3 tests pass)
- cargo clippy -p ghostty-vt --all-targets -- -D warnings