Fixes#8785
This is the callback AppKit sends when it wants to know if our
application can handle sending and receiving certain types of data.
The prior implementaiton was incorrect and would erroneously claim
support over combinations that we couldn't handle (at least, at the
SurfaceView layer).
This corrects the implementation. The services we expect still show up
and the error in 8785 goes away.
This has no meaningful functionality yet, it was one of the paths I was
looking at for #8505 but didn't pursue further. But I still think that
this makes more sense in general for the macOS app and will likely be
more useful later.
Fixes#2473
This commit changes `ghostty_surface_ime_point` to return a full rect
with the width/height calculated for the preedit.
The `firstRect` function, which calls `ghostty_surface_ime_point` was
previously setting the width/height to zero. macOS didn't like this. We
then changed it to just hardcode it to width/height of one cell. This
worked but made it so the IME cursor didn't follow the preedit.
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).
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
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.
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.
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).
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).
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.
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.
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.
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.
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).