Commit Graph

16267 Commits (push-srtsmpvulpwv)

Author SHA1 Message Date
Mitchell Hashimoto 0e93fbfe76
libghostty: handle non-monotonic selection times in SelectionGesture
We expect monotonic time but since this is libghostty-exposed we need to 
be more careful about guarding what we accept. This also practically makes
it easier to integrate with various languages.

Compare the two instants first and treat backwards timestamps like any
other failed repeat. The next press becomes a fresh single-click anchor,
and a regression test covers the reset behavior.
2026-05-27 14:09:34 -07:00
Mitchell Hashimoto 4e2d7c314b
libghostty: optimize bits for selection gesture validation fields 2026-05-27 11:05:33 -07:00
Mitchell Hashimoto 3e0477a14a
example/c-vt-selection-gesture 2026-05-27 11:01:25 -07:00
Mitchell Hashimoto f0fcb10406
libghostty: selection gesture deep press 2026-05-27 10:57:50 -07:00
Mitchell Hashimoto 603684ba11
libghostty: selection gesture autotick 2026-05-27 10:55:15 -07:00
Mitchell Hashimoto 90fd1ec2e7
libghostty: selection gesture drag events 2026-05-27 10:53:10 -07:00
Mitchell Hashimoto 3fd2c66a04
libghostty: selection gesture release event 2026-05-27 10:49:18 -07:00
Mitchell Hashimoto 5ac8e6569a
libghostty: add ghostty_selection_gesture_event 2026-05-27 10:47:26 -07:00
Mitchell Hashimoto bbfa984aec
libghostty: GhosttySelectionGestureEvent 2026-05-27 10:42:29 -07:00
Mitchell Hashimoto 2f61ba036e
libghostty: starting the SelectionGesture API, just init/get 2026-05-27 09:02:25 -07:00
Mitchell Hashimoto 3103ae8838
macos: avoid duplicate appearance sync on tab focus (#12828)
Close #12825

Skip the initial emissions from the focused surface appearance
publishers after a tab focus change. The focused surface is already
synced immediately, so the initial Combine values only repeat the same
titlebar and background updates. Subsequent derived config and OSC
background changes still resync the window appearance.



https://github.com/user-attachments/assets/f229fb95-4b4c-4040-85ac-0acfcc54ca82



Assigned to Codex GPT 5.5(medium)
PS: Sry for I don't write zig and let AI write this.
2026-05-27 07:52:42 -07:00
Mitchell Hashimoto 756fda776b
cli: rework +ssh-cache internals and user interface (#12814)
This change primarily focused on a revised +ssh-cache user interface,
but it also reworks a bunch of the internals.

The primary CLI improvement is support for positional arguments and a
consistent list output format that includes both the ISO-formatted
timestamp and relative age.

ghostty +ssh-cache # List all cached destinations
    ghostty +ssh-cache user@example.com          # Show that destination
ghostty +ssh-cache example.com # Show all users on that host
ghostty +ssh-cache --add=user@example.com # Manually add a destination
    ghostty +ssh-cache --remove=user@example.com # Remove a destination
ghostty +ssh-cache --prune=30d # Remove entries older than 30 days
    ghostty +ssh-cache --clear                   # Clear entire cache

Notable, we now support a --prune operation that replaces the previous
--expire-days flag that was never actually hooked up to anything (!!).
--prune also supports a wider range of Duration-based values.

We're also much more consistent with error codes: 0=success, 1=failure,
2=usage.

While working on those changes, I also reworked the cache internals,
particularly the code around timestamp handling and errors. For example,
I dropped the explicit error sets because they were growing unwieldy,
and in practice we only matched on a subset of those errors.

Lastly, overall test coverage should be much improved, especially around
the time- and allocation-related operations.

---

*AI Disclosure:* I made a lot of iterative, AI-assisted (Claude Opus
4.7) correctness passes over this work. It was particularly helpful in
tracing through the various failure modes, and it wrote those unit tests
in the process.
2026-05-27 07:52:00 -07:00
Mitchell Hashimoto 8518986b1e
macOS: clear stale OSC 11 background cache on config change (#12822)
## Summary

`SurfaceView` caches the background color set by OSC 11 in
`backgroundColor`. `TerminalWindow.preferredBackgroundColor` consults
that cache before falling back to `derivedConfig.backgroundColor`, so
once OSC 11 has fired the cached value masks any later config change.

After a light/dark theme auto-switch (e.g. `theme =
light:my-light,dark:my-dark`) this leaves the window chrome on the
previous theme's color until the application next emits OSC 11.

In `ghosttyConfigDidChange`, after updating `derivedConfig`, drop the
cache when it no longer matches the new config-derived background. A
subsequent `ghosttyColorDidChange` repopulates it as before, so
within-config OSC 11 behavior is unchanged.

## Reproduction

1. Configure `theme = light:SomeLight,dark:SomeDark` where the two
themes have visibly different background colors.
2. Open a terminal session where any application (e.g. a shell startup
script) has sent OSC 11 to set a custom background color.
3. Switch macOS appearance (System Settings → Appearance).
4. **Before**: window chrome stays the previous theme's color until the
terminal next emits OSC 11.
5. **After**: window chrome immediately updates to the new theme's
background color.

## Changes

- `SurfaceView_AppKit.swift` — one guard: if the cached
`backgroundColor` disagrees with the new
`derivedConfig.backgroundColor`, set it to `nil`.
2026-05-27 07:51:12 -07:00
Mitchell Hashimoto c343c5a67a
Extract click/drag selection handling into SelectionGesture (#12830)
Refactor terminal text selection into a reusable `SelectionGesture`
state machine. Most importantly, this means our click+drag logic around
selection is now fully unit tested! And we found bugs! And fixed them!

The large line increase in this diff is mainly comments + tests.

I've wanted to do this forever so we can unit test this, but I was
kicked in the butt to do it recently because reimplementing selection
logic in libghostty consumers turns out to be complex and error prone
and we have a perfectly battle tested logic machine here so why not
extract it?

Behavioral changes from main surfaced via unit testing:

- Dragging now drags by output across semantic output blocks when the
initial press was an output selection. This matches the behavior of
dragging continuing whatever the initial selection logic was.
- Selection autoscroll now stops when the click anchor is invalidated by
a screen change (e.g. primary to alt)
- Deep press (macOS force touch) now selects the word at the original
press location and consumes the active drag gesture, preventing later
movement from dragging or autoscrolling that selection. This matches
built-in macOS apps.
- Mouse release records whether the gesture moved away from the pressed
cell, so link and prompt clicks are skipped after a drag while normal
clicks still activate them.

Example usage:

```zig
var gesture: terminal.SelectionGesture = .init;
defer gesture.deinit(t);

const press_selection = try gesture.press(t, .{
    .time = try std.time.Instant.now(),
    .pin = press_pin,
    .xpos = mouse_x,
    .ypos = mouse_y,
    .max_distance = cell_width,
    .repeat_interval = mouse_interval,
    .word_boundary_codepoints = selection_word_chars,
    .behaviors = &.{ .cell, .word, .output },
});
try t.screens.active.select(press_selection);

if (gesture.drag(t, drag_event)) |drag_selection| {
    try t.screens.active.select(drag_selection);
}

gesture.release(t, .{ .pin = release_pin });
```
2026-05-27 07:48:23 -07:00
Mitchell Hashimoto 68959c5c63
terminal: fix selection gesture edge cases
Selection gestures now treat releases with invalidated anchors as dragged,
so a press that crosses screen boundaries cannot also activate links or
prompt clicks on release. Cell drags that create a same-cell selection also
mark the gesture as dragged, which keeps click-only actions from firing
after a threshold-crossing drag.

Autoscroll now resolves the drag pin after moving the viewport instead of
reusing the pin from before the scroll. This keeps the selection aligned
with the row currently under the pointer. The inspector also validates the
tracked click pin before displaying it so stale pins from inactive screens
are ignored.
2026-05-27 06:58:44 -07:00
Mitchell Hashimoto 7d4d1e5819
terminal: add configurable behaviors based on click count 2026-05-27 06:32:51 -07:00
Mitchell Hashimoto 82a73f2bf1
terminal: SelectionGesture press returns standard behaviors 2026-05-27 06:26:07 -07:00
Mitchell Hashimoto 9b00bb436a
terminal: better SelectionGesture docs 2026-05-27 06:20:22 -07:00
ghostty-vouch[bot] ce4128afc4
Update VOUCHED list (#12829)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/12827#discussioncomment-17075382)
from @trag1c.

Denounce: @Cznorth

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-27 12:33:56 +00:00
Tunglies 5368adcd29
macos: avoid duplicate appearance sync on tab focus
Close #12825

Skip the initial emissions from the focused surface appearance publishers after a tab focus change. The focused surface is already synced immediately, so the initial Combine values only repeat the same titlebar and background updates. Subsequent derived config and OSC background changes still resync the window appearance.
2026-05-27 19:43:41 +08:00
Mitchell Hashimoto f5f9d32d0a
terminal: SelectionGesture deep press 2026-05-26 21:36:22 -07:00
Mitchell Hashimoto df98b6d983
terminal: SelectionGesture autoscrollTick 2026-05-26 21:26:49 -07:00
Mitchell Hashimoto 141c7d44d2
SelectionGesture: release event 2026-05-26 21:17:03 -07:00
Mitchell Hashimoto 229f4c1f4f
terminal: SelectionGesture handles word/line drag 2026-05-26 21:04:22 -07:00
Mitchell Hashimoto c00cdd886b
SelectionGesture: drag events 2026-05-26 20:56:49 -07:00
Mitchell Hashimoto 33f1558801
core: mouse left release renderer lock made more coarse
This will make our selection gesture extraction a bit easier.
2026-05-26 17:02:20 -07:00
Adam Bouker 57d202066d macOS: clear stale OSC 11 background cache on config change
SurfaceView caches the background color set by OSC 11 in
backgroundColor. TerminalWindow.preferredBackgroundColor consults
that cache before falling back to derivedConfig.backgroundColor,
so once OSC 11 has fired the cached value masks any later config
change. After a light/dark theme auto-switch this leaves the
window chrome on the previous theme's color until the application
next emits OSC 11.

In ghosttyConfigDidChange, after updating derivedConfig, drop the
cache when it no longer matches the new config-derived background.
A subsequent ghosttyColorDidChange repopulates it as before, so
within-config OSC 11 behavior is unchanged.
2026-05-26 14:11:45 -05:00
Jeffrey C. Ollie 2e5ad917eb
apprt/gtk: fix audio-bell GStreamer thread leak (reuse one MediaFile per surface) (#12815)
## Problem

Every audio bell calls `gtk.MediaFile.newForFilename`, which spins up a
full GStreamer pipeline. The GTK4 GStreamer backend's GL sink starts
`gstglcontext`/`gldisplay-event` threads that are **never joined on
teardown**, so allocating a fresh `MediaFile` per ring leaks a pipeline
and ~4 threads on every bell. The old `notify::ended -> unref` handler
discarded the pipeline but did not (and could not) join those threads.

A long-running instance accumulated **705 threads over ~4h** of normal
use.

## Fix

Cache one `MediaFile` per surface (`priv.bell_media`), rebuilt only when
`bell-audio-path` changes and unref'd on `dispose`. Each bell now
replays the same pipeline via `seek(0)` + `play()` instead of creating a
new one. `seek(0)` is required so an ended stream plays again (cf.
#8957).

## Verification

Confirmed on a real running instance with the fix: GStreamer's global
element counter only ever reached `oggdemux4` over an hour of use (one
pipeline per bell-ringing surface, reused for every subsequent bell) and
the process thread count stayed flat — versus the per-bell growth
before.

## Commits

1. **The fix** — reuse one MediaFile per surface.
2. **Unit regression test** — guards the `bellMediaFile` reuse contract
(same path → same object, changed path → rebuild). Runs in the existing
`test-gtk` CI job; needs no display.
3. **End-to-end CI job** *(kept separate so it can be dropped
independently)* — `test/bell-leak.sh` + a `test-gtk-bell-leak` workflow
job that runs ghostty headless (Xvfb + software GL), rings 120 bells,
and fails if the thread count grows per-bell. It's heavier and more
environment-sensitive (needs Xvfb/Mesa/GStreamer on the runner), so it's
isolated for easy review/removal.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-05-26 11:20:02 -05:00
Mitchell Hashimoto 14df684a70
core: adapt Surface to use SelectionGesture with press only 2026-05-25 15:48:20 -07:00
Mitchell Hashimoto d86ff37a58
terminal: SelectionGesture, but only with mouse press 2026-05-25 15:48:16 -07:00
Nikolay Bryskin 9910a1a475
test: add audio-bell thread-leak NixOS check (GNOME/Wayland)
Adds a bell-leak-check-gnome NixOS test (nix/tests.nix) that launches
Ghostty under GNOME on Wayland, rings 100 bells in the window, and fails
if the GUI process thread count grows per-bell — the end-to-end
signature of the GStreamer pipeline leak fixed in this branch. Verified
locally: growth of ~1 thread over 100 bells, vs ~+400 pre-fix.

Replaces the earlier Xvfb shell script + workflow job: per review, X11
support in GNOME is going away, and this belongs as a Nix check
alongside the other *-gnome tests rather than a standalone script.

The VM has no GPU, so it renders via llvmpipe; the test gives the guest
enough cores/RAM for software GL and tolerates the +new-window D-Bus
activation exceeding its client-side timeout (the window still comes up)
by waiting for the window rather than hard-failing on the call.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 01:06:21 +03:00
Nikolay Bryskin 0708f932a5
apprt/gtk: add regression test for audio-bell MediaFile reuse
Guards the contract that prevents the bell thread leak: bellMediaFile
must return the same cached MediaFile for an unchanged path and only
rebuild when the path changes. A revert to per-bell allocation (the
leak) would fail this. Runs in the existing test-gtk CI job; needs no
display or playback since the path bookkeeping is all that's asserted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 23:43:04 +03:00
Nikolay Bryskin 0b6d91e531
apprt/gtk: reuse one audio-bell MediaFile per surface to fix thread leak
Each audio bell called gtk.MediaFile.newForFilename, which spins up a
full GStreamer pipeline. The GTK4 GStreamer backend's GL sink starts
gstglcontext/gldisplay-event threads that are never joined on teardown,
so allocating a MediaFile per ring leaked a pipeline and ~4 threads on
every bell. A long-running instance accumulated 705 threads over ~4h of
normal use.

Cache one MediaFile per surface (priv.bell_media), rebuilt only when
bell-audio-path changes and unref'd on dispose. Each bell now replays
the same pipeline via seek(0)+play() instead of creating a new one. The
notify::ended -> unref handler is removed: it was what discarded (and
leaked) a pipeline per ring. seek(0) is required so an ended stream
plays again (#8957).

Verified on a real instance: GStreamer's global element counter reached
only oggdemux4 over an hour of use (one pipeline per bell-ringing
surface, reused) and thread count stayed flat, versus per-bell growth
before.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 23:43:01 +03:00
ghostty-vouch[bot] a746d0f728
Update VOUCHED list (#12816)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/12815#issuecomment-4537093020)
from @jcollie.

Vouch: @nikicat

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-25 20:38:13 +00:00
Jon Parise ac69942cdc cli: rework +ssh-cache internals and user interface
This change primarily focused on a revised +ssh-cache user interface,
but it also reworks a bunch of the internals.

The primary CLI improvement is support for positional arguments and a
consistent list output format that includes both the ISO-formatted
timestamp and relative age.

    ghostty +ssh-cache                           # List all cached destinations
    ghostty +ssh-cache user@example.com          # Show that destination
    ghostty +ssh-cache example.com               # Show all users on that host
    ghostty +ssh-cache --add=user@example.com    # Manually add a destination
    ghostty +ssh-cache --remove=user@example.com # Remove a destination
    ghostty +ssh-cache --prune=30d               # Remove entries older than 30 days
    ghostty +ssh-cache --clear                   # Clear entire cache

Notable, we now support a --prune operation that replaces the previous
--expire-days flag that was never actually hooked up to anything (!!).
--prune also supports a wider range of Duration-based values.

We're also much more consistent with error codes: 0=success, 1=failure,
2=usage.

While working on those changes, I also reworked the cache internals,
particularly the code around timestamp handling and errors. For example,
I dropped the explicit error sets because they were growing unwieldy,
and in practice we only matched on a subset of those errors.

Lastly, overall test coverage should be much improved, especially around
the time- and allocation-related operations.
2026-05-25 16:00:21 -04:00
ghostty-vouch[bot] 2d0fb81751
Update VOUCHED list (#12813)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/12793#discussioncomment-17052752)
from @bo2themax.

Vouch: @LePips

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-25 17:54:35 +00:00
Mitchell Hashimoto cb28160b5a
elvish: remove community maintenance note (#12812)
The Elvish integration is currently actively maintained by the Ghostty
maintainers. Contributions are of course still welcome.
2026-05-25 09:07:19 -07:00
Mitchell Hashimoto 53e400ad85
cli: fix readEntries leak and double-free (#12811)
readEntries had two memory bugs on the allocation failure path, both
only reachable under OOM:

- The map itself was never freed if we ran into an allocation failure
- The unconditional `errdefer`s for the dupe'd hostname and terminfo
values could double-free if there was a later allocation failure.

This change restructures this function so that these values are dupe'd
up-front, and then their ownership is tracked using optionals that can
be null'ed out once their ownership is transferred into the map.

Both of these cases are now covered by unit tests.
2026-05-25 09:07:09 -07:00
Jon Parise 16d7c8f2b4 elvish: remove community maintenance note
The Elvish integration is currently actively maintained by the Ghostty
maintainers. Contributions are of course still welcome.
2026-05-25 11:56:37 -04:00
Jon Parise a5550a2dcb cli: fix readEntries leak and double-free
readEntries had two memory bugs on the allocation failure path, both
only reachable under OOM:

- The map itself was never freed if we ran into an allocation failure
- The unconditional `errdefer`s for the dupe'd hostname and terminfo
  values could double-free if there was a later allocation failure.

This change restructures this function so that these values are dupe'd
up-front, and then their ownership is tracked using optionals that can
be null'ed out once their ownership is transferred into the map.

Both of these cases are now covered by unit tests.
2026-05-25 11:49:01 -04:00
ghostty-vouch[bot] ae52f97dca
Update VOUCHED list (#12809)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/12807#issuecomment-4534655288)
from @pluiedev.

Denounce: @eric-assetpass

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-25 13:31:49 +00:00
Mitchell Hashimoto b869a6e5ab
libghostty: expose per-cell selection state (#12798)
Render-state rows already expose their selected range, but cell-oriented
C API consumers had to fetch that row range separately and duplicate the
containment check while rendering.

Add a SELECTED row-cells data kind that carries the row selection into
the row-cells wrapper and returns whether the current cell column is in
that inclusive range. The field remains separate from cell colors and
style so selection stays an explicit render overlay policy.

For performance reasons, the span-based row getter is recommended still
but this is a convenient thing to do for cell-oriented folks.
2026-05-24 20:28:58 -07:00
Mitchell Hashimoto edf2da0157
libghostty: expose per-cell selection state
Render-state rows already expose their selected range, but
cell-oriented C API consumers had to fetch that row range separately
and duplicate the containment check while rendering.

Add a SELECTED row-cells data kind that carries the row selection into
the row-cells wrapper and returns whether the current cell column is in
that inclusive range. The field remains separate from cell colors and
style so selection stays an explicit render overlay policy.

For performance reasons, the span-based row getter is recommended still
but this is a convenient thing to do for cell-oriented folks.
2026-05-24 20:24:16 -07:00
Mitchell Hashimoto cf9e85ecd7
deal with large outputs from xdg-open/rundll32/open (#12797)
Depending on your system config, `xdg-open` may stay open for extended
periods, and potentially log more than the 50kb of output that we were
previously able to deal with. This changes `open()` so that output on
`stdout` is just directly ignored. Any output from `stderr` is immedialy
logged rather than collected for later logging.

Note that this will generally occur if your system is not configured
with the DBus portals that `xdg-open` uses to open URLs rather than
launching programs like your web browser directly. This could be seen as
user misconfiguration but we should deal with it robustly anyway.
2026-05-24 19:49:04 -07:00
Jeffrey C. Ollie bb375a2f75
deal with large outputs from xdg-open/rundll32/open
Depending on your system config, `xdg-open` may stay open for extended
periods, and potentially log more than the 50kb of output that we were
previously able to deal with. This changes `open()` so that output on
`stdout` is just directly ignored. Any output from `stderr` is immedialy
logged rather than collected for later logging.

Note that this will generally occur if your system is not configured
with the DBus portals that `xdg-open` uses to open URLs rather than
launching programs like your web browser directly. This could be seen as
user misconfiguration but we should deal with it robustly anyway.
2026-05-24 20:35:39 -05:00
Mitchell Hashimoto c5946f4fef
libghostty: detach tracked grid refs on free (#12795)
Tracked grid references previously held a raw terminal wrapper pointer
and were required to be freed before the terminal. If callers kept one
past terminal destruction, later tracked-ref calls could dereference
freed terminal or page-list memory before detecting that the reference
was no longer meaningful.

Track live C tracked-grid-ref handles from the terminal wrapper and
detach them before tearing down terminal storage. Detached refs now
report no value through the tracked-ref APIs and can still be freed by
the caller. Update the C API docs to describe this lifetime behavior and
add a regression test for using a tracked ref after terminal free.

This introduces some overhead but tracked pins shouldn't be numerous and
this dramatically improves safety.

No API changes due to this (just more safety).
2026-05-24 14:21:58 -07:00
Mitchell Hashimoto 5f08694759
libghostty: selection APIs for C (#12794)
Adds libghostty-vt selection APIs read/write, formatting, inspecting,
and rendering selection state from C.

| Introduced type/function | Purpose |
| --- | --- |
| `GhosttyRenderStateRowSelection` | Row-local inclusive selection range
returned by render row queries. |
| `GhosttyTerminalSelectWordOptions` | Options for deriving a word
selection from a grid ref. |
| `GhosttyTerminalSelectWordBetweenOptions` | Options for finding the
nearest selectable word between two refs. |
| `GhosttyTerminalSelectLineOptions` | Options for deriving line
selections, including semantic prompt boundaries. |
| `GhosttyTerminalSelectionFormatOptions` | Options for formatting the
active or caller-provided selection. |
| `GhosttySelectionOrder` | Describes endpoint ordering, including
rectangular mirrored orders. |
| `GhosttySelectionAdjust` | Operations for moving a selection endpoint.
|
| `ghostty_terminal_select_word` | Derive a word selection snapshot. |
| `ghostty_terminal_select_word_between` | Derive the nearest word
selection between two refs. |
| `ghostty_terminal_select_line` | Derive a line selection snapshot. |
| `ghostty_terminal_select_all` | Derive a selection covering all
selectable content. |
| `ghostty_terminal_select_output` | Derive a semantic command-output
selection. |
| `ghostty_terminal_selection_format_buf` | Format a selection into a
caller-provided buffer. |
| `ghostty_terminal_selection_format_alloc` | Format a selection into an
allocated buffer. |
| `ghostty_terminal_selection_adjust` | Mutate a selection snapshot
endpoint. |
| `ghostty_terminal_selection_order` | Query selection endpoint order. |
| `ghostty_terminal_selection_ordered` | Return a selection with
normalized endpoint order. |
| `ghostty_terminal_selection_contains` | Test whether a point is inside
a selection. |
| `ghostty_terminal_selection_equal` | Compare two selection snapshots
using terminal semantics. |
2026-05-24 14:14:54 -07:00
Mitchell Hashimoto 03df613e39
libghostty: detach tracked grid refs on free
Tracked grid references previously held a raw terminal wrapper pointer and
were required to be freed before the terminal. If callers kept one past
terminal destruction, later tracked-ref calls could dereference freed
terminal or page-list memory before detecting that the reference was no
longer meaningful.

Track live C tracked-grid-ref handles from the terminal wrapper and detach
them before tearing down terminal storage. Detached refs now report no
value through the tracked-ref APIs and can still be freed by the caller.
Update the C API docs to describe this lifetime behavior and add a
regression test for using a tracked ref after terminal free.

This introduces some overhead but tracked pins shouldn't be numerous
and this dramatically improves safety.
2026-05-24 14:13:26 -07:00
Mitchell Hashimoto 2ce5db29ca
libghostty: selection formatting 2026-05-24 14:01:35 -07:00
Mitchell Hashimoto eb777b8036
libghostty: selectWordBetween in C 2026-05-24 13:53:31 -07:00