Commit Graph

1387 Commits (78e539d68453fcedb29b31c7a296a9a816c7858e)

Author SHA1 Message Date
Mitchell Hashimoto c75bade896
macos: `window-width/height` is accurate even with other widgets
Fixes #2660

Rather than calculate our window frame size based on various chrome
calculations, we now utilize SwiftUI layouts and view intrinsic content
sizes with `setContentSize` to setup our content size ignoring all our
other widgets.

I'm sure there's some edge cases I'm missing here but this should be a
whole lot more reliable on the whole.
2025-11-28 13:32:03 -08:00
Lukas 94f88c8b54
macOS: fix toggle_visibility behaviour with tabbed windows
This fixes regression of #5690, which kind of comes from #9576. 05b42919d5 (before #9576) has weird behaviours too, restored windows are not properly focused. With this pr, we only order `selectedWindow` front so we won't mess up with its selection state and the order of the tab group.
2025-11-28 10:14:07 +01:00
Mitchell Hashimoto 5c1679209d
macos: add hover styles to search buttons, cursor changes 2025-11-27 13:01:51 -08:00
Lukas dc08d057fe
macOS: use ConcentricRectangle on Tahoe 2025-11-26 21:00:14 +01:00
Lukas cbcd52846c
macOS: fix search dragging animation when corner is not changed 2025-11-26 21:00:14 +01:00
Qwerasd 4b01163c79 fix(macos): use strings' utf-8 lengths for libghostty calls
Swift conveniently converts strings to UTF-8 encoded cstrings when
passing them to external functions, however our libghostty functions
also take a length and we were using String.count for that, which
returns the number of _characters_ not the byte length, which caused
searches with multi-byte characters to get truncated.

I went ahead and changed _all_ invocations that pass a string length to
use the utf-8 byte length even if the string is comptime-known and all
ASCII, just so that it's proper and if someone copies one of the calls
in the future for user-inputted data they don't reproduce this bug.

ref:
https://developer.apple.com/documentation/swift/string/count
https://developer.apple.com/documentation/swift/stringprotocol/lengthofbytes(using:)
2025-11-26 12:00:58 -07:00
avarayr f5b923573d
macOS: move search result counter inside text field
Move the search result counter (e.g. "1/30") inside the search text
field using an overlay, preventing layout shift when results appear.

This PR was authored with Claude Code.
2025-11-26 13:04:05 -05:00
Mitchell Hashimoto 5b4394d211
macos: end_search for ending search 2025-11-26 08:57:24 -08:00
Mitchell Hashimoto c51170da9c
add end_search binding 2025-11-26 08:50:06 -08:00
Mitchell Hashimoto f7b14a0142
macos: debounce search requests with length less than 3 2025-11-26 08:50:06 -08:00
Mitchell Hashimoto 339abf97f7
macos: can allow single char searches now 2025-11-26 08:50:06 -08:00
Mitchell Hashimoto 1bb2d4f1c2
macos: only end search if we previously had one 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto 93656fca5a
macos: show progerss correctly for search 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto 0e974f85ed
macos: fix iOS build 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto c20af77f98
macos: handle search progress/total apprt actions 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto d4a2f3db71
macos: search overlay shows search progress 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto 7835ad0ea4
macos: more menu items 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto 3f7cfca4b4
macos: add find menu item 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto 949a8ea53f
macos: dummy search state for iOS 2025-11-26 08:50:05 -08:00
Mitchell Hashimoto cfbc219f5c
macos: enter and shift+enter move the results 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto efc05523e0
macos: enter goes to next result 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto 3ce19a02ba
macos: hook up the next/prev search buttons 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto ad8a6e0642
search thread needs to take an allocated needle 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto 5ee000f58f
macos: search input starts the search up 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto 081d73d850
macos: changes to SearchState trigger calls to internals 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto 56d4a7f58e
macos: start_search refocuses the search input 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto c61d28a3a4
macos: esc returns focus back to surface 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto b7e70ce534
apprt: end_search 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto bc44b187d6
macos: hook up start_search apprt action to open search 2025-11-26 08:50:04 -08:00
Mitchell Hashimoto b87d57f029
macos: search overlay 2025-11-26 08:50:03 -08:00
Lukas 2a627a4665
macOS: fix the animation of showing&hiding command palette 2025-11-25 11:22:14 +01:00
Vinícius Soares 92aa960381 Add flag for quick terminal 2025-11-23 12:43:11 -03:00
Lukas 6f75cc56f6
macOS: Only change the icon if needed
Fixes #9666
2025-11-22 16:48:39 +01:00
Lukas 2f1427f529
macOS: match scroller’s appearance with surface’s background 2025-11-17 18:20:24 +01:00
Lukas 011fc77caa
macOS: Fix dictation icon's position while speaking 2025-11-16 12:17:31 +01:00
Mitchell Hashimoto caf5040a6d
macOS: find correct tab bar when in fullscreen (#9596)
Fixes #9597
2025-11-15 14:13:30 -08:00
Lukas 8d1dd332c6
macOS: fix misplaced frame modifier
As per #9504, this was supposed to be on `ZStack`, not on the overlay. See also #9503. I cherry-picked it in the wrong place before.
2025-11-15 10:14:43 +01:00
Lukas b124b78313
macOS: find correct tab bar when in fullscreen
Fixes #9593
2025-11-15 08:10:05 +01:00
Daniel Wennberg 49bf73458b don't autohide scrollers 2025-11-14 07:40:51 -08:00
Daniel Wennberg d48f855a48 macOS: set scrollbar size to .small 2025-11-14 07:36:54 -08:00
Mitchell Hashimoto 5ab23e6493
macOS: restore visiblity state when hiding quick terminal (#9576)
Fixes #8414 and a case where `toggle_visibility` is not working after
hiding using `cmd+h`


https://github.com/user-attachments/assets/be28c2d9-b416-467f-9fe9-7b7c97278330
2025-11-14 07:29:46 -08:00
Lukas 1486be0cdf
macOS: add more cursor style and fixes #8409 2025-11-13 18:20:09 +01:00
Lukas bcb5112b24
macOS: restore visiblity state when hiding quick terminal 2025-11-13 11:30:43 +01:00
Mitchell Hashimoto eff3619878
macos: Require fullScreenMode on fullscreenStyle 2025-11-11 09:21:15 -08:00
Lukas 2debeb0f13
macOS: save effective fullscreen styles 2025-11-11 18:16:40 +01:00
Lukas 8437be8ee1
macOS: 'restore' non native fullscreen styles 2025-11-11 18:11:15 +01:00
Mitchell Hashimoto 791d8f8200
macos: add a "restart later" option to the installing state 2025-11-11 07:27:03 -08:00
Lukas f5bddb346c
macOS: support `close_all_windows` action 2025-11-10 17:54:46 +01:00
Lukas 7ca858d404
macOS: move focus if command palette is not showing 2025-11-10 10:11:34 +01:00
Lukas 7e3aba7c99
macOS: remove `readyToInstall` state in update capsule
There is a sparkle-related 'issue' with the previous implementation. When you download/install in the `updateAvailable` state, if you don't install it, then check the updates again. Sparkle loses its downloaded stage in the delegate (it's normal when I use the sparkle source code). This time, when you click install in the `updateAvailable` state, it just uses the previous downloaded package and starts to install, without calling `showReady(toInstallAndRelaunch:)`.

I think removing `readyToInstall` in our customed ui, will reduce one step to install an update for most of the users out there, which makes sense, since the current package is pretty small, only takes a few seconds to download for a normal network, and they intended to install this update.
2025-11-09 20:24:24 +01:00
Lukas 52d3329f84
macOS: use unobtrusive when quick terminal is visible 2025-11-09 13:32:50 +01:00
Lukas 84082c2b96
macOS: equalize splits when double tapping on SplitView divider (#9524)
Resolves Issue #8357 

### Implementation

Following the existing `onResize` callback pattern in
`TerminalSplitTreeView`, I added an `onEqualize` callback to
`SplitView`. When a divider is double-tapped, the callback retrieves a
surface from that `TerminalView`'s `SplitTree` and calls `splitEqualize`
to equalize the entire tree.

### Context

There is an existing PR #8364 that implements this feature but uses
`focusedSurface`, which doesn't work for unfocused windows. Since that
PR has been inactive for a few months after requested changes, I've
implemented this alternative approach.

Credit to @liby for that initial implementation!

### AI Usage

I chatted with Claude Code in Plan mode to understand the relationship
between surfaces and the split tree/split views, but I wrote all the
code myself.

### Screenshot


https://github.com/user-attachments/assets/0efd70ef-c90e-4b50-b853-b05e2ca2be67
2025-11-09 09:07:09 +01:00
Daniel Wennberg e3ff49e653 macOS: Update core surface size when config changes 2025-11-08 23:34:56 -08:00
Sean Kelly e298620828 macOS: equalize splits when double tapping on SplitView divider 2025-11-08 23:16:16 -08:00
Daniel Wennberg 5845a7bd29 macOS: Update core surface size when scroller style changes 2025-11-08 22:41:59 -08:00
Daniel Wennberg 3142c5aa60 macOS: Don't clip surfaceView to contentView
Fixes #9248
2025-11-08 09:34:02 -08:00
Mitchell Hashimoto 12c8b6c1aa
macOS: Refactor scrollview to preserve state across split tree changes (#9446)
Fixes #9444
2025-11-07 15:10:45 -08:00
Mitchell Hashimoto 04563a16b6
macos: simplify the code to a more understandable style 2025-11-07 14:24:56 -08:00
Lars 1eecd448e9 remove needsConfirm 2025-11-07 14:16:10 -08:00
Lars f94cb01ec8 macOS: attach close confirmation alert to the first window that actually needs it 2025-11-07 14:16:10 -08:00
Lars 3f20f153c5 macOS: fix undo new tab will cause a crash 2025-11-07 14:14:44 -08:00
Mitchell Hashimoto f54c3d9209
macOS: set the macos-icon from a separate thread (#9485)
Closes #8793
2025-11-06 09:55:57 -07:00
Mitchell Hashimoto ec2ef5cf21
macOS: fix Dictation icon starting above the text, not below (#9488)
Partially fixes #8493.

After dictating some texts, the icon still appears above, but it will
return to its right position after resizing or `\n` (saying newline, not
hitting enter).

This behaviour is better than before, where the icon always appeared
above.

> Quicklook doesn't seem to call this on Tahoe, but it still works well
anyway.

### Reference:


9e905357bb/src/nsterm.m (L7426)



https://github.com/user-attachments/assets/6bf818c3-a0bb-412f-ae06-673f67cdeae4
2025-11-06 09:55:36 -07:00
Lars c8c36a6035
macOS: fix funky resolution in quick terminal 2025-11-06 16:13:05 +01:00
Lars 98ae1dbd10
macOS: fix Dictation icon starting above the text, not below
Partially fixes #8493.

After dictating some texts, the icon still appears above, but it will return to its right position after resizing or `\n` (saying newline, not hitting enter).

This behaviour is better than before, where the icon always appeared above.

### Reference:

9e905357bb/src/nsterm.m (L7426)
2025-11-05 18:22:08 +01:00
Lars 7472fb7732
macOS: set the macos-icon from a separate thread 2025-11-05 12:27:35 +01:00
Daniel Wennberg afc64f6285 Refactor scrollview to preserve state across split tree changes 2025-11-04 00:02:21 -08:00
Daniel Wennberg 9002c5dbd2 Preserve surface content size across backing updates 2025-11-04 00:02:21 -08:00
Daniel Wennberg d678e2e305 Use notifications to deal with NSScrollPocket 2025-11-04 00:02:21 -08:00
Mitchell Hashimoto 901708e8da
input: write_*_file actions take an optional format
Fixes #9398
2025-10-31 09:49:59 -07:00
Daniel Wennberg 951374cd1c Fix documentView padding calculations 2025-10-31 00:39:03 -07:00
Mitchell Hashimoto 5c1f036613
macos: assert only one text-plain gets written to clipboard 2025-10-30 15:16:15 -07:00
Mitchell Hashimoto 0f1c46e4a4
macos: support setting multiple clipboard content types 2025-10-30 14:01:58 -07:00
Lukas c7d5d1b9fc
macOS: make text editor in clipboard confirmation non focusable (#9400)
With its being `focusable`(default), the first responder became the text
editor instead of the paste button.

This fixes the issue where one can't confirm with the keyboard.

This doesn't affect its selection.
2025-10-29 21:30:03 -07:00
Daniel Wennberg 88444d4bd7 macOS: Adjust documentView padding on layout changes 2025-10-27 10:43:47 -07:00
Dusk 27b0978cd5
macos: use system beep for bell (#9339)
This seems pretty straightforward. I've tested it and it does what I'd
expect it to do.

Fixes #9338
2025-10-26 03:24:52 +00:00
Lukas fd969b53a5
macOS: fix #8282 (#9343)
After `ghostty_app_update_config`, `ghostty_action_config_change_s` was
fired with the correct config. This happens synchronously, which will
update `App.config` in `App.configChange(_:target:v:)`.

Previously, after updating, `App.config` was set with the stale one,
which caused #8282.
2025-10-25 20:08:32 -07:00
Lars d39cc6d478
macOS: update window appearance based on `preferredBackgroundColor` 2025-10-25 19:35:34 +02:00
Mitchell Hashimoto 5c574e7745
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:22:35 -07:00
Daniel Wennberg e2fe0cf53a
macOS: remove scroll edge styling with hidden titlebar (#9317)
With `macos-titlebar-style = hidden`, creating splits or cycling
fullscreen sometimes produces a transparent overlay in the titlebar
area, clipping the top of the surfaces:

<img width="504" height="272" alt="Screenshot 2025-10-22 at 21 27 28"
src="https://github.com/user-attachments/assets/e28c5226-2e47-4c1d-8c14-b286fdb261f3"
/>

This is actually SwiftUI styling for scroll views, and the fact that it
pops up even though the titlebar is hidden is possibly a SwiftUI bug; at
least it's causing frustration for others too, see
https://developer.apple.com/forums/thread/798392 and
https://stackoverflow.com/questions/79776037/strange-nsscrollpocket-height-on-my-nstableview-in-fullscreen-mode-on-macos-taho.

I tried setting `.scrollEdgeEffectHidden()` on various nodes in the
SwiftUI hierarchy, but couldn't get it to work, so I ended up resorting
to an old-fashioned game of imperative whack-a-mole. Now:

<img width="504" height="272" alt="Screenshot 2025-10-22 at 21 28 47"
src="https://github.com/user-attachments/assets/e4499f16-5bd0-43cd-a7de-37fbc56eb1c4"
/>

AI disclosure (my first!): I consulted copilot trying to figure out of
the whole SwiftUI/AppKit situation and whether there might be a
declarative solution on the SwiftUI side. Just chatting in general terms
without showing real-world code. No dice.
2025-10-23 08:33:39 -07:00
Mitchell Hashimoto b764055c33
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-22 16:14:28 -07:00
Mitchell Hashimoto 014de2992e
macos: goto_split direction is performable (#9284)
Fixes #9283

There was a comment here noting this deficiency. GTK implements this
properly.
2025-10-19 20:29:36 -07:00
Mitchell Hashimoto ea505ec51d
macos: use stable display UUID for quick terminal screen tracking
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.

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-17 21:04:23 -07:00
Mitchell Hashimoto 5b7f145640
macos: make terminal smaller to account for legacy scrollbar
When the preferred scrollbar style is "legacy", the scrollbar takes up
space that offsets the actual terminal. To prevent reflow, we detect
this before the scrollbar becomes visible and shrink our terminal width
to prepare for it.

This doesn't account for the style changing at runtime, yet.
2025-10-17 20:08:03 -07:00
Daniel Wennberg 51b2374616 Add window padding to scrollView document height 2025-10-17 00:14:21 -07:00
Daniel Wennberg ffead466c7 Remove hidden titlebar safe area for SurfaceScrollView 2025-10-17 00:06:00 -07:00
Lars cc91e2ad16
macOS: remove background from SurfaceScrollView 2025-10-16 23:52:07 +02:00
Mitchell Hashimoto 4b34b2389a
config: add `scrollbar` config to control when scrollbars appear 2025-10-16 14:06:48 -07:00
Mitchell Hashimoto 7207ff08d5
macos: SurfaceScrollView 2025-10-16 14:06:46 -07:00
Mitchell Hashimoto 3d837cbbce
macos: "Check for updates" cancels whatever the current update state is (#9203)
This mainly allows users who have a pending update but didn't install it
for some time to re-check to see if there is something newer in the mean
time.
2025-10-14 07:31:31 -07:00
Mitchell Hashimoto 75734a4d07
macos: clarify the "ready to install update" state
- The copy is updated to better explain what the user should do next.
- The symbol is updated to make it clear the update isn't yet installed.
2025-10-13 21:06:01 -07:00
Xiangbao Meng dafb9e89a3
macOS: use default app for `*.ghostty` files first (#9180)
A small improvement for #8885, tested `config` and `config.ghostty`

<img width="526" height="267" alt="image"
src="https://github.com/user-attachments/assets/d09305ab-4a87-4393-b09c-804e618968f3"
/>
2025-10-13 06:52:00 -07:00
Mitchell Hashimoto 8f1a014afd
macos: clean up the "installing" update state (#9170)
This includes multiple changes to clean up the "installing" state:

- Ghostty will not confirm quit, since the user has already confirmed
they want to restart to install the update.
- If termination fails for any reason, the popover has a button to retry
restarting.
- The copy and badge symbol have been updated to better match the
reality of the "installing" state.

<img width="1756" height="890" alt="CleanShot 2025-10-12 at 15 04 08@2x"
src="https://github.com/user-attachments/assets/1b769518-e15f-4758-be3b-c45163fa2603"
/>

AI written:
https://ampcode.com/threads/T-623d1030-419f-413f-a285-e79c86a4246b fully
understood.
2025-10-12 15:20:26 -07:00
Joshie cbeb6890c9
Add `.ghostty` extension to `config` (#8885)
Resolves #8689

For various reason, ghostty wants to have a unique file extension for
the config files. The name was settled on `config.ghostty`. This will
help with tooling. See #8438 (original discussion) for more details.

This PR introduces the preferred default of `.ghostty` while still
supporting the previous `config` file. If both files exist, a warning
log is sent.

The docs / website will need to be updated to reflect this change. 

> [!NOTE]
> Only tested on macOS 26.0.

---------

Co-authored-by: Mitchell Hashimoto <m@mitchellh.com>
2025-10-12 13:48:06 -07:00
Xiangbao Meng 03e71e86a4
macOS: distinguish between Debug and Release(Stable/Tip) (#9149)
### Background

Been running Ghostty locally for a while now, and I use the Finder
service a lot. It often confuses me which one is the official one, until
I actually open it.

### Changes

- Use blueprint to distinguish from release app, if no custom icon
specified
- Change BundleDisplayName to Ghostty[Debug]
- Enable Info.plist preprocessing for reading
`$(INFOPLIST_KEY_CFBundleDisplayName)` for providing different services
with different configurations
> (Preprocessing was once reverted
before](https://github.com/ghostty-org/ghostty/commit/6508fec), so I'm
not sure whether this follows the 'rules' here, but for now, there are
no links in the plist file, so I think it’s
[safe](https://developer.apple.com/library/archive/technotes/tn2175/_index.html#:~:text=can%20pass%20the-,%2Dtraditional,-flag%20to%20the)
to enable it
2025-10-12 13:07:29 -07:00
Xiangbao Meng 8d8821004e
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-12 13:04:18 -07:00
Xiangbao Meng 47a8f8083d
macOS: Fix more `macos-titlebar-style` related issues (#9163)
### This PR depends on #9162 

#1691 doesn't seem to be an issue anymore, but changing appearance while
Ghosty is active will result in similar nastiness.



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



### Changes

- [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-12 07:31:42 -07:00
Xiangbao Meng cbc06a0abc
macOS: Support building with Xcode 16 (#9162)
With this you can test most of the old tab bar behaviour without using a
virtual machine
2025-10-12 07:25:18 -07:00
Mitchell Hashimoto d3ee3c5b8a
macos: update permission request response should move state back to idle (#9151)
Previously, the permission request response would not move the state so
it'd stay in the titlebar.
2025-10-11 14:49:31 -07:00
Mitchell Hashimoto ac2f040b31
macos: Show "Update and Restart" in the Command Palette (#9131)
If an update is available, you can now trigger the full download,
install, and restart from a single command palette action. This allows
for a fully keyboard-driven update process.

While an update is being installed, an option to cancel or skip the
current update is also shown as an option, so that can also be
keyboard-driven.

This currently can't be bound to a keyboard action, but that may be
added in the future if there's demand for it.

**AI Disclosure:** Amp was used considerably. I reviewed all the code
and understand it.

## Demo



https://github.com/user-attachments/assets/df6307f8-9967-40d4-9a62-04feddf00ac2
2025-10-10 13:40:35 -07:00