Add five new AppleScript commands to Ghostty.sdef mirroring the existing
App Intents for terminal input:
- `input text`: send text to a terminal as if pasted
- `send key`: simulate a keyboard event with optional action and modifiers
- `send mouse button`: send a mouse button press/release event
- `send mouse position`: send a mouse cursor position event
- `send mouse scroll`: send a scroll event with precision and momentum
A shared `input action` enumeration (press/release) is used by both key
and mouse button commands. Modifier keys are passed as a comma-separated
string parameter (shift, control, option, command).
Add two new AppleScript commands to the scripting dictionary:
- `focus terminal <terminal>` — focuses the given terminal and brings
its window to the front.
- `close terminal <terminal>` — closes the given terminal without a
confirmation prompt.
Each command is implemented as an NSScriptCommand subclass following
the same pattern as the existing split command.
Add a new `split` command to the AppleScript scripting dictionary that
splits a terminal in a given direction (right, left, down, up) and
returns the newly created terminal.
The command is exposed as:
split terminal <terminal> direction <direction>
Also adds a `fourCharCode` String extension for converting four-character
ASCII strings to their FourCharCode (UInt32) representation.
## Summary
This extends the macOS bell implementation to support the `audio` bell
feature, bringing it to parity with GTK/Linux.
Previously, macOS only had the `system` feature (`NSSound.beep()`). This
PR adds:
- **`audio` bell feature on macOS**: plays the file at `bell-audio-path`
using `NSSound(contentsOfFile:)`, respecting `bell-audio-volume`
- **`cval()` on the `Path` type**: allows `Path` values (a union type)
to be returned through the C API, which is needed for Swift to read
`bell-audio-path`
- **Removes `(GTK only)` restriction** from `bell-audio-path` and
`bell-audio-volume` documentation
## How it works
In `AppDelegate.swift`, when the bell rings and the `audio` feature is
enabled, Ghostty now:
1. Reads `bell-audio-path` from config
2. Loads it as an `NSSound`
3. Applies `bell-audio-volume` and plays it
Falls back gracefully if the path is not set or the file cannot be
loaded.
## Example config
```
bell-features = audio
bell-audio-path = /System/Library/Sounds/Glass.aiff
bell-audio-volume = 0.8
```
## Testing
- Set `bell-features = audio` and `bell-audio-path` to any valid audio
file
- Trigger a bell with `echo -e '\a'`
- Audio should play at the configured volume
Extends the macOS bell implementation to support the `audio` bell
feature by playing a user-specified audio file via NSSound.
Previously, macOS only supported the `system` feature (NSSound.beep()).
This change adds support for:
- `audio` bell feature: plays the file at `bell-audio-path` using
NSSound, respecting the `bell-audio-volume` setting
- Adds `cval()` to the `Path` type so it can be returned via the C API
Also removes the "(GTK only)" restriction from `bell-audio-path` and
`bell-audio-volume` documentation, as these options now work on macOS.
Example config:
bell-features = audio
bell-audio-path = /System/Library/Sounds/Glass.aiff
bell-audio-volume = 0.8
This fixes two overlapping issues regarding window positioning and Cmd+W window closures on macOS:
1. `window-position-x` and `window-position-y` coordinates were being ignored on initial launch because `TerminalWindow.setInitialWindowPosition` depended on the `TerminalController`, which isn't fully attached during `awakeFromNib`. This logic was moved so explicit coordinates are correctly enforced.
2. When closing a window via Cmd+W (leaving the app active), reopening the window would continuously cascade down and to the right rather than restoring to the previous position. It now checks if there are other windows open before cascading.
3. `LastWindowPosition` was updated to save both the frame origin and size (width/height), ensuring that restoring a closed window correctly mimics native AppKit State Restoration size behaviors while honoring explicit configurations.
Depends on #11030
- Update constraints of `TerminalGlassView`
- Use `TerminalViewContainer.DerivedConfig` to map styling properties
- Add TerminalViewContainerTests
- Instead of using delay, now the view updates are explicitly called by
window controllers
* ensure that `ghostty.h` compiles during basic Zig tests
* ensure that non-exhaustive enums are kept synchronized between
`ghostty.h` and their respective Zig counterpart.
* adjust some enums that varied from established conventions
Fixes#11029 (probably)
If you renamed the app bundle, the prior check would infinite loop due
to the combination of two bugs: invalid termination checks and
hardcoding "Ghostty.app"
Fixes#10935
This is a more robust way to detect "is my surface focused" because that
question usually means "is my surface the last focused surface" if a
_different_ surface is not focused. We already have used this pattern
all over but we should extend it to SwiftUI too.