Commit Graph
7 Commits
Author SHA1 Message Date
ddidderr 2e5ec06b4e fix(renderer): prevent display teardown starvation during output floods
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
2026-10-15 18:42:36 +02:00
ddidderr 9010117d08 fix-deviant(links): bound hover lookup and renderer regex work
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)
2026-10-15 00:02:47 +02:00
ddidderr 184cdd5c62 fix: close the tail items from the targeted re-audit
Resolves the 13 rows still partial in docs/rewrite/notes/review-rv4-
codex.md (details in final-Z5.md):
- Escaped config strings are decoded to raw bytes at every OS boundary:
  Flatpak cwd/argv to D-Bus, screen-file paths, the default config
  template, GHOSTTY_RESOURCES_DIR/TERMINFO/shell integration/
  bindtextdomain consumers, custom shader loading, list-themes hyperlinks.
- osbytes escapes literal U+FDD0 on non-Unix too (bijective everywhere);
  the GTK paste dialog only decodes text that was actually encoded.
- shadertoy: whole-array uses of iChannelTime rebuild a plain float[4]
  from the std140-padded members (naga-validated, MSL offsets checked).
- libghostty-vt: the OSC parser holds caller-allocated storage inline
  and command payloads borrow from it, so ghostty_osc_end performs no
  global allocations (verified from Rust and C).
- crash: aarch64 Linux minidump context fixed; macOS fatal signals record
  siginfo, registers and a fault-safe stack walk.
- tripwire: selectionString map allocation-failure cleanup test ported.
- libghostty-vt emits the versioned soname libghostty-vt.so.0 at build
  time (no patchelf needed at install).

Test Plan:
- cargo test --workspace (3342 passed)
- just check-macos; just check-macos x86_64-apple-darwin;
  just check-windows; just check-wasm
- cargo check --target aarch64-unknown-linux-gnu -p ghostty-crash
2026-10-12 08:45:21 +02:00
ddidderr 452b782149 feat(macos): port Ghostty's macOS code paths (Metal, CoreText, Darwin)
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)
2026-10-12 06:02:39 +02:00
ddidderr 2fbb43317c feat(renderer): port the generic renderer, renderer thread and state
Ports renderer/{generic,cell,row,link,State,Overlay,image,Thread}.zig:
- generic.rs builds GPU cell buffers from terminal RenderState each
  frame: backgrounds, shaped text runs with glyph atlases and nerd font
  constraints, all cursor styles, decorations via sprites, selection and
  search colors, min-contrast, bold/faint/blink handling, preedit,
  padding extension, background image, custom shader uniforms, link
  hover underlines, scrollbar and health reporting.
- The renderer thread updates CPU-side state only and asks the host to
  redraw; the app runtime calls draw_frame from the GLArea render signal
  (the GL context lives on the GTK thread, as in Ghostty).
- ghostty_renderer::state::{State, SharedState} is the canonical shared
  renderer state (termio's interim copy will switch to it).

Deviations: overlay uses a direct RGBA rasterizer instead of z2d; bg
images decode with png/jpeg-decoder instead of wuffs; zero-length link
matches advance by one char (Zig would loop forever).

Kitty image rendering is implemented in image::State but not yet called
from generic::update_kitty (raced with the terminal-side wiring).

Test Plan:
- cargo test -p ghostty-renderer (69 unit + 9 headless EGL tests that
  render a Terminal through the full pipeline and check pixels)
2026-10-11 23:09:52 +02:00
ddidderr c548e63bd1 feat(renderer): port the OpenGL backend, shaders and size math
Ports the terminal-independent half of ZIG/src/renderer (OpenGL only):
- opengl/*: buffers, frames, pipelines, render passes, samplers,
  targets, textures and the OpenGL GraphicsAPI backend on top of glow;
  the GTK GLArea glue is replaced by a get_proc_address loader closure
- the GLSL shaders, copied verbatim and embedded; uniform/vertex structs
  as bytemuck Pod types with std140 offsets asserted in tests
- shadertoy custom shaders converted with naga (GLSL in -> validate ->
  GLSL 430 out) instead of glslang + spirv-cross
- size (screen/grid/cell/padding math), cursor style logic, backend
  health, options and message types

The crate opts into unsafe_code = "deny"; unsafe glow calls live only in
opengl/gl.rs. A headless EGL integration test builds every pipeline and
the converted shadertoy shaders on Mesa and reads back rendered pixels.

Note: Zig's shadertoy Uniforms order the selection background/foreground
colors opposite to the GLSL block (likely an upstream bug); kept as in
Zig for parity and recorded in the notes.

Deferred to the next renderer pass: generic, cell, image, link, row,
State, Thread, Overlay (need terminal render state).

Test Plan:
- cargo test -p ghostty-renderer (33 tests incl. tests/egl_headless.rs)
2026-10-11 22:26:09 +02:00
ddidderr 987f2957ad chore: scaffold Cargo workspace for the Ghostty rewrite
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
2026-10-11 21:41:11 +02:00