Commit Graph

8475 Commits

Author SHA1 Message Date
Mitchell Hashimoto
db092ac3ce renderer: extract rebuildRow to its own function 2026-01-20 12:07:42 -08:00
Mitchell Hashimoto
112363c4e1 font: Collection.getEntry explicit error set 2026-01-20 11:57:22 -08:00
Mitchell Hashimoto
e875b453b7 font/shaper: hook functions can't fail 2026-01-20 11:51:01 -08:00
Mitchell Hashimoto
e3c39ed502 renderer: cell.Contents.resize errdefer handling is now safe 2026-01-20 11:46:27 -08:00
Mitchell Hashimoto
7204f7ef9e renderer: remove palette_dirty, rely on terminal state 2026-01-20 11:34:53 -08:00
Mitchell Hashimoto
8786745969 renderer: don't access shared state for custom shader color palettes 2026-01-20 11:25:27 -08:00
ClearAspect
8d2eb280db custom shaders: add colorscheme information to shader uniforms
Adds palette and color scheme uniforms to custom shaders, allowing
custom shaders to access terminal color information:

  - iPalette[256]: Full 256-color terminal palette (RGB)
  - iBackgroundColor, iForegroundColor: Terminal colors (RGB)
  - iCursorColor, iCursorText: Cursor colors (RGB)
  - iSelectionBackgroundColor, iSelectionForegroundColor: Selection
colors (RGB)

Colors are normalized to [0.0, 1.0] range and update when the palette
changes via OSC sequences or configuration changes. The palette_dirty
flag tracks when colors need to be refreshed, initialized to true to
ensure correct colors on new surfaces.
2026-01-20 11:15:09 -08:00
Mitchell Hashimoto
cb25c0a8ae build: libghostty-vt now depends on uucode directly
This doesn't add any real weight to it, we only need it for a type
definition. This fixes our example builds.
2026-01-20 10:18:47 -08:00
Martin Emde
c2deda3231 config: switch certain physical keybinds to unicode
Switches several default keybindings from physical key codes

`.physical = .equal // or .bracket_left or .bracket_right`

to unicode characters

`.unicode = '=' // or '[' or ']'`

to support alternative keyboard layouts like Dvorak and
keyboards with dedicated plus keys (like German layouts).

I found in testing that all of these must be fixed at once otherwise
the bracket physical keys overshadew the correct (for dvorak) plus key.
With this fix, tab and pane navigation (cmd+[], cmd+shift+[]), as well
as cmd+shift+equals and cmd+equals work as expected on dvoark layout on MacOS.
2026-01-20 09:58:34 -08:00
Mitchell Hashimoto
492eb40d28 gtk: add GSettings generic module and respect gtk-enable-primary-paste on gtk systems (#10328)
# Add GSettings Support for Primary Paste

Implements support for `org.gnome.desktop.interface
gtk-enable-primary-paste` to allow users to disable middle-click paste.
Also refactors GTK Settings access into a reusable generic module.

## Changes

- **NEW**: `src/apprt/gtk/gsettings.zig` - Generic GTK Settings reader
supporting `bool` and `c_int` types, portal-aware for Flatpak/Snap
- **MODIFIED**: `src/apprt/gtk/class/surface.zig` - Reads primary paste
setting and refactors gtk-xft-dpi to use new module

## Behavior
- Setting `false` → Middle-click paste blocked
- Setting `true` or unavailable → Middle-click paste works (default)
- Uses GTK Settings API which automatically uses XDG Desktop Portal in
sandboxed environments

Note: No unit tests added as this is a thin wrapper around GTK Settings
API that's already tested indirectly through surface.zig. Happy to add
tests if desired, though they would require an active display
environment and skip on most CI systems.
2026-01-20 09:49:48 -08:00
Mitchell Hashimoto
c8ffc0faa5 termio: report color scheme synchronously (#9705)
The reporting of color scheme was handled asynchronously by queuing a
handler in the surface. This could lead to race conditions where the DSR
is reported after subsequent VT sequences.

Fixes #5922
2026-01-20 09:48:43 -08:00
Mitchell Hashimoto
49b2b8d644 unicode: switch to uucode grapheme break to (mostly) match unicode spec (#9680)
This PR builds on https://github.com/ghostty-org/ghostty/pull/9678 ~so
the diff from there is included here (it's not possible to stack PRs
unless it's a PR against my own fork)--review that one first!~

This PR updates the `graphemeBreak` calculation to use `uucode`'s
`computeGraphemeBreakNoControl`, which has [tests in
uucode](215ff09730/src/x/grapheme.zig (L753))
that confirm it passes the `GraphemeBreakTest.txt` (minus some
exceptions).

Note that the `grapheme_break` (and `grapheme_break_no_control`)
property in `uucode` incorporates `emoji_modifier` and
`emoji_modifier_base`, diverging from UAX #29 but matching UTS #51. See
[this comment in
uucode](215ff09730/src/grapheme.zig (L420-L434))
for details.

The `grapheme_break_no_control` property and
`computeGraphemeBreakNoControl` both assume `control`, `cr`, and `lf`
have been filtered out, matching the current grapheme break logic in
Ghostty.

This PR keeps the `Precompute.data` logic mostly equivalent, since the
`uucode` `precomputedGraphemeBreak` lacks benchmarks in the `uucode`
repository (it was benchmarked in [the original PR adding `uucode` to
Ghostty](https://github.com/ghostty-org/ghostty/pull/8757)). Note
however, that due to `grapheme_break` being one bit larger than
`grapheme_boundary_class` and the new `BreakState` also being one bit
larger, the state jumps up by a factor of 8 (u10 -> u13), to 8KB.

## Benchmarks

~I benchmarked the old `main` version versus this PR for
`+grapheme-break` and surprisingly this PR is 2% faster (?). Looking at
the assembly though, I'm thinking something else might be causing that.
Once I get to the bottom of that I'll remove the below TODO and include
the benchmark results here.~

When seeing the speedup with `data.txt` and maybe a tiny speedup on
English wiki, I was surprised given the 1KB -> 8KB tables. Here's what
AI said when I asked it to inspect the assembly:
https://ampcode.com/threads/T-979b1743-19e7-47c9-8074-9778b4b2a61e, and
here's what it said when I asked it to predict the faster version:
https://ampcode.com/threads/T-3291dcd3-7a21-4d24-a192-7b3f6e18cd31

It looks like two loads got reordered and that put the load that
depended on stage1 -> stage2 -> stage3 second, "hiding memory latency".
So that makes the new one faster when looking up the `grapheme_break`
property. These gains go away with the Japanese and Arabic benchmarks,
which spend more time processing utf8, and may even have more grapheme
clusters too.

### with data.txt (200 MB ghostty-gen random utf8)

<img width="1822" height="464" alt="CleanShot 2025-11-26 at 08 42 03@2x"
src="https://github.com/user-attachments/assets/56d4ee98-21db-4eab-93ab-a0463a653883"
/>

### with English wiki dump

<img width="2012" height="506" alt="CleanShot 2025-11-26 at 08 43 15@2x"
src="https://github.com/user-attachments/assets/230fbfb7-272d-4a2a-93e7-7268962a9814"
/>

### with Japanese wiki dump

<img width="2008" height="518" alt="CleanShot 2025-11-26 at 08 43 49@2x"
src="https://github.com/user-attachments/assets/edb408c8-a604-4a8f-bd5b-80f19e3d65ee"
/>

### with Arabic wiki dump

<img width="2010" height="512" alt="CleanShot 2025-11-26 at 08 44 25@2x"
src="https://github.com/user-attachments/assets/81a29ac8-0586-4e82-8276-d7fa90c31c90"
/>


TODO:

* [x] Take a closer look at the assembly and understand why this PR (8
KB vs 1 KB table) is faster on my machine.
* [x] _(**edit**: checking this off because it seems unnecessary)_ If
this turns out to actually be unacceptably slower, one possibility is to
switch to `uucode`'s `precomputedGraphemeBreak` which uses a 1445 byte
table since it uses a dense table (indexed using multiplication instead
of bitCast, though, which did show up in the initial benchmarks from
https://github.com/ghostty-org/ghostty/pull/8757 a small amount.)

AI was used in some of the uucode changes in
https://github.com/ghostty-org/ghostty/pull/9678 (Amp--primarily for
tests), but everything was carefully vetted and much of it done by hand.
This PR was made without AI with the exception of consulting AI about
whether the "Prepend + ASCII" scenario is common (hopefully it's right
about that being uncommon).
2026-01-20 09:44:15 -08:00
Mitchell Hashimoto
2e0141fcdf config: clarify selection-word-boundary docs 2026-01-20 09:38:41 -08:00
mauroporras
9b7c20f500 refactor: use u21 for Unicode codepoints and Zig 0.15 ArrayList
- Change all codepoint types from u32 to u21 to align with Zig stdlib
- Update ArrayList to use Zig 0.15 unmanaged pattern (.empty)
- Remove unnecessary @intCast when encoding UTF-8
- Fix formatEntry to use stack-allocated buffer
2026-01-20 09:37:31 -08:00
mauroporras
6f662d70bc refactor: clean up selection-word-chars documentation and formatting 2026-01-20 09:37:31 -08:00
mauroporras
27602bb4b4 refactor: optimize selection-word-chars with pre-parsed codepoints
Refactor the selection-word-chars implementation to parse UTF-8 boundary
characters once during config initialization instead of on every selection
operation.

Changes:
- Add SelectionWordChars type that stores pre-parsed []const u32 codepoints
- Parse UTF-8 to codepoints in parseCLI() during config load
- Remove UTF-8 parsing logic from selectWord() hot path (27 lines removed)
- Remove arbitrary 64-character buffer limit
- Update selectWord() and selectWordBetween() to accept []const u32
- Update DerivedConfig to store codepoints directly
- Update all tests to use codepoint arrays

Benefits:
- No runtime UTF-8 parsing overhead on every selection
- No arbitrary character limit (uses allocator instead)
- Cleaner separation of concerns (config handles parsing, selection uses data)
- Better performance in selection hot path
2026-01-20 09:37:31 -08:00
mauroporras
811e3594eb feat: add configurable word boundary characters for text selection
Add new `selection-word-chars` config option to customize which characters
mark word boundaries during text selection operations (double-click, word
selection, etc.). Similar to zsh's WORDCHARS environment variable, but
specifies boundary characters rather than word characters.

Default boundaries: ` \t'"│`|:;,()[]{}<>$`

Users can now customize word selection behavior, such as treating
semicolons as part of words or excluding periods from boundaries:

    selection-word-chars = " \t'\"│`|:,()[]{}<>$"

Changes:
- Add selection-word-chars config field with comprehensive documentation
- Modify selectWord() and selectWordBetween() to accept boundary_chars parameter
- Parse UTF-8 boundary string to u32 codepoints at runtime
- Update all call sites in Surface.zig and embedded.zig
- Update all test cases to pass boundary characters
2026-01-20 09:37:31 -08:00
evertonstz
8c9891b5de Refactor primary paste settings handling and documentation for clarity 2026-01-20 14:32:47 -03:00
Mitchell Hashimoto
6730afe312 macOS: Add GhosttyUITests (Drafting to save some ci checks) (#9185)
### Background

~~I was trying to add a few UI test cases for
`macOS-titlebar-style`[Already in this PR]~~. In order to do this, I
need a way from `GhosttyKit` to load a temporary configuration without
messing around with users'.

### Changes

- Add `ghostty_config_load_file` using the existing
[`loadFile`](dafb9e89a3/src/config/Config.zig (L3399))
- Use `xcbeautify` to format test&build errors
**Couldn't find a way to do this in `GhosttyXcodebuild`, if you have a
better approach please let me know!**
- Add GhosttyUITests target and test cases for
`GhosttyTitlebarTabsUITests`(#2349) and `GhosttyThemeTests`(#9360)

### NOTE

Running UI tests on the runner could be **very** slow and I couldn't
find a way to guarantee success, so I made these only runnable by
manually testing in Xcode.

Better to squash this🤪

> > Some of the test cases could fail when testing all the cases
together; a rerun would succeed.
2026-01-20 09:30:39 -08:00
Mitchell Hashimoto
7abdc94540 feat: Select/Copy Links On Right Click If Present (#9298)
This is a solution for
https://github.com/ghostty-org/ghostty/issues/2107.

**AI Disclosure:** I used Gemini CLI to help me with this PR because
while I have many years of programming experience, this is my first time
writing Zig. I prototyped a couple different approaches with AI before
landing on this one, so AI generated various prototypes and I chose the
final imlementation. I've verified that my code compiles and works as
intended.

When a user right-clicks, and there's no existing selection, the
existing behavior is to try to select the word under the cursor:


3548acfac6/src/Surface.zig (L3740-L3742)

This PR tweaks that behavior _slightly_: If there's a link under our
cursor, as determined by `linkAtPos`, select the link (to copy with the
right-click context menu). Otherwise, select the word as before.

As noted in https://github.com/ghostty-org/ghostty/issues/2107, this
matches the behavior of iTerm and Gnome Terminal.

It's worth noting that `linkAtPos` already does the right thing in terms
of checking the links from config and their highlight/hover states
(modified by Ctrl or Super depending on platform).


3548acfac6/src/Surface.zig (L3896-L3901)

It also therefore respects `link-url` from config.


3548acfac6/src/config/Config.zig (L3411-L3416)

By using `linkAtPos`, we get all that behavior for free. In practical
terms, that means:
- If I'm holding Ctrl so a link is underlined and I right click on it,
it selects the underlined link.
- If I'm not holding Ctrl and I right click on a link that is no
underlined, it selects the word as before.
- This behavior respects per-platform key bindings and user config
settings.

`linkAtPos` requires that the render state mutex is held. I believe it's
safe to call because we're inside a block holding the mutex:

3548acfac6/src/Surface.zig (L3702-L3704)

**Original Behavior:**
(first without ctrl, then with ctrl)


https://github.com/user-attachments/assets/f9236c44-bea4-4be8-a54b-24d5ae24b2e7

**New Behavior:**
(first without ctrl, then with ctrl, then pasting)


https://github.com/user-attachments/assets/1e7fa1a9-236e-471d-9504-c820c68600bb
2026-01-20 09:30:25 -08:00
evertonstz
bc067fc782 Refactor gtk_enable_primary_paste to remove optional type and simplify condition checks 2026-01-20 14:23:22 -03:00
evertonstz
7b6147aa28 Refactor GValueType and getImpl functions to use type-based switches for improved clarity and maintainability 2026-01-20 14:23:10 -03:00
Lars
9c5d4a5511 ghosttyKit: add ghostty_config_load_file 2026-01-20 09:15:14 -08:00
Mitchell Hashimoto
7d9de9afd9 gtk: Session Search (#10155)
Gtk implementation of #9945. Fixes #9948.

This adds session search to the command palette on Gtk, allowing you to jump to any surface by title or working directory. The main difference to the Mac OS implementation is that tabs do not have colors by which to search. I also have not implemented the flashing behavior when a split is focused.

The same, or as close as I could make it, behavior that was introduced for command sorting is also implemented for Gtk. Granted, as I haven't tested this new feature on Mac OS, my understanding of the behavior of it is based on the code and the screencast from the PR.

https://github.com/user-attachments/assets/d50d93a8-fe32-4d39-ba41-1f766010a293

One thing I noticed during development, which I left unsolved as I also didn't see it solved in the Mac OS implementation (though I haven't tested it), is that if you are zoomed into a split, then focusing a different split doesn't do anything. There's a configuration option that I forgot the name of, related to zoom behavior during navigation, that I would expect to be respected, but I wasn't able to get it to work, so I left it for a later iteration.

The majority of the code was generated with Claude Sonnet 4.5. Although I have reviewed and iterated on the code thoroughly, I am not experienced with Zig and I would not be surprised if there are issues that I did not notice, and would appreciate them being pointed out (and ideally explained if it's not obvious to a non-Zig developer).
2026-01-20 08:51:38 -08:00
Mitchell Hashimoto
63075c926e shell-integration: initial nushell shell integration (#10274)
Nushell <https://www.nushell.sh/> is a modern interactive shell that
provides many shell features out-of-the-box, like `title` support. Our
shell integration therefore focuses on Ghostty-specific features like
`sudo`.

We use Nushell's module system to provide a `ghostty` module containing
our shell integration features. This module is automatically loaded from
$XDG_DATA_DIRS/nushell/vendor/autoload/ when `nushell` shell integration
is enabled.

Exported module functions need to be explicitly "used" before they're
available to the interactive shell environment. We do that automatically
by adding `--execute "use ghostty *"` to the `nu` command line.

This imports all available functions, and individual shell features are
runtime-guarded by the script code (using $GHOSTTY_SHELL_FEATURES). We
can consider further refining this later.

When automatic shell integration is disabled, users can still manually
source and enable the shell integration module:

source
$GHOSTTY_RESOURCES_DIR/shell-integration/nushell/vendor/autoload/ghostty.nu
    use ghostty *

This initial work implements our TERMINFO-aware `sudo` wrapper (via the
`sudo` shell feature). Support for additional features, like `ssh-env`
and `ssh-terminfo`, will follow (#9604).
2026-01-20 08:33:13 -08:00
Mitchell Hashimoto
c4dcb8849e Use underline for preedit texts instead of inverting colors (#10368)
issue: https://github.com/ghostty-org/ghostty/issues/10366

Presently, IME preediting texts are rendered with inverted colors
styles. This pull request changes that style to adding underlines.

Before
<img width="314" height="60" alt="image"
src="https://github.com/user-attachments/assets/183410c3-06b5-4157-b3a2-37188f507e4c"
/>

After
<img width="320" height="63" alt="image"
src="https://github.com/user-attachments/assets/d50b8898-7db1-4b4e-ad73-0a157f63068c"
/>

If it is preferred that adding configure like `ime-preedit-text-style`
with default value `invert` to keep the current behaviour as is, I can
add such a config (see https://github.com/shivaduke28/ghostty/pull/1 ).

Thanks!

Disclosure: This PR was written primarily by Claude Code.
2026-01-20 08:24:30 -08:00
Tommy Brunn
0c8b51c7ab gtk: Add todo for replacing jump sort key with surface id
Using a pointer for this is a bit icky. Once Ghostty adds unique ids to
surfaces, we can sort by that id instead. This can potentially also be
used to navigate to the surface instead of having the command palette
reference the surfaces directly.
2026-01-20 17:09:15 +01:00
Tommy Brunn
f2b5a9192a gtk: Clean up title sorting 2026-01-20 17:05:14 +01:00
evertonstz
bff21222d4 Refactor gsettings keys to use string literals for GTK settings and update related tests 2026-01-20 12:12:04 -03:00
Mitchell Hashimoto
ae8d2c7a3e terminal: fix up some of the manual handling, comments 2026-01-19 12:17:09 -08:00
Mitchell Hashimoto
a8b31ceb84 terminal: restoreCursor is now longer fallible
We need to have sane behavior in error handling because the running
program that sends the restore cursor command has no way to realize it
failed. So if our style fails to add (our only fail case) then we revert
to no style.

https://ampcode.com/threads/T-019bd7dc-cf0b-7439-ad2f-218b3406277a
2026-01-19 12:12:19 -08:00
Mitchell Hashimoto
c412b30cb5 terminal: splitForCapacity, manualStyleUpdate uses this 2026-01-19 11:59:00 -08:00
Mitchell Hashimoto
4e60a85099 terminal: setAttribute failure reverts back to prior style 2026-01-19 11:52:39 -08:00
Mitchell Hashimoto
93a070c6de terminal: PageList split operation 2026-01-19 11:52:37 -08:00
Mitchell Hashimoto
f9699eceb0 terminal: PageList.compact 2026-01-19 09:18:58 -08:00
Mitchell Hashimoto
93436217c8 terminal: page.exactRowCapacity 2026-01-19 09:16:49 -08:00
Mitchell Hashimoto
d6cb84d12f terminal: remap tracked pins in backfill optimization path during resize (#10377)
Fixes #10369

When `resizeWithoutReflowGrowCols` copies rows to a previous page with
spare capacity, tracked pins pointing to those rows were not being
remapped. This left pins pointing to the original page which was
subsequently destroyed.

The fix adds pin remapping for rows copied to the previous page,
matching the existing remapping logic for rows copied to new pages.

I also added new integrity checks to verify that our tracked pins are
always valid at points where internal operations complete.

Thanks to @grishy for finding this!

**AI disclosure:** Amp used for verifying and fixing this bug. I
reviewed the results and just did minor manual tweaks.
https://ampcode.com/threads/T-019bd6d7-0645-73dd-8fd7-659f019fa83d and
https://ampcode.com/threads/T-019bd6c9-cc2e-73bc-bbaa-f8766e11c234
2026-01-19 09:15:09 -08:00
Mitchell Hashimoto
d67dd08a21 terminal: remap tracked pins in backfill path during resize
Fixes #10369

When `resizeWithoutReflowGrowCols` copies rows to a previous page with
spare capacity, tracked pins pointing to those rows were not being remapped. 
This left pins pointing to the original page which was subsequently destroyed.

The fix adds pin remapping for rows copied to the previous page,
matching the existing remapping logic for rows copied to new pages.

I also added new integrity checks to verify that our tracked pins are
always valid at points where internal operations complete.

Thanks to @grishy for finding this!
2026-01-19 09:11:49 -08:00
Jeffrey C. Ollie
1daba40247 osc 133: handle bare keys with no '='
Fixes #10379
2026-01-19 10:59:00 -06:00
Tobias Kohlbau
836d794b9e termio: report color scheme synchronously
The reporting of color scheme was handled asynchronously by queuing a
handler in the surface. This could lead to race conditions where the
DSR is reported after subsequent VT sequences.

Fixes #5922
2026-01-19 07:49:57 +01:00
Mitchell Hashimoto
250877eff6 terminal: increaseCapacity should preserve dirty flag (#10374)
This never caused any known issues, but it's a bug! `increaseCapacity`
should produce a node with identical contents, just more capacity. We
were forgetting to copy over the dirty flag.

I looked back at `adjustCapacity` and it also didn't preserve the dirty
flag so presumably downstream consumers have been handling this case
manually. But, I think semantically it makes sense for
`increaseCapacity` to preserve the dirty flag.

This bug was found by AI (while I was doing another task). I fixed it
and wrote the test by hand though.
2026-01-18 14:52:56 -08:00
Mitchell Hashimoto
3ee30058ab terminal: increaseCapacity should preserve dirty flag
This never caused any known issues, but it's a bug! `increaseCapacity`
should produce a node with identical contents, just more capacity. We
were forgetting to copy over the dirty flag.

I looked back at `adjustCapacity` and it also didn't preserve the dirty
flag so presumably downstream consumers have been handling this case
manually. But, I think semantically it makes sense for
`increaseCapacity` to preserve the dirty flag.

This bug was found by AI (while I was doing another task). I fixed it
and wrote the test by hand though.
2026-01-18 14:47:12 -08:00
shivaduke28
b0c868811d use underline instead of inverting colors for preedit text 2026-01-18 16:22:11 +09:00
Jon Parise
5423d64c6a ssh-cache: use AtomicFile to write the cache file
We previously wrote our new cache file into a temporary directory and
the (atomically) renamed it to the canonical cache file path. This
rename operation unfortunately only works when both files are on the
same file system, and that's not always the case (e.g. when $TMPDIR is
on its own file system).

Instead, we can use Zig's AtomicFile to safely perform this operation
inside of the cache directory.

There's a new risk of a crash leaving the temporary file around in this
directory (and not getting cleaned up like $TMPDIR-based files), but the
probability is low and those files will only be readable by the creating
user (mode 0o600).

There's a new test cash that verifies the expected AtomicFile clean up
behavior. I also switched the file-oriented tests to use testing.tmpDir
rather than using our application-level TempDir type.
2026-01-17 20:44:22 -05:00
Mitchell Hashimoto
464c31328e terminal: grow prune check should not prune if required for active
Fixes #10352

The bug was that non-standard pages would mix the old
`growRequiredForActive` check and make our active area insufficient in
the PageList.

But, since scrollbars now require we have a cached `total_rows` that our
safety checks always verify, we can remove the old linked list traversal
and switch to some simple math in general across all page sizes.
2026-01-16 21:26:54 -08:00
Mitchell Hashimoto
56237efeef PageList overflow detection and protection (#10337)
Fixes #10258  
Replaces #10284

1. `Page.Capacity` now uses smaller bit-width integers that represent a
true maximum capacity for various fields.
2. On 64-bit systems, a maxed out `Page.Capacity` (every field `maxInt`)
can be represented in an addressable allocation (total required memory
less than 64 bits). This means `Page.layout` can't overflow.
3. All `adjustCapacity` functions replaced with `increaseCapacity` which
doesn't allow specifying the resulting value, which makes it so overflow
is only possible in significantly fewer places, making it easier to
handle in general.
4. `increaseCapacity` can return a new error `OutOfSpace` which happens
when overflow is detected. This means that no valid page can accommodate
the desired capacity increase because we're already at the max. The
caller is expected to handle this.
5. Updated our resize so that the only possible error is system OOM, we
handle the new `OutOfSpace` by copying the recent reflowed row into a
new page and continuing.

A very, very high-level overview is below. The "overflow" here papers
over a bunch of details where the prior usize capacities flowed through
to Page.layout and ultimately RefCountedSet and other managed types
which then caused incorrect calculations on total memory size required.

```mermaid
flowchart TB
    subgraph Before["Before: adjustCapacity"]
        A1[capacity: usize] --> A2["capacity *= 2"]
        A2 --> A3{Overflow?}
        A3 -->|"Not detected"| A4["Massive allocation or crash"]
    end
    
    subgraph After["After: increaseCapacity"]
        B1["capacity: bounded int<br/>(u16/u32)"] --> B2["capacity *= 2"]
        B2 --> B3{Overflow?}
        B3 -->|"OutOfSpace error"| B4["Graceful handling:<br/>move row to new page"]
        B3 -->|"Success"| B5["Normal allocation"]
    end
    
    Before --> After
    
    classDef beforeStyle fill:#3d1a1a,stroke:#ff6b6b,color:#ff6b6b
    classDef afterStyle fill:#1a3d3a,stroke:#4ecdc4,color:#4ecdc4
    
    class A1,A2,A3,A4 beforeStyle
    class B1,B2,B3,B4,B5 afterStyle
```
2026-01-16 14:52:28 -08:00
Mitchell Hashimoto
df35363b15 terminal: more robust handling of max_page_size
not 100%
2026-01-16 14:47:53 -08:00
Mitchell Hashimoto
442a395850 terminal: ensure our std_capacity fits within max page size 2026-01-16 14:25:01 -08:00
Qwerasd
69066200ef fix: handle double tmux control mode exit command 2026-01-16 16:58:58 -05:00
Mitchell Hashimoto
85a3d623b2 terminal: increaseCapacity should reach maxInt before overflow 2026-01-16 13:43:56 -08:00