Commit Graph

1898 Commits

Author SHA1 Message Date
Mitchell Hashimoto
77537c8065 macos: handled untrusted OSC8 hyperlinks more carefully
OSC8 hyperlinks previously executed directly via the NSWorkspace opener
so a malicious application can just do whatever it wanted and trick the
user into opening something through Launch Services.

This PR notifies apprt of OSC8 hyperlinks so they can be handled
specially. In this PR, I added macOS-specific handling of OSC8 through a
variety of improvements:

  - Preview text is sanitized, so invisible Unicode characters now show.
  - Questionable-looking URLs require confirmation to open, but a user
    can confirm to open.
  - Very questionable or definitely unsafe URLs are blocked with an 
    alert that only allows the user to copy the link. The alert also
    notifies the user why.
2026-08-05 10:22:28 -07:00
Leah Amelia Chen
f17b425aac surface: use id instead of intFromPtr
intFromPtr was always a hack that we had to use before we had stable
surface IDs, and it was always slightly unsafe. Let's do it properly
this time.
2026-08-05 14:40:45 +08:00
Leah Amelia Chen
9e30f70f23 gtk: do not set bell ringing if already focused (#13597) 2026-08-05 14:18:45 +08:00
Mitchell Hashimoto
ca56412bf2 gtk: forward middle click to TUIs with mouse reporting (#13108)
Fix for Issue #12940 
I actually do not know if this has already been resolved and the issue
is just still open. Either way, here's a fix. Now we run a check to see
if the current program is accepting mouse events before discarding the
middle click.
2026-08-04 08:53:39 -07:00
Lauri Tirkkonen
f5419b9b15 gtk: do not set bell ringing if already focused 2026-08-04 20:40:32 +09:00
Mitchell Hashimoto
74b426458b gtk: use native blur on GTK 4.23.3+ (#13586)
Finally, what was previously thought impossible, is now possible.
The blur region itself is far more accurate than what we can conjure up
on our own, and in a much more finetuned and detailed way too.
Thank you, GTK devs!

Closes #13581
2026-08-03 20:55:14 -07:00
Leah Amelia Chen
3263fc6c4b gtk: use native blur on GTK 4.23.3+
Finally, what was previously thought impossible, is now possible.
The blur region itself is far more accurate than what we can conjure up
on our own, and in a much more finetuned and detailed way too.
Thank you, GTK devs!
2026-08-04 07:16:18 +08:00
Leah Amelia Chen
04f1bc0960 winproto/wayland: disable custom blur on GTK >=4.23.3
GTK 4.23.3 added its own (much smarter) implementation of background blur,
which means our implementation is not only redundant, it also crashes the
program because a surface cannot have multiple associated blur objects.
Ergo, don't do custom blur on newer GTK versions.

See #13578
2026-08-04 07:10:01 +08:00
Daniel Kinzler
90da3aba58 gtk: fix split sizing to eliminate flickering
For widget resizes the split ratio is now synced directly from the
propMaxPosition callback in the SplitTreeSplit widget, instead of an
idle callback. With this change all surfaces will be sized correctly
from the start, in a single round of size allocation in GTK. Previously,
surfaces would initially be shown with the wrong size for a few frames
until the idle callback ran, resulting in visible flickering. This was
especially visible when resizing a split quickly by holding down the
resize keybind.

Moved logic to sync split ratio between gtk.Paned widget and split tree
into new syncSplitRatio function in the SplitTreeSplit widget. Added
debug assertions and log warnings to syncSplitRatio where we look up
the split tree.
2026-08-01 21:29:14 +02:00
Jeffrey C. Ollie
7a512c3125 gtk: fix capitalization of banner title 2026-08-01 11:03:10 -05:00
Uzair Aftab
2c0d2588a7 inspector: make FileChooser cast type-safe 2026-07-31 18:40:49 +02:00
Uzair Aftab
ad96613a8c inspector: add copy and export for terminal IO events
Adds "Copy" and "Export to file" buttons to the Terminal IO inspector
so recorded VT events can be saved outside the app for sharing or
analysis.

Export is wired up through a new export_terminal_io apprt action,
handled with a native save dialog on both macOS and GTK.
2026-07-30 08:08:25 +02:00
Jeffrey C. Ollie
adfef29776 wayland/Hotkeys: polish & simplify (#13512)
I've come up with a way to avoid manually allocating each entry which
honestly makes the code flow much more smoothly. Basically you collect
all the applicable keybinds first, then try to bind them with their
stable memory addresses.
2026-07-29 10:10:34 -05:00
Leah Amelia Chen
c3b5cab941 wayland/Hotkeys: polish & simplify
I've come up with a way to avoid manually allocating each entry which
honestly makes the code flow much more smoothly. Basically you collect
all the applicable keybinds first, then try to bind them with their
stable memory addresses.
2026-07-29 22:18:55 +08:00
Jeffrey C. Ollie
1cc5e7bec1 update zig-gobject to 0.3.2
Includes better ZIg 0.16 compat and updates for Gnome 50.
2026-07-28 15:52:01 -05:00
Tim Culverhouse
2f3814ca5e gtk: honor suspended window state
GTK exposes the Wayland xdg_toplevel suspended state when the
compositor knows a window is not visible. Ghostty previously only used
widget map state, so it could continue rendering a mapped surface on an
inactive workspace or behind other windows.

Combine the mapped and suspended states for surface occlusion and update
all displayed surfaces whenever the toplevel suspension state changes.

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fa965-aa5f-7099-85b4-a9679d2c8bd3
2026-07-28 10:47:58 -05:00
Aurelien Brabant
7ee3ac9ec8 refactor: use arena allocator 2026-07-26 17:50:33 +02:00
Aurelien Brabant
0075c75b61 refactor: remove unneeded appendAssumeCapacity 2026-07-26 17:09:52 +02:00
Aurelien Brabant
3024c5d19e refactor: address nits 2026-07-26 16:37:46 +02:00
Aurelien Brabant
88bd4fdcea feat: implement vicinae-hotkey-v1 2026-07-26 05:47:40 +02:00
Mitchell Hashimoto
b988efcfe5 fix some 0.16 translation regressions 2026-07-22 08:07:06 -07:00
Chris Marchesi
e8525c0fd9 Update to Zig 0.16.0
This commit represents the majority of the work necessary to upgrade
Ghostty to use Zig 0.16.0.

Key parts:

* In addition to its previous responsibilities, the global state now
  houses state for global I/O implementations and the process
  environment. It is now also utilized in the main application along
  with the C library. Where necessary, global state is isolated from key
  parts of the implementation (e.g., in libghostty subsystems), and it's
  expected that this list will grow.

* We currently manage our own C translation layer where necessary. In
  these cases, cImport has been removed in favor of the new external
  translate-c package. Due to fixes that have needed be made to properly
  translate the dependencies that were swapped out, as mentioned, we
  have had to backport fixes from the current translate-c package (and
  the upstream Arocc dependency). We will host this ourselves until Zig
  0.17.0 is released with these fixes.

* Where necessary (only a small number of cases), some stdlib code from
  0.15.2 (and even from 0.17.0) has been taken, adopted, and vendored in
  lib/compat.

Co-authored-by: Leah Amelia Chen <hi@pluie.me>
2026-07-21 12:35:05 -07:00
yak
004c88e41e fix: set max window clamp to current monitor size 2026-07-05 10:41:06 -04:00
AJ Khullar
488b7109bb gtk: forward middle click to TUIs with mouse reporting 2026-06-28 12:37:08 +08:00
Jeffrey C. Ollie
e5b65a2ce3 config: add gtk-horizontal-tab-scroll option (#12659)
I've implemented a GTK toggle (gtk-horizontal-tab-scroll) for the
2-finger tab swiping introduced in #10575.

This resolves the issue presented in #11566. Simply put, this allows
users to decide whether or not they want to use horizontal tab scrolling
or just have the events passed through. Passing through the horizontal
scroll events allows programs like Neovim to use them for horizontal
scrolling.

This PR was largely generated by Claude Code and fully reviewed/refined
by me.
2026-06-27 01:58:13 -05:00
Daniel Kinzler
0a117e0797 gtk: fix missing dbus connection causing crash
Changes GlobalShortcuts.refresh to do nothing when there is no dbus connection and GlobalShortcuts.close to always clean up arena memory.
2026-06-24 13:26:42 +02:00
Mitchell Hashimoto
7092b39445 GTK: Improve Split Close Behavior (#11173)
## Summary
- Adds a "Close Split" option to the right-click context menu in the
split submenu
- Allows users to close the focused split pane directly from the context
menu

Reference discussion:
https://github.com/ghostty-org/ghostty/discussions/10982
2026-06-06 14:02:16 -07:00
Jon Parise
c4e1ab8883 core: send selection_changed notification
The core had no signal to the apprt when the active selection changed,
so a consumer (e.g. a screen reader) kept reading a stale selection
until some unrelated query refreshed it.

This change adds a payload-less selection_changed action that's fired on
a selection state transition. The apprt reads the current selection
through the normal read path.

This consolidates selection state changes so the notification fires
consistently: all sites route through setSelection rather than calling
screen.select directly, including the mouse paths that previously
bypassed it for clipboard timing.

The new setSelectionAndCopy extends setSelection with the additional
'copy_on_select' behavior.

On macOS, this posts .ghosttySelectionDidChange, which is debounced
before posting a NSAccessibility .selectedTextChanged notification.

GTK has no consumer yet and no-ops the action.
2026-06-02 19:37:49 -04:00
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
00jciv00
5ea45919d7 config: add gtk-horizontal-tab-scroll option
Add a boolean config option to enable/disable two-finger horizontal
touchpad scrolling for switching tabs. Defaults to true to preserve
existing behavior.

When tab scrolling is disabled or the scroll source is not a touchpad,
forward horizontal scroll events to the terminal so applications like
neovim can handle them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 11:46:56 -04: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