1250 Commits

Author SHA1 Message Date
Mitchell Hashimoto
240c9b8afc gtk: add option to always display the tab bar (#5590)
Also fixes crashes in both vanilla GTK and Adwaita implementations of
`closeTab`, which erroneously close windows twice when there are no more
tabs left (we probably already handle it somewhere else).
2025-06-27 09:14:13 -07:00
Mitchell Hashimoto
83690744b2 reintroduce App.create 2025-06-27 09:12:20 -07:00
Jeffrey C. Ollie
1979fb92f4 embedded: fix core app init 2025-06-27 09:05:32 -07:00
Jeffrey C. Ollie
c6f23bbb32 core: con't copy App and apprt.App
Besides avoiding copying, this allows consumers to choose to allocate
these structs on the stack or to allocate on the heap. It also gives the
apprt.App a stable pointer sooner in the process.
2025-06-27 09:05:32 -07:00
Jeffrey C. Ollie
81403f59ce dbus and systemd activation - take 2
This replaces #7433. The improvements are:

1) Install the systemd user service in the proper directory depending
on if it's a 'user' install or a 'system' install. This is controlled
either by using the `--system` build flag (as most packages will) or by
the `-Dsystem-package` flag.

2) Add the absolute path to the `ghostty` binary in the application
file, the DBus service, and the systemd user service. This is done so
that they do not depend on `ghostty` being in the `PATH` of whatever
is launching Ghostty. That `PATH` is not necessarily the same as the
`PATH` in a user shell (especially for DBus activation and systemd user
services).

3) Adjust the DBus bus name that is expected by the system depending on
the optimization level that Ghostty is compiled with.
2025-06-26 10:28:46 -07:00
Mitchell Hashimoto
a8091fedf3 fix tests 2025-06-25 16:28:31 -04:00
Leah Amelia Chen
dbe6035da0 config: add command-palette-entry config option 2025-06-25 16:18:20 -04:00
Leah Amelia Chen
d419e5c922 gtk(command_palette): filter out more unimplemented actions 2025-06-25 16:18:20 -04:00
Leah Amelia Chen
832f27596c gtk(command_palette): grab focus correctly 2025-06-25 16:18:20 -04:00
Mitchell Hashimoto
f941a2185e Revert "linux: add dbus and systemd activation services (#7433)"
Reverts two commits:

977cd530c7bb9551de93900170bdaec4601b1b5b
820b7e432b57cd08c49d2e76cce4cb78016f0418

These break build from source on Linux for two reasons:

1.) The systemd user service needs to be installed in the `share`
prefix, not the `lib` prefix. This lets it get picked up in `~/.local`
but is also correct for just standard FHS paths.

2.) The `ghostty` path in the systemd user service needs to be absolute.
We should interpolate in the build install prefix to form an absolute
path.
2025-06-24 22:07:09 -04:00
Mitchell Hashimoto
977cd530c7 linux: add dbus and systemd activation services (#7433) 2025-06-24 18:14:24 -04:00
Leorize
faf9d59160 core, apprt: make runtimes implement resourcesDir directly 2025-06-24 07:36:09 -04:00
Leorize
1688f2576c core, gtk: implement host resources dir for Flatpak
Introduces host resources directory as a new concept: A directory
containing application resources that can only be accessed from the host
operating system. This is significant for sandboxed application runtimes
like Flatpak where shells spawned on the host should have access to
application resources to enable integrations.

Alongside this, apprt is now allowed to override the resources lookup
logic.
2025-06-24 07:35:28 -04: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
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
-k
43b8472ad2 style: fix formatting 2025-06-21 14:11:50 -07:00
-k
e09657e263 Add FreeBSD support
Following 7aeadb06ee
2025-06-21 14:11:50 -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
5259d0fa55 macos: starting to work on new libghostty data models 2025-06-21 06:39:19 -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
e1ee180172 apprt/embedded: API to read text can get top left/bottom right coords 2025-06-15 13:06:38 -07:00
Mitchell Hashimoto
c5f921bb06 apprt/embedded: improve text reading APIs (selection, random points) 2025-06-15 07:59:19 -07:00
Jeffrey C. Ollie
649cca61eb gtk: use exhaustive switch for initial-window 2025-06-13 10:22:16 -05:00
Jeffrey C. Ollie
8824d11e1c linux: add dbus and systemd activation services 2025-06-13 10:22:12 -05:00
Mitchell Hashimoto
804d270ba1 macOS: Undo/Redo for changes to windows, tabs, and splits (#7535)
This PR implements the ability to undo/redo new and closed windows,
tabs, and splits.

## Demo


https://github.com/user-attachments/assets/98601810-71b8-4adb-bfa4-bdfaa2526dc6

## Details

### Undo Timeout

Running terminal sessions _remain running_ for a configurable period of
time after close, during which time they're undoable. This is similar to
"email unsend" (since email in the traditional sense can't be unsent,
clients simply hold onto it for a period of time before sending).

This behavior is not unique to Ghostty. The first and only place I've
seen it is in iTerm2. And iTerm2 behaves similarly, although details of
our behavior and our implementation vary greatly.

The configurable period of time is done via the `undo-timeout`
configuration. The default value is 5 seconds. This feels reasonable to
be and is grounded in being the default for iTerm2 as well, so it's
probably a safe choice.

Undo can be disabled by setting `undo-timeout = 0`. 

### Future

The actions that can be potentially undone/redone can be easily expanded
in the future. Some thoughts on things that make sense to me:

- Any sort of split resizing, including equalization
- Moving tabs or splits

#### What about Linux?

I'd love to support this on Linux. I don't think any other terminal on
Linux has this kind of feature (definitely might be wrong, but I've
never seen it and I've looked at a lot of terminal emulators 😄 ). But
there's some work to be done to get there.

## TODO for the Draft PR

This is still a draft. There are some items remaining (list will update
as I go):

- [x] Undoing a closed window is sometimes buggy still and I'm not sure
why, I have to dig into this.
- [x] New window should be undoable
- [x] New tab should be undoable
- [x] Close All Windows should be undoable
- [x] I think I have to get rid of TerminalManager. Undone windows won't
be in TerminalManager's list of controllers and I think that's going to
break a lot of things.
- [x] I haven't tested this with QuickTerminal at all. I expect bugs
there but I want undo to work with splits there.
- [x] Close window with the red traffic light button doesn't trigger
undo
- [x] Closing window with multiple tabs undoes them as separate windows
2025-06-08 12:54:55 -07:00
Mitchell Hashimoto
6e77a5a6ca macos: address quick terminal basic functionality with new API 2025-06-07 13:07:31 -07:00
Mitchell Hashimoto
966c4f98c7 apprt/glfw,gtk: noop undo/redo actions 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
Leorize
ea0766e62b gtk/CommandPalette: prevent leaks on initialization
* Deallocate the builder after use
* Don't hold a reference to `Command` after appending to `GListStore`
2025-06-07 12:00:51 -05:00
Mitchell Hashimoto
5edf0dffda gtk/TabView: do not closeTab within close-page signal handler (#7515)
`TabView` assumes to be the sole owner of all `Tab`s within a Window. As
such, it could close the managed `Window` once all tabs are removed from
its widget.

However, during `AdwTabView::close-page` signal triggered by libadwaita,
the `Tab` to be closed will gain an another reference for the duration
of the signal, breaking `TabView.closeTab` (called via
`Tab.closeWithConfirmation`) assumptions that having no tabs meant they
are all destroyed.

This commit solves the issue by scheduling `Tab.closeWithConfirmation`
to be run after `AdwTabView::close-page` signal has finished processing.

Fixes #7426
2025-06-05 07:36:10 -07:00
Mitchell Hashimoto
2e0a23aa77 gtk: make requesting attention configurable (#7521)
Partially fixes #7520
2025-06-05 07:29:17 -07:00
Leah Amelia Chen
77479feee6 gtk: make requesting attention configurable 2025-06-05 00:29:49 +02:00
Leorize
4e39144d39 gtk/TabView: do not closeTab within close-page signal handler
`TabView` assumes to be the sole owner of all `Tab`s within a Window.
As such, it could close the managed `Window` once all tabs are removed
from its widget.

However, during `AdwTabView::close-page` signal triggered by libadwaita,
the `Tab` to be closed will gain an another reference for the duration
of the signal, breaking `TabView.closeTab` (called via
`Tab.closeWithConfirmation`) assumptions that having no tabs meant they
are all destroyed.

This commit solves the issue by scheduling `Tab.closeWithConfirmation`
to be run after `AdwTabView::close-page` signal has finished processing.
2025-06-03 03:19:13 -05:00
Leorize
58cece07f0 gtk/GlobalShortcuts: don't request session with no shortcuts
There aren't any reason to pay the D-Bus tax if you don't use global
shortcuts.
2025-06-02 20:55:04 -05:00
Mitchell Hashimoto
5306e7cf56 config: add launched-from to specify launch source
Related to #7433

This extracts our "launched from desktop" logic into a config option.
The default value is detection using the same logic as before, but now
this can be overridden by the user.

This also adds the systemd and dbus activation sources from #7433.

There are a number of reasons why we decided to do this:

  1. It automatically gets us caching since the configuration is only
     loaded once (per reload, a rare occurrence).

  2. It allows us to override the logic when testing. Previously, we
     had to do more complex environment faking to get the same
     behavior.

  3. It forces exhaustive switches in any desktop handling code, which
     will make it easier to ensure valid behaviors if we introduce new
     launch sources (as we are in #7433).

  4. It lowers code complexity since callsites don't need to have N
     `launchedFromX()` checks and can use a single value.
2025-06-02 08:45:02 -07:00
Leah Amelia Chen
1ff9162598 gtk(wayland,x11): refactors (#7485) 2025-05-31 08:17:11 +02:00
Mitchell Hashimoto
2b9e781933 gtk: clean up per-surface cgroup on close
Fixes #6766

This ensures that during surface deinit the cgroup is removed. By the
time the surface is deinitialized, the subprocess should already be
dead so the cgroup can be safely removed. If the cgroup cannot be
removed for any reason we log a warning.
2025-05-30 19:31:04 -07:00
Leah Amelia Chen
f99c988b27 gtk(wayland): automatically bind globals 2025-05-30 23:42:48 +02:00
Leah Amelia Chen
9ded668819 gtk(wayland,x11): remove even more redundant checks 2025-05-30 23:42:42 +02:00
Leah Amelia Chen
157f50e2de gtk: request user attention on bell (#7482)
I'm not sure if this should be enabled by default like the tab
animation, but on KDE at least this is unintrusive enough for me to
always enable by default. Alacritty appears to agree with me as well.

Fixes #7124
2025-05-30 23:33:12 +02:00
Leah Amelia Chen
bdcbb9fd42 gtk(wayland): customize keyboard interactivity for quick terminal (#7477)
Fixes #7476
2025-05-30 22:50:56 +02:00
Leah Amelia Chen
90f431005b gtk: request user attention on bell
I'm not sure if this should be enabled by default like the tab
animation, but on KDE at least this is unintrusive enough for me to
always enable by default. Alacritty appears to agree with me as well.
2025-05-30 22:43:07 +02:00
Mitchell Hashimoto
2ad86cde69 OSC: allow multiple set/reset/report operations per OSC (#7429) 2025-05-30 13:16:57 -07:00
Leah Amelia Chen
6959fa8438 gtk(wayland): explicitly set layer name
Even though gtk4-layer-shell's documentation claims that "nobody quite
knows what it's for", some compositors (like Niri) can define custom
rules based on the layer name and it's beneficial in those cases to
define a distinct name just for our quick terminals.
2025-05-30 19:26:18 +02:00
Leah Amelia Chen
dee7c835de gtk(wayland): remove redundant check 2025-05-30 19:26:18 +02:00
Leah Amelia Chen
71a1ece7e9 gtk(wayland): gtk4-layer-shell -> layer-shell
It was getting a bit too unwieldy.
2025-05-30 19:26:18 +02:00
Leah Amelia Chen
6fac355363 gtk(wayland): fallback when on-demand mode isn't supported
This shouldn't be a real problem anymore since as of now (May 2025)
all major compositors support at least version 4, but let's do this
just in case.
2025-05-30 19:26:18 +02:00
Leah Amelia Chen
4d18c06804 gtk(wayland): customize keyboard interactivity for quick terminal
Fixes #7476
2025-05-30 19:26:11 +02:00
Jeffrey C. Ollie
d3cb6d0d41 GTK: add action to show the GTK inspector
The default keybinds for showing the GTK inspector (`ctrl+shift+i` and
`ctrl+shift+d`) don't work reliably in Ghostty due to the way Ghostty
handles input. You can show the GTK inspector by setting the environment
variable `GTK_DEBUG` to `interactive` before starting Ghostty but that's
not always convenient.

This adds a keybind action that will show the GTK inspector. Due to
API limitations toggling the GTK inspector using the keybind action is
impractical because GTK does not provide a convenient API to determine
if the GTK inspector is already showing. Thus we limit ourselves to
strictly showing the GTK inspector. To close the GTK inspector the user
must click the close button on the GTK inspector window. If the GTK
inspector window is already visible but is hidden, calling the keybind
action will not bring the GTK inspector window to the front.
2025-05-29 16:07:57 -05:00
Jeffrey C. Ollie
bcf4d55dad OSC: nest ColorOperation-related structs 2025-05-29 11:37:08 -05:00