Prior to #7044, on macOS, our shell-integrated command line would be
executed under exec -l, which causes bash to be started as a login
shell. This matches the macOS platform norms.
The change to direct command execution meant that we'd skip that path,
and bash would start as a normal interactive (non-login) shell on macOS.
We fixed this in #7253 by adding `--login` to the `bash` direct command
on macOS.
This avoided some of the overhead of starting an extra process just to
get a login shell, but it unfortunately doesn't quite match the bash
environment we get when shell integration isn't enabled (namely, $0
doesn't get the login-shell-identifying "-" prefix).
Instead, this change implements the approach proposed in #7254, which
switches the bash shell integration path to use a .shell command, giving
us the same execution environment as the non-shell-integrated command.
Fixed: When reflowing content with many graphemes, the code incorrectly
increased hyperlink_bytes capacity
instead of grapheme_bytes, causing GraphemeMapOutOfMemory errors.
Added: An unit test for this specific issue.
This PR was written primarily by Opus.
Closes: #9863
When reflowing content with many graphemes, the code incorrectly increased hyperlink_bytes capacity
instead of grapheme_bytes, causing GraphemeMapOutOfMemory errors.
Description:
Context menu works on tabs with titlebar-style=tabs on MacOS Tahoe 26
Closes#9817
Demo:
https://github.com/user-attachments/assets/60eaae6e-a3ff-41eb-8c86-ba700490d6e2
Note:
- Tried first a passthrough-views approach, but AppKit’s internal
toolbar subviews continued intercepting right-clicks.
- Runtime subclassing proposed by Claude also worked but was rejected as
too fragile.
- Final solution routes secondary-click events at the window level using
sendEvent(_:), forwarding them to the tab bar only when the click is
visually within its bounds.
AI Disclosure:
AI (Claude Code and Codex) assisted with early explorations, but final
implementation was developed manually after evaluating and discarding
the unsafe subclassing approach proposed by Claude.
With this PR, the macos scrollbar always uses the overlay style. If the
OS preferred style is `.legacy`, we flash the scroller when the mouse is
moved over it, such that users can still click and drag without relying
on scroll wheels or gestures.
Implements #9610.
There are a few lines of code that could technically be removed after
this change as they're only needed to make surfaces work correctly with
the legacy scrollbar, but I decided to leave them in since they do no
harm (see code comments). This ensures correct behavior if, for whatever
reason, some corner case brings back the legacy scrollbar, or if someone
decides to experiment with scrollbar styles in the future.
### Background
After #9344, the Ghostty theme won't change after switching systems',
and reverting #9344 will bring back the issue it fixed.
The reason these two issues are related is because the scheme change is
based on changes of `effectiveAppearance`, which is also affected by
setting the window's `appearance` or changing
`NSAppearance.currentDrawing()`.
### Changes
Instead of observing `effectiveAppearance`, we now explicitly update the
color scheme of surfaces, so that we can control when it happens to
avoid callback loops and redundant updates.
### Regression Tests
- [x] #8282
- [x] Reloading with `window-theme = light` should update Ghostty with
the default dark theme with a dark window theme (break before
[#83104ff](83104ff27a))
- [x] `window-theme = light \n macos-titlebar-style = native` should
update Ghostty with the default dark theme with a light window theme
- [x] Reloading from the default config to `theme=light:3024
Day,dark:3024 Night \n window-theme = light`, should update Ghostty with
the theme `3024 Day` with a light window theme (break on
[#d39cc6d](d39cc6d478))
- [x] Using `theme=light:3024 Day,dark:3024 Night`; Switching the
system's appearance should change Ghostty's appearance (break on
[#d39cc6d](d39cc6d478))
- [x] Reloading from `theme=light:3024 Day,dark:3024 Night` with a light
window theme to the default config, should update Ghostty with the
default dark theme with a dark window theme
- [x] Reloading from the default config to `theme=light:3024
Day,dark:3024 Night \n window-theme=dark`, should update Ghostty with
the theme `3024 Night` with a dark window theme
- [x] Reloading from `theme=light:3024 Day,dark:3024 Night \n
window-theme=dark` to `theme=light:3024 Day,dark:3024 Night` with light
system appearance, should update Ghostty from dark to light
- [x] Reload with quick terminal open