Fixes#1052
This implements a `close_all_windows` binding in the core and implements
it for macOS specifically. This will ask for close confirmation if any
surface in any of the windows requires confirmation.
This is bound by default to option+shift+command+w to match Safari. The
binding is generall option+command+w but users may expect this to also
mean "Close All Other Tabs" which is the changed behavior if any tabs
are present in a standard macOS application. So I chose to follow Safari
instead.
This doesn't implement this feature for GTK, that's left as an exercise
for a contributor.
Fixes#1052
This implements the about window as a custom window with a view
controller. This lets us implement the proper responder chain so that
our custom close window IBActions do the right thing.
This has an additional benefit that we can easily customize this window
going forward.
This menu got list in #215 and with it we lost the ability to use the
macOS emoji picker via the `Cmd+Ctrl Space` shortcut, for example.
This adds a standard Edit menu back to the main menu.
This adds support for what's commonly referred to as "non-native
fullscreen": a fullscreen-mode that doesn't use macOS' native fullscreen
mechanism and thus doesn't use animations and a separate space on which
to display the fullscreen window. Instead it's really fast and it allows
the user to `Cmd+tab` to other windows, with the fullscreen-ed window
staying in the background.
Another name for it is "traditional fullscreen" since it was the default
pre Mac OS X Lion, if I remember correctly.
Other applications that offer macOS non-native fullscreen:
- Kitty: https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.macos_traditional_fullscreen
- wezterm: https://wezfurlong.org/wezterm/config/lua/config/native_macos_fullscreen_mode.html
- MacVim
- IINA: fc66b27d50/iina/MainWindowController.swift (L1401-L1423)
- mpv: https://mpv.io/manual/stable/#options-native-fs
- iTerm2
Adding this wasn't straightforward, as it turned out. Mainly because
SwiftUI's app lifecycle management doesn't allow one to use a custom
class for the windows it creates. And without custom classes we'd always
get a warning when entering/leaving fullscreen mode.
So what I did here is the following:
- remove SwiftUI app lifecycle management
- introduce `MainMenu.xib` to define the main menu via interface builder
- add `GhosttyAppController` to handle requests from the app
- add a `main.swift` file to boot up the app without a storyboard and
without SwiftUI lifecycle management
- introduce the `FullScreenHandler` to manage non-native fullscreen -
this is where the "magic" is
But since removing the SwiftUI lifecycle management also means removing
the top-level `App` that means I had to introduce the menu (which I
mentioned), but also tab and window management.
So I also added the `WindowService` which manages open tabs and windows.
It's based on the ideas presented in
https://christiantietze.de/posts/2019/07/nswindow-tabbing-multiple-nswindowcontroller/
and essentially keeps tracks of windows.
Then there's some auxilliary changes: `CustomWindow` and `WindowController` and so on.
Now everything still works, in addition to non-native fullscreen:
* opening/closing of tabs
* opening/closing of windows
* splits
* `gotoTab`
Worthy of note: when toggling back from non-native fullscreen to
non-fullscreen I had to manually implement the logic to re-add the
window back to a tabgroup. The only other app that supports tabs with
non-native FS is iTerm2 and they have implemented their own tab
management to keep the tab bar even in non-native FS -- that's a bit too
much for me. Every other app has non-native apps and doesn't have to
wory about it.