Commit Graph

14971 Commits

Author SHA1 Message Date
Mitchell Hashimoto
c8a0092301 fix: calculate cell size before presenting gtk window (#10459)
Fixes #7937

Added `computeInitialSize` to GTK `Surface` and call it in GTK
`Application` before the first `present()`, so the window manager
centers the correct size on initial show.

The issue occurs because the core `Surface.recomputeInitialSize()` runs
only after the renderer is initialized. In GTK, the `GLArea` isn’t
realized until after `present()`, so the initial size arrives too late
for WM centering.

**Limitations**: when we precompute size before `present()` we do not
have access to padding, so the sizing will be very slightly off... but
since it is only off a few pixels I was unable to tell visually that it
wasn't perfectly centered.

**Other thoughts**: I was hesitant to make changes to core `Surface`
because the issue is Linux-specific, but it may make sense to extract a
helper from `recomputeInitialSize` to avoid duplicating the sizing math.

**AI Disclosure:** I used AI to explore the project, help with any
language / API questions (I've never used zig before and rarely use
gtk), and make implementation suggestions.
2026-03-03 08:12:48 -08:00
Mitchell Hashimoto
cb06b9b001 terminfo: add support for SGR dim (#11144)
This PR implements the fix discussed in
https://github.com/ghostty-org/ghostty/discussions/11128.

Before:

<img width="818" height="96" alt="before"
src="https://github.com/user-attachments/assets/788f981f-3d1b-4c60-bf85-0c297641cae7"
/>

After:

<img width="813" height="93" alt="after"
src="https://github.com/user-attachments/assets/a530015a-053a-4680-9a85-812aa8df3d91"
/>
2026-03-03 07:17:32 -08:00
Riccardo Mazzarini
4ce782b63f terminfo: add support for SGR dim
This PR implements the fix discussed in
https://github.com/ghostty-org/ghostty/discussions/11128
2026-03-03 09:48:48 +01:00
Mitchell Hashimoto
2502ca294e config: respect cursor-click-to-move for OSC133 click to move (#11141)
When cursor-click-to-move is set to false, disable all prompt
click-to-move mechanisms including shell-native methods such as OSC 133
cl= (arrow key synthesis) and click_events.

I forgot to port this config over when we did the OSC133 stuff.

Also update the config documentation to accurately describe the current
behavior.

Fixes #11138
2026-03-02 20:21:15 -08:00
Mitchell Hashimoto
bb646926f8 config: respect cursor-click-to-move for OSC133 click to move
When cursor-click-to-move is set to false, disable all prompt
click-to-move mechanisms including shell-native methods such as OSC 133
cl= (arrow key synthesis) and click_events. 

I forgot to port this config over when we did the OSC133 stuff.

Also update the config documentation to accurately describe the current
behavior.

Fixes #11138
2026-03-02 20:15:49 -08:00
Mitchell Hashimoto
391c9044bc pkg/afl++: remove @@ from run target since we use in-memory targets 2026-03-02 19:36:43 -08:00
Leah Amelia Chen
d3c3770435 Nix pkgs pin dependencies (#11121) 2026-03-03 08:42:27 +08:00
rhodes-b
eaa83b82b3 address comments 2026-03-02 17:25:04 -06:00
Mitchell Hashimoto
aa157c09ab terminal: fix insertBlanks orphaned spacer_tail beyond right margin (#11137)
When insertBlanks clears the entire region from cursor to the right
margin (scroll_amount == 0), a wide character whose head is at the right
margin gets cleared but its spacer_tail just beyond the margin is left
behind, causing a "spacer tail not following wide" page integrity
violation.

Move the right-margin wide-char cleanup from inside the scroll_amount >
0 block to before it, so it runs unconditionally — matching the
rowWillBeShifted pattern of cleaning up boundary-straddling wide chars
up front.

Found via AFL++ fuzzing. #11109
2026-03-02 11:32:28 -08:00
ghostty-vouch[bot]
5fa42dd802 Update VOUCHED list (#11139)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11128#discussioncomment-15976454)
from @mitchellh.

Vouch: @noib3

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-02 19:31:32 +00:00
Mitchell Hashimoto
177612a4cf terminal: fix insertBlanks orphaned spacer_tail beyond right margin
When insertBlanks clears the entire region from cursor to the right
margin (scroll_amount == 0), a wide character whose head is at the right
margin gets cleared but its spacer_tail just beyond the margin is left
behind, causing a "spacer tail not following wide" page integrity
violation.

Move the right-margin wide-char cleanup from inside the scroll_amount >
0 block to before it, so it runs unconditionally — matching the
rowWillBeShifted pattern of cleaning up boundary-straddling wide chars
up front.

Found via AFL++ fuzzing. #11109
2026-03-02 11:24:54 -08:00
Mitchell Hashimoto
4768ffff73 terminal: fix insertLines/deleteLines orphaned cells on full clear (#11136)
When deleteLines or insertLines count >= scroll region height, all rows
go through the clear-only path (no shifting). This path did not call
rowWillBeShifted, leaving orphaned spacer_tail cells when wide
characters straddled the right margin boundary, causing a "spacer tail
not following wide" page integrity violation.

Add rowWillBeShifted before clearCells in the else branch of both
functions.

Found via AFL++ fuzzing. #11109
2026-03-02 11:02:14 -08:00
Mitchell Hashimoto
678601d94a terminal: fix no-reflow resize leaving stale spacer heads (#11135)
resizeWithoutReflowGrowCols has a fast path that reuses existing page
capacity when growing columns: it simply bumps page.size.cols without
touching cell data. If any row has a spacer_head at the old last column
(from a wide char that did not fit), that cell is no longer at the end
of the now-wider row, causing a page integrity violation.

Fix by checking for spacer_head cells at the old last column before
taking the fast path. If any are found, fall through to the slow path
which handles spacer heads correctly via cloneRowFrom.

Found by AFL++ stream fuzzer. #11109
2026-03-02 10:58:10 -08:00
Mitchell Hashimoto
b39a00ddfa terminal: fix insertLines/deleteLines orphaned cells on full clear
When deleteLines or insertLines count >= scroll region height, all rows
go through the clear-only path (no shifting). This path did not call
rowWillBeShifted, leaving orphaned spacer_tail cells when wide characters
straddled the right margin boundary, causing a "spacer tail not following
wide" page integrity violation.

Add rowWillBeShifted before clearCells in the else branch of both
functions.

Found via AFL++ fuzzing. #11109
2026-03-02 10:57:41 -08:00
Mitchell Hashimoto
1ba9f9187e terminal: fix no-reflow resize leaving stale spacer heads
resizeWithoutReflowGrowCols has a fast path that reuses existing page
capacity when growing columns: it simply bumps page.size.cols without
touching cell data. If any row has a spacer_head at the old last column
(from a wide char that did not fit), that cell is no longer at the end
of the now-wider row, causing a page integrity violation.

Fix by checking for spacer_head cells at the old last column before
taking the fast path. If any are found, fall through to the slow path
which handles spacer heads correctly via cloneRowFrom.

Found by AFL++ stream fuzzer. #11109
2026-03-02 10:32:58 -08:00
Mitchell Hashimoto
8cddd384c6 terminal: fix printCell corrupting previous row when overwriting wide char (#11134)
printCell, when overwriting a wide cell with a narrow cell at x<=1 and
y>0, unconditionally sets the last cell of the previous row to .narrow.
This is intended to clear a spacer_head left by a wrapped wide char, but
the cell could be a spacer_tail if a wide char fit entirely on the
previous row. Setting a spacer_tail to .narrow orphans the preceding
.wide cell, which later causes an integrity violation in insertBlanks
(assert that the cell after a .wide is .spacer_tail).

Fix by guarding the assignment so it only fires when the previous row's
last cell is actually a .spacer_head. The same fix is applied in both
the .wide and .spacer_tail branches of printCell.

Found by AFL++ stream fuzzer. #11109
2026-03-02 07:32:59 -08:00
Mitchell Hashimoto
e7030e73db terminal: fix printCell corrupting previous row when overwriting wide char
printCell, when overwriting a wide cell with a narrow cell at x<=1 and
y>0, unconditionally sets the last cell of the previous row to .narrow.
This is intended to clear a spacer_head left by a wrapped wide char, but
the cell could be a spacer_tail if a wide char fit entirely on the
previous row. Setting a spacer_tail to .narrow orphans the preceding
.wide cell, which later causes an integrity violation in insertBlanks
(assert that the cell after a .wide is .spacer_tail).

Fix by guarding the assignment so it only fires when the previous row's
last cell is actually a .spacer_head. The same fix is applied in both
the .wide and .spacer_tail branches of printCell.

Found by AFL++ stream fuzzer.
2026-03-02 07:28:12 -08:00
Mitchell Hashimoto
9d3c46c4bc terminal: fix insertBlanks integrity violation with wide char at right margin (#11132)
insertBlanks checks whether the last source cell being shifted is wide
and clears it to avoid splitting, but it did not check the destination
cells at the right edge of the scroll region. When a wide character
straddles the right scroll margin (head at the margin, spacer_tail just
beyond it), the swap loop displaced the wide head without clearing the
orphaned spacer_tail, causing a page integrity violation
(InvalidSpacerTailLocation).

Fix by checking the cell at the right margin (last destination cell)
before the swap loop and clearing it along with its spacer_tail when it
is wide.

Found by AFL++ stream fuzzer. #11109
2026-03-02 06:42:54 -08:00
Mitchell Hashimoto
90e96a3891 terminal: fix insertBlanks integrity violation with wide char at right margin
insertBlanks checks whether the last source cell being shifted is wide
and clears it to avoid splitting, but it did not check the destination
cells at the right edge of the scroll region. When a wide character
straddles the right scroll margin (head at the margin, spacer_tail just
beyond it), the swap loop displaced the wide head without clearing the
orphaned spacer_tail, causing a page integrity violation
(InvalidSpacerTailLocation).

Fix by checking the cell at the right margin (last destination cell)
before the swap loop and clearing it along with its spacer_tail when it
is wide. 

Found by AFL++ stream fuzzer. #11109
2026-03-02 06:37:43 -08:00
ghostty-vouch[bot]
913c12097b Update VOUCHED list (#11123)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11118#discussioncomment-15967576)
from @pluiedev.

Vouch: @jguthmiller

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-02 05:38:01 +00:00
ghostty-vouch[bot]
22e29bb1f0 Update VOUCHED list (#11122)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/11121#issuecomment-3982187512)
from @jcollie.

Vouch: @rhodes-b

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-02 05:18:17 +00:00
rhodes-b
5e7a5cc9c1 pin python depds to latest tag 2026-03-01 23:04:07 -06:00
Mitchell Hashimoto
7665efc3a1 fuzz: new stream corpus from 2 hour run 2026-03-01 20:19:44 -08:00
Mitchell Hashimoto
f3da60aef5 terminal: fix integrity violation printing wide char with hyperlink at right edge (#11119)
Printing a wide character at the right edge of the screen with an active
hyperlink triggered a page integrity violation (UnwrappedSpacerHead).
printCell wrote the spacer_head to the cell and then called
cursorSetHyperlink, whose internal integrity check observed the
spacer_head before printWrap had a chance to set the row wrap flag.

Fix by setting row.wrap = true before calling printCell for the
spacer_head case, so all integrity checks see a consistent state.
printWrap sets wrap again afterward, which is harmless. Found by AFL++
stream fuzzer.

#11109
2026-03-01 20:08:30 -08:00
Mitchell Hashimoto
43ec4ace47 fuzz: add replay-crashes.nu to help find crash repros 2026-03-01 20:08:17 -08:00
Mitchell Hashimoto
97c11af347 terminal: fix integrity violation printing wide char with hyperlink at right edge
Printing a wide character at the right edge of the screen with an active
hyperlink triggered a page integrity violation (UnwrappedSpacerHead).
printCell wrote the spacer_head to the cell and then called
cursorSetHyperlink, whose internal integrity check observed the
spacer_head before printWrap had a chance to set the row wrap flag.

Fix by setting row.wrap = true before calling printCell for the
spacer_head case, so all integrity checks see a consistent state.
printWrap sets wrap again afterward, which is harmless. Found by AFL++
stream fuzzer.
2026-03-01 19:56:32 -08:00
ghostty-vouch[bot]
ca31828c93 Update VOUCHED list (#11116)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/11115#issuecomment-3981600125)
from @mitchellh.

Vouch: @markdorison

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-02 01:59:52 +00:00
Guilherme Nandi Tiscoski
533ad9e3fa i18n: update pt_BR translations (#10635)
Add missing pt_BR translations reported in
https://github.com/ghostty-org/ghostty/issues/10632 for version 1.3
2026-03-02 01:31:03 +00:00
ghostty-vouch[bot]
24546426c8 Sync CODEOWNERS vouch list (#11114)
Sync CODEOWNERS owners with vouch list.

## Added Users

- @derVedro

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-02 00:02:03 +00:00
Mitchell Hashimoto
2d69568a67 terminal: handle trailing colon in SGR underline parsing (#11113)
A trailing colon with no following sub-parameter (e.g. "ESC[58:4:m")
leaves the colon separator bit set on the last param without adding
another entry to the params array. When the SGR parser later iterates to
that param (4 = underline) and sees the colon bit, it entered the colon
path which asserted slice.len >= 2, but the slice only had one element.

Replace the assert with a bounds check that treats the malformed
sequence as a default single underline.

Add a regression test reproducing the crash from AFL++ fuzzing
(afl-out/stream/default/crashes/id:000021).

#11109
2026-03-01 15:38:28 -08:00
Mitchell Hashimoto
ec4c5f90a8 terminal: fix panic on CSI g (TBC) with overflowing param (#11112)
A fuzz crash found that CSI g with a parameter that saturates to u16 max
(65535) causes @enumFromInt to panic when narrowing to TabClear
(enum(u8)). Use std.meta.intToEnum instead, which safely returns an
error for out-of-range values.

#11109
2026-03-01 15:38:14 -08:00
Mitchell Hashimoto
f253c54fac terminal: handle trailing colon in SGR underline parsing
A trailing colon with no following sub-parameter (e.g. "ESC[58:4:m")
leaves the colon separator bit set on the last param without adding
another entry to the params array. When the SGR parser later iterates
to that param (4 = underline) and sees the colon bit, it entered the
colon path which asserted slice.len >= 2, but the slice only had one
element.

Replace the assert with a bounds check that treats the malformed
sequence as a default single underline.

Add a regression test reproducing the crash from AFL++ fuzzing
(afl-out/stream/default/crashes/id:000021).
2026-03-01 15:28:56 -08:00
Mitchell Hashimoto
a595c00f3c terminal: fix panic on CSI g (TBC) with overflowing param
A fuzz crash found that CSI g with a parameter that saturates to
u16 max (65535) causes @enumFromInt to panic when narrowing to
TabClear (enum(u8)). Use std.meta.intToEnum instead, which safely
returns an error for out-of-range values.
2026-03-01 15:15:27 -08:00
Mitchell Hashimoto
1ead8f4275 fuzz: terminal.vtStream fuzzer (#11109)
This augments our libghostty fuzzing to add fuzzing for
`terminal.vtStream` which exercises a LOT more codepaths than the pure
parser (thousands of tuples compared to hundreds with `afl-showmap` on
the two binaries). I also fixed up a few more minor things: prettier
ignores AFL related files, lib-vt exports the readonly streams, etc.
2026-03-01 15:08:47 -08:00
Mitchell Hashimoto
8cebcaa468 fuzz: stream cmin 2026-03-01 15:00:13 -08:00
Mitchell Hashimoto
dce2326c4c fix up gitattributes 2026-03-01 14:55:07 -08:00
Mitchell Hashimoto
1c65611446 prettier should ignore various fuzz files 2026-03-01 14:55:07 -08:00
Mitchell Hashimoto
33fbd73247 fuzz/stream: clean up 2026-03-01 14:55:07 -08:00
Mitchell Hashimoto
4f44879c3b Clean up how fuzzers are laid out 2026-03-01 14:55:07 -08:00
Mitchell Hashimoto
e081a4abb4 fuzz/vt-stream 2026-03-01 14:55:07 -08:00
Mitchell Hashimoto
1e027c9f20 terminal: insertBlanks should not crash with count 0 and CSI @ clamps to 1 min (#11111)
CSI @ (ICH) with an explicit parameter of 0 should be clamped to 1,
matching xterm behavior. Previously, a zero count reached
Terminal.insertBlanks which called clearCells with an empty slice,
triggering an out-of-bounds panic.

Fix the stream dispatch to clamp 0 to 1 via @max, and add a defensive
guard in insertBlanks for count == 0. Found by AFL++ stream fuzzer.
#11109
2026-03-01 14:54:56 -08:00
Mitchell Hashimoto
9157eb439a terminal: insertBlanks should not crash with count 0 and CSI @ clamps [1,)
CSI @ (ICH) with an explicit parameter of 0 should be clamped to 1,
matching xterm behavior. Previously, a zero count reached
Terminal.insertBlanks which called clearCells with an empty slice,
triggering an out-of-bounds panic.

Fix the stream dispatch to clamp 0 to 1 via @max, and add a defensive
guard in insertBlanks for count == 0. Found by AFL++ stream fuzzer.
2026-03-01 14:50:24 -08:00
Mitchell Hashimoto
8c22cb0601 terminal: fix out-of-bounds access in CSI W handler with no params (#11110)
CSI ? W (cursor tabulation control) accessed input.params[0] without
first checking that params.len > 0, causing an index out-of-bounds panic
when the sequence had an intermediate but no parameters.

Add a params.len == 1 guard before accessing params[0].

Found by AFL++ fuzzing #11109
2026-03-01 14:30:42 -08:00
Mitchell Hashimoto
dcaa8f3979 terminal: fix out-of-bounds access in CSI W handler with no params
CSI ? W (cursor tabulation control) accessed input.params[0] without
first checking that params.len > 0, causing an index out-of-bounds
panic when the sequence had an intermediate but no parameters.

Add a params.len == 1 guard before accessing params[0].

Found by AFL++ fuzzing.
2026-03-01 14:24:57 -08:00
Mitchell Hashimoto
72df30f14b docs: add clarification for pre-vouching contributors (#11096)
If this PR is accepted, it will add a clarification to the contribution
guidelines to inform pre-vouching contributors that they are still
required to apply for vouching as would a first-time contributor.
2026-03-01 13:27:17 -08:00
ghostty-vouch[bot]
db7c140100 Update VOUCHED list (#11107)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11102#discussioncomment-15964699)
from @mitchellh.

Vouch: @mischief

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-01 21:25:32 +00:00
Mitchell Hashimoto
a48cb630a8 libghostty-vt parser fuzzing, generic fuzz harness, using AFL++ (#11089)
This adds a `test/fuzz-libghostty` which is a standalone `zig build`
target for building an AFL++ instrumented executable for fuzzing the
libghostty-vt parser. I also added a `pkg/afl++` (based on zig-afl-kit)
so instrumenting objects and using AFL++ is a bit easier.

Fuzzing `libghostty-vt`'s parser is as easy as `zig build run`, but see
the README for a lot more details. I ran the fuzzer for ~14 hours total
and only found one crash #11088. I'm pretty confident at this point our
Parser layer isn't obviously crash-able, but need to instrument more
places to fuzz.

We don't use Zig's built-in fuzzing yet because as of 0.15 (our current
stable), it isn't ready and AFL++ is an industry proven tool to do this.
2026-03-01 13:16:52 -08:00
Mitchell Hashimoto
125b6e9f6c Clear key state overlay on "ignore" action (#11103)
This fixes a bug in the key state sequence overlay.

## Demo

In my ghostty config, I have

    keybind = ctrl+space>escape=ignore
    keybind = ctrl+space>p=toggle_command_palette
    ...

because I use `ctrl+space>` sequences for most things and so hitting
`esc` is my way to bail out of the sequence if I change my mind.

I just switched to tip and got the new GTK key sequence overlay. Here's
what I saw. In these screen recordings, the sequence of keys I press is

ctrl+space, escape, ctrl+space, escape, ctrl+space, escape, ctrl+space,
p


https://github.com/user-attachments/assets/4a37bc7e-b75c-4bd1-99de-f21f4211b5b5

after the fix:


https://github.com/user-attachments/assets/023be88e-1299-4219-920c-1b1134b2888c

## Notes

I believe this was also a leak, since the queued keys wouldn't be
deinited.

**AI usage:** Claude Code suggested the fix, then I read enough code to
convince myself that it makes sense.
2026-03-01 13:15:55 -08:00
Alexandre Antonio Juca
c735fd8c47 Update CONTRIBUTING.md
Co-authored-by: Jeffrey C. Ollie <jeff@ocjtech.us>
2026-03-01 22:05:30 +01:00
Alexandre Antonio Juca
3972426852 chore: improve grammer 2026-03-01 21:56:46 +01:00