Commit Graph

12214 Commits (6d2dd585a5d87fa745d48188dd096ca6e63014d0)

Author SHA1 Message Date
Mitchell Hashimoto 6d2dd585a5
os: allow the mac-address-as-hostname parsing to happen everywhere 2025-10-23 10:14:48 -07:00
Mitchell Hashimoto 28952a7bb0
macos: use TextEditor instead of Text for clipboard confirmation (#9324)
Fixes #9322

SwiftUI `Text` has huge performance issues. On my maxed out MBP it hangs
for any text more than 100KB (it took ~8s to display it!). `TextEditor`
with a constant value works much better and handles scrolling for us,
too!
2025-10-23 09:54:46 -07:00
Mitchell Hashimoto b9df743e04
macos: window-position-x/y works with window-width/height (#9313)
Fixes #9132

We were processing our window size defaults separate from our window
position and the result was that you'd get some incorrect behavior.
Unify the logic more to fix the positioning.

Note there is room to improve this further, I think that all initial
positioning could go into the controller completely. But I wanted to
minimize the diff for a backport.
2025-10-23 09:54:41 -07:00
Jared Gizersky 8d2d557da9
os: handle nil languageCode/countryCode in setLangFromCocoa (#9290)
Fixes a crash when NSLocale returns nil for languageCode or countryCode
properties. This can happen when the app launches without locale
environment variables set.

The crash occurs at `src/os/locale.zig:87-88` when trying to call
`getProperty()` on a nil object. The fix adds a null check and falls
back to `en_US.UTF-8` instead of dereferencing null.

## Testing
Tested by running with locale variables unset:
```bash
unset LC_ALL && ./zig-out/Ghostty.app/Contents/MacOS/ghostty
```

Before: segmentation fault  
After: launches successfully with fallback locale
2025-10-23 09:54:36 -07:00
Mitchell Hashimoto 36f647e875
input: modify other keys 2 should use all mods, ignore consumed mods (#9289)
Fixes #8900

Our xterm modify other keys state 2 encoding was stripped consumed mods
from the keyboard event. This doesn't match xterm or other popular
terminal emulators (but most importantly: xterm). Use the full set of
mods and add a test to verify this.

Reproduction:

```
printf '\033[>4;2m'
cat
```

Then press `ctrl+shift+h` and compare across terminals.
2025-10-23 09:54:31 -07:00
Mitchell Hashimoto d2a459b7c2
build: add -Demit-themes option to emit/omit theme resources (#9288)
We'll backport this to 1.2.x for distros that would prefer this.
2025-10-23 09:49:48 -07:00
Mitchell Hashimoto bbbb52ed75
macos: goto_split direction is performable (#9284)
Fixes #9283

There was a comment here noting this deficiency. GTK implements this
properly.
2025-10-23 09:48:44 -07:00
Mitchell Hashimoto ed91bdadd6
cli: fix +ssh-cache IPv6 address validation (#9281)
The host validation code previously expected IPv6 addresses to be
enclosed in [brackets], but that's not how ssh(1) expects them.

This change removes that requirement and reimplements the host
validation routine to check for valid hostnames and IP addresses (IPv4
and IPv6) using standard routines rather than custom logic.

Fixes #9251
2025-10-23 09:47:57 -07:00
Mitchell Hashimoto 508cc8300a
os: add RFC 1123-compliant hostname.isValid (#9276)
std.net.isValidHostname is currently too generous. It considers strings
like ".example.com", "exa..mple.com", and "-example.com" to be valid
hostnames, which is incorrect according to RFC 1123 (the currently
accepted standard).

Until the standard library function is improved, we can use this local
implementation that does follow the RFC 1123 standard.

I asked Claude to perform an audit of the code based on its understand
of the RFC. It suggested some additional test cases and considers the
overall implementation to be robust (its words) and standards compliant.

Ref: https://www.rfc-editor.org/rfc/rfc1123
2025-10-23 09:46:30 -07:00
Mitchell Hashimoto 0aa016f948
fix: fish shell integration should not update the universal `fish_user_paths` variable (#9273)
`fish_add_path` by default updates the `fish_user_paths` universal
variable which makes the modification persist across shell sessions.

The integration also tries to update the `fish_user_paths` when the
desired path already appears in the `PATH` environment variable but not
in `fish_user_paths`. Because `fish_user_paths` will always be inserted
before the inherited `PATH` env. This makes the added path
unintentionally has a higher priority.

This patch fixes the above issues by adding `--global` and `--path`
options to `fish_user_paths` which limits the modification scope and
ensures that the path won't be added if it already exists in `PATH`.

Ref: https://fishshell.com/docs/current/cmds/fish_add_path.html
2025-10-23 09:46:01 -07:00
Mitchell Hashimoto 61f74158be
macos: use stable display UUID for quick terminal screen tracking (#9256)
NSScreen instances can be garbage collected at any time, even for
screens that remain connected, making NSMapTable with weak keys
unreliable for tracking per-screen state.

This changes the quick terminal to use CGDisplay UUIDs as stable
identifiers, keyed in a strong dictionary. Each entry stores the window
frame along with screen dimensions, scale factor, and last-seen
timestamp.

**This should make quick terminal size restore more stable than 1.2.2.**

Rules for pruning:
- Entries are invalidated when screens shrink or change scale
- Entries persist and update when screens grow (allowing cached state to
work with larger resolutions)
- Stale entries for disconnected screens expire after 14 days.
- Maximum of 10 screen entries to prevent unbounded growth
2025-10-23 09:45:44 -07:00
Mitchell Hashimoto d3128243ec
renderer: force a full rebuild on any font grid change (#9252)
Fixes #2731 (again)

This regressed in 1.2 due to the renderer rework missing porting this. I
believe this issue is still valid even with the rework since the font
grid changes the atlas and if there are still cached cells that
reference the old atlas coordinates it will produce garbage.
2025-10-23 09:42:02 -07:00
Mitchell Hashimoto 62df12c040
termio: color change operations must gracefully handle renderer mailbox full (#9224)
Fixes #9191

This changes our color change operations from writing to the renderer
mailbox directly to using our `rendererMailboxWriter` function which
handles the scenario where the mailbox is full by yielding the lock,
waking up the renderer, and retrying later.

This is a known deadlock scenario we've worked around since the private
beta days, but unfortunately this slipped through and I didn't catch it
in review.

What happens here is it's possible with certain escape sequences for the
IO thread to saturate other mailboxes with messages while holding the
terminal state lock. This can happen to any thread. This ultimately
leads to starvation and all threads deadlock.

Our IO thread is the only thread that produces this kind of massive
stream of events while holding the lock, so we have helpers in it to
attempt to queue (cheap, fast) and if that fails then to yield the lock,
wakeup the target thread, requeue, and grab the lock again (expensive,
slow).
2025-10-23 09:41:48 -07:00
Mitchell Hashimoto 56896311a6
Selection dragging should not process when terminal screen changes (#9223)
This hasn't caused any known bugs but leads to selection memory
corruption and assertion failures in runtime safe modes. When the
terminal screen changes (primary to secondary) and we have an active
dragging mode going either by moving the mouse or our selection tick
timer, we should halt.

We still keep the mouse state active which lets selection continue once
the screen switches back.
2025-10-23 09:41:31 -07:00
Mitchell Hashimoto 2ebbe39b9e
termio: don't start scroll timer if its already active (#9195)
This might fix #9191, but since I don't have a reproduction I can't be
sure. In any case, this is a bad bug that should be fixed.

The issue is that we weren't checking our scroll timer completion state.
This meant that if `start_scroll_timer` was called multiple times within
a single loop tick, we'd enqueue our completion multiple times, leading
to various undefined behaviors.

If we don't enqueue anything else in the interim, this is safe by
chance. But if we enqueue something else, then we'd hit a queue
assertion failure and honestly I'm not totally sure what would happen.

I wasn't able to trigger the "bad" case, but I was able to trigger the
benign case very easily. Our other timers such as the renderer cursor
timer already have this protection.

Let's fix this and continue looking...
2025-10-23 09:41:20 -07:00
Xiangbao Meng 0af32d06b5
macOS: fix title misalignment in tabs (#9168)
While I was testing #9166, noticed another edge case🤯. 

This appears both in Tahoe and Sequoia👇🏻


https://github.com/user-attachments/assets/9cecea35-1241-4f31-9c15-0f2a7a6f342a
2025-10-23 09:32:24 -07:00
Xiangbao Meng 5c9ceab0bf
macOS: Fix more `macos-titlebar-style` related issues (#9163)
Ghosty is active will result in similar nastiness.

https://github.com/user-attachments/assets/fcd7761e-a521-4382-8d7a-9d93dc0806bc

- [Sequoia/Ventura] Fix flickering new tab icon, and it also didn't
respond to window's key status change correctly
- [Sequoia/Ventura] Fix after changing appearance, tab bar may disappear
or have inconsistent background colour
- Fix initial tint of reset zoom button on Sequoia/Ventura with
`macos-titlebar-style=tabs` and all `native/transparent` titlebars
- Fix title alignment with custom font with `native/transparent`
titlebar
2025-10-23 09:31:39 -07:00
Daniel Wennberg 537b304cd6
font: Apply `adjust-icon-height` to both large and small icons (#9160)
As pointed out in #9156, an unintended consequence of all the work to
get icon sizing right is that `adjust-icon-height` now only applies to
the small icons you get when the next cell is not whitespace. Large
icons are unaffected.

With this PR, `adjust-icon-height` affects the maximum height of every
symbol specifying the `.icon` constraint height, regardless of
constraint width. This includes most Nerd Font icons, but excludes emoji
and other unicode symbols, and also excludes terminal graphics-oriented
Nerd Font symbols such as Powerline symbols.

In the following screenshots, **Baseline** is without
`adjust-icon-height`, while **Before** and **After** are with
`adjust-icon-height = -25%`.

**Baseline**
<img width="711" height="95" alt="Screenshot 2025-10-11 at 23 28 20"
src="https://github.com/user-attachments/assets/7499db4d-75a4-4dbd-b107-8cb5849e31a3"
/>

**Before** (only small icons affected)
<img width="711" height="95" alt="Screenshot 2025-10-11 at 23 20 12"
src="https://github.com/user-attachments/assets/9afd9fbf-ef25-44cc-9d8e-c39a69875163"
/>


**After** (both small and large icons affected, but not emoji)
<img width="711" height="95" alt="Screenshot 2025-10-11 at 23 21 05"
src="https://github.com/user-attachments/assets/90999f59-3b43-4684-9c8e-2c3c1edd6d18"
/>
2025-10-23 09:30:43 -07:00
Alan Wu 7203f735c8
Fix fish shell cursor integration in fish vi mode (#9157)
Previously, the fish shell integration interfered with fish's builtin vi
mode cursor switching configurations such as `$fish_cursor_default` and
`$fish_cursor_insert`.

```console
$ ghostty --config-default-files=false -e fish --no-config --init-command 'source "$GHOSTTY_RESOURCES_DIR"/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish; fish_vi_key_bindings'
```

The above command starts fish in vi mode with Ghostty shell
integrations. Manually loading the integration is necessary due to
`--no-config` blocking auto injection.

1. At the prompt, fish is in insert mode, and the cursor is a blinking
beam. However, press escape and then "i" to exit then re-enter insert
mode, and the cursor will be a solid beam due to the
`$fish_cursor_unknown` setting. Without the shell integration, insert
mode always uses a solid beam cursor.

2. A similar problem shows if we start fish with `fish_vi_key_bindings
default`. The cursor ends up as a blinking beam in normal mode only due
to the shell integration interfering. This glitch can also be reset away
by entering then exiting insert mode.

3. Also, `$fish_cursor_external` has no effect when used with shell
integration. After `fish_vi_key_bindings`, set it to `line`, run cat(1),
and shell integration will give you a blinking block, not the asked for
line/beam.

I verified that this patch makes the shell integration stop interfering
in three scenarios above, and it still changes the cursor when not using
fish's vi mode.

Note that `$fish_cursor_*` variables can be set when fish isn't in vi
mode, so they're not great signals for the shell integration hooks.
2025-10-23 09:30:37 -07:00
Daniel Wennberg 877206660d
fix(font): Additional scale group tweaks (#9152)
Of course #9142 would require a minor follow-up!

* Scale groups can cut across patch sets, but not across fonts. We had
some scale group mixing between Font Awesome and the weather symbols,
which is removed by this PR.[^cp_table_full]
* There's one case where a scale group includes a glyph that's not part
of any patch sets, just for padding out the group bounding box.
Previously, an unrelated glyph from a different font would be pulled in.
Now we use an appropriate stand-in. (See code comment for details.)
* I noticed overlaps weren't being split between each side of the
bounding box, they were added to both sides, resulting in twice as much
padding as specified.

Screenshots showing the extra vertical padding for progress bar elements
due to the second bullet point:

**Before**
<img width="191" height="42" alt="Screenshot 2025-10-11 at 15 33 54"
src="https://github.com/user-attachments/assets/cf288cce-86d3-46fd-ae86-18e5c274b0e4"
/>

**After**
<img width="191" height="42" alt="Screenshot 2025-10-11 at 15 33 20"
src="https://github.com/user-attachments/assets/7ac799c7-bf50-4e65-a74a-f8a2c42d2441"
/>

[^cp_table_full]: Forming and using the merged `cp_table_full` table
should have been a red flag. Such a table doesn't make sense, it would
be a one-to-many map. You need the names of the original fonts to
disambiguate.
2025-10-23 09:30:29 -07:00
Daniel Wennberg 1658c86eba
font(fix): Extract and apply Nerd Font codepoint mapping table (#9142)
Fixes #9076

**Before** 
<img width="128" height="57" alt="Screenshot 2025-10-11 at 00 07 09"
src="https://github.com/user-attachments/assets/a6b416d5-dae1-4cea-a836-00640ceaf39b"
/>

**After**
<img width="128" height="57" alt="Screenshot 2025-10-11 at 00 07 31"
src="https://github.com/user-attachments/assets/7d2df7b1-4767-4e2d-84d2-8301da5c6602"
/>

These screenshots show the chevrons mentioned in
https://github.com/ghostty-org/ghostty/discussions/7820#discussioncomment-14617170,
which should be scaled as a group but were not until this PR.

The added code downloads each individual symbol font file from the Nerd
Fonts github repo (making sure to get the version corresponding to the
vendored `font-patcher.py`) and iterates over all of them to build the
correct and complete codepoint mapping table. The table is saved to
`nerd_font_codepoint_tables.py`, which `nerd_font_codegen.py` will reuse
if possible instead of downloading the font files again.

I'm not going to utter any famous last words or anything, but... after
this, I don't think the number of remaining issues with icon
scaling/alignment is _large._
2025-10-23 09:28:29 -07:00
Brice 5ecb00fd48
GTK fix quick terminal autohide (#9139)
This is pretty much a direct port of the previous GTK app. still inside
of the `isActive` handler for a window


7e429d73d6/src/apprt/gtk/Window.zig (L822-L837)

Fixes: https://github.com/ghostty-org/ghostty/discussions/9137
2025-10-23 09:28:11 -07:00
Xiangbao Meng 6a2eb6757b
macOS: Fix New Tab behaviours (#9124)
- Fix `macos-dock-drop-behavior = new-tab` not working, which also
affects `open /path/to/directory -a Ghostty.app`
- Fix 'New Tab' in dock icon not working **when Ghostty's not active**

### Issue preview with `1.2.2(12187)`


https://github.com/user-attachments/assets/18068cc2-c25d-4360-97ab-cec22d5d3ff4
2025-10-23 09:28:04 -07:00
Mitchell Hashimoto e8bcd4031c
apprt/gtk: set the correct window title from the start (#9120)
Previous PR: #8535 (merged but problem persists)
Issues: #5934

The Ghostty window will always start with the title "Ghostty" at
startup, and then immediately change to the correct window title. This
is a problem when using compositors like Hyprland and Niri if you want
to create rules for floating windows and similar, as the window title
isn't detected at startup.

This fixes the bad behaviour both for title configured in the config
file, and for processes started with the --title argument.

In this fix I've updated the `tags.zig` `closureComputedTitle()`
function to get the title from the passed in config, and use that as a
fallback before the default `Ghostty` fallback.

Previous behaviour as logged by `niri msg event-stream`:

> Window opened or changed: Window { id: 19, title: Some("Ghostty"),
app_id: Some("com.mitchellh.ghostty-debug"), pid: Some(802495),
workspace_id: Some(1), is_focused: true, is_floating: false, is_urgent:
false, layout: WindowLayout { pos_in_scrolling_layout: Some((3, 1)),
tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) } }
Window layouts changed: [(6, WindowLayout { pos_in_scrolling_layout:
Some((4, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) })]
Window opened or changed: Window { id: 19, title:
Some("pr-test-title-fix"), app_id: Some("com.mitchellh.ghostty-debug"),
pid: Some(802495), workspace_id: Some(1), is_focused: true, is_floating:
false, is_urgent: false, layout: WindowLayout { pos_in_scrolling_layout:
Some((3, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) } }

New behaviour:

> Window opened or changed: Window { id: 20, title:
Some("pr-test-title-fix"), app_id: Some("com.mitchellh.ghostty-debug"),
pid: Some(804534), workspace_id: Some(1), is_focused: true, is_floating:
false, is_urgent: false, layout: WindowLayout { pos_in_scrolling_layout:
Some((3, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) } }
Window layouts changed: [(6, WindowLayout { pos_in_scrolling_layout:
Some((4, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) })]

This fixes the problem as shown in the output. I have only tested this
on Linux (Arch with Niri).
2025-10-23 09:27:54 -07:00
Xiangbao Meng d6df0d145c
Fix `macos-titlebar-tabs` related issues (#9090)
### This pr fixes multiple issues related to `macos-titlebar-tabs`

- [Window title clipping **on
Tahoe**](https://github.com/ghostty-org/ghostty/discussions/9027#discussion-8981483)
- Clipped tab bar **on Tahoe** when creating new ones in fullscreen
> Sequoia doesn't seem to have this issue (at least I didn't reproduce
myself)
- [Title missing **on Tahoe** after dragging a tab into a separate
window](https://github.com/ghostty-org/ghostty/discussions/9027#discussioncomment-14617088)
- [Clipped tab bar **on Tahoe** after dragging from one tab group to
another](https://github.com/ghostty-org/ghostty/discussions/9027#discussioncomment-14626078)
- [Stretched tab bar after switching system
appearance](https://github.com/ghostty-org/ghostty/discussions/9027#discussioncomment-14626918)


### Related issues
I checked all of the open sub-issues in #2349 , most of them should be
fixed in latest main branch (I didn't reproduce)

- [#1692](https://github.com/ghostty-org/ghostty/issues/1692)
@peteschaffner
- [#1945](https://github.com/ghostty-org/ghostty/issues/1945) this one I
reproduce only on Tahoe, and fixed in this pr, @injust
- [#1813](https://github.com/ghostty-org/ghostty/issues/1813) @jacakira
- [#1787](https://github.com/ghostty-org/ghostty/issues/1787)
@roguesherlock
- [#1691](https://github.com/ghostty-org/ghostty/issues/1691) ~**haven't
found a solution yet**(building zig on VM is a pain**)~
> Tried commenting out `isOpaque` check in
`TitlebarTabsVenturaTerminalWindow`, which would fix the issue, but I
see the note there about transparency issue.
  >
> After commenting it out, it worked fine for me with blur and opacity
config, so **I might need some more background on this**. Didn't include
this change yet.
  > 
> [See screenshot
here](https://github.com/user-attachments/assets/eb17642d-b0de-46b2-b42a-19fb38a2c7f0)



### Minor improvements

- Match window title style with `window-title-font-family` and focus
state
  
<img width="843" height="198" alt="image"
src="https://github.com/user-attachments/assets/0138c4fa-1a4b-4bab-a415-b32695899ccf"
/>

---------

Co-authored-by: Mitchell Hashimoto <m@mitchellh.com>
2025-10-23 09:27:41 -07:00
Mitchell Hashimoto a04730650f
terminal: add semi-colon character to word boundary list for easier selection (#9069)
Sorry, I'm living dangerously here and haven't started a discussion.

New ghostty user. When working interactively with SQL clients you're
often writing semi-colons at the end of statements, e.g. `select * from
table;`

It's super annoying when you double-click to select the word `table` it
actually selects `table;` Anecdotally, this behaviour disagrees with
other terminals I've tried (tho not exhaustive).

Disclosure: Claude wrote this code but, ironically, I "assisted it" by
pointing to the file and function after uncovering issue #30 and
relevant PR.
2025-10-23 09:27:26 -07:00
Mitchell Hashimoto 262c8517be
Bump version to 1.2.3 2025-10-23 09:26:01 -07:00
Mitchell Hashimoto 7071a22cb5
v1.2.2 2025-10-08 10:02:24 -07:00
Mitchell Hashimoto a586b47dc9
Implement and use generic approx equality tester (#8979)
Seems like there needs to be a general, easy-to-use solution for
approximate equality testing of containers holding floats (see, e.g.,
https://github.com/ghostty-org/ghostty/pull/8563#pullrequestreview-3281357931).
How's this?
2025-10-08 09:59:22 -07:00
Mitchell Hashimoto c8efb2a8c9
font: Add comprehensive constraint tests (#9023)
As promised in #8990.

I opted for hardcoded metrics and bounding boxes rather than actually
loading fonts and glyphs, both to avoid backend dependence and limit the
focus to the constraint calculations themselves, and because I wanted to
test a case that isn't exhibited by any of the fonts available in the
repo.

This also fixes an error from #8990, probably due to a botched
cherry-pick or rebase.
2025-10-08 09:59:12 -07:00
Mitchell Hashimoto 62ed472d9e
Revert "renderer: slightly optimize screen copy" (#8974)
This reverts commit fcea09e413 because it
appears to be causing memory leaks.
2025-10-08 09:57:14 -07:00
Mitchell Hashimoto 436bc4c2b9
Set version to 1.2.1 2025-10-06 10:07:14 -07:00
Mitchell Hashimoto 0993fef615
macos: fix missing file for iOS 2025-10-06 09:47:44 -07:00
Mitchell Hashimoto 3cf81f64bd
apprt/gtk: only close with no windows active if close delay is off (#9053)
Fixes #9052
2025-10-06 09:22:22 -07:00
Mitchell Hashimoto 15dc72e26f
Update iTerm2 2025-10-06 09:08:20 -07:00
Mitchell Hashimoto c583505430
Expand `~` in `macos-custom-icon` (#9024)
Since #8999, `macos-custom-icon` works when its a fully expanded
absolute path like `/Users/username/dir/icon.icns`, but not when it's
abbreviated as `~/dir/icon.icns`. Users were understandably surprised
and confused by this. This PR adds tilde expansion using `NSString`s
built-in property for this.

Also removed a line from the config docs that seemed erroneous. Given
that the option has a functional default, it seems incorrect to say that
it's required.
2025-10-06 09:05:34 -07:00
Mitchell Hashimoto d8d232e5a2
macos: avoid any zero-sized content size increments (#9020)
Fixes #9016
2025-10-06 09:05:22 -07:00
Mitchell Hashimoto 8dd810521c
Fix Weird Behavior in CoreText Shaper (#9002)
You can pretty simply reproduce a crash on `main` in `Debug` mode by
running `printf "مرحبًا \n"` with your primary font set to one that
supports Arabic such as Cascadia Code/Mono or Kawkab Mono, which will
cause CoreText to output the shaped glyphs non-monotonically which hits
the assert we have in the renderer.

In `ReleaseFast` this assert is skipped and because we already moved
ahead to the space glyph (which belongs at the end but is emitted first)
all of the glyphs up to that point are lost. I believe this is probably
the cause of #8280, I tested and this change seems to fix it at least.

Included in this PR is a little optimization: we were allocating buffers
to copy glyphs etc. from runs to every time, even though CoreText
provides `CTRunGet*Ptr` functions which get *pointers* to the internal
storage of these values- these aren't guaranteed to return a usable
pointer but in that case we can always fall back to allocating again.
Also avoided allocation while processing glyphs by ensuring capacity
beforehand immediately after creating the `CTLine`.

The performance impact of this PR is negligible on my machine and
actually seems to be positive, probably due to avoiding allocations if I
had to guess.
2025-10-06 09:04:48 -07:00
Mitchell Hashimoto 24f883904d
gtk: fix duplicate signal handlers (#9001)
Signal handlers are connected to surface objects in two spots - when a
tab is added to a page and when the split tree changes. This resulted in
duplicate signal handlers being added for each surface. This was most
noticeable when copying the selection to the clipboard - you would see
two "Copied to clipboard" toasts. Ensure that there is only one signal
handler by removing any old ones before adding the new ones.
2025-10-06 09:04:44 -07:00
Mitchell Hashimoto 3ff4b6c062
fix(config): Make `macos-custom-icon` null-terminated (#8999)
The config option `macos-custom-icon` wasn't working because, to pass
successfully through the C API to Swift, the string must be
null-terminated.

Fixes
https://discord.com/channels/1005603569187160125/1423192859112116224
2025-10-06 09:04:01 -07:00
Mitchell Hashimoto 630c5981b7
fix(font): Let powerline glyphs be wide (#8994)
regressed in the handling of the Powerline glyphs themselves by letting
them get caught in an early exit that imposes a constraint width of 1.
This PR fixes the regression and adds corresponding tests. Tried to be
somewhat principled about why the special treatment is warranted, hence
the new helper function `isGraphicsElement`.

**Before**
<img width="270" height="44" alt="Screenshot 2025-10-02 at 00 16 54"
src="https://github.com/user-attachments/assets/9e975434-114c-44d5-a4ed-ac6a954b9d00"
/>

**After**
<img width="270" height="44" alt="Screenshot 2025-10-02 at 00 16 11"
src="https://github.com/user-attachments/assets/20545e74-c9f9-4a6b-9bf0-a7cf1d38c3a0"
/>
2025-10-06 09:02:58 -07:00
Mitchell Hashimoto fd326d6af4
fix(font): Fix positioning of scaled glyphs that don’t specify alignment (#8990)
Follow-up to #8563, which broke scaling without alignment. This change
recovers the behavior from before #8563, such that a scaled group is
clamped to the constraint width and height if necessary, and otherwise,
scaling does not shift the center of the group bounding box.

As a part of this change, horizontal alignment was rewritten to assume
the face is flush with the left edge of the cell. The cell-to-face
offset in the rendering code is then applied regardless of the value of
`align_horizontal`. This both simplifies the code and improves
consistency, as it ensures that the offset is the same for all
non-bitmap glyphs (rounded in FreeType, not rounded in CoreText). It's
the right thing to do following the align-to-face changes in #8563.
2025-10-06 09:02:33 -07:00
Mitchell Hashimoto 3184187f2d
feat: add GHOSTTY_BIN_DIR to path via shell integration (#8976)
Closes #8956

Elvish written by Copilot, the rest was written by me with AI
documentation.
2025-10-06 09:01:41 -07:00
Mitchell Hashimoto ee82baadde
gtk: some bell features need to happen on receipt of every BEL (#8962)
Some bell features should be triggered on the receipt of every BEL
character, namely `audio` and `system`. However, Ghostty was setting a
boolean to `true` upon the receipt of the first BEL. Subsequent BEL
characters would be ignored until that boolean was reset to `false`,
usually by keyboard/mouse activity.

This PR fixes the problem by ensuring that the `audio` and `system`
features are triggered every time a BEL is received. Other features
continue to be triggered only when the `bell-ringing` boolean state
changes.

Fixes #8957
2025-10-06 09:01:34 -07:00
Mitchell Hashimoto e974d58615
Inline All The Things (#8946)
I used the new CPU counter mode in Instruments.app to track down
functions that had instruction delivery bottlenecks (indicating i-cache
misses) and picked a bunch of trivial functions to mark as inline (plus
a couple that are only used once or twice and which benefit from
inlining).

The size of `macos-arm64/libghostty-fat.a` built with `zig build
-Doptimize=ReleaseFast -Dxcframework-target=native` goes from
`145,538,856` bytes on `main` to `145,595,952` on this branch, a
negligible increase.

These changes resulted in some pretty sizable improvements in vtebench
results on my machine (Apple M3 Max):
<img width="983" height="696" alt="image"
src="https://github.com/user-attachments/assets/cac595ca-7616-48ed-983c-208c2ca2023f"
/>

With this, the only vtebench test we're slower than Alacritty in (on my
machine, at 130x51 window size) is `dense_cells` (which, IMO, is so
artificial that optimizing for it might actually negatively impact real
world performance).

I also did a pretty simple improvement to how we copy the screen in the
renderer, gave it its own page pool for less memory churn. Further
optimization in that area should be explored since in some scenarios it
seems like as much as 35% of the time on the `io-reader` thread is spent
waiting for the lock.

> [!NOTE]
> Before this is merged, someone really ought to test this on an x86
processor to see how the performance compares there, since this *is*
tuning for my processor specifically, and I know that M chips have
pretty big i-cache compared to some x86 processors which could impact
the performance characteristics of these changes.
2025-10-06 08:59:22 -07:00
Mitchell Hashimoto 1a94e7b016
fix(font): Final font patcher fixes (#8847)
This is my final set of fixes to the font patcher/icon scaling code. It
builds on #8563 and there's not much reason to pay attention here until
that one has been reviewed (the unique changes in this PR only touch the
two `nerd_font_*` files; the other 8 files in the diff are just #8563).
However, I wanted to make sure the full set of changes/fixes I propose
are out in the open, such that any substantial edits by maintainers
(like in #7953) can take into account the full context.

I think this and the related patches should be considered fixes, not
features, so I hope they can be considered for a 1.2.x release.

This PR fixes some bugs in the extraction of scale and alignment rules
from the `font_patcher` script. Roughly in order of importance:

* Nerd fonts apply an offset to some codepoint ranges when extracting
glyphs from their original font (e.g., Font Awesome) and placing them in
a Nerd Font. Rules are specified in terms of the former codepoints, but
must be applied to the latter. This offset was previously not taken into
account, so rules were applied to the wrong glyphs, and some glyphs that
should have rules didn't get any.
* Previously, the rules from every single patch set was included, but
the embedded Symbols Only font doesn't contain all of them. Most
importantly, there's a legacy patch set that only exists for historical
reasons and is never used anymore, which was overwriting some other
rules because of overlapping codepoint ranges. Also, the Symbols Only
font contains no box drawing characters, so those rules should not be
included. With this PR, irrelevant patch sets are filtered out.
* Some patch sets specify overlapping codepoint ranges, though in
reality the original fonts don't actually cover the full ranges and the
overlaps just imply that they're filling each other's gaps. During font
patching, the presence/absence of a glyph at each codepoint in the
original font takes care of the ambiguity. Since we don't have that
information, we need to hardcode which patch set "wins" for each case
(it's not always the latest set in the list). Luckily, there are only
two cases.
* Many glyphs belong to scale groups that should be scaled and aligned
as a unit. However, in `font_patcher`, the scale group is _not_ used for
_horizontal_ alignment, _unless_ the entire scale group has a single
advance width (remember, the original symbol fonts are not monospace).
This PR implements this rule by only setting `relative_width` and
`relative_x` if the group is monospace.

There are some additional tweaks to ensure that each codepoint actually
gets the rule it's supposed to when it belongs to multiple scale groups
or patch sets, and to avoid setting rules for codepoints that don't
exist in the embedded font.
2025-10-06 08:57:52 -07:00
Mitchell Hashimoto bdc1dc4363
fix(font): Apply glyph constraints before thickening and centering before quantizing (#8580)
In CoreText, when thickening (font smoothing) is enabled or Ghostty is
synthesizing a bold face, the glyph bounding box is padded to make sure
the thicker glyph can fit. Currently, this happens before applying
constraints (scaling and alignment), which makes the size and position
of constrained glyphs dependent on font size, font thickening strength,
and display DPI.

With this PR, constraints are applied before any other adjustments, and
padding is applied directly to the rasterization canvas without
modifying any metrics.

For consistency, I also moved constraint application above emboldening
in the FreeType code, although under that API, the two operations are
orthogonal as far as I can tell.

Secondly, this PR moves glyph centering above bitmap quantization, as
centering is generally fractional and will therefore undo the quantizing
if done after.

Supersedes #8552.
2025-10-06 08:57:39 -07:00
Mitchell Hashimoto 055281febf
apprt/gtk: do not close window if tab overview is open with no tabs (#8955)
Fixes #8944

When we drag the only tab out of the tab overview, this triggers an
`n-pages` signal with 0 pages. If we close the window in this state, it
causes both Ghostty to exit AND the drag/drop to fail. Even if we
pre-empt Ghostty exiting by modifying the application class, the
drag/drop still fails and the application leaks memory and enters a bad
state.

The solution is to keep the window open if we go to `n-pages == 0` and
we have the tab overview open.

Interestingly, if you click to close the final tab from the tab
overview, Adwaita closes the tab overview so it still triggers the
window closing behavior (this is good, this is desired).
2025-09-29 13:03:12 -07:00
Mitchell Hashimoto 64edc95e92
gtk: make Enter confirm "Change Terminal Title" (#8949)
Fixes https://github.com/ghostty-org/ghostty/discussions/8697 by making
`OK` the suggested default and activating it by default.

Previously `OK` was `destructive` which imo is not a good approach for
just setting a terminal title.
2025-09-29 13:03:05 -07:00
Mitchell Hashimoto 359d735213
feat: enable scaling mouse-scroll-multiplier for both precision and discrete scrolling (#8927)
Resolves Issue: #8670 

Now precision and discrete scrolling can be scaled independently.
Supports following configuration,

```code
# Apply everywhere
mouse-scroll-multiplier = 3

# Apply separately
mouse-scroll-multiplier = precision:0.1,discrete:3 (default)

# Also it's order agnostic
mouse-scroll-multiplier = discrete:3,precision:2

# Apply one, default other
mouse-scroll-multiplier = precision:2
```

The default precision value is set 0.1, as it felt natural to me at
least on my track-pad. I've also set the min clamp value precision to
0.1 as 0.01 felt kind of useless to me but I'm unsure.
2025-09-29 13:02:54 -07:00