Commit Graph

1866 Commits

Author SHA1 Message Date
Jeffrey C. Ollie
2c62d182ce gtk: fix context menu hiding quick-terminal (#12843)
Fixes #12783 where opening the context menu (with right click) inside
the quick-terminal will hide the quick-terminal if autohide is enabled.

The cause of this issue is the quick-terminal window becoming inactive
and immediately active again when you open the context-menu. When the
window becomes inactive, the autohide feature hides the quick-terminal.
The temporary focus loss in GTK is triggered by GDK focus change events,
which probably originate from the windowing backend treating the context
menu as its own window. Whereas in GTK the context menu is not a
separate window but instead part of the widget tree of the window it was
opened from, so even when the context menu has focus that window is
still the active one in GTK.

As a fix `Window.propIsActive`, which implements the autohide logic,
will now do its work from a timeout callback, since there is probably no
reliable way to distinguish a temporary focus loss from a real one from
inside GTK and I'm not sure we can make any assumptions about the timing
of things happening in the windowing backend. A 100ms delay should be
long enough for the focus state to settle while still hiding the
quick-terminal quickly.

I reproduced the bug and verified the fix on Wayland with both Hyprland
and KDE. Temporary focus loss happens on X11+KDE as well, although it
doesn't matter there because there is no quick-terminal.

### AI Disclosure

No AI was used, code and comments were written by myself.
2026-05-29 22:44:30 -05:00
Daniel Kinzler
ff963f3119 Renamed timeout source and callback function. Added comment explaining timeout delay. 2026-05-29 17:40:25 +02:00
Daniel Kinzler
1753d57bfd remove timeout source when window is disposed 2026-05-28 15:08:12 +02:00
Daniel Kinzler
37997f8dbe Use a timeout callback to wait for changes in window active state to settle. Depending on the backend a window might temporarily become inactive.
Fixes an issue where quick-terminal would disappear when opening the surface context menu.
2026-05-26 18:26:17 +02:00
Nikolay Bryskin
0708f932a5 apprt/gtk: add regression test for audio-bell MediaFile reuse
Guards the contract that prevents the bell thread leak: bellMediaFile
must return the same cached MediaFile for an unchanged path and only
rebuild when the path changes. A revert to per-bell allocation (the
leak) would fail this. Runs in the existing test-gtk CI job; needs no
display or playback since the path bookkeeping is all that's asserted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 23:43:04 +03:00
Nikolay Bryskin
0b6d91e531 apprt/gtk: reuse one audio-bell MediaFile per surface to fix thread leak
Each audio bell called gtk.MediaFile.newForFilename, which spins up a
full GStreamer pipeline. The GTK4 GStreamer backend's GL sink starts
gstglcontext/gldisplay-event threads that are never joined on teardown,
so allocating a MediaFile per ring leaked a pipeline and ~4 threads on
every bell. A long-running instance accumulated 705 threads over ~4h of
normal use.

Cache one MediaFile per surface (priv.bell_media), rebuilt only when
bell-audio-path changes and unref'd on dispose. Each bell now replays
the same pipeline via seek(0)+play() instead of creating a new one. The
notify::ended -> unref handler is removed: it was what discarded (and
leaked) a pipeline per ring. seek(0) is required so an ended stream
plays again (#8957).

Verified on a real instance: GStreamer's global element counter reached
only oggdemux4 over an hour of use (one pipeline per bell-ringing
surface, reused) and thread count stayed flat, versus per-bell growth
before.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 23:43:01 +03:00
Mike Bommarito
88d30bb30a gtk: wire occlusionCallback to GLArea map/unmap
Calls core_surface.occlusionCallback(visible) from the existing
glareaMap/glareaUnmap handlers (added in #12698) so the renderer
thread learns when a surface is off-screen.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 22:50:03 -04:00
Jeffrey C. Ollie
4b7bf0b20e IPC: add +toggle-quick-terminal command (#12661)
Add `+toggle-quick-terminal` as a first-class IPC action, following the
same pattern as `+new-window`. This provides a proper CLI command
(`ghostty +toggle-quick-terminal`) to toggle the quick terminal on a
running Ghostty instance.

Closes discussion #12618
2026-05-17 21:03:09 -05:00
Daniel Kinzler
9f72eb9d7c added back accidentally deleted empty line 2026-05-15 17:52:48 +02:00
Daniel Kinzler
93d1142ada small formatting changes 2026-05-15 17:20:57 +02:00
Daniel Kinzler
54a38e8134 Distinguish resize and manual update using a combination of
max-position and position properties. Listening to drag events directly
did not work that well.
2026-05-14 15:45:29 +02:00
Daniel Kinzler
e59e27f8bd Fix nested splits disappearing and focus being lost.
The cause of these bugs is that GTK can initially allocate
a split/surface a width/height of 0 which causes it to
get unmapped and lose focus. Additionally the split ratio is
only set once but not accurately for tiny splits, which can keep
a surface invisible even when the split gets resized later.

To fix these problems the split ratio is always checked and
possibly corrected when a split gets resized. Changes in a split
ratio caused by the user dragging the divider are detected
separately using an event controller. If a surface loses focus
we restore it once the surface becomes mapped again.
2026-05-12 14:13:35 +02:00
Hua Jiang
81af65766f feat: add +toggle-quick-terminal IPC command
Expose toggle-quick-terminal as a proper IPC action so it can be
triggered via 'ghostty +toggle-quick-terminal' from the command line,
instead of calling the raw D-Bus org.gtk.Actions.Activate interface.

This follows the same pattern as the existing +new-window IPC command:

  - Add toggle_quick_terminal to apprt.ipc.Action enum (Zig + C ABI)
  - Create apprt/gtk/ipc/toggle_quick_terminal.zig (GTK D-Bus handler)
  - Route .toggle_quick_terminal in apprt/gtk/App.zig performIpc
  - Register toggle-quick-terminal GAction in application.zig
  - Add +toggle-quick-terminal CLI handler in cli/
  - Register in cli/ghostty.zig Action enum, runMain, and options
  - Add stub in apprt/embedded.zig
  - Update include/ghostty.h C header enum

Usage:
  ghostty +toggle-quick-terminal

Closes: #12618
2026-05-12 09:03:14 +08:00
Mitchell Hashimoto
0b56ae2cc7 gtk: fix quick terminal breaking when manually toggled off while auto-hide is enabled (#12471)
Fixes quick terminal breaking when auto-hide is enabled and quick
terminal is manually toggled off (#11679).

`quick-terminal-autohide` is implemented by the `Window.propIsActive`
function in `apprt/gtk/class/window.zig` which calls
`Window.toggleVisibility` when the quick terminal window becomes
inactive (loses focus). However `Window.propIsActive` is also triggered
when you manually hide the quick terminal because hiding it causes the
window to become inactive. Normally that should just toggle the quick
terminal off and immediately back on, but there is also a re-entrancy
issue. Manually toggling off the terminal causes the
`Application.toggleQuickTerminal` (in `apprt/gtk/class/application.zig`)
to run which sets off the call chain `Window.toggleVisibility ->
gtk_widget_set_visible -> ... GTK signal/event handling ... ->
Window.propIsActive -> Window.toggleVisibility ->
gtk_widget_set_visible`.
The nested calls to `gtk_widget_set_visible` cause the GTK window state
to become corrupted. The window is marked visible, but is not actually
visible or just shows a placeholder. What exactly happens depends on the
compositor and how it handles moving window focus.

Reproduced the bug on KDE and hyprland and verified the fix on both.

### Changes

`apprt/gtk/class/window.zig`: added check to `Window.propIsActive` to
only toggle quick-terminal if it is inactive **and** visible.

### AI Disclosure

Found the bug without AI using "printf debugging" then traced it through
GTK with valgrind. Used GPT5.4 in setting up valgrind and researching
how signals/events move through GTK internally.
2026-04-27 09:26:24 -07:00
Mitchell Hashimoto
8e2a13cb60 gtk/SurfaceScrolledWindow: wrap root child with another Adw.Bin (#12426)
Due to a known Gtk issue, the scrolled_window at the root of the
template is free-ed twice on dispose. This causes crashes when used with
GNOME 49 platform (Gtk 4.20, libadwaita 1.8.5).

Workaround this issue by wrapping the root child in another Adw.Bin,
similar to widgets like ResizeOverlay.

LLM was used to perform discovery against a manually recorded Valgrind
trace, and helped tracking down known fixes for this problem. The
comment in code was taken from another instance in the repository.

Fixes https://github.com/ghostty-org/ghostty/discussions/12306

Assisted-by: OpenAI GPT-5.4
2026-04-25 09:22:59 -07:00
Leorize
560b7ba8e8 gtk/SurfaceScrolledWindow: wrap root child with another Adw.Bin
Due to a known Gtk issue, the scrolled_window at the root of the
template is free-ed twice on dispose. This causes crashes when used with
GNOME 49 platform (Gtk 4.20, libadwaita 1.8.5).

Workaround this issue by wrapping the root child in another Adw.Bin,
similar to widgets like ResizeOverlay.

LLM was used to perform discovery against a manually recorded Valgrind
trace, and helped tracking down known fixes for this problem.

Fixes https://github.com/ghostty-org/ghostty/discussions/12306

Assisted-by: OpenAI GPT-5.4
2026-04-25 09:18:21 -07:00
Lukas
7c91cef28d config: use Config to check key binding instead of App
Previously `ghostty_app_key_is_binding` (unlike Surface) is just using `config.keybind` to check whether a KeyEvent is in the set or not.

After this, I can add unit tests for keybinding more easily, with dummy configs.
2026-04-24 18:26:56 +02:00
Christo Wilken
9a9002202b macos: add pid and tty properties to AppleScript terminal class
Expose the foreground process PID and TTY device path as read-only properties on the AppleScript terminal class and App Intents TerminalEntity. This enables reliable process-to-terminal mapping for automation tools when multiple terminals share the same CWD.

Closes #11592
Closes #10756

Session: 019d341c-a165-7843-a2f7-2f426114cf17
2026-04-20 15:16:03 +02:00
Daniel Kinzler
2648668da9 fix quick-terminal breaking when it is manually toggled while autohide is enabled 2026-04-13 19:01:56 +02:00
Lukas
c8702ece8f gtk(chore): fix typos
### AI Disclosure

Claude wrote the regex to ignore base64-encoded sequences
2026-04-01 13:08:55 +02:00
Jeffrey C. Ollie
c2dd7579e2 core/gtk: ensure that first surface gets marked as focused surface by app (#12029) 2026-03-31 15:29:18 -05:00
Jeffrey C. Ollie
4b5f2d60e7 core/gtk: ensure that first surface gets marked as focused surface by app 2026-03-31 14:57:41 -05:00
Jeffrey C. Ollie
dee8598dc0 gtk: use surface id for notifications instead of pointer 2026-03-31 14:53:19 -05:00
Mitchell Hashimoto
4803d58bb4 apprt/embedded: fix ghostty_surface_free_text parameter mismatch
Fixes #12020

The C header declared ghostty_surface_free_text with both a
ghostty_surface_t and ghostty_text_s* parameter, but the Zig
implementation only accepted a *Text parameter. This caused the
surface pointer to be interpreted as the text pointer, so the
actual text allocation was never freed.
2026-03-31 09:46:35 -07:00
Jeffrey C. Ollie
af36959942 gtk: only trigger resize callbacks and overlay when size actually changes
Fixes #11970

Also fixes problem that resize overlay would intercept mouse activity
while active.
2026-03-29 23:38:34 -05:00
Michael Stevens
c0a124f3ca gtk: disable kinetic scrolling for trackpads until 4.20.1
Until gtk 4.20.1 trackpads have kinetic scrolling behavior regardless
of `Gtk.ScrolledWindow.kinetic_scrolling`. As a workaround, set
EventControllerScroll.kinetic to false on all controllers.

`observeControllers()` has this warning:
> Calling this function will enable extra internal bookkeeping to track controllers and emit signals on the returned listmodel. It may slow down operations a lot.
> Applications should try hard to avoid calling this function because of the slowdowns.

but judging from the [source](5301a91f1c/gtk/gtkwidget.c (L12375-L12383))
this is a one time penalty since we free the result immediately afterwards.

Fixes https://github.com/ghostty-org/ghostty/discussions/11460
2026-03-28 17:36:17 -04:00
Timon de Groot
8bc75907b5 gtk: Fix casing for openUri 2026-03-23 07:29:36 +01:00
Timon de Groot
919e586c51 gtk/portal: Improve OpenURI lifecycle 2026-03-22 21:10:46 +01:00
Timon de Groot
37d297c03c gtk/portal: General improvements
- Token is formatted without allocation
- Reusable function for formatToken
- Tests in portal.zig are actuall included now
2026-03-22 21:09:38 +01:00
Timon de Groot
855a6b01fc gtk: Open urls with openuri portal 2026-03-22 18:17:09 +01:00
Leah Amelia Chen
27fd1c7788 gtk/winproto: fix memleak & other tweaks 2026-03-18 03:37:03 +08:00
Leah Amelia Chen
80ab5d92ea gtk/x11: use BlurRegion 2026-03-18 03:07:58 +08:00
Leah Amelia Chen
5abf21c1e2 gtk/wayland: complete blur region calculation
It took me a while and with lots of trial and error to arrive here,
but the end result looks pretty good.
2026-03-18 03:07:58 +08:00
Leah Amelia Chen
9e2e99c55f gtk/wayland: replace KDE blur with ext-background-effect-v1
The venerable KDE blur protocol has been replaced with the compositor-
agnostic ext-background-effect-v1 protocol, to be implemented by Niri and
others. The new protocol is much easier to use overall, though we do need
to calculate the blur region manually like X11.
2026-03-18 03:07:46 +08:00
Jeffrey C. Ollie
79162279d9 gtk: move audio playback into separate file, enabling reuse 2026-03-16 19:53:24 -05:00
Jeffrey C. Ollie
8a40e37b86 gtk: refactor application id and resource path 2026-03-16 18:26:37 -05:00
Leah Amelia Chen
2318e18df3 gtk/wayland: refactor global handling (#11559) 2026-03-16 18:06:37 +00:00
Leah Amelia Chen
8966d37985 gtk/wayland: refactor global handling
The way we originally handled globals gradually escalated into an unholy
mess of ad-hoc helper functions and special-case handlers, which proved
to be hard to scale. Using a type-erased EnumMap like this makes
everything *far* easier to work and reason with, I think.

Also nuked the `xdg_wm_dialog_v1` hack that was necessary to prevent
old versions of gtk4-layer-shell crashing. If by the time of 1.4's
release people are still using those versions, it's on them.
2026-03-17 01:14:59 +08:00
Mitchell Hashimoto
a811b6074b Lots of duplicate word typos + typo (#11539)
TL;DR: this description is (intentionally) nonsense but I ran
`\b(\w+)\s\1\b` over `src` and stole a singular typo fix from #11528.

Replacement of #11528 with 100% less slop and 99% less AI; I didn't feel
like saying no to free(ish) typo checking. Note that many of the fixes
there were outright incorrect (and clearly had no review from sentient
lifeforms, contrary to its—sorry, it's—description). A lot of extra
double words were caught with a handy `rg --pcre2 '\b(\w+)\s+\1\b' src`;
you could say this PR was “ripgrep-assisted” the way that one was
“AI-assisted”. Rather ironic since that PR also claims to have used grep
via Claude Code, but missed a lot of them.

The its → it's changes from that PR were elided; I decided to run a `rg
"\bit'?s\b" src`, but someone REALLY likes their its, so I reverted my
changes as there were an extremely large number of changes (probably a
hundred files with multiple hundred cases). The only other change was
“baout” → “about”.

# AI Usage

Claude Code was used by proxy for finding baout. Claude Code was used by
proxy for realizing that the correct spelling is about. Claude Code was
not used for fixing it. Oh my god it was so difficult to fix, the
original PR had it so easy. I had to type out the file name (fish's AI
sorry I mean autocomplete helped though) and like, type /baout, press R,
press ab, then save and exit. This is so difficult you know we should
use an AI for this, like this is so hard I don't know how people manage.

All changes were verified by me: I consulted the dictionary to delve
into double-checkment of “in existence; being in evidence; apparent.”
Uhhh insert assorted other AI impersonation here maybe? THE LLM IN ME
WANTS TO ESCAPE PLEASE HELP
2026-03-16 09:52:35 -07:00
Leah Amelia Chen
600f59ae31 gtk: implement quick-terminal-screen for Linux/Wayland (#11117) 2026-03-16 06:30:02 +00:00
Kat
6fabf775bb Lots of duplicate word typos + typo. 2026-03-16 09:19:09 +11:00
Mitchell Hashimoto
ab269e2c79 config: add progress-style option (#11289)
Adds progress-style config to control OSC 9;4 progress bar visibility.
Defaults to true, set false to hide.

Fixes #11241

AI Disclosure: Claude Code (Opus 4.6) used for codebase exploration,
code review, and testing assistance. All code written and reviewed by
hand.
2026-03-11 20:46:59 -07:00
Michal Olechowski
84d48d1c6a config: add progress-style option
Add option to disable OSC 9;4 ConEmu progress bars via config.

Fixes #11241
2026-03-12 01:33:25 +01:00
Mitchell Hashimoto
86c2a2e87f input: add direct set_surface_title and set_tab_title actions
Fixes #11316

This mirrors the `prompt` actions (hence why there is no window action
here) and enables setting titles via keybind actions which importantly
lets this work via command palettes, App Intents, AppleScript, etc.
2026-03-11 09:25:08 -07:00
Mitchell Hashimoto
04d5efc8eb config: working-directory expands ~/ prefix
Fixes #11336

Introduce a proper WorkingDirectory tagged union type with home, inherit,
and path variants. The field is now an optional (?WorkingDirectory) where
null represents "use platform default" which is resolved during Config.finalize
to .inherit (CLI) or .home (desktop launcher).
2026-03-10 14:33:40 -07:00
Mitchell Hashimoto
aaad43c235 macos: make paste_from_clipboard performable on macos
Fixes #10751
2026-03-10 10:25:14 -07:00
rhodes-b
1d59f5dbcd pass search active state through blueprint 2026-03-08 15:57:28 -05:00
rhodes-b
8635fef7a5 if search is active dont apply unfocused options 2026-03-08 00:24:46 -06:00
Jeffrey C. Ollie
c920a88cdc GTK: add 'move' to the drop target actions
Fixes #11175
2026-03-04 23:31:41 -06:00
Mitchell Hashimoto
46522a8779 gtk: +new-window now respects --working-directory and -e (#10809)
Fixes: #8862
Fixes: #10716

This adds the machinery to pass configuration settings received over
DBus down to the GObject Surface so that that configuration information
can be used to override some settings from the current "live" config
when creating a new window. Currently it's only possible to override
`--working-directory`, `--command`, and `--title`. `-e` on the `ghostty
+new-window` CLI works as well.

Adding more overridable settings is possible, but being able to fully
override any possible setting would better be served with a major revamp
of how Ghostty handles configs, which is way out of scope at the moment.
2026-03-04 15:09:58 -08:00