This changes the way Ghostty assigns itself and subprocesses to
cgroups and how resource controls are applied.
* Ghostty itself no longer modifies it's own cgroup or moves itself
to a transient scope. To modify the main Ghostty process' resource
controls ensure that you're launching Ghostty with a systemd unit and
use the standard systemd methods for overriding and applying changes
to systemd units.
* If configured (on by default), the process used to run your command
will be moved to a transient systemd scope after it is forked from
Ghostty but before the user's command is executed. Resource controls
will be applied to the transient scope at this time. Changes to
the `linux-cgroup*` configuration entries will not alter existing
commands. If changes are made to the `linux-cgroup*` configuration
entries commands will need to be relaunched. Resource limits can also
be modified after launch outside of Ghostty using systemd tooling. The
transient scope name can be shown by running `systemctl --user whoami`
in a shell running inside Ghostty.
Fixes#2084.
Related to #6669
## Summary
- Fixes#10345 — `copy_title_to_clipboard` now copies the user-set
custom title instead of the raw terminal title
- Adds a new `copy_title` apprt action as [suggested by
@mitchellh](https://github.com/ghostty-org/ghostty/issues/10345#issuecomment-2601002974)
- Each platform (GTK + macOS) resolves the effective title (user
override → terminal title fallback) before copying to clipboard
## Changes
- **`src/apprt/action.zig`** — New `copy_title` void action
- **`include/ghostty.h`** — C ABI enum entry
- **`src/Surface.zig`** — Binding handler now dispatches apprt action
instead of inline logic
- **`src/apprt/gtk/class/surface.zig`** — `getEffectiveTitle()` helper
(returns `title_override orelse title`)
- **`src/apprt/gtk/class/application.zig`** — GTK action handler
- **`macos/.../Ghostty.App.swift`** — macOS handler using
`surfaceView.title` + `NSPasteboard`
*Note*: This PR was *AI* assisted.
When a user renames a surface via "Change Terminal Title" and then
uses copy_title_to_clipboard, the raw terminal title was copied
instead of the custom name.
This adds a new `copy_title` apprt action so each platform resolves
the effective title (user override or terminal-set) before copying
to clipboard.
Fixes#10345
This adds the ability to use two fingers on a touchpad to scroll left
or right on a Ghostty window to change tab pages. Uses the same basic
machinery as scrolling up and down the scrollback buffer. Scrolling
pages does not wrap around at the start or end of the tabs.
Refer to discussion #10000
When a tab contains only a single split, resize_split and
toggle_split_zoom actions now return false (not performed). This allows
keybindings marked with `performable: true` to pass the event through to
the terminal program.
The performable flag causes unperformed actions to be treated as if the
binding didn't exist, so the key event is sent to the terminal instead
of being consumed.
- Add isSplit() helper to SplitTree to detect single-pane vs split state
- Update GTK resizeSplit/toggleSplitZoom to return false when single
pane
- Update macOS resizeSplit/toggleSplitZoom to return Bool and check
isSplit
- Add unit test for isSplit method
# Add GSettings Support for Primary Paste
Implements support for `org.gnome.desktop.interface
gtk-enable-primary-paste` to allow users to disable middle-click paste.
Also refactors GTK Settings access into a reusable generic module.
## Changes
- **NEW**: `src/apprt/gtk/gsettings.zig` - Generic GTK Settings reader
supporting `bool` and `c_int` types, portal-aware for Flatpak/Snap
- **MODIFIED**: `src/apprt/gtk/class/surface.zig` - Reads primary paste
setting and refactors gtk-xft-dpi to use new module
## Behavior
- Setting `false` → Middle-click paste blocked
- Setting `true` or unavailable → Middle-click paste works (default)
- Uses GTK Settings API which automatically uses XDG Desktop Portal in
sandboxed environments
Note: No unit tests added as this is a thin wrapper around GTK Settings
API that's already tested indirectly through surface.zig. Happy to add
tests if desired, though they would require an active display
environment and skip on most CI systems.
The reporting of color scheme was handled asynchronously by queuing a
handler in the surface. This could lead to race conditions where the DSR
is reported after subsequent VT sequences.
Fixes#5922
Add new `selection-word-chars` config option to customize which characters
mark word boundaries during text selection operations (double-click, word
selection, etc.). Similar to zsh's WORDCHARS environment variable, but
specifies boundary characters rather than word characters.
Default boundaries: ` \t'"│`|:;,()[]{}<>$`
Users can now customize word selection behavior, such as treating
semicolons as part of words or excluding periods from boundaries:
selection-word-chars = " \t'\"│`|:,()[]{}<>$"
Changes:
- Add selection-word-chars config field with comprehensive documentation
- Modify selectWord() and selectWordBetween() to accept boundary_chars parameter
- Parse UTF-8 boundary string to u32 codepoints at runtime
- Update all call sites in Surface.zig and embedded.zig
- Update all test cases to pass boundary characters
Gtk implementation of #9945. Fixes#9948.
This adds session search to the command palette on Gtk, allowing you to jump to any surface by title or working directory. The main difference to the Mac OS implementation is that tabs do not have colors by which to search. I also have not implemented the flashing behavior when a split is focused.
The same, or as close as I could make it, behavior that was introduced for command sorting is also implemented for Gtk. Granted, as I haven't tested this new feature on Mac OS, my understanding of the behavior of it is based on the code and the screencast from the PR.
https://github.com/user-attachments/assets/d50d93a8-fe32-4d39-ba41-1f766010a293
One thing I noticed during development, which I left unsolved as I also didn't see it solved in the Mac OS implementation (though I haven't tested it), is that if you are zoomed into a split, then focusing a different split doesn't do anything. There's a configuration option that I forgot the name of, related to zoom behavior during navigation, that I would expect to be respected, but I wasn't able to get it to work, so I left it for a later iteration.
The majority of the code was generated with Claude Sonnet 4.5. Although I have reviewed and iterated on the code thoroughly, I am not experienced with Zig and I would not be surprised if there are issues that I did not notice, and would appreciate them being pointed out (and ideally explained if it's not obvious to a non-Zig developer).
Using a pointer for this is a bit icky. Once Ghostty adds unique ids to
surfaces, we can sort by that id instead. This can potentially also be
used to navigate to the surface instead of having the command palette
reference the surfaces directly.
When a tab contains only a single split, resize_split and toggle_split_zoom
actions now return false (not performed). This allows keybindings marked with
`performable: true` to pass the event through to the terminal program.
The performable flag causes unperformed actions to be treated as if the
binding didn't exist, so the key event is sent to the terminal instead of
being consumed.
- Add isSplit() helper to SplitTree to detect single-pane vs split state
- Update GTK resizeSplit/toggleSplitZoom to return false when single pane
- Update macOS resizeSplit/toggleSplitZoom to return Bool and check isSplit
- Add unit test for isSplit method
The reporting of color scheme was handled asynchronously by queuing a
handler in the surface. This could lead to race conditions where the
DSR is reported after subsequent VT sequences.
Fixes#5922
Adds the `selection_for_search` action, with Cmd+E keybind by default.
This action inputs the currently selected text into the search
field without changing focus, matching standard macOS behavior.