Files
ddidderr 4787565397 feat: port GTK version fallbacks, helpgen, bench modes, CLI leftovers
- 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)
2026-10-12 06:38:33 +02:00

5.4 KiB

compat-GC: GTK/libadwaita compat fallbacks, bench modes, helpgen, CLI Windows

Sub-notes: compat-GC-bench.md, compat-GC-helpgen.md, compat-GC-cli.md.

1. GTK / libadwaita compatibility (crates/ghostty-apprt-gtk)

Ghostty's own minimum (finding)

ZIG/src/build/SharedDeps.zig runs blueprint.zig over every entry of gresource.blueprints, which refuses to compile a <maj>.<min>/x.blp if the libadwaita headers are older than that version; the list contains 1.5/ files (window, tab, command palette, ...). So Ghostty 1.3.1 cannot be built against libadwaita < 1.5, and the Zig code calls gtk_css_provider_load_from_bytes (4.12) and gtk_im_context_activate_osk (4.14) unguarded. Ghostty's real minimum is therefore GTK 4.14 / libadwaita 1.5, which is what the crate already required; I verified this by compiling with gtk4 features v4_8/v4_10 (fails on load_from_bytes/activate_osk) and v4_14 (compiles). The only change to the requirement is dropping the unneeded gnome_44 feature. In Zig the fallbacks below are only reachable in a (hypothetical) build against older headers; they are ported with identical selection logic.

Version gating (gtk_version.rs, adw_version.rs)

Zig's atLeast = comptime header version AND runtime library version. Rust:

  • cargo features are the "header version": adw_1_3 < adw_1_4 < adw_1_5 and gtk_4_16 (gtk/v4_16); all are default. BUILD_LEVEL / const fn comptime_at_least read them; at_least = comptime_at_least && runtime_at_least; runtime_at_least/runtime_until unchanged. COMPTIME_VERSION (pkg-config) is kept for +version output.
  • Types that Zig selects at comptime are selected with cfg(feature = ...).
  • Debug builds only: GHOSTTY_DEBUG_FAKE_GTK_VERSION / GHOSTTY_DEBUG_FAKE_ADW_VERSION (e.g. 1.4.0) override the runtime version answers (fake_version.rs; no Zig counterpart) so runtime branches can be exercised on new libraries.
  • Root build.rs links the binary with -z lazy (Rust defaults to -z now) so symbols only used behind a runtime check (GTK 4.16 gtk_css_section_get_bytes) don't stop an older library from loading the program, like Zig's lazy binding.

Fallbacks ported

Zig Rust
class/dialog.zig Parent = AlertDialog / MessageDialog, present/close class/dialog.rs: DialogParent + present/close per cfg adw_1_5; macros dialog_subclass_wrapper!/impl_dialog_parent! give the three subclasses (close-confirmation, config-errors, clipboard) the right @extends chain and response override for both parents
clipboard_confirmation_dialog.zig can_remember, template 1.4 vs 1.0 cfg_attr template resource ui/1.4 (adw_1_4) vs ui/1.0; remember_choice child only with SwitchRow; CAN_REMEMBER; remember=false without it
debug_warning.zig Parent adw.Bin/gtk.Box, template 1.3/1.2 class/debug_warning.rs cfg adw_1_3
surface_child_exited.zig Banner / SurfaceChildExitedNoop class/surface_child_exited.rs: noop widget (no template, NOOP, close-request emitted from set_child_exited); Surface::child_exited returns false for the noop, as in Zig. NB: Zig has no 1.2/surface-child-exited.blp (the task text assumed one); the pre-Banner implementation is the Noop
window.zig actionAbout adw::AboutDialog if supports_dialogs() else gtk::show_about_dialog
application.zig signalCssParsingError (GTK >= 4.16 branch) css.rs: domain code message + \n<source bytes> (CssSection::bytes) behind gtk_4_16 + runtime check, plain line otherwise; tested via parsing_error_message
blueprint variants build.rs already compiles 1.0/1.2/1.3/1.4/1.5 variants (same list as gresource.zig) into the gresource; the class selects at build level (as Zig)

Verification

  • cargo clippy -p ghostty-apprt-gtk --all-targets -D warnings clean with default features AND with default = [] (temporarily edited), i.e. both the new and the fallback code compile.
  • Default build: GTK app runs with the debug replay hook (paste dialog shows GhosttyClipboardConfirmationDialog with the remember switch; no GTK criticals).
  • Fallback build (default = [], run via the replay hook): the paste confirmation and the close confirmation come up as adw::MessageDialog-based GhosttyClipboardConfirmationDialog / GhosttyCloseConfirmationDialog (transient for the window), the binary has no BIND_NOW.
  • Workspace gate (excluding L1's in-progress ghostty-lib): cargo clippy --workspace --all-targets -D warnings, cargo test --workspace, cargo +nightly fmt --all pass. +help, +list-actions [--docs], +list-keybinds --help, +show-config --help are byte-identical to /usr/bin/ghostty.

Deviation found by the runtime check

Zig's GhosttyCloseConfirmationDialog registers a close-request signal; with the MessageDialog (a GtkWindow) parent that name already exists in the class ancestry and GObject aborts. Zig's fallback has the same latent bug (dead code upstream). The fallback build here names it dialog-close-request (close_confirmation_dialog.rs::CLOSE_REQUEST); default build unchanged.

Not testable here

Real old libraries (GTK < 4.16 / libadwaita < 1.5) are not installed; only the compile-time fallback selection and the version arithmetic are exercised.

2-4

See the sub-notes. Deviations vs the task text: Zig CodepointWidth has no uucode mode (bench); Zig does no file locking on Windows, so the faithful port is a no-op there (cli).