Commit Graph

15658 Commits

Author SHA1 Message Date
Mitchell Hashimoto
7269fa7d14 lib: rename GHOSTTY_EXPORT to GHOSTTY_API (#11994)
Rename the shared library visibility macro from GHOSTTY_EXPORT to
GHOSTTY_API across all public C headers. This applies to both the
libghostty-vt headers under include/ghostty/vt/ and the main
include/ghostty.h header.

This is a bit more idiomatic compared to other C libs and addresses the
fact that we're not always exporting...
2026-03-30 10:51:52 -07:00
Mitchell Hashimoto
40d108599f lib: rename GHOSTTY_EXPORT to GHOSTTY_API
Rename the shared library visibility macro from GHOSTTY_EXPORT to
GHOSTTY_API across all public C headers. This applies to both the
libghostty-vt headers under include/ghostty/vt/ and the main
include/ghostty.h header.

This is a bit more idiomatic compared to other C libs and addresses the
fact that we're not always exporting...
2026-03-30 10:26:32 -07:00
Mitchell Hashimoto
53871e4d52 libghostty: WASM VT example, add ghostty_type_json (#11992)
This adds a new `example/wasm-vt` example that initializes a terminal,
lets you write text to write to it, and shows you the screen state.

In doing so, I realized that writing structs in WASM is extremely
painful. You had to do manually hardcoded sizes and byte offsets and
it's scary as hell! So I added a new `ghostty_type_json` API that
returns a C string with JSON-encoded type information about all exported
C structures.

## Example

<img width="1912" height="1574" alt="CleanShot 2026-03-30 at 10 20
16@2x"
src="https://github.com/user-attachments/assets/7cae92bc-3403-4e4c-958c-b7ea58026afe"
/>
2026-03-30 10:24:00 -07:00
Mitchell Hashimoto
bd7415f4b7 terminal: clean up some types tests 2026-03-30 10:21:08 -07:00
Mitchell Hashimoto
3c6e98c5a7 vt: export the new API 2026-03-30 10:16:39 -07:00
Mitchell Hashimoto
0c38e8be60 vt: simplify ghostty_type_json to return null-terminated string
The function previously took a size_t* out-parameter for the string
length. Since the JSON blob is now null-terminated, the len parameter
is unnecessary. Remove it from the Zig implementation, C header, and
the WASM example consumer which no longer needs to allocate and free
a usize just to read the length.
2026-03-30 10:16:19 -07:00
Mitchell Hashimoto
6479d90ca5 example/wasm-vt: use ghostty_type_json for struct layouts
Replace hardcoded byte offsets and struct sizes with dynamic lookups
from the ghostty_type_json API. On WASM load, the type layout JSON
is fetched once and parsed into a lookup table. Two helpers,
fieldInfo and setField, use this metadata to write struct fields at
the correct offsets with the correct types.

This removes the need to manually maintain wasm32 struct layout
comments and magic numbers for GhosttyTerminalOptions and
GhosttyFormatterTerminalOptions, so the example stays correct if
the struct layouts change.
2026-03-30 10:16:19 -07:00
Mitchell Hashimoto
2e827cc39d vt: add ghostty_type_json for struct layout metadata
Add a new C API function that returns a comptime-generated JSON string
describing the size, alignment, and field layout of every C API extern
struct. This lets FFI consumers (particularly WASM) construct structs
by byte offset without hardcoding platform-specific layout.

The JSON is built at comptime using std.json.Stringify via a
StructInfo type that holds per-struct metadata and implements
jsonStringify. A StaticStringMap keyed by C struct name provides
lookup by name as well as iteration for the JSON serialization.

The function is declared in types.h alongside the other common types
and exported as ghostty_type_json.
2026-03-30 10:16:19 -07:00
Mitchell Hashimoto
8fab3ac3f3 example/wasm-vt 2026-03-30 10:16:19 -07:00
Mitchell Hashimoto
6d4528e471 libghostty: add GHOSTTY_EXPORT for shared lib symbol visibility (#11977)
## Summary

Add a `GHOSTTY_EXPORT` annotation macro to all public function
declarations across both `ghostty.h` (the main libghostty header) and
the `include/ghostty/vt/` headers (the libghostty-vt API). This is the
standard pattern used by C libraries that support both static and shared
library builds.

On Windows, functions need `__declspec(dllexport)` when building the DLL
and `__declspec(dllimport)` when consuming it, or they won't be visible
across the DLL boundary. On Linux/macOS with GCC/Clang,
`__attribute__((visibility("default")))` keeps the public API visible
when building with `-fvisibility=hidden`, which reduces symbol table
size and avoids collisions.

The macro resolves to nothing for static builds (when `GHOSTTY_STATIC`
is defined) and on compilers that don't support visibility attributes,
so this is a no-op for the current macOS static library path.

## Why

I looked at how popular C libraries handle this and every serious one
follows the same pattern:

- SDL (`SDL_DECLSPEC`)
- cURL (`CURL_EXTERN`)
- SQLite (`SQLITE_API`)
- zlib (`ZEXTERN`)
- FreeType (`FT_EXPORT`) -- already vendored by Ghostty
- GLFW (`GLFWAPI`)
- Lua (`LUA_API`)

The header comment says "the API is built to be more general purpose"
and the long-term goal is libghostty as a reusable library. Export
annotations are table stakes for that -- they explicitly mark the public
API surface, enable proper shared library builds on all platforms, and
give consumers the right linker hints.

## Test plan

- [x] Windows build and full test suite
- [x] Linux build and full test suite
- [x] macOS build, full test suite, and app launch verified working
- [x] macOS xcodebuild app build and launch verified working
- [x] Shared library symbol inspection on all three platforms
- [x] Linux: validated version script + LLD restricts exports to only
ghostty_* (107/107, 0 leaked, 12 MB .so)
- [x] Linux: C link test against restricted .so -- compiled, linked, ran
successfully
- [x] Windows: DLL exports verified (102 ghostty_ + 3 unavoidable
CRT/simdutf)
2026-03-30 10:15:49 -07:00
Alessandro De Blasis
80e35af763 cmake: define GHOSTTY_STATIC for static library consumers
The ghostty-vt-static target needs to propagate GHOSTTY_STATIC to
consumers so that GHOSTTY_EXPORT resolves to nothing instead of
__declspec(dllimport) on Windows. Without this, static linking
fails with unresolved __imp_ghostty_* symbols.
2026-03-30 18:56:09 +02:00
Mitchell Hashimoto
d643792f36 macOS: add keyboard shortcut test (#11986)
This is the first step (also another step forward for completing #7879)
to fix various responder issues regarding keyboard shortcuts. I tried my
best to separate changes chunk by chunk; there will follow up pr based
on this to fix them.

This pr doesn't change any existing behaviours/flaws, but following
changes will be easier to review after this.

## AI Disclosure

Claude wrote most of the test cases
2026-03-30 09:20:35 -07:00
Mitchell Hashimoto
1672e891b9 macOS: remove redundant tab event overrides (#11984)
- Revert 5540f5f249, middle click comes
out of box with native tabbing, but we override it wrong previous.
- Reverts 894e8d91ba, I check it the
commit right before it and all the way back to
ffe4afe538, right mouse down on tab bar
works well without any issue
- Add back reverted handling in #11150


https://github.com/user-attachments/assets/8660368e-05ae-45b0-aa81-6196f3434daf
2026-03-30 09:19:33 -07:00
Mitchell Hashimoto
bf3f9b3150 macOS: fix focus update when using search or command palette (#11978)
This fixes two things:

1. Surface focus state is not consistent with first responder state when
the search bar is open.
> Reproduce: Open search, switch to another app and back, observe the
cursor state of the surface.
> And after switching back, `cmd+shift+f` will close the search bar,
surface will become focused but not first responder, so it will not
accept any input
2. Command palette is not focused when built with Xcode 26.4 (26.3 works
fine).
> This is weird to me, because the tip (and built with 26.3) works fine.
I guess it's related to the SDK update? I couldn’t be sure what went
wrong, but dispatching it to the next loop works as previously.
  > Also cleaned some previous checks when quickly open and reopen.
  > This fix works great both with 26.4 and 26.3



https://github.com/user-attachments/assets/c9cf4c1b-60d9-4c71-802c-55f82e40eec7
2026-03-30 09:18:28 -07:00
Mitchell Hashimoto
f66cf179cd gtk: only trigger resize callbacks and overlay when size actually changes (#11972)
Fixes #11970

Also fixes problem that resize overlay would intercept mouse activity
while active.
2026-03-30 08:45:50 -07:00
Mitchell Hashimoto
fdb914c680 build(deps): bump cachix/install-nix-action from 31.10.2 to 31.10.3 (#11967)
Bumps
[cachix/install-nix-action](https://github.com/cachix/install-nix-action)
from 31.10.2 to 31.10.3.
<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.3</h2>
<h2>What's Changed</h2>
<ul>
<li>nix: 2.34.2 -&gt; 2.34.4 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/271">cachix/install-nix-action#271</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cachix/install-nix-action/compare/v31...v31.10.3">https://github.com/cachix/install-nix-action/compare/v31...v31.10.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="96951a368b"><code>96951a3</code></a>
Merge pull request <a
href="https://redirect.github.com/cachix/install-nix-action/issues/271">#271</a>
from cachix/create-pull-request/patch</li>
<li><a
href="6281169445"><code>6281169</code></a>
nix: 2.34.2 -&gt; 2.34.4</li>
<li>See full diff in <a
href="51f3067b56...96951a368b">compare
view</a></li>
</ul>
</details>
<br />
2026-03-30 08:31:03 -07:00
dependabot[bot]
3864fa585f build(deps): bump cachix/install-nix-action from 31.10.2 to 31.10.3
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 31.10.2 to 31.10.3.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Changelog](https://github.com/cachix/install-nix-action/blob/master/RELEASE.md)
- [Commits](51f3067b56...96951a368b)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-30 15:22:36 +00:00
Jeffrey C. Ollie
7ad3888819 cli: add pager support to +explain-config (#11940)
Add a new Pager type that wraps output to an external pager program when
stdout is a TTY, following the same conventions as git. The pager
command is resolved from $PAGER, falling back to `less`. An empty $PAGER
disables paging. If the pager fails to spawn, we fall back to stdout.

Previously, +explain-config wrote directly to stdout with no paging,
which meant long help text would scroll by. Now output is automatically
piped through the user's preferred pager when running interactively. A
--no-pager flag is available to disable this.
2026-03-30 10:12:33 -05:00
Jon Parise
840ab46009 cli: also recognize $GHOSTTY_PAGER
When defined, GHOSTTY_PAGER takes precedence over PAGER. If either of
those variables is set to an empty value, paging is disabled.
2026-03-30 10:53:53 -04:00
Jon Parise
11d45cd43c cli: add pager support for +show-config 2026-03-30 10:48:07 -04:00
Jon Parise
62f8a1cbcf cli: use a caller-provided write buffer
This follows Zig's conventions more closely, where the caller owns the
write buffer.
2026-03-30 10:48:07 -04:00
Jon Parise
4a0cca1c5b cli: add pager support to +explain-config
Add a new Pager type that wraps output to an external pager program when
stdout is a TTY, following the same conventions as git. The pager
command is resolved from $PAGER, falling back to `less`. An empty $PAGER
disables paging. If the pager fails to spawn, we fall back to stdout.

Previously, +explain-config wrote directly to stdout with no paging,
which meant long help text would scroll by. Now output is automatically
piped through the user's preferred pager when running interactively. A
--no-pager flag is available to disable this.
2026-03-30 10:48:07 -04:00
Lukas
de8139bbc3 macOS: move MenuShortcutManager to a separate file 2026-03-30 16:10:06 +02:00
Lukas
1845dd26b6 macOS: extract menu shortcut syncing into MenuShortcutManager 2026-03-30 16:09:21 +02:00
Lukas
65cd31dc79 macOS: add NormalizedMenuShortcutKeyTests 2026-03-30 15:47:07 +02:00
Lukas
5c5f645b61 macOS: support reloading temporary config for testing 2026-03-30 15:47:07 +02:00
Lukas
51cd63871d macos: passthrough right mouse down event to TabTitleEditor if needed (#11150) 2026-03-30 12:22:54 +02:00
Lukas
5de30c0dce Revert "macOS: fix tab context menu opens on macOS 26 with titlebar tabs (#9831)"
This reverts commit 894e8d91ba, reversing
changes made to 4a173052fb.
2026-03-30 12:09:51 +02:00
Lukas
5c5029b0c4 Revert "macos: add support for middle-click tab close for macos-titlebar-style = tabs (#11963)"
This reverts commit 5540f5f249, reversing
changes made to cca4c788ad.
2026-03-30 12:08:49 +02:00
Lukas
013579cfcf macOS: fix initial focus of command palette when building with Xcode 26.4
Tip works fine, but I've tried release and debug build with Xcode 26.4, it failed to focus as expected
2026-03-30 10:03:09 +02:00
Lukas
32920b6b2a macOS: handle surface focus more gracefully
This will fix surface focus state is not consistent with first responder state when the search bar is open
2026-03-30 10:03:09 +02:00
Alessandro De Blasis
0c765c7c58 libghostty: add GHOSTTY_EXPORT to VT headers
Extend GHOSTTY_EXPORT annotations to all public function declarations
in include/ghostty/vt/ headers. Add GHOSTTY_EXPORT macro to types.h
with ifndef guard so both ghostty.h and VT headers share the same
definition without conflict.
2026-03-30 09:28:11 +02:00
Alessandro De Blasis
bd413cc7bd libghostty: add GHOSTTY_EXPORT for shared library symbol visibility 2026-03-30 08:20:24 +02:00
Jeffrey C. Ollie
af36959942 gtk: only trigger resize callbacks and overlay when size actually changes
Fixes #11970

Also fixes problem that resize overlay would intercept mouse activity
while active.
2026-03-29 23:38:34 -05:00
Mitchell Hashimoto
5540f5f249 macos: add support for middle-click tab close for macos-titlebar-style = tabs (#11963)
Fixes #11962

### Summary
This PR implements a fix for:
https://github.com/ghostty-org/ghostty/discussions/10264

This allows the `macos-titlebar-style` setting `tabs` to behave the same
way other titlebar style options do with middle click handling.

### AI Disclosure
I used claude code (Sonnet 4.6) to identify the best place to start when
implementing this change, as well as for general Swift questions. The
code within this PR is written by me.
2026-03-29 15:24:16 -07:00
Nicholas Ochoa
3f6683df02 macos: add support for middle-click tab close 2026-03-29 15:19:35 -07:00
Mitchell Hashimoto
cca4c788ad terminal: update page_serial_min properly when erasing a page to avoid crash in search (#11965)
Fixes #11957

erasePage now updates page_serial_min when the first page is erased, and
asserts that only front or back pages are erased since page_serial_min
cannot represent serial gaps from middle erasure.

eraseRows can still technically destroy middle pages but no caller does
that today. We'll have to rethink this eventually.
2026-03-29 15:14:43 -07:00
Mitchell Hashimoto
d784600fd6 terminal: update page_serial_min in erasePage
Fixes #11957

erasePage now updates page_serial_min when the first page is erased,
and asserts that only front or back pages are erased since
page_serial_min cannot represent serial gaps from middle erasure.

To enforce this invariant at the API level, PageList.eraseRows is
now private. Two public wrappers replace it: eraseHistory always
starts from the beginning of history, and eraseActive takes a y
coordinate (with bounds assertion) and always starts from the top
of the active area. This makes middle-page erasure impossible by
construction.
2026-03-29 15:10:12 -07:00
ghostty-vouch[bot]
10956bfa48 Update VOUCHED list (#11961)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11960#discussioncomment-16371359)
from @jcollie.

Vouch: @nicholas-ochoa

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-29 19:59:59 +00:00
Mitchell Hashimoto
1c14b9615b fix(libghostty): ensure memory is zeroed in runtime safety modes for wasm/freestanding (#11955)
Zero page memory on freestanding/wasm where allocator reuses freed slots
without clearing. Allows recreating a new or multiple terminals.
2026-03-29 06:40:09 -07:00
Elias Andualem
420de124f0 fix: ensure memory is zeroed in runtime safety modes for wasm/freestanding 2026-03-29 17:28:18 +08:00
Mitchell Hashimoto
debcffbadb libghostty: make headers C++ compatible (#11950)
The headers were not C++ compatible and would fail compiling before (see
https://github.com/ghostty-org/ghostty/discussions/11878). The only
reason is because our typedefs would conflict since we named them
identically.

This also adds a `c-vt-stream` example and a `cpp-vt-stream` example,
the latter primarily to verify we can build in C++ mode.
2026-03-28 18:45:56 -07:00
Mitchell Hashimoto
1fcd80daab libghostty: add cpp-vt-stream example and fix C++ header compatibility
Add a cpp-vt-stream example that verifies libghostty headers compile
cleanly in C++ mode. The example is a simplified C++ port of
c-vt-stream.

The headers used the C idiom `typedef struct Foo* Foo` for opaque
handles, which is invalid in C++ because struct tags and typedefs
share the same namespace. Fix all 12 opaque handle typedefs across the
headers to use a distinct struct tag with an Impl suffix, e.g.
`typedef struct GhosttyTerminalImpl* GhosttyTerminal`. This is a
source-compatible change for existing C consumers since the struct
tags were never referenced directly.
2026-03-28 18:38:58 -07:00
Mitchell Hashimoto
741f1d129a example/c-vt-stream 2026-03-28 18:34:15 -07:00
Mitchell Hashimoto
0f6e733f8c build: use VERSION file if present, expose via libghostty (#11932)
If a `VERSION` file is present from our build root, prefer that as our
version source of truth over `build.zig.zon`. This file is automatically
created in source tarballs and will allow us to cut pre-release tarballs
of libghostty in particular (but affects all) that has a more specific
version than what can be in build.zig.zon.

This also adds the APIs necessary to extract this via the C API.

I started prepping for a separate libghostty version but not sure if
I'll wire that up in this PR yet or not...
2026-03-28 18:29:34 -07:00
Mitchell Hashimoto
a95bfdfe14 Update iTerm2 colorschemes (#11946)
Upstream release:
https://github.com/mbadolato/iTerm2-Color-Schemes/releases/tag/release-20260323-152405-a2c7b60
2026-03-28 18:29:11 -07:00
mitchellh
5421326678 deps: Update iTerm2 color schemes 2026-03-29 00:23:08 +00:00
Jeffrey C. Ollie
4903e2821d gtk: disable kinetic scrolling for trackpads until 4.20.1 (#11793)
Until gtk 4.20.1 trackpads have kinetic scrolling behavior regardless of
`Gtk.ScrolledWindow.kinetic_scrolling`. As a workaround, set
EventControllerScroll.kinetic to false on all controllers.

`observeControllers()` has this warning:
> Calling this function will enable extra internal bookkeeping to track
controllers and emit signals on the returned listmodel. It may slow down
operations a lot.
> Applications should try hard to avoid calling this function because of
the slowdowns.

but judging from the
[source](5301a91f1c/gtk/gtkwidget.c (L12375-L12383))
this is a one time penalty since we free the result immediately
afterwards.

Fixes https://github.com/ghostty-org/ghostty/discussions/11460.

### AI usage
Zed + Opus 4.5 generated the first pass, but it missed freeing the
result of `observeControllers()` and conveniently binding
`scrolled_window` to the blueprint. Figuring out what was going on also
took a lot of [human
debugging](https://github.com/ghostty-org/ghostty/discussions/11460#discussioncomment-16245664).
2026-03-28 19:08:15 -05:00
Michael Stevens
c0a124f3ca gtk: disable kinetic scrolling for trackpads until 4.20.1
Until gtk 4.20.1 trackpads have kinetic scrolling behavior regardless
of `Gtk.ScrolledWindow.kinetic_scrolling`. As a workaround, set
EventControllerScroll.kinetic to false on all controllers.

`observeControllers()` has this warning:
> Calling this function will enable extra internal bookkeeping to track controllers and emit signals on the returned listmodel. It may slow down operations a lot.
> Applications should try hard to avoid calling this function because of the slowdowns.

but judging from the [source](5301a91f1c/gtk/gtkwidget.c (L12375-L12383))
this is a one time penalty since we free the result immediately afterwards.

Fixes https://github.com/ghostty-org/ghostty/discussions/11460
2026-03-28 17:36:17 -04:00
ghostty-vouch[bot]
baad0aa666 Update VOUCHED list (#11938)
Triggered by [discussion
comment](https://github.com/ghostty-org/ghostty/discussions/11823#discussioncomment-16358799)
from @mitchellh.

Vouch: @karesansui-u

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-28 18:18:35 +00:00