Commit Graph

14995 Commits

Author SHA1 Message Date
Kat
0797b281ec Add Kazakh translation (#10670)
Dear maintainers,

This PR adds Kazakh language translation file and necessary edits to
CODEOWNERS and i18n file with the list of locales.

Please review (and squash when committing)

Thank you!
2026-03-04 18:34:51 +00:00
Baurzhan Muftakhidinov
2772c90885 i18n: add Kazakh translation (kk) 2026-03-04 22:02:37 +05:00
Mitchell Hashimoto
53ef42266a macos: Ghostty.Shell.escape unit tests (#11162)
*AI Disclosure:* These were written using the Claude Agent in Xcode
26.3, partly as an excuse to try out that latest integration.
2026-03-04 08:12:15 -08:00
Jon Parise
a716b9c4d4 macos: Ghostty.Shell.escape unit tests 2026-03-04 11:00:03 -05:00
Mitchell Hashimoto
619e33a4fe macos: implement audio bell support with bell-audio-path (#11154)
## Summary

This extends the macOS bell implementation to support the `audio` bell
feature, bringing it to parity with GTK/Linux.

Previously, macOS only had the `system` feature (`NSSound.beep()`). This
PR adds:

- **`audio` bell feature on macOS**: plays the file at `bell-audio-path`
using `NSSound(contentsOfFile:)`, respecting `bell-audio-volume`
- **`cval()` on the `Path` type**: allows `Path` values (a union type)
to be returned through the C API, which is needed for Swift to read
`bell-audio-path`
- **Removes `(GTK only)` restriction** from `bell-audio-path` and
`bell-audio-volume` documentation

## How it works

In `AppDelegate.swift`, when the bell rings and the `audio` feature is
enabled, Ghostty now:
1. Reads `bell-audio-path` from config
2. Loads it as an `NSSound`
3. Applies `bell-audio-volume` and plays it

Falls back gracefully if the path is not set or the file cannot be
loaded.

## Example config

```
bell-features = audio
bell-audio-path = /System/Library/Sounds/Glass.aiff
bell-audio-volume = 0.8
```

## Testing

- Set `bell-features = audio` and `bell-audio-path` to any valid audio
file
- Trigger a bell with `echo -e '\a'`
- Audio should play at the configured volume
2026-03-03 20:08:04 -08:00
Mitchell Hashimoto
98ad1d955c use proper type for optional path 2026-03-03 19:53:15 -08:00
Jeffrey C. Ollie
73ce40c623 build(deps): bump cachix/install-nix-action from 31.9.1 to 31.10.0 (#11157)
Bumps
[cachix/install-nix-action](https://github.com/cachix/install-nix-action)
from 31.9.1 to 31.10.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cachix/install-nix-action/releases">cachix/install-nix-action's
releases</a>.</em></p>
<blockquote>
<h2>v31.10.0</h2>
<h2>What's Changed</h2>
<ul>
<li>nix: 2.33.3 -&gt; 2.34.0 by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/cachix/install-nix-action/pull/267">cachix/install-nix-action#267</a>
Release notes: <a
href="https://discourse.nixos.org/t/nix-2-34-0-released/75818">https://discourse.nixos.org/t/nix-2-34-0-released/75818</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cachix/install-nix-action/compare/v31.9.1...v31.10.0">https://github.com/cachix/install-nix-action/compare/v31.9.1...v31.10.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="19effe9fe7"><code>19effe9</code></a>
Merge pull request <a
href="https://redirect.github.com/cachix/install-nix-action/issues/267">#267</a>
from cachix/create-pull-request/patch</li>
<li><a
href="d3f3b99dd1"><code>d3f3b99</code></a>
nix: 2.33.3 -&gt; 2.34.0</li>
<li>See full diff in <a
href="2126ae7fc5...19effe9fe7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cachix/install-nix-action&package-manager=github_actions&previous-version=31.9.1&new-version=31.10.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2026-03-03 20:18:08 -06:00
dependabot[bot]
69df92b56a build(deps): bump cachix/install-nix-action from 31.9.1 to 31.10.0
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 31.9.1 to 31.10.0.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](2126ae7fc5...19effe9fe7)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-version: 31.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-04 00:15:23 +00:00
ghostty-vouch[bot]
c93cf52108 Update VOUCHED list (#11156)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/10982#discussioncomment-15990906)
from @jcollie.

Vouch: @cmwetherell

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-04 00:06:57 +00:00
Mitchell Hashimoto
4c83872317 macOS: Refine tab title editing (#11150)
- Pass through mouse down event to `TabTitleEditor` if needed
- Pass through right mouse down event to `TabTitleEditor` if needed
- Hide close button when editing tab title

Refactor:
- Use a separated struct to hide and restore tab states


https://github.com/user-attachments/assets/e69838f5-e199-437c-b53b-a491e9d5b752
2026-03-03 14:15:32 -08:00
ghostty-vouch[bot]
0149fd7139 Update VOUCHED list (#11155)
Triggered by
[comment](https://github.com/ghostty-org/ghostty/issues/11154#issuecomment-3993830083)
from @mitchellh.

Vouch: @alaasdk

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-03 22:02:49 +00:00
Alaa Ali
b215291914 macos: implement audio bell support with bell-audio-path
Extends the macOS bell implementation to support the `audio` bell
feature by playing a user-specified audio file via NSSound.

Previously, macOS only supported the `system` feature (NSSound.beep()).
This change adds support for:
- `audio` bell feature: plays the file at `bell-audio-path` using
  NSSound, respecting the `bell-audio-volume` setting
- Adds `cval()` to the `Path` type so it can be returned via the C API

Also removes the "(GTK only)" restriction from `bell-audio-path` and
`bell-audio-volume` documentation, as these options now work on macOS.

Example config:
  bell-features = audio
  bell-audio-path = /System/Library/Sounds/Glass.aiff
  bell-audio-volume = 0.8
2026-03-03 23:00:50 +01:00
Mitchell Hashimoto
ee4c6f88c5 build: link to the system FontConfig by default on non-macOS systems (#11152)
Because of the global shared state that FontConfig maintains, FontConfig
must be linked dynamically to the same system FontConfig shared library
that GTK uses. Ghostty's default has been changed to always link to the
system FontConfig library on non-macOS systems. If that is overridden
(by specifying `-fno-sys=fontconfig` during the build) Ghostty may crash
when trying to locate glyphs that are not available in the default font.

Fixes #10432
2026-03-03 12:51:44 -08:00
Jeffrey C. Ollie
89f9dd7848 build: link to the system FontConfig by default on non-macOS systems
Because of the global shared state that FontConfig maintains, FontConfig
must be linked dynamically to the same system FontConfig shared library
that GTK uses. Ghostty's default has been changed to always link to the
system FontConfig library on non-macOS systems. If that is overridden
(by specifying `-fno-sys=fontconfig` during the build) Ghostty may crash
when trying to locate glyphs that are not available in the default font.

Fixes #10432
2026-03-03 14:40:00 -06:00
Mitchell Hashimoto
2d5bb18e29 input: send composed text in kitty keyboard protocol (#11149)
When the kitty keyboard protocol "report all keys as escape codes" mode
was active, composed/IME text (e.g. from dead keys or compose sequences)
was silently dropped.

This happened because the composed text is sent within our GTK apprt
with key=unidentified and no unshifted_codepoint, so no kitty entry was
found and the encoder returned without producing any output. The
plain-text fallback was also skipped because report_all bypasses it.

Send composed text as raw UTF-8 when no kitty entry is found, matching
the behavior of Kitty on Linux for me.

Fixes #10049
2026-03-03 09:04:32 -08:00
Mitchell Hashimoto
fdfc9fea2f input: send composed text in kitty keyboard protocol
When the kitty keyboard protocol "report all keys as escape codes" mode
was active, composed/IME text (e.g. from dead keys or compose sequences)
was silently dropped. 

This happened because the composed text is sent within our GTK apprt
with key=unidentified and no unshifted_codepoint, so no kitty entry was
found and the encoder returned without producing any output. The
plain-text fallback was also skipped because report_all bypasses it.

Send composed text as raw UTF-8 when no kitty entry is found, matching
the behavior of Kitty on Linux for me.

Fixes #10049
2026-03-03 08:57:24 -08:00
Mitchell Hashimoto
562721e6d1 fuzz: add OSC parser fuzzer (#11148)
I'm running this now, 10 minutes with nothing but I figure this is a big
enough target we should also add this.
2026-03-03 08:47:17 -08:00
Lukas
4437707132 macos: use a separated struct to hide and restore tab states 2026-03-03 17:42:17 +01:00
Mitchell Hashimoto
d2175d1b56 fuzz: add OSC parser fuzzer 2026-03-03 08:37:45 -08:00
Lukas
78fdff34a9 macos: hide close button when editing tab title 2026-03-03 17:24:56 +01:00
Lukas
661470897e macos: passthrough right mouse down event to TabTitleEditor if needed 2026-03-03 17:24:56 +01:00
Mitchell Hashimoto
2f0039d419 macos: finish editing tab title when the window resigns as key window (#11147)
This fixes #11146 and also #10993. Updated the comments added in #11052.

> After finishing editing when the window resigns as the key window,
using `labelFrame.minY` is fine with the same usage as #10993, but when
double-clicking with text selected it will move up again 🤷🏻‍♂️.

This makes focus state more accurate with cursor shape on the surface,
when editing the title for a tab in another window group.

[Incorrect
example](https://github.com/user-attachments/assets/c3c4e774-a683-44e7-9bb6-3be79ac72ec2)
2026-03-03 08:17:05 -08:00
Lukas
205c05d59d macos: passthrough mouse down event to TabTitleEditor if needed 2026-03-03 17:15:12 +01:00
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
Lukas
e6e5f3ffe1 macos: finish editing tab title when the window resigns as key window 2026-03-03 16:34:11 +01: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