Commit Graph

8303 Commits

Author SHA1 Message Date
Mitchell Hashimoto
7d0157e69a macOS: add Cmd+J "Jump to Selection" menu item and default binding
This matches other built-in macOS apps like Terminal, Notes, Safari. We
already had the binding, just needed to create the menu.

https://ampcode.com/threads/T-019b956a-f4e6-71b4-87fa-4162258d33ff
2026-01-06 14:30:11 -08:00
Mitchell Hashimoto
09c7240fb2 macOS: Selection for Find feature (#10192)
Adds the `selection_for_search` action, with Cmd+E keybind by default.
This action inputs the currently selected text into the search field
without changing focus, matching standard macOS behavior.

Implements discussion #9776 and #10036

<details><summary>AI Disclosure</summary>
<p>

Tab completions with Codestral.
Reviewed by Gemini 3 Flash via chatting.
No Agentic coding tools were involved.

</p>
</details>
2026-01-06 14:26:03 -08:00
Mitchell Hashimoto
3ba4f17f0d zig fmt 2026-01-06 14:21:42 -08:00
Mitchell Hashimoto
f07d600e43 macos: start_search with needle changes needle 2026-01-06 14:14:22 -08:00
Mitchell Hashimoto
8e28f58b42 rename the selection search binding, unify into start_search action 2026-01-06 14:10:42 -08:00
Mitchell Hashimoto
45abfa9190 font: add bitmap font tests for BDF, PCF, and OTB formats (#10193)
Adds test coverage for bitmap font rendering in the FreeType backend
using the Spleen 8x16 font in three formats:

- BDF (Bitmap Distribution Format)
- PCF (Portable Compiled Format)
- OTB (OpenType Bitmap)

Tests validate glyph dimensions and pixel-perfect rendering against
expected patterns, following the model established by the existing
TerminusTTF test.

Spleen was chosen because it ships in all three required formats from a
single source, providing consistent test data across formats. Its BSD
2-Clause license is compatible with the existing font licenses in the
repo (OFL, MIT). No existing embedded fonts could be used since they are
all TTF/OTF files that use the TrueType loader rather than the
BDF/PCF/OTB loaders being tested.

Addresses #8524.

---

This PR was written with assistance from Claude Code.
2026-01-06 09:26:27 -08:00
Britt Binler
896615c004 font: add bitmap font tests for BDF, PCF, and OTB formats
Add test coverage for bitmap font rendering using the Spleen 8x16 font
in three formats: BDF (Bitmap Distribution Format), PCF (Portable
Compiled Format), and OTB (OpenType Bitmap). Tests validate glyph
rendering against expected pixel patterns.

Addresses #8524.
2026-01-06 09:14:33 -08:00
Aaron Ruan
9b6a3be993 macOS: Selection for Find feature
Adds the `selection_for_search` action, with Cmd+E keybind by default.
This action inputs the currently selected text into the search
field without changing focus, matching standard macOS behavior.
2026-01-06 22:21:55 +08:00
Jeffrey C. Ollie
f3e90e23d9 Lower unimplemented OSC from warning to debug 2026-01-05 15:47:49 -06:00
Mitchell Hashimoto
c5bc6bb2ce fix: use flush instead of end on stdout in code generators for Windows compatibility (#10150)
This fixes the Windows build failure discussed in
https://github.com/ghostty-org/ghostty/discussions/10148

When building on Windows, `symbols-unigen` and `props-unigen` crash with
`error.FileTooBig` because `stdout.end()` calls `setEndPos()` to
truncate the output. Windows does not support `SetEndOfFile` on pipes or
console handles - it returns `ERROR_INVALID_PARAMETER`, which Zig maps
to `error.FileTooBig`.

Using `flush()` instead of `end()` is correct here because:

1. `end()` flushes AND truncates - useful when overwriting files that
might have leftover content
2. For stdout captured as a pipe, there's nothing to truncate - we're
writing sequentially to a fresh pipe
3. `flush()` ensures all buffered data is sent, which is all that's
needed

CI before fix was failing with FileTooBig, after fix builds
successfully:
https://github.com/remorses/opentui/actions/runs/20671299561/job/59352503875
2026-01-05 11:44:13 -08:00
Mitchell Hashimoto
dda27d43be font/shaper: Fix CoreText position.y for some scripts (#10179)
This PR simplifies and corrects the logic for placing a glyph
vertically, by using the `position.y` from `CoreText` directly, instead
of using an offset from the cell's starting `y`. The logic was incorrect
from the beginning, always treating the first glyph of a cell as being
at `y` of zero. We only need to be subtracting the cell's starting `x`
to align the glyphs to the cell grid.

Enabling the commented out logging, I found no instances of `position.y
differs from old offset.y` lines with `JetBrains Mono` with ligatures
turned on, but running
[ttylang](https://github.com/jacobsandlund/ttylang) (printing the
Universal Declaration of Human Rights in various languages) revealed 676
instances of this, with many only slightly off.

An example log from some Tai Tham text is the following, and this PR
adds a test based on this:

```
...pos=(0.00,-8.21) run_offset=(69.41,-8.21) cell_offset=(69.41,-8.21) old offset.y=0.00 cps = \u{1a49}\u{1a60} \u{1a3f}▸\u{1a69} \u{1a2f} → ᩉ᩠ᨿᩩᨯ
```

Browsers display this as:

ᩉ᩠ᨿᩩ

`main` is printing:

<img width="852" height="90" alt="CleanShot 2026-01-05 at 10 28 17@2x"
src="https://github.com/user-attachments/assets/c97b738c-8fe4-48b5-81f8-e0e79f1a9269"
/>

this PR prints:

<img width="958" height="90" alt="CleanShot 2026-01-05 at 10 29 07@2x"
src="https://github.com/user-attachments/assets/88fd26a7-8041-4b33-ab02-56f411204b04"
/>

Since this is a ligature of two different grapheme clusters, Ghostty
ends up subtracting too much of the `x` value with the `cell_offset.x`
(starting x), so neither of the screenshots above are correct, but the
second is closer and gets the `y` value right.

AI disclaimer: I didn't use AI for the code, but did ask it about this
Tai Tham text and why it wasn't a single grapheme cluster:
https://ampcode.com/threads/T-019b8ea2-1822-75bb-a8eb-55a9ddb9f7ea
2026-01-05 11:17:16 -08:00
Jacob Sandlund
15899b70fb simplify run_offset_x comment 2026-01-05 10:35:22 -05:00
Jacob Sandlund
7aec7effea Add test for Tai Tham letter position.y difference 2026-01-05 10:12:05 -05:00
Jacob Sandlund
41f63384f5 Turn off debugging 2026-01-05 09:59:37 -05:00
Jacob Sandlund
f31d2b99ae Merge remote-tracking branch 'upstream/main' into coretext-position-y 2026-01-05 09:58:10 -05:00
Jacob Sandlund
d38558aee1 Show current cp with ▸ in list of cps 2026-01-05 09:34:17 -05:00
Peter Cardenas
f36abed35a fix: reset progress bar on reset terminal 2026-01-05 05:26:33 -08:00
Jacob Sandlund
1d4a5d91e0 More debugging for position.y differences 2026-01-04 21:24:45 -05:00
Tommy D. Rossi
e2de0bfd93 fix: clarify error codes in comment 2026-01-03 13:44:29 +01:00
Tommy D. Rossi
4ea669562e fix: use flush instead of end on stdout in code generators for Windows compatibility 2026-01-03 13:43:27 +01:00
Martin Emde
ec2612f9ce Add iTimeFocus shader uniform to track time since focus 2026-01-01 13:11:54 -08:00
Mitchell Hashimoto
f2bc722a58 pkg/dcimgui: fix wchar size mismatch 2025-12-31 13:36:40 -08:00
Mitchell Hashimoto
965ffb1750 pkg/dcimgui: add freetype 2025-12-31 13:20:27 -08:00
Mitchell Hashimoto
f1ba5297b8 build: fix imgui on GTK 2025-12-31 13:20:03 -08:00
Mitchell Hashimoto
896361f426 Fix up API calls for initialization 2025-12-31 13:01:28 -08:00
Mitchell Hashimoto
978400b0b0 replace cimgui with dcimgui 2025-12-31 10:42:10 -08:00
Jacob Sandlund
0a648cddf8 shaping: Use position.y directly for CoreText 2025-12-30 17:36:45 -05:00
qingyunha
5c4af69765 Update Vim filetype detection patterns
Fixes #10094
2025-12-30 08:47:18 +08:00
Mitchell Hashimoto
61df50d70b input: add end_key_sequence binding action
End the currently active key sequence, if any, and flush the
keys up to this point to the terminal, excluding the key that
triggered this action.

For example: `ctrl+w>escape=end_key_sequence` would encode
`ctrl+w` to the terminal and exit the key sequence.

Normally, an invalid sequence will reset the key sequence and
flush all data including the invalid key. This action allows
you to flush only the prior keys, which is useful when you want
to bind something like a control key (`ctrl+w`) but not send
additional inputs.
2025-12-29 12:07:54 -08:00
Mitchell Hashimoto
e3dd5b93e6 gtk: pass through keypress when clipboard has no text (#10089)
## Summary

When `paste_from_clipboard` is triggered but the clipboard contains no
text (e.g., an image), the action now returns `false` to indicate it
couldn't be performed. This enables the `performable:` keybind prefix to
work correctly for paste actions.

## Problem

On GTK/Linux, when a user has `keybind = ctrl+v=paste_from_clipboard`
and the clipboard contains an image (not text), pressing Ctrl+V does
nothing. Applications like `opencode` that handle their own clipboard
reading via `wl-paste` never receive the keypress.

## Solution

Make `clipboardRequest` return `bool` to indicate whether the action
could be performed. For paste requests on GTK, synchronously check if
the clipboard contains text formats before starting the async read. When
no text format is available, return `false`.

Users can now use:
```
keybind = performable:ctrl+v=paste_from_clipboard
```

When the clipboard has no text, the keybind is not consumed and Ctrl+V
passes through to the terminal application.

## Changes

- `Surface.startClipboardRequest` now returns `bool`
- `paste_from_clipboard` / `paste_from_selection` actions return the
result
- GTK apprt checks clipboard formats synchronously before async read
- Embedded apprt always returns `true` (can't check synchronously)

## Testing

1. Add `keybind = performable:ctrl+v=paste_from_clipboard` to config
2. Copy an image to clipboard
3. Open an application that handles image paste (e.g., `opencode`)
4. Press Ctrl+V
5. Image pastes successfully (app receives keypress and handles
clipboard itself)

## Disclaimer

Most of the changes is done with Opus 4.5
2025-12-29 09:39:17 -08:00
cyppe
972b65eb1b review 2025-12-29 18:32:25 +01:00
Mitchell Hashimoto
86d5048dad terminal: PageList needs to fix up viewport pin after row change
From #10074

The test comments explain in detail.
2025-12-29 09:12:25 -08:00
cyppe
8331447398 Improve type detection 2025-12-29 16:15:02 +01:00
cyppe
0da650e7dd gtk: support performable keybinds for clipboard paste
Make clipboardRequest return bool to indicate whether the action could
be performed. For paste requests, synchronously check if the clipboard
contains text formats before starting the async read.

This allows 'performable:paste_from_clipboard' keybinds to pass through
when the clipboard contains non-text content (e.g., images), enabling
terminal applications to handle their own clipboard reading.

Changes:
- Surface.startClipboardRequest now returns bool
- paste_from_clipboard/paste_from_selection actions return the result
- GTK apprt checks clipboard formats synchronously before async read
- Embedded apprt always returns true (can't check synchronously)
- All other call sites discard the return value with _
2025-12-29 15:50:06 +01:00
cyppe
8a419e5526 gtk: pass through keypress when clipboard has no text
When paste_from_clipboard is triggered but the clipboard contains no
text (e.g., an image), send the raw Ctrl+V keypress to the terminal
instead of silently returning. This allows applications to handle
their own clipboard reading (e.g., via wl-paste for images on Wayland).
2025-12-29 09:58:09 +01:00
Chris Marchesi
6d36193378 deps: update z2d to v0.10.0
Release notes at:
 https://github.com/vancluever/z2d/blob/v0.10.0/CHANGELOG.md

Mainly a maintenance update with regards to Ghostty use, with a couple
of minor changes required to some type references to match new API
semantics.
2025-12-28 12:30:36 -08:00
Mitchell Hashimoto
c00d7fc5c4 shell-integration: ensure clean env on failure (#10035)
Our shell integration routines can now fail when resources are missing.
This change introduces tests to ensure that they leave behind a clean
environment upon failure.

The bash integration needed a little reordering to support this.
2025-12-26 13:29:27 -08:00
Mitchell Hashimoto
14f592b8d4 macOS: Don't duplicate command palette entries for terminal commands
This is a regression introduced when we added macOS support for custom
entries. I mistakingly thought that only custom entries were in the
config, but we do initialize it with all!
2025-12-26 11:03:50 -08:00
Mitchell Hashimoto
26b104c9e0 terminal: Fix possible crash on RenderState with invalid mouse point
Fixes #10032
2025-12-26 10:45:15 -08:00
Mitchell Hashimoto
ebcc350018 datastruct/circ_buf: fix n=0 edge cases (#10066)
From #10063

This fixes and tests various edge cases around noop operations.
2025-12-26 10:36:36 -08:00
Mitchell Hashimoto
eb5d2e034b datastruct/circ_buf: fix n=0 edge cases
From #10063

This fixes and tests various edge cases around noop operations.
2025-12-26 10:33:52 -08:00
Mitchell Hashimoto
79cc22e186 terminal: fix crash when sliding window sees empty node
Related to #10063

This fixes a crash that can happen if the SlidingWindow search portion
sees a zero-byte page. 

We have more fixes to implement in the circular buffer handling but
putting the fix at this layer also prevents some unnecessary allocations
for zero-byte data.
2025-12-26 10:26:12 -08:00
Zongyuan Li
88e471e015 fix(iOS): fix iOS app startup failure
Fixes #7643

This commit address the issue with 3 minor fixes:
1. Initialize ghostty lib before app start, or global allocator will
   be null.
2. `addSublayer` should be called on CALayer object, which is the
   property 'layer' of UIView
3. According to apple's [document](https://developer.apple.com/documentation/metal/mtlstoragemode/managed?language=objc),
   managed storage mode is not supported by iOS. So always use shared
   mode.

FYI, another [fix](https://github.com/mitchellh/libxev/pull/204) in libxev
is also required to make iOS app work.
2025-12-26 18:53:45 +08:00
Mitchell Hashimoto
f54ac11080 terminal: search will re-scroll to navigate to a single match
Fixes #9958
Replaces #9989

This changes the search navigation logic to always scroll if there is a
selected search result so long as the search result isn't already within
the viewport.
2025-12-25 13:50:02 -08:00
rezky_nightky
bf73f75304 chore: fixed some typo
Author: rezky_nightky <with dot rezky at gmail dot com>
Repository: ghostty
Branch: main
Signing: GPG (4B65AAC2)
HashAlgo: BLAKE3

[ Block Metadata ]
BlockHash: c37f4ee817412728a8058ba6087f5ca6aaff5a845560447d595d8055972d0eac
PrevHash: 3510917a780936278debe21786b7bae3a2162cb3857957314c3b8702e921b3d4
PatchHash: 5e5bb4ab35df304ea13c3d297c6d9a965156052c82bccf852b1f00b7bcaa7dd4

FilesChanged: 18
Lines: +92 / -92

Timestamp: 2025-12-25T17:27:08Z
Signature1: c1970dbb94600d1e24dfe8efcc00f001664db7b777902df9632a689b1d9d1498
Signature2: 30babb1e3ca07264931e067bfe36c676fb7988c2e06f8c54e0c9538fe7c7fc9a
2025-12-26 00:27:08 +07:00
Mitchell Hashimoto
017021787c config: RepeatableCommand cval 2025-12-24 14:26:47 -08:00
Jon Parise
141e64cede shell-integration: always call setupFeatures (#10033)
Our existing logic already ensured that setupFeatures() was always
called, but that was happening from two code paths: explicitly when
shell integration is .none and implicitly via setup().

We can simplify this by always calling setupFeatures() once, outside of
the (automatic) shell integration path.

There's one small behavioral change: we previously didn't set up shell
features in the automatic shell integration path if we didn't have a
resources directory (as a side effect). Resources are required for shell
integrations, but we don't need them to export GHOSTTY_SHELL_FEATURES,
which could potentially still be useful on its on.
2025-12-24 09:08:28 -05:00
Mitchell Hashimoto
0db0655ea5 Invalid key sequence does not encode if a catch_all has ignore
This adds some new special case handling for key sequences when an
unbound keyboard input is received. If the current keybinding set scope
(i.e. active tables) has a `catch_all` binding that would `ignore`
input, then the entire key sequence is dropped.

Normally, when an unbound key sequence is received, Ghostty encodes it
and sends it to the running program. 

This special behavior is useful for things like Vim mode which have `g>g`
to scroll to top, and a `catch_all=ignore` to drop all other input. If
the user presses `g>h` (unbound), you don't want `gh` to show up in your 
terminal input, because the `catch_all=ignore` indicates that the user
wants that mode to drop all unbound input.
2025-12-23 20:31:05 -08:00
Jon Parise
256c3b9ffb shell-integration: ensure clean env on failure
Our shell integration routines can now fail when resources are missing.
This change introduces tests to ensure that they leave behind a clean
environment upon failure.

The bash integration needed a little reordering to support this.
2025-12-23 14:51:09 -05:00
Mitchell Hashimoto
634c3353fe GTK: UI for key sequences and tables (#10034)
Fixes #2127 

This adds a UI similar to macOS to show the current state of key
sequences and/or key tables.


https://github.com/user-attachments/assets/4399d2af-a88c-4b70-922b-7727dc4d2053

**AI disclosure:** AI was used for various things, but I did write most
of the code myself, especially around the memory management of
properties since agents can't get that quite right yet. 😄
2025-12-23 11:27:03 -08:00