77 Commits

Author SHA1 Message Date
Daniel Wennberg
c2c267439b macos: fix hasWindowButtons logic 2025-06-05 13:48:53 -07:00
Mitchell Hashimoto
efc1ceab5d macOS: New value-based split tree implementation, move split logic out of SwiftUI into AppKit (#7523)
This is a major rework of how we represent, handle, and render splits in
the macOS app.

This new PR moves the split structure into a dedicated, generic
(non-Ghostty-specific) value-type called `SplitTree<V>`. All logic
associated with splits (new split, close split, move split, etc.) is now
handled by notifications on `BaseTerminalController`. The view hierarchy
is still SwiftUI but it has no logic associated with it anymore and
purely renders a static tree of splits.

Previously, the split hierarchy was owned by AppKit in a type called
`SplitNode` (a recursive class that contained the tree structure). All
logic around creating, zooming, etc. splits was handled by notification
listeners directly within the SwiftUI hierarchy. SwiftUI managed a
significant amount of state and we heavily used bindings, publishers,
and more. The reasoning for this is mostly historical: splits date back
to when Ghostty tried to go all-in on SwiftUI. Since then, we've taken a
more balanced approach of SwiftUI for views and AppKit for data and
business logic, and this has proven a lot more maintainable.

## Spatial Navigation

Previously, focus moving was handled by traversing the tree structure.
This led to some awkward behaviors. See:
https://github.com/ghostty-org/ghostty/issues/524#issuecomment-2668396095

In this PR, we now handle focus moving spatially. This means that move
"left" means moving to the visually left split (from the top-left
corner, a future improvement would be to do it from the cursor
position).

Concretely, given the following split structure:

```
+----------+-----+
|          |  b  |
|          |     |
|   a      +-----+
|          |     |
|          |     |
|          |     |
|          |     |
|----------|  d  |
|   c      |     |
|          |     |
+----------+-----+
```

Moving "right" from `c` now moves to `d`. Previously, it would go to
`b`. On Linux, it still goes to `b`.

## Value Types

One of the major architectural shifts is moving **purely to immutable
value types.** Whenever a split property changes such as a new split,
the ratio between splits, zoomed state, etc. we _create an entirely new
`SplitTree` value_ and replace it along the entire view hierarchy. This
is in some ways wasteful, but split hierarchies are relatively small
(even the largest I've seen in practical use are dozens of splits, which
is small for a computer). And using value types lets us get rid of a ton
of change notification soup around the SwiftUI hierarchy. We can rely on
reference counting to properly clean up our closed views.

> [!NOTE]
> 
> As an aside, I think value types are going to make it a lot easier in
the future to implement features like "undo close." We can just keep a
trailing list of surface tree states and just restore them. This PR
doesn't do anything like that, but it's now possible.

## SwiftUI Simplicity

Our SwiftUI view hierarchy is dramatically simplified. See the
difference in `TerminalSplitTreeView` (new) vs `TerminalSplit` (old).
There's so much less logic in our new views (almost none!). All of it is
in the AppKit layer which is just way nicer.

## AI Notes

This PR was heavily written by AI. I reviewed every line of code that
was rewritten, and I did manually rewrite at every step of the way in
minor ways. But it was very much written in concert. Each commit usually
started as an AI agent writing the whole commit, then nudging to get
cleaned up in the right way.

One thing I found in this task was that until the last commit, I kept
the entire previous implementation around and compiling. The agent
having access to a previous working version of code during a refactor
made the code it produced as follow up in the new architecture
significantly better, despite the new architecture having major
fundamental differences in how it works!
2025-06-05 12:59:43 -07:00
Mitchell Hashimoto
e3bc3422dc macos: handle split resizing 2025-06-05 07:05:11 -07:00
Mitchell Hashimoto
1707159441 new SplitTree 2025-06-05 07:05:11 -07:00
Daniel Wennberg
232a46d2dc Add option to hide macOS traffic lights 2025-06-02 09:22:01 -07:00
Daniel Wennberg
12a01c0460 Hide main title when covered by tabs 2025-06-02 09:10:22 -07:00
Daniel Wennberg
85beda9c49 Fix reset zoom button visibility in macOS "tabs" mode when no tabs 2025-06-02 09:09:04 -07:00
Martin Hettiger
f83729ba48 macos: add float on top feature for terminal windows 2025-05-01 09:13:33 -07:00
Aaron Ruan
4291e1c5d7 fix: use surfaceConfig.backgroundColor to determine if the theme is light or dark
Signed-off-by: Aaron Ruan <i@ar212.com>
2025-02-21 15:32:24 -08:00
Qwerasd
5477eb87c1 macOS: prevent native window drag by top region when titlebar hidden
The native window drag region is driven ultimately by the window's
`contentLayoutRect`, so we can just override it in `TerminalWindow`
to return a rect the size of the full window, disabling the gesture
without causing any side effects by altering the responder chain.
2025-01-23 13:35:52 -08:00
Mitchell Hashimoto
f0c2d3d75a macos: fix retain cycle preventing window from freeing 2025-01-06 07:02:04 -08:00
Damien Mehala
ade07c4c3c fix: quick terminal focus-follows-mouse behaviour
Quick Terminal now focuses on the surface under the mouse
pointer when `focus-follows-mouse` is enabled.

Fixes #3337
2024-12-30 11:04:21 -08:00
Mitchell Hashimoto
3bf1fdd7de macos: titlebar tabs can find titlebar container in fullscreen
Fixes #2850

In native fullscreen, the titlebar container is no longer part of our
NSWindow and is instead a separate window called
NSToolbarFullScreenWindow. We now search for this window when we are in
native fullscreen.
2024-11-29 10:35:02 -08:00
Qwerasd
2852c771b1 macos: fix various titlebar tabs problems in macOS 15.0
- Toolbar overflow indicator showing
- Doubled title on single-tab windows
- Tabs not properly placed in bar on restore of saved window
2024-09-16 22:54:00 -06:00
pnodet
7ff9af1520 style(macos): cleanup trailing spaces 2024-08-21 21:53:09 +02:00
Mitchell Hashimoto
e3f299ac80 macos: relabel tabs when mergeAllWindows is called
Fixes #1902
2024-07-02 14:08:21 -07:00
Mitchell Hashimoto
c9c1bd0531 macos: titlebar tabs should do nothing if no titlebar
Fixes #1876
2024-06-25 10:03:05 -07:00
Cameron Dart
29fb70197c macos: surface focus follow mouse 2024-06-10 16:07:33 -07:00
Mitchell Hashimoto
4dde7edfab config: macos-titlebar-style, remove titlebar-tabs option
Fixes #1833

This is an attempt to simplify the logic that has organically grown
convoluted over time with regards to how the titlebar and tab bar is
styled.

This field is one unified field that ONLY addresses titlebar and tab bar
styling. It can be one of "native", "transparent", or "tabs". The
"native" field is the new behavior in this commit: it makes the titlebar
and tab bar appearance be absolutely native. We do not color anything
(if we do its a bug).

The "transparent" option is the previous `macos-titlebar-tabs = false`
setting where the titlebar/tab bar is native but colored according to
the window background color.

The "tabs" option is `macos-titlebar-tabs = true`.

The `window-theme = auto` affect on titlebar appearance has been
removed. Now, the titlebar will NEVER be styled with "native" and MAY be
styled with "transparent" and will ALWAYS be styled with "tabs" (since
that's a totally custom look anyways).
2024-06-07 12:12:48 -07:00
Mitchell Hashimoto
47874742a1 Extract guard statement 2024-05-21 08:58:10 +02:00
Troels Thomsen
6366d562ca Recognize system theme 2024-05-19 23:01:09 +02:00
Mitchell Hashimoto
eee58b9ce6 macos: titlebar styling always applies to titlebar tabs 2024-05-17 20:38:51 -04:00
Mitchell Hashimoto
69a3137956 macos: use enum for window theme 2024-05-17 16:31:18 -04:00
Pete Schaffner
c437416014 Make title/tab bar respect window-theme setting 2024-05-14 20:17:28 -04:00
Mitchell Hashimoto
7a8c2fb8a0 Merge pull request #1623 from peteschaffner/titlebar-unzoom-button
Add un-zoom button to titlebar and tabs
2024-04-12 10:23:14 -07:00
Jon Parise
c09035f228 macos: fall back to the system titlebar font
We allow titlebarFont to be nil to differentiate between "system" (nil)
and "custom" (non-nil) behavior. For the "system" case, we need to use
the system _titlebar_ font (rather than just the default system font),
to match the system's conventions.
2024-04-12 09:05:35 -07:00
Pete Schaffner
620c0f9450 Fix new tab icon color not updating sometimes 2024-04-05 21:12:11 +02:00
Pete Schaffner
b947ed0070 Update titlebar tabs when config changes 2024-04-05 16:40:04 +02:00
Pete Schaffner
4ede25dd00 Update standard title/tab bar when config changes 2024-04-05 15:19:55 +02:00
Pete Schaffner
e4066aaa85 Put titlebar font code where it was intended 2024-04-03 15:36:04 +02:00
Pete Schaffner
ab26863088 Merge remote-tracking branch 'upstream/main' into titlebar-unzoom-button 2024-04-03 15:25:51 +02:00
Pete Schaffner
a0a1c991b5 Fix conflicting constraints issue 2024-04-02 22:31:23 +02:00
Pete Schaffner
f086bff651 Make things work with really dark backgrounds
This fixes issue #1549
2024-04-02 22:28:34 +02:00
Pete Schaffner
cf6017e777 Revert "Revert "Merge pull request #1550 from peteschaffner/titlebar-unzoom-button""
This reverts commit 7f59d844c098f65158b4c5674f53371e0c4a4f1a.
2024-03-28 10:48:05 +01:00
Jon Parise
baf75dfaaf macos: configurable titlebar fonts
Add support for configurable fonts for window and tab titles. This is
only implemented for macOS (and could be macOS-only if other platforms
aren't able to support this using their windowing toolkits). It plays
nicely with regular and titlebar tabs.
2024-03-26 16:56:39 -07:00
Mitchell Hashimoto
7f59d844c0 Revert "Merge pull request #1550 from peteschaffner/titlebar-unzoom-button"
This reverts commit 6b7a1ce1eb364936b58408bd67bbeaf0d3dc8579, reversing
changes made to b68e1c6a5d17b7e7b35902873a3241ee663f49a3.
2024-03-26 14:53:26 -07:00
Pete Schaffner
21ed1187a4 Select and uzoom when clicking button in unselected tab 2024-02-26 10:03:14 +01:00
Pete Schaffner
b6bfb9dac5 Don't use a toolbar for the traditional title/tab bar
I forgot I can use a `NSTitlebarAccessoryViewController` to house the
button
2024-02-25 21:47:15 +01:00
Pete Schaffner
55621c214c Rename "Un-zoom" to "Reset Zoom" and add tooltips 2024-02-25 12:40:43 +01:00
Pete Schaffner
c189f855d8 Reorganize a bit 2024-02-24 10:29:14 +01:00
Pete Schaffner
34f5bf4fe6 Move unzoom button logic into TerminalWindow
This fixed some bugs with keeping the correct button state when
reordering tabs
2024-02-23 22:30:03 +01:00
Pete Schaffner
dc60afc261 Get unzoom button working with standard title/tab bar
To do this I forced a toolbar, so that we would have a place to put the
button when no tabs were opened. I also took the opportunity to make the
standard title/tab bar meld better with the terminal's background color,
just as we do with titlebar tabs.
2024-02-23 15:08:35 +01:00
Troels Thomsen
a874280e4b Avoid repainting new tab button for native tab bar 2024-02-16 13:57:11 -08:00
Pete Schaffner
aad302f236 Make new tab icon respond to window's key status 2024-02-11 14:24:35 +01:00
Pete Schaffner
595c1e222b Remove vibrant layer before re-adding it 2024-02-11 13:52:11 +01:00
Pete Schaffner
1bcec0d49f Make new tab button images vibrant
This makes them blend better with the background in windows with
transparency.
2024-02-11 00:55:33 +01:00
Pete Schaffner
3b6bac0121 Make special blending mode class more generic
This allows us to specify what kind of context we'd like our vibrant
layer to exist in (light or dark).
2024-02-11 00:53:18 +01:00
Mitchell Hashimoto
49cc5e2f47 Merge pull request #1483 from peteschaffner/improve-titlebar-tabs-background-color
Improve titlebar unselected tabs background color
2024-02-10 07:52:24 -08:00
Mitchell Hashimoto
0e482b8519 macos: nitpicks 2024-02-10 07:52:02 -08:00
Mitchell Hashimoto
56b453a93f macos: comment why we guard 2024-02-09 14:22:21 -08:00