Commit Graph

1339 Commits (77b038dcb6c239a2885ebcaeeec9042ad1eb47e3)

Author SHA1 Message Date
Mitchell Hashimoto 04956f3dc1
macos: require confirmation to run any script 2025-08-28 12:34:04 -07:00
Mitchell Hashimoto f1ea30dcf1
macos: when executing a script directly, always wait after command 2025-08-28 11:26:33 -07:00
Mitchell Hashimoto 19a27383f8
macos: use visible frame for quick terminal sizing calculation
Fixes #8418

This fixes issues where left/right positions would be cut off from the
menu bar. And makes it so that size 100%,100% doesn't overflow into the
non-visible space of the edge of the screen.
2025-08-27 06:59:02 -07:00
Mitchell Hashimoto 520eaec61c
macos: fix quick terminal issue where closing while fullscreen 2025-08-26 10:40:41 -07:00
Alexander Lais e676eae640 macos: fix quick terminal fullscreen
Fullscreen on quick terminal was failing with a crash, when it tried
to save the state of a non-existent toolbar and its accessory view
controllers.
2025-08-26 10:36:06 -07:00
Mitchell Hashimoto ae48f323d7
macos: style changes for quick terminal sizing 2025-08-26 10:20:16 -07:00
Mitchell Hashimoto a90bf58080
config: change quick terminal size C layout to tagged union 2025-08-26 09:52:26 -07:00
Friedrich Stoltzfus 466fdfffe6 macOS: rename c struct, relocate QuickTerminalSize file
Renamed the ghostty_quick_terminal_size_u to
ghostty_quick_terminal_size_s and moved the QuickTerminalSize file to
the Ghostty folder as requested.
2025-08-26 09:47:31 -07:00
Friedrich Stoltzfus 58e7400ea5 macOS: Round quick terminal window position coordinates
This resolves an issue where the right side of the quick terminal would
not resize equally to the left side if adjusting the width from the left
side.
2025-08-26 09:47:31 -07:00
Friedrich Stoltzfus e5ad6603f4 Merge branch 'main' into quick-term-initial-size 2025-08-26 09:47:31 -07:00
Friedrich Stoltzfus 7cc0728fe5 macOS: enable quick terminal manual resizing
You can now resize the quick terminal both vertically and horizontally. To incorporate adjusting the custom secondary size on the quick terminal we needed to have the ability to resize the width (if from top, bottom, or center), and height (if from right, left, or center). The quick terminal will retain the user's manually adjusted size while the app is open. A new feature with this is that when the secondary size is adjusted (or primary if the quick terminal is center), the size will increase or decrease on both sides of the terminal.
2025-08-26 09:47:31 -07:00
Friedrich Stoltzfus 17f7f204e1 macOS: update zig and c structs for quick terminal size
Applying the feedback given by @pluiedev to use an enum to specify the
type of quick terminal size configuration given (pixels or percentage).
Updated the Swift code to work with the enum as well.
2025-08-26 09:47:31 -07:00
Friedrich Stoltzfus 63cd424678 macOS: Add support for quick terminal sizing configuration
Added C bindings for the already existing quick-terminal-size
configuration. Created a new QuickTerminalSize struct to hold these
values in Swift. Updated the QuickTerminal implementation to use the
user's configuration if supplied. Retains defaults. Also adds support to
customize the width of the quick terminal (height if quick terminal is
set to right or left).
2025-08-26 09:47:31 -07:00
Jeffrey C. Ollie 52a25e9c69
parameterize close_tab
- Add mode (`this`/`other`) parameter to `close_tab` keybind/apprt action.
- Keybinds will default to `this` if not specified, eliminating backward
  compatibility issues (`keybind=x=close_tab` === `keybind=x=close_tab:this`).
- Remove `close_other_tabs` keybind and apprt action.
2025-08-25 11:00:26 -05:00
jamylak c26323d697 Close other tabs feature on Mac.
Supporting command line, file menu and keybindings.
Default mac shortcut of `super + alt + o` (other)

Not able to test on Linux so excluding `close_other_tabs` from `gtk` for now
make a default short cut for close other tabs
2025-08-24 07:55:08 -07:00
Mitchell Hashimoto 54f8dff308
macos: if parent window is fullscreen, new window is fullscreen too
Fixes #8229

This was a regression. 

The discussion noted in #8229 requests we create a new window on the 
non-fullscreen desktop but that isn't how Ghostty has behaved
historically. I bisected back and tried 1.1.3 as well and we always
created a new fullscreen window when the parent was fullscreen.

This behavior matches iTerm2. Its noteworthy that native tabbing and
Apple apps such as Terminal.app and Safari do NOT do this. For both of
these, new window creates a _tab_ when in fullscreen. I don't think
that's particularly desirable, though.
2025-08-22 14:31:50 -07:00
Tobias Pape 4fdf0b687e typo found typos, typo may keep them 2025-08-22 09:19:25 -07:00
Tobias Pape 85cba70c2e Work around strange SwiftUI behavior in "older" macOSen.
The Quick Terminal would not appear anymore, as somewhere
in the framework the Quick Terminal Window's geometry
gets corrupted when the window is added to the UI.

This works around by caching the windows geometry and
reusing it afterwards
2025-08-22 09:17:49 -07:00
Moeeze Hassan f4009721a1 macOS: order out alert sheets to avoid Stage Manager focus loss
Signed-off-by: Moeeze Hassan <fammas.maz@gmail.com>
2025-08-22 09:05:20 -07:00
Daniel Wennberg 7d60c7c75b macos: move activation to after new window/tab is created 2025-08-21 15:16:20 -07:00
Mitchell Hashimoto 056ccc9818
macOS: update sparkle (#8337)
There aren't any noteworthy changes here we're just using a very old
version. Additionally, our CI was using... different versions!
2025-08-21 14:56:50 -07:00
Mitchell Hashimoto 1ce56a12fa
update sparkle
There aren't any noteworthy changes here we're just using a very old
version. Additionally, our CI was using... different versions!
2025-08-21 14:08:32 -07:00
Aljoscha Krettek f736ee8865 macos: in new_window action, activate App
This change makes sure that the new window is focused and visible.

When commit 33d128bcff removed the
TerminalManager class and moved its functionality into
TerminalController, it accidentally removed app activation for windows
triggered by global keybinds.

How the bug works:

   1. Menu actions (like File → New Window) call AppDelegate.newWindow()
      which:
      2. Calls TerminalController.newWindow()
      3. AND explicitly calls NSApp.activate(ignoringOtherApps: true) in
         the AppDelegate
   4. Global keybind actions trigger ghosttyNewWindow() notification
      handler which:
      5. Only calls TerminalController.newWindow()
      6. Does NOT call NSApp.activate(ignoringOtherApps: true)
   7. While TerminalController.newWindow() does call
      NSApp.activate(ignoringOtherApps: true) internally, this call
      happens before the async dispatch that shows the window, so the
      activation occurs but the window isn't focused when it's actually
      shown.
   8. In the old TerminalManager.newWindow(), the activation happened
      immediately before the async dispatch, ensuring proper timing for
      window focus.

The fix would be to either move the NSApp.activate() call back into
TerminalController.newWindow(), as it was for TerminalManager, or add
the activation call to the notification handlers in AppDelegate.
2025-08-21 14:03:00 -07:00
Mitchell Hashimoto e01ff4093a
macos: have macos-dock-drop-behavior apply to all drops 2025-08-21 10:45:17 -07:00
David Keegan f9ad061ea8 Add macos-dock-drop-folder-behavior configuration option
This adds a new configuration option that controls whether folders
dropped onto the Ghostty dock icon open in a new tab (default) or
a new window.

The option accepts two values:
- tab: Opens folders in a new tab in the main window (default)
- window: Opens folders in a new window

This is useful for users who prefer window-based workflows over
tab-based workflows when opening folders via drag and drop.
2025-08-21 10:30:26 -07:00
Mitchell Hashimoto f178f4419e
macos: fix iOS builds 2025-08-21 10:03:25 -07:00
Nicholas Mata f1c68f698b Correct Swift formatting inconsistencies 2025-08-21 10:00:15 -07:00
Nicholas Mata 5948bd3f02 Add support for 'custom' on 'macos_icon' to support a completely custom app icon 2025-08-21 10:00:15 -07:00
Nicholas Mata 29419e7aac Make macos icon persistent even when app is closed 2025-08-21 10:00:15 -07:00
Mitchell Hashimoto 63ca777e0f
macos: show the copy menu item if we have any text selected 2025-08-19 14:23:50 -07:00
Alexander Lais 1f378e6775
fix: capture screenshot for app intents views as NSImage
SwiftUI's ImageRenderer must not be called outside the main thread.

The `@MainActor` annotation is only relevant for our own code, not
for calls from frameworks. The machinations around Shortcuts end up
calling the displayRepresentation method outside the main thread.

By capturing the screenshot as NSImage, all data is retained and can
be processed outside the main thread.
2025-08-08 16:53:26 +02:00
Aaron Ruan 1f710768e9
Update Float on Top menu icon to square.filled.on.square 2025-07-28 09:26:54 +08:00
Weizhao Ouyang b7f6da7857 macos: add more Tahoe menu item icons from SF Symbols
Signed-off-by: Weizhao Ouyang <o451686892@gmail.com>
2025-07-25 22:14:13 +08:00
Bryan Lee 852eb2e0d5
Fix tab titles not being preserved with window-save-state
Add serialization for tab titles in SurfaceView to persist user-set titles across app restarts. Bump TerminalRestorableState version to 4 to handle the new format.
2025-07-23 23:21:44 +08:00
William Walker 7962651dd8
fix: rename tab title popup focus 2025-07-14 17:23:59 -04:00
Mitchell Hashimoto 02b08e0ec9
macos: restore tabs correctly into a single window
Fixes #7941

I don't fully understand the fix here. Its code we've had for awhile it
was just in the wrong place after I refactored our window management.
The comment clearly states why its there but I don't know why it is
required.
2025-07-14 11:22:38 -07:00
Jeffrey C. Ollie cd9174e7e8
show child exited: fix macos build 2025-07-11 22:56:20 -05:00
Jeffrey C. Ollie 033d8c3099
core/gtk: add apprt action to show native GUI warning when child exits
Addresses #7649 for the core and GTK. macOS support will need to be
added later.

This adds an apprt action to show a native GUI warning of some kind when
the child process of a terminal exits.

Also adds a basic GTK implementation of this. In GTK it overlays an
Adwaita banner at the bottom of the window (similar to the banner that
shows up in at the top of windows in debug builds).
2025-07-11 22:56:20 -05:00
Mitchell Hashimoto 9fa26387ef
build: `zig build test` runs Xcode tests on macOS
Related to #7879

This commit updates `zig build test` to run Xcode tests, too. These run
in parallel to the Zig tests, so they don't add any time to the test.

The Xcode tests will _not_ run when: (1) the target is not macOS, or (2)
the `-Dtest-filter` option is non-empty. This makes it so that this
change doesn't affect non-macOS and doesn't affect the general dev cycle
because you usually will run `-Dtest-filter` when developing a core
feature.

I didn't add a step to only run Xcode tests because I find that when I'm
working in Xcode I'm probably going to run the tests from there anyways.
The integration with `zig build test` is just a convenience, especially
around CI.

Speaking of CI, this change also makes it so this will run in CI.
2025-07-10 21:08:51 -07:00
Mitchell Hashimoto c990d35d6d
macos: add benchmark tests to our Xcode project 2025-07-09 15:06:24 -07:00
Mitchell Hashimoto b7ffbf933f
macos: open URLs with NSWorkspace APIs instead of `open`
Fixes #5256

This updates the macOS apprt to implement the `OPEN_URL` apprt action to
use the NSWorkspace APIs instead of the `open` command line utility.

As part of this, we removed the `ghostty_config_open` libghostty API and
instead introduced a new `ghostty_config_open_path` API that returns the
path to open, and then we use the `NSWorkspace` APIs to open it (same
function as the `OPEN_URL` action).
2025-07-06 21:01:01 -07:00
Mitchell Hashimoto 984d123fe4
macos: support configuration via CLI arguments
This makes it so `zig build run` can take arguments such as
`--config-default-files=false` or any other configuration. Previously,
it only accepted commands such as `+version`.

Incidentally, this also makes it so that the app in general can now take
configuration arguments via the CLI if it is launched as a new instance
via `open`. For example:

    open -n Ghostty.app --args --config-default-files=false

This previously didn't work. This is kind of cool.

To make this work, the libghostty C API was modified so that
initialization requires the CLI args, and there is a new C API to try to
execute an action if it was set.
2025-07-05 21:31:23 -07:00
Mitchell Hashimoto 8c3caee15c
macOS: zig build run disables window saved state 2025-07-05 19:58:17 -07:00
Mitchell Hashimoto 7bd90e6ec4
Build system can build macOS app bundle and open it
`zig build run` on macOS now builds the app bundle via the `xcodebuild`
CLI and runs it. The experience for running the app is now very similar
to Linux or the prior GLFW build, where the app runs, blocks the zig
command, and logs to the terminal.

`xcodebuild` has its own build cache system that we can't really hook
into so it runs on every `zig build run` command, but it does cache and
I find its actually relatively fast so I think this is a good
replacement for the glfw-based system.
2025-07-04 13:32:15 -07:00
Mitchell Hashimoto d8838cff0b
macOS: remove @DeferredProperty usage from TerminalEntity
This fixes an Apple Shortcuts crash for macOS 15 and earlier.
Unfortunately it looks like we can't guard these with `@available`. I'm
going to report an Apple Feedback about this but for now this gets
shortcuts working on macOS 15 and earlier.
2025-07-04 07:30:26 -07:00
Mitchell Hashimoto 2fa4fc8902
reload configuration on SIGUSR2
This is done at the apprt-level for a couple reasons.

  (1) For libghostty, we don't have a way to know what the embedding
      application is doing, so its risky to create signal handlers that
      might overwrite the application's signal handlers.

  (2) It's extremely messy to deal with signals and multi-threading.
      Apprts have framework access that handles this for us.

For GTK, we use g_unix_signal_add.

For macOS, we use `DispatchSource.makeSignalSource`. This is an awkward
API but made for this purpose.
2025-07-01 15:51:58 -07:00
Daniel Wennberg 886e33d7b7 make hiddenStyleMask static 2025-06-30 11:21:55 -07:00
Daniel Wennberg b1f788a768 macos: don't overwrite the .fullScreen styleMask option in reapplyHiddenStyle 2025-06-30 10:36:48 -07:00
Islam Sharabash 22a624e560 Equalize splits based on children oriented in the same direction
This changes equalization so it only counts children oriented in the
same direction.

This makes splits a bit more aesthetic, and replicates how split
equalization works in neovim.
2025-06-28 09:01:41 +02:00
Mitchell Hashimoto 471098df30
macOS: Run scripts using stdin rather than executing directly
Fixes #7647

See #7647 for context. This commit works by extending the `input` work
introduced in #7652 to libghostty so that the macOS can take advantage
of it. At that point, its just the macOS utilizing `input` in order to
set the command and `exit` up similar to Terminal and iTerm2.
2025-06-22 21:06:32 -04:00
Mitchell Hashimoto 02e05a85fc
macOS: Fix window-decoration=none regression on Tahoe
This regression may have existed on Sequoia too, but I only saw it on
Tahoe.

The issue is that we should not be setting up titlebar accessory views
when there is no titlebar. This was triggering an AppKit assertion.

To further simplify things, I always use the basic window styling if
window decorations are off, too.
2025-06-22 07:28:30 -07:00
Qwerasd 5bfdb1b9cf
The Big Renderer Rework (#7620)
It's here, the long-foretold and long-procrastinated renderer rework!
Hopefully this makes it easier to adapt and modify the renderer in the
future and ensures feature parity between Metal and OpenGL. Despite
having been a lot of work to write initially, with the abstraction layer
in place I feel like working on the renderer will be a much more
pleasant experience going forward.

## Key points
- CPU-side renderer logic is now mostly unified via a generic
`Renderer`.
- A graphics API abstraction layer over OpenGL and Metal has been
introduced.
- Minimum OpenGL version bumped to `4.3`, so can no longer be run on
macOS; I used the nix VM stuff for my testing during development. (Edit
by @mitchellh: Note for readers that Ghostty still works on macOS, but
the OpenGL backend doesn't, only the Metal one)
- The OpenGL backend now supports linear blending! Woohoo! The default
`alpha-blending` has been updated to `linear-corrected` since it's
essentially a strict improvement over `native`. The default on macOS is
still `native` though to match other mac apps in appearance, since macOS
users are more sensitive to text appearance.
- Custom shaders can now be hot reloaded.
- The background color is once again drawn by us, so custom shaders can
interact with it properly. In general, custom shaders should be a little
more robust.

## The abstraction layer
The general hierarchy of the abstraction layer is as such:
```
 [ GraphicsAPI ] - Responsible for configuring the runtime surface
    |     |        and providing render `Target`s that draw to it,
    |     |        as well as `Frame`s and `Pipeline`s.
    |     V
    | [ Target ] - Represents an abstract target for rendering, which
    |              could be a surface directly but is also used as an
    |              abstraction for off-screen frame buffers.
    V
 [ Frame ] - Represents the context for drawing a given frame,
    |        provides `RenderPass`es for issuing draw commands
    |        to, and reports the frame health when complete.
    V
 [ RenderPass ] - Represents a render pass in a frame, consisting of
   :              one or more `Step`s applied to the same target(s),
 [ Step ] - - - - each describing the input buffers and textures and
   :              the vertex/fragment functions and geometry to use.
   :_ _ _ _ _ _ _ _ _ _/
   v
 [ Pipeline ] - Describes a vertex and fragment function to be used
                for a `Step`; the `GraphicsAPI` is responsible for
                these and they should be constructed and cached
                ahead of time.

 [ Buffer ] - An abstraction over a GPU buffer.

 [ Texture ] - An abstraction over a GPU texture.
```
More specific documentation can be found on the relevant structures.

## Miscellany
Renderers (which effectively just means the generic renderer) are now
expected to only touch GPU resources in `init`, certain lifecycle
functions such as the `displayRealized`/`displayUnrealized` callbacks
from GTK-- and `drawFrame`; and are also expected to be thread-safe.
This allows the renderer thread to build the CPU-side buffers
(`updateFrame`) even if we can only *draw* from the app thread.

Because of this change, we can draw synchronously from the main thread
on macOS when necessary to always have a frame of the correct size
during a resize animation. This was necessary to allow the background to
be drawn by our GPU code (instead of setting a background color on the
layer) while still avoiding holes during resize.

The OpenGL backend now theoretically has access to multi-buffering, but
it's disabled (by setting the buffer count to 1) because it
synchronously waits for frames to complete anyway which means that the
extra buffers were just a waste of memory.

## Validation
To validate that there are no significant or obvious problems, I
exercised both backends with a variety of configurations, and visually
inspected the results. Everything looks to be in order.

The images are available in a gist here:
https://gist.github.com/qwerasd205/c1bd3e4c694d888e41612e53c0560179

## Memory
Here's a comparison of memory usage for ReleaseFast builds on macOS,
between `main` and this branch.
Memory figures given are values from Activity Monitor measuring windows
of the same size, with two tabs with 3 splits each.

||Before|After|
|-:|-|-|
|**Memory**|247.9 MB|224.2 MB|
|**Real Memory**|174.4 MB|172.5 MB|

Happily, the rework has slightly *reduced* the memory footprint- likely
due to removing the overhead of `CAMetalLayer`. (The footprint could be
reduced much further if we got rid of multi-buffering and satisfied
ourselves with blocking for each frame, but that's a discussion for
another day.)

If someone could do a similar comparison for Linux, that'd be much
appreciated!

## Notes / future work
- There are a couple structures that *can* be unified using the
abstraction layer, but I haven't gotten around to unifying yet.
Specifically, in `renderer/(opengl|metal)/`, there's `cell.zig` and
`image.zig`, both of which are substantially identical between the two
backends. `shaders.zig` may also be a candidate for unification, but
that might be *overly* DRY.
- ~~I did not double-check the documentation for config options, which
may mention whether certain options can be hot-reloaded; if it does then
that will need to be updated.~~ Fixed: be5908f
- The `fragCoord` for custom shaders originates at the top left for
Metal, but *bottom* left for OpenGL; fixing this will be a bit annoying,
since the screen texture is likewise vertically flipped between the two.
Some shaders rely on the fragcoord for things like falling particles, so
this does need to be fixed.
- `Target` should be improved to support multiple types of targets right
now it only represents a framebuffer or iosurface, but it should also be
able to represent a texture; right now a kind of messy tagged union is
used so that steps can accept both.
- Custom shader cursor uniforms (#6912) and terminal background images
(#4226, #5233) should be much more straightforward to implement on top
of this rework, and I plan to make follow-up PRs for them once this is
merged.
- I *do* want to do a rework of the pipelines themselves, since the way
we're rendering stuff is a bit messy currently, but this is already a
huge enough PR as it is- so for now the renderer still uses the same
rendering passes that Metal did before.
- We should probably add a system requirements section to the README
where we can note the minimum required OpenGL version of `4.3`, any even
slightly modern Linux system will support this, but it would be good to
document it somewhere user-facing anyway.

# TODO BEFORE MERGE
- [x] Have multiple people test this on both macOS and linux.
- [ ] ~~Have someone with a better dev setup on linux check for memory
leaks and other problems.~~ (Skipped, will merge and let tip users
figure this out, someone should *specifically* look for memory leaks
before the next versioned release though.)
- [x] Address any code review feedback.
2025-06-21 22:00:01 -06:00
Mitchell Hashimoto c1c3f639c5
macos: Ghostty Icon Update for macOS Tahoe
This updates the Ghostty icon to be compatible with macOS Tahoe
(supports glass effects, light/dark, tinting, etc.). This icon is made
in the new Apple Icon Composer as the source format, and all other
formats are exported from it.

This commit also updates the icon for non-Apple platforms because the
icon is fundamentally the same and I don't see any reason to maintain
multiple icons of fundamentally the same design and style.

This commit also includes updates to the macOS app so that the About
Window and so on will use the new icon.
2025-06-21 12:34:49 -07:00
Mitchell Hashimoto 296f340ff4
macos: the approval dialog is now forever 2025-06-21 06:53:09 -07:00
Mitchell Hashimoto 020976bf88
macos: address some feedback 2025-06-21 06:42:32 -07:00
Mitchell Hashimoto e4c13cdba8
macos: Optional/Array extensions need to build for iOS too 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto b6559d0899
macos: add a macos-shortcut config 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto 647f29bad1
macos: intents all ask for permission 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto 027171bd5d
macos: can set env vars on new terminal 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto f8bc9b547c
macos: support env vars for surface config, clean up surface config 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto e6c24fbf0a
macos: remove confirmation option for close terminal 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto 2c1e83ba2f
macos: intent to open quick terminal 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto f096675eaf
macos: Close Terminal Intent 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto 2df301e2fb
macos: mouse pos and scroll intents 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto bc134016f7
macos: move mousePos and mousScroll to Ghostty.Surface 2025-06-21 06:39:20 -07:00
Mitchell Hashimoto 4445a9c637
macos: add mouse button intent 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto 71b6e223af
macos: input keyboard event can send modifiers and actions now 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto 93619ad420
macos: Ghostty.Key 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto a6074040e7
macos: input intent 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto c904e86883
macos: invoke keybind intent 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto 14e46d0979
macos: InvokeCommandPaletteIntent and CommandEntity 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto 5259d0fa55
macos: starting to work on new libghostty data models 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto bbb69c8f27
macos: NewTerminalIntent returns Terminal, can split 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto 683b38f62c
macos: can specify parent terminal for new terminal intent 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto b8d4463754
macos: terminal not found should be an error 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto e51a93ee7c
macos: Terminal entity has screen contents deferred 2025-06-21 06:39:19 -07:00
Mitchell Hashimoto 93f0ee2089
macos: GetTerminalDetails intent 2025-06-21 06:39:18 -07:00
Mitchell Hashimoto 2aa731a64e
macos: TerminalEntity 2025-06-21 06:39:18 -07:00
Mitchell Hashimoto 7ae5018fe8
macos: new terminal intent 2025-06-21 06:39:18 -07:00
Qwerasd 371d62a82c renderer: big rework, graphics API abstraction layers, unified logic
This commit is very large, representing about a month of work with many
interdependent changes that don't separate cleanly in to atomic commits.

The main change here is unifying the renderer logic to a single generic
renderer, implemented on top of an abstraction layer over OpenGL/Metal.

I'll write a more complete summary of the changes in the description of
the PR.
2025-06-20 15:18:41 -06:00
Mitchell Hashimoto 30a8ba1bf6
macos: disambiguate close tab vs close window for confirmation (#7618)
This fixes an issue where pressing the red close button in a window or
the "x" button on a tab couldn't differentiate and would always close
the tab or close the window (depending on tab counts).

It seems like in both cases, AppKit triggers the `windowShouldClose`
delegate method on the controller, but for the close window case it
triggers this on ALL the windows in the group, not just the one that was
clicked.

I implemented a kind of silly coordinator that debounces
`windowShouldClose` calls over 100ms and uses that to differentiate
between the two cases.
2025-06-17 16:24:46 -07:00
Mitchell Hashimoto 51b9fa751a
macos: disambiguate close tab vs close window for confirmation
This fixes an issue where pressing the red close button in a window or
the "x" button on a tab couldn't differentiate and would always close
the tab or close the window (depending on tab counts).

It seems like in both cases, AppKit triggers the `windowShouldClose`
delegate method on the controller, but for the close window case it
triggers this on ALL the windows in the group, not just the one
that was clicked.

I implemented a kind of silly coordinator that debounces
`windowShouldClose` calls over 100ms and uses that to differentiate
between the two cases.
2025-06-17 16:16:14 -07:00
Mitchell Hashimoto e6c77789d3
macOS: Confirm close on window close
Fixes #7615

We were incorrectly closing the window without confirmation when there
were no tabs.
2025-06-17 15:03:10 -07:00
Mitchell Hashimoto 6d283c012e
ci: build macOS releases with Xcode 26
Resolves #7591

This moves our CI to build macOS on Sequoia (macOS 15) with Xcode 26,
including the new macOS 26 beta SDK.

Importantly, this will make our builds on macOS 26 use the new styling.

I've added a new job that ensures we can continue to build with Xcode 16 and
the macOS 15 SDK, as well, although I think that might come to an end
when we switch over to an IconComposer-based icon. I'll verify then. For
now, we continue to support both.

I've also removed our `hasLiquidGlass` check, since this will now always
be true for macOS 26 builds.
2025-06-17 13:44:13 -07:00
Mitchell Hashimoto d0f116da35
macOS: Basic Read-Only Accessibility Integration (#7601)
This integrates with macOS accessibility APIs to expose Ghostty terminal
structure and content.

This is a very, very bare implementation and the terminal contents
currently reported are the _full screen and scrollback_ which is way too
much for realistic human accessibility use. The target use case for this
PR is to enable automated tooling (namely, AI screen readers). However,
this is all groundwork we'll need to iterate and improve the
accessibility work anyways.

To make this work, I also replatformed some of our hacky C APIs onto a
more robust `ghostty_surface_read_text` API that can now read arbitrary
ranges of the screen into C strings for consumers to use. This will be
useful in more places going forward (hint hint).

## Before

Accessibility tooling can't read anything, Ghostty has no attributes, no
contents, just shows up as a square.

![CleanShot 2025-06-15 at 14 06
55@2x](https://github.com/user-attachments/assets/55eba1b4-6fd4-4d78-9434-5d672f374c67)

## After

A lot of metadata, including the screen contents as text.

![CleanShot 2025-06-15 at 14 07
25@2x](https://github.com/user-attachments/assets/e14cb7df-e4e2-4cc4-a214-004a8459f353)

Also, split hierarchies are navigable:



https://github.com/user-attachments/assets/a7b2ffb7-dbeb-41b2-8705-9c3200812c4d
2025-06-15 15:10:27 -07:00
Mitchell Hashimoto a2b4a2c0e4
macos: complete more ax APIs for terminal accessibility 2025-06-15 14:00:39 -07:00
Mitchell Hashimoto e69c756c89
macos: auto-expire cached screen contents 2025-06-15 13:55:06 -07:00
Mitchell Hashimoto 839d89f2dc
macos: simple cache of screen contents for ax 2025-06-15 13:46:40 -07:00
Mitchell Hashimoto c5f921bb06
apprt/embedded: improve text reading APIs (selection, random points) 2025-06-15 07:59:19 -07:00
Mitchell Hashimoto be437f5b64
macos: bare minimum terminal ax 2025-06-15 07:56:05 -07:00
Mitchell Hashimoto c90eb2e952
macos: AX for debug warning 2025-06-15 07:56:05 -07:00
Mitchell Hashimoto 4237dad240
macOS: simple SplitView AX
Proper labels, action to move the divider
2025-06-15 07:56:05 -07:00
Mitchell Hashimoto 57c79fa357
macos: Tahoe menu item icons, missed the "Ghostty" menu entirely
This is a follow up to #7594, I missed an entire menu.
2025-06-15 07:48:20 -07:00
Mitchell Hashimoto 7cc7f6cb06 macos 15 regression: transparent style shouldn't draw border
This fixes a regression from our Tahoe window styling changes on
earlier, stable versions of macOS. We need to set 
"titlebarAppearsTransparent" to true in order to hide the bottom
border.
2025-06-15 06:51:11 -07:00
Mitchell Hashimoto 9e45da17d0
macos: menu item symbols for Tahoe (#7594)
This is recommended for macOS Tahoe and all standard menu items now have
associated images. This makes our app look more polished and native for
macOS Tahoe.

On earlier versions of macOS (macOS 15 and earlier), we _do not_ set the
menu item image. Cocoa has supported menu item images for a long time
but it isn't idiomatic to show them in earlier versions, so we only do
this for later macOS versions.

For icon choice, I tried to copy other native macOS apps as much as
possible, mostly from Xcode. It looks like a lot of apps aren't updated
yet. I'm absolutely open to suggestions for better icons but I think
these are a good starting point.

One menu change is I moved "reset font size" above "increase font size"
which better matches other apps (e.g. Terminal.app).


https://github.com/user-attachments/assets/50a68326-221f-454f-9a9c-078878010a63
2025-06-14 19:50:58 -07:00
Mitchell Hashimoto 202020cd7d macos: menu item symbols for Tahoe
This is recommended for macOS Tahoe and all standard menu items now have
associated images. This makes our app look more polished and native for
macOS Tahoe.

For icon choice, I tried to copy other native macOS apps as much as
possible, mostly from Xcode. It looks like a lot of apps aren't updated
yet. I'm absolutely open to suggestions for better icons but I think
these are a good starting point.

One menu change is I moved "reset font size" above "increase font size"
which better matches other apps (e.g. Terminal.app).
2025-06-14 19:44:24 -07:00
Mitchell Hashimoto c4a978b07a
macos: set toolbar title `isBordered` to avoid glass view
This was recommended by the WWDC25 session on AppKit updates. My hack
was not the right approach.
2025-06-14 13:50:02 -07:00
Mitchell Hashimoto 928603c23e
macos: use a runtime liquid glass check for our Tahoe styling 2025-06-13 20:20:56 -07:00
Mitchell Hashimoto 1b6142b271 macos: don't restore tab bar with non-native fs 2025-06-13 15:02:06 -07:00
Mitchell Hashimoto ac4b0dcac0 macos: fix transparent tabs on sequoia 2025-06-13 14:57:54 -07:00
Mitchell Hashimoto 1388c277d5 macos: sequoia should use same tab bar identifier as TerminalWindow 2025-06-13 14:43:04 -07:00
Mitchell Hashimoto 8cfc904c0c macos: fix up some sequoia regressions 2025-06-13 14:39:12 -07:00
Mitchell Hashimoto a7df90ee55
macos: remove split zoom accessory when tabs appear 2025-06-13 13:36:42 -07:00
Mitchell Hashimoto f7f0514b9f
macos: move old toolbar into ventura file 2025-06-13 13:14:16 -07:00
Mitchell Hashimoto 59812c3b02
macos: remove TODO 2025-06-13 12:27:44 -07:00
Mitchell Hashimoto b1b74d3421
comments 2025-06-13 12:25:21 -07:00
Mitchell Hashimoto 00d41239da
macOS: prep the tab bar when system appearance changes 2025-06-13 12:22:29 -07:00
Mitchell Hashimoto 17ad77b5b0
macos: fix background color of terminal window to match surface 2025-06-12 21:36:00 -07:00
Mitchell Hashimoto 9d9c451b0a
macos: titlebar tabs handle hidden traffic buttons 2025-06-12 20:03:21 -07:00
Mitchell Hashimoto d84c30ce71
macos: titlebar tabs should be transparent 2025-06-12 18:10:37 -07:00
Mitchell Hashimoto 5f99670247
macos: tahoe titlebar tabs taking shape 2025-06-12 17:52:15 -07:00
Mitchell Hashimoto 6ae8bd737a
macos: hide the reset zoom titlebar accessory when tab bar is shown 2025-06-12 15:13:23 -07:00
Mitchell Hashimoto 5c8f1948ce
macos: remove the duplicated reset zoom accessory view from legacy 2025-06-12 14:42:09 -07:00
Mitchell Hashimoto de40e7ce02
macos: non-native fullscreen should restore toolbars 2025-06-12 14:36:33 -07:00
Mitchell Hashimoto 658ec2eb6f
macos: add reset zoom to all window titles 2025-06-12 14:33:53 -07:00
Mitchell Hashimoto 70029bf82a
macos: tahoe terminal tabs shows title 2025-06-12 13:39:19 -07:00
Mitchell Hashimoto 5877913ab8
macoS: Split out terminal tabs for ventura vs tahoe 2025-06-12 12:06:30 -07:00
Mitchell Hashimoto fd785f98bb
macos: titlebar tabs uses legacy window for now 2025-06-12 11:39:10 -07:00
Mitchell Hashimoto ccfd33022f
macos: only titlebar tabs uses legacy styling now 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto e5cb33e911
typos 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto 63e56d0402
macos: titlebar fonts work with new terminal window 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto a804dab288
macos: native terminal style works with new subclasses 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto dfa7a114de
macos: make transparent titlebars robust against show/hide tabs 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto 3595b2a847
macos: transparent titlebar handles transparent background 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto 6ce7f612a6
macos: transparent titlebar needs to be rehidden when tabs change 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto 7d02977482
macos: add NSView hierarchy debugging code 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto 4d33a73fc4
wip: redo terminal window styling 2025-06-11 15:18:02 -07:00
Mitchell Hashimoto 3db5b3da75
macos: hidden titlebar windows should cascade on new tab
Windows with `macos-titlebar-style = hidden` create new windows when the
new tab binding is pressed. This behavior has existed for a long time.

However, these windows did not cascade, meaning they'd appear overlapped
directly on top of the previous window, which is kind of nasty.

This commit changes it so that new windows created via new tab from a
hidden titlebar window will cascade.
2025-06-10 14:31:41 -07:00
Mitchell Hashimoto 1f340b4b2d
macos: for windowShouldClose, only close the tab if we have multiple
Fixes a regression from our undo/redo rework. We were accidentally
closing the entire window when the "X" button in the tab bar was
clicked.
2025-06-10 12:39:09 -07:00
Mitchell Hashimoto 2b9a6a4820
macos: unsplit window shouldn't allow split zooming
This was always the case, and is a recent regression from the SplitTree
rework. This brings it back to the previous behavior.
2025-06-10 12:11:18 -07:00
Mitchell Hashimoto e4cd90b8a0
macos: set explicit identity for split tree view based on structure
Fixes #7546

SwiftUI uses type and structure to identify views, which can lead
to issues with tree like structures where the shape and type is the same
but the content changes. This was causing #7546.

To fix this, we need to add explicit identity to the split tree view
so that SwiftUI can differentiate when it needs to redraw the view.

We don't want to blindly add Hashable to SplitTree because we don't want
to take into account all the fields. Instead, we add an explicit
"structural identity" to the SplitTreeView that can be used by SwiftUI.
2025-06-08 20:11:58 -07:00
Mitchell Hashimoto 26e1dd8f8e
macos: clear out the surface trees to prevent repeat undo
see the comment
2025-06-08 12:41:45 -07:00
Mitchell Hashimoto 3de3f48faf
macos: fix undo/redo for closing windows with multiple tabs
When closing a window that contains multiple tabs, the undo operation
now properly restores all tabs as a single tabbed window rather than
just restoring the active tab.

The implementation:
- Collects undo states from all windows in the tab group before closing
- Sorts them by their original tab index to preserve order
- Clears tab group references to avoid referencing garbage collected objects
- Restores all windows and re-adds them as tabs to the first window
- Tracks and restores which tab was focused (or focuses the last tab if none were)

AI prompts that generated this commit are below.

Each separate prompt is separated by a blank line, so this session was
made up with many prompts in a back-and-forth conversation.

> We need to update the undo/redo implementation in
> @macos/Sources/Features/Terminal/TerminalController.swift `closeWindowImmediately`
> to handle the case that multiple windows in a tab group are closed all at once,
> and to restore them as a tabbed window. To do this, I think we should collect
> all the `undoStates`, sort them by `tabIndex` (null at the end), and then on j
> restore, restore them one at a time but add them back to the same tabGroup. We
> can't use the tab group in the `undoState` because it will be garbage collected
> by then. To be sure, we should just set it to nil.

I should note at this point that the feature already worked, but the
code quality and organization wasn't up to my standards. If someone
using AI were just trying to make something work, they might be done at
this point.

I do think this is the biggest gap I worry about with AI-assisted
development: bridging between the "it works" stage at a junior quality
and the "it works and is maintainable" stage at a senior quality. I
suspect this will be a balance of LLMs getting better but also senior
code reviewers remaining highly involved in the process.

> Let's extract all the work you just did into a dedicated private method
> called `registerUndoForCloseWindow`

Manual: made some tweaks to comments, moved some lines around, didn’t change
any logic.

> I think we can pull the tabIndex directly from the undoState instead of
> storing it in a tuple.

> Instead of `var undoStates`, I think we can create a `let undoStates` and
> build and filter and sort them all in a chain of functional mappings.

> Okay, looking at your logic for restoration, the `var firstController` and
> conditionals are littly messy. Can you make your own pass at cleaning those
> up and I'll review and provide more specific guidance after.

> Excellent. Perfect. The last thing we're missing is restoring the proper
> focused window of the tab group. We should store that and make sure the
> proper window is made key. If no windows were key, then we should make the
> last one key.

> Excellent. Any more cleanups or comments you'd recommend in the places you
> changed?

Notes on the last one: it gave me a bunch of suggestions, I rejected most but
did accept some.

> Can you write me a commit message summarizing the changes?

It wrote me a part of the commit message you're reading now, but I
always manually tweak the commit message and add my own flair.
2025-06-08 08:08:01 -07:00
Mitchell Hashimoto ec043e1386
macos: red traffic light should be undoable 2025-06-08 07:00:51 -07:00
Mitchell Hashimoto 6f6d493763
macos: show quick terminal on undo/redo 2025-06-07 13:14:21 -07:00
Mitchell Hashimoto 6e77a5a6ca
macos: address quick terminal basic functionality with new API 2025-06-07 13:07:31 -07:00
Mitchell Hashimoto 20744f0482
macos: fix some CI build issues 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto 973a2afdde
macos: make sure we're not registering unnecessary undos 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto b234cb2014
macos: only process reopen if already activated 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto aeede903f5
macos: undo close all windows 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto d92db73f25
macos: undo new tab 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto 636b1fff8a
macos: initial window shouldn't support undo 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto 797c10af37
macos: undo new window 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto 33d128bcff
macos: remove TerminalManager
All logic related to TerminalController is now in TerminalController.
2025-06-07 12:46:15 -07:00
Mitchell Hashimoto 5507ec0fc0
macos: compile errors in CI 2025-06-07 12:46:15 -07:00
Mitchell Hashimoto d2d3852026
macos: remove debug log 2025-06-07 12:46:14 -07:00
Mitchell Hashimoto 49cc88f0d3
macos: configurable undo timeout 2025-06-07 12:46:14 -07:00
Mitchell Hashimoto 3e02c0cbd5
macos: fix an incorrect bindable write during view update 2025-06-07 12:46:14 -07:00
Mitchell Hashimoto b044f4864a
add undo/redo keybindings, default them on macOS 2025-06-07 12:46:14 -07:00
Mitchell Hashimoto e1847da139
macos: more robust undo tab that goes back to the same position 2025-06-07 12:46:14 -07:00