Commit Graph

1923 Commits (main)

Author SHA1 Message Date
Mitchell Hashimoto 19e5053b28
macos: only show the grab handle in fullscreen if there are splits (#11381)
Fixes #11376
2026-03-11 10:08:25 -07:00
Mitchell Hashimoto 12bc1e7860
macos: only show the grab handle in fullscreen if there are splits
Fixes #11376
2026-03-11 10:02:09 -07:00
Lukas 596d502a75
macOS: restore window frame under certain conditions 2026-03-11 17:45:10 +01:00
Lukas 45d360dc68
macOS: set the initial window position after window is loaded 2026-03-11 17:45:09 +01:00
Lukas e8c82ca1af
macOS: save frame only if the window is visible 2026-03-11 17:45:09 +01:00
Lukas 0af9938ad2
macos: add UI test for window position restore across titlebar styles
Tests that window position and size are correctly restored after
reopen for all four macos-titlebar-style variants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:45:09 +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
ydah c2206542d3 macos: fix tab title rename hit testing and focus handling in fullscreen mode 2026-03-11 07:24:49 -07:00
Mitchell Hashimoto 6dd5b856b0
macos: disable Tahoe one-time codes
This disables all the automatic one-time code inputs in Ghostty.
It'd be really neat to actually dynamically change this (not sure if its
possible with NSTextContext or how often thats cached) but for now we
should just fully disable it.
2026-03-10 19:41:22 -07:00
Lukas 90dc4315e2
macos: add test cases for Ghostty.Config properties
Test boolean, string, enum, and numeric config properties using
TemporaryConfig to verify defaults and parsed values.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-10 20:03:17 +01:00
Lukas 32934445cf
macos: add TemporaryConfig for AI to write test cases 2026-03-10 19:45:52 +01:00
Mitchell Hashimoto 71f81527ad
macos: remove IntrinsicSizeTimingTests temporarily
These were too flaky.
2026-03-10 11:08:47 -07:00
Mitchell Hashimoto f88b42ad39
macos: add enum type for macos-titlebar-style (#11262) 2026-03-10 10:58:47 -07:00
Mitchell Hashimoto c06ede5849
macos: make paste_from_clipboard performable on macos (#11328)
Fixes #10751
2026-03-10 10:31:22 -07:00
Mitchell Hashimoto aaad43c235
macos: make paste_from_clipboard performable on macos
Fixes #10751
2026-03-10 10:25:14 -07:00
Selman Kayrancioglu 6092c299d5 macos: reset mouse state on focus loss to prevent phantom drag
Fixes phantom mouse drag/selection when switching splits or apps.
The suppressNextLeftMouseUp flag and core mouse click_state were not
being reset on focus transitions, causing stale state that led to
unexpected drag behavior.

- Reset suppressNextLeftMouseUp in focusDidChange when losing focus
- Defensively reset the flag when processing normal clicks
- Reset core mouse.click_state and left_click_count on focus loss
2026-03-10 09:54:08 -07:00
Lukas de0f2ab22d
macos: add enum type for macos-titlebar-style 2026-03-10 17:15:14 +01:00
Mitchell Hashimoto 3782d118e1
macOS: restore keyboard focus after inline tab title edit (#11320)
## Summary

- After finishing an inline tab title edit (via keybind or
double-click), all keyboard input is lost because
`TabTitleEditor.finishEditing()` sets `makeFirstResponder(nil)`, leaving
the window itself as first responder with no path back to the terminal
surface.
- Adds a `tabTitleEditorDidFinishEditing` delegate callback to
`TabTitleEditorDelegate` that fires after every edit (commit or cancel).
- `TerminalWindow` implements it by calling
`makeFirstResponder(focusedSurface)` to restore keyboard focus to the
terminal.

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

## Testing

- [x] Bind `prompt_tab_title` to a keybind (e.g. `keybind =
cmd+shift+i=prompt_tab_title`)
- [x] Trigger inline tab title edit via keybind, press Enter — verify
keyboard input works immediately
- [x] Trigger inline tab title edit via keybind, press Escape — verify
keyboard input works immediately
- [x] Double-click a tab title, press Enter — verify keyboard input
works immediately
- [x] Double-click a tab title, press Escape — verify keyboard input
works immediately
- [x] Verify Cmd+number tab switching works after all of the above
- [x] Verify split pane focus is correct after editing tab title with
splits open

AI disclosure: Codebase exploration and review via [Claude
Code](https://claude.com/claude-code)
2026-03-10 08:59:51 -07:00
chronologos 7629130fb4 macOS: restore keyboard focus after inline tab title edit
After finishing an inline tab title edit (via keybind or double-click),
`TabTitleEditor.finishEditing()` calls `makeFirstResponder(nil)` to
clear focus from the text field, leaving the window itself as first
responder. No code path restores focus to the terminal surface, so all
keyboard input is lost until the user clicks into a pane.

Add a `tabTitleEditorDidFinishEditing` delegate callback that fires
after every edit (commit or cancel). TerminalWindow implements it by
calling `makeFirstResponder(focusedSurface)` to hand focus back to the
terminal.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-10 08:52:00 -07:00
Lukas a6cd1b08af
macOS: fix intrinsicContentSize race in windowDidLoad (#11256)
Add initialContentSize fallback on TerminalViewContainer so
intrinsicContentSize returns the correct value immediately,
without waiting for @FocusedValue to propagate. This removes
the need for the DispatchQueue.main.asyncAfter 40ms delay.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:35:49 +01:00
Lukas cfedda1a0e
macOS: add regression tests for intrinsicContentSize race (#11256)
Tests that validate intrinsicContentSize returns a correct value when
TerminalController.windowDidLoad() reads it. Currently fail, proving
the race condition where @FocusedValue hasn't propagated
lastFocusedSurface before the 40ms timer fires.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:27:38 +01:00
Mitchell Hashimoto a6ee1fb292
macos: increase window-width/height apply delay from 10ms to 40ms
Band-aid for #10304

We don't have a robust fix yet but this should help mitigate more
scenarios.
2026-03-09 08:42:07 -07:00
Mitchell Hashimoto dd3d72c3de
Revert "macOS: filter proper intrinsicContentSize when opening new window (#11257)"
This reverts commit 3445c9afda, reversing
changes made to 1e981f858a.
2026-03-09 08:33:24 -07:00
Lukas 3c93c35869 macOS: filter proper intrinsicContentSize when opening new window
Fixes #11256
2026-03-09 08:21:29 -07:00
Mitchell Hashimoto 233fb12081
macos: add AppleScript front window and focused terminal properties
This adds two new propeties to make it easy to get the frontmost (main)
window and the focused terminal within a tab. We already had a property
to get the selected tab of a tab group.
2026-03-08 20:00:21 -07:00
Lukas df4d9bc0d0
macos: fix quick terminal glassy background 2026-03-08 15:22:37 +01:00
Mitchell Hashimoto ed9a6cb648
macos: implement the quit command 2026-03-07 07:29:40 -08:00
Mitchell Hashimoto 210b01ad60
macos: use direct parameters for object-targeting commands
Change split, focus, close, activate window, select tab, close tab, and
close window commands to accept their target object as a direct parameter
instead of a named parameter. This produces natural AppleScript syntax:

  activate window (window 1)
  close tab (tab 1 of window 1)
  split (terminal 1) direction right

instead of the awkward redundant form:

  activate window window (window 1)
  close tab tab (tab 1 of window 1)
  split terminal (terminal 1) direction right

The implementation moves command logic from NSScriptCommand subclasses
into responds-to handler methods on ScriptTerminal, ScriptWindow, and
ScriptTab, which is the standard Cocoa Scripting pattern for commands
whose direct parameter is an application class.
2026-03-07 07:23:59 -08:00
Mitchell Hashimoto 038ebef16c
address some PR feedback 2026-03-07 07:07:10 -08:00
Mitchell Hashimoto 259a41d503
macos: rename surface config working directory to not be ambiguous 2026-03-06 15:16:03 -08:00
Mitchell Hashimoto 221a1639af
swiftlint 2026-03-06 15:07:04 -08:00
Mitchell Hashimoto 25fa58143e
macos: add macos-applescript config 2026-03-06 15:04:20 -08:00
Mitchell Hashimoto 28b4e2495d
macos: Add AppleScript commands for window and tab control
Add scripting dictionary commands for activating windows, selecting tabs,
closing tabs, and closing windows.

Implement the corresponding Cocoa AppleScript command handlers and expose
minimal ScriptWindow/ScriptTab helpers needed to resolve live targets.

Verified by building Ghostty and running osascript commands against the
absolute Debug app path to exercise all four new commands.
2026-03-06 14:35:31 -08:00
Mitchell Hashimoto d271c8ccaa
macos: add new tab command 2026-03-06 12:55:43 -08:00
Mitchell Hashimoto 4d5de702f2
macos: allow split command surface configuration 2026-03-06 12:35:01 -08:00
Mitchell Hashimoto 459eaa2640
macos: order AppleScript dictionary definitions
Document the preferred Ghostty.sdef top-level order in AGENTS.md and reorder 
Ghostty Suite definitions to classes, records, enums, then commands.
2026-03-06 12:28:02 -08:00
Mitchell Hashimoto a3adeb0166
macos: use value-style AppleScript surface configuration records
Add a `surface configuration` record type to the scripting dictionary,
implement `new surface configuration` (with optional copy-from), and allow
`new window` to accept `with configuration`.
2026-03-06 12:16:40 -08:00
Mitchell Hashimoto 959c2f51ac
macos: add AppleScript new window command
Add a `new window` command to the scripting dictionary and wire it to
`NSApplication` so AppleScript can create Ghostty windows.

The command returns a scripting `window` object for the created window,
with a fallback to a direct wrapper when AppKit window ordering has not
yet refreshed in the current run loop.
2026-03-06 08:38:51 -08:00
Mitchell Hashimoto 122d0ecdfd
macos: expose name (title) on window, tab, and terminal via AppleScript
Add a `name` property (code `pnam`, cocoa key `title`) to the window, tab,
and terminal classes in the scripting definition. This follows the standard
Cocoa scripting convention where `name`/`pnam` maps to the `title` KVC key,
matching what Apple does in CocoaStandard.sdef for NSWindow.

Also fixes the pre-existing terminal `title` property which used a custom
four-char code (`Gttl`) that AppleScript could not resolve directly — only
via `properties of terminal`. All three classes now use the standard `pnam`
code so `name of window 1`, `name of tab 1 of window 1`, and
`name of terminal 1` all work correctly.
2026-03-06 08:13:49 -08:00
Mitchell Hashimoto e514035519
macos: add terminals element to window and tab AppleScript classes
Expose terminal surfaces as elements on both ScriptWindow and ScriptTab,
allowing AppleScript to enumerate terminals scoped to a specific window
or tab (e.g. `terminals of window 1`, `terminals of tab 1 of window 1`).

Changes:
- Add `<element type="terminal">` to window and tab classes in Ghostty.sdef
- Add `terminals` computed property and `valueInTerminalsWithUniqueID:`
  lookup to ScriptWindow (returns all surfaces across all tabs)
- Add `terminals` computed property and `valueInTerminalsWithUniqueID:`
  lookup to ScriptTab (returns surfaces within that tab)
2026-03-06 08:06:52 -08:00
Mitchell Hashimoto f72d41675b
macos: fix AppleScript quit command being silently ignored
The application class in Ghostty.sdef was missing a responds-to
declaration for the quit command. Apple's Cocoa Scripting requires
the application class to explicitly declare it responds to quit via
handleQuitScriptCommand: for the aevtquit event to be dispatched.
2026-03-06 08:03:16 -08:00
Mitchell Hashimoto 341d8bdf75
macos: AppleScript windows/tabs
Add ScriptWindow and ScriptTab classes to expose window/tab hierarchy
to AppleScript, along with the corresponding sdef definitions.
2026-03-06 07:59:58 -08:00
Mitchell Hashimoto d03338c1b5
macos: fix iOS build 2026-03-05 21:29:55 -08:00
Mitchell Hashimoto ffe622ed30
macos: add standard application properties and commands
Add standard Cocoa scripting definitions to the AppleScript dictionary:

- Application properties: name, frontmost, version
- Standard Suite commands: exists, quit

These are backed by built-in Cocoa scripting classes (NSExistsCommand,
NSQuitCommand) and standard NSApplication KVC keys, so no Swift code
changes are needed.
2026-03-05 21:23:49 -08:00
Mitchell Hashimoto fd5ad1f574
macos: add AppleScript commands for text input, key, and mouse events
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).
2026-03-05 21:17:34 -08:00
Mitchell Hashimoto 1742aeda50
macos: add focus and close AppleScript commands for terminals
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.
2026-03-05 20:59:03 -08:00
Mitchell Hashimoto ef669eeae7
macos: add AppleScript `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.
2026-03-05 20:54:34 -08:00
Mitchell Hashimoto 40c74811f1
macos: fix perform action 2026-03-05 20:32:57 -08:00
Mitchell Hashimoto 52c0709d88
macos: add ability for agents to run debug app 2026-03-05 20:30:31 -08:00
Mitchell Hashimoto c90a782e59
macos: implement basic read-only applescript stuff 2026-03-05 20:10:01 -08:00
Mitchell Hashimoto 291fbf55cb
macos: AppleScript starting 2026-03-05 20:03:28 -08:00
Mitchell Hashimoto 04aff46022
macos: add build script, update AGENTS.md, skip UI tests
This is an update to address common agentic issues I run into,
but the `build.nu` script may be generally helpful to people using
the Nix env since `xcodebuild` is broken by default in Nix due to the
compiler/linker overrides Nix shell does.
2026-03-05 19:55:50 -08:00
Tim Culverhouse d1468086ef
macos: defer key-window focus sync to reduce churn
Amp-Thread-ID: https://ampcode.com/threads/T-019cb9fe-b11b-753f-99e7-8ecc52b73ec4
Co-authored-by: Amp <amp@ampcode.com>
2026-03-04 12:43:51 -06:00
Tim Culverhouse 3ee8ef4f65
macos: suppress split-focus click mouse reports
Amp-Thread-ID: https://ampcode.com/threads/T-019cb9fe-b11b-753f-99e7-8ecc52b73ec4
Co-authored-by: Amp <amp@ampcode.com>
2026-03-04 12:43:51 -06:00
Jon Parise a716b9c4d4 macos: Ghostty.Shell.escape unit tests 2026-03-04 11:00:03 -05:00
Mitchell Hashimoto 619e33a4fe
macos: implement audio bell support with bell-audio-path (#11154)
## 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
2026-03-03 20:08:04 -08:00
Mitchell Hashimoto 98ad1d955c
use proper type for optional path 2026-03-03 19:53:15 -08:00
Alaa Ali b215291914 macos: implement audio bell support with bell-audio-path
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
2026-03-03 23:00:50 +01:00
Lukas 4437707132
macos: use a separated struct to hide and restore tab states 2026-03-03 17:42:17 +01:00
Lukas 78fdff34a9
macos: hide close button when editing tab title 2026-03-03 17:24:56 +01:00
Lukas 661470897e
macos: passthrough right mouse down event to TabTitleEditor if needed 2026-03-03 17:24:56 +01:00
Lukas 205c05d59d
macos: passthrough mouse down event to TabTitleEditor if needed 2026-03-03 17:15:12 +01:00
Lukas e6e5f3ffe1
macos: finish editing tab title when the window resigns as key window 2026-03-03 16:34:11 +01:00
Abdurrahman 0d5b9d554c
Update macos/Sources/Features/Terminal/TerminalController.swift
apply reviewer suggestion for cascading

Co-authored-by: Lukas <134181853+bo2themax@users.noreply.github.com>
2026-02-28 18:02:40 +01:00
A-AKB 6e622f8c75 fix(macos): extract window cascade logic into helper function 2026-02-28 01:43:00 +01:00
A-AKB 0db32ab9a8 macos: fix window size/position restoration on Cmd+W close
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.
2026-02-28 01:34:18 +01:00
Lukas df53f75ad1
macOS: refine window tint for liquid glass (#11018)
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
2026-02-27 10:49:12 -08:00
Jeffrey C. Ollie ea5b07d20f
core: add tests for `ghostty.h`
* 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
2026-02-27 09:22:23 -06:00
Lukas e55ebf0008
macos: workaround for TabTitleEditor alignment issue 2026-02-27 10:21:11 +01:00
Mitchell Hashimoto 3ee63035d3
macos: DockTilePlugin finds app bundle via `.app` suffix
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"
2026-02-26 19:58:53 -08:00
Mitchell Hashimoto a5909dfa1d
macos: command finished notifications always show up 2026-02-26 13:40:41 -08:00
Joseph Martinsen f4ddddc4b7 macos: refactor command finish notification duration handling 2026-02-26 13:17:19 -08:00
Joseph Martinsen 3b5a7b77d3 macos: implement notify on command finish 2026-02-26 13:12:29 -08:00
Mitchell Hashimoto dcb7c9a4b8
macos: show the notification count number in the badge 2026-02-26 10:21:35 -08:00
Mitchell Hashimoto 5389fdfbaf
macos: lint 2026-02-26 10:14:22 -08:00
Mitchell Hashimoto 454a89e011
macos: clean up badge request state 2026-02-26 10:10:42 -08:00
Mitchell Hashimoto 3aca722415
macos: further simplication of AppDelegate bell state 2026-02-26 09:52:26 -08:00
Mitchell Hashimoto 79ca4daea6
macos: try to clean up Appdelegate combine mess 2026-02-26 09:47:17 -08:00
Mitchell Hashimoto ea8bf17df8
macos: use combine to coalesce bell values 2026-02-26 09:39:23 -08:00
Mitchell Hashimoto d05fb652ed
macos: update AGENTS.md 2026-02-26 09:10:00 -08:00
Mitchell Hashimoto c60e24d200
macos: update to Sparkle 2.9 2026-02-26 08:49:42 -08:00
Noah Bernsohn c4766dff77 fix: restore terminalTitle variable removed in previous edit 2026-02-26 07:18:06 -08:00
Noah Bernsohn 62c1d50757 Update macos/Sources/Features/Command Palette/TerminalCommandPalette.swift
Co-authored-by: Lukas <134181853+bo2themax@users.noreply.github.com>
2026-02-26 07:18:06 -08:00
Noah Bernsohn f38234bc5b apprt: show title override in command palette jump commands 2026-02-26 07:18:05 -08:00
Mitchell Hashimoto e6da439e43
macos: style changes 2026-02-26 07:09:08 -08:00
Lukas 05a125533b
macos: fix glass tinting when theme changes 2026-02-26 11:24:54 +01:00
Mitchell Hashimoto 610e1f5f47
macos: add Weak to iOS build 2026-02-25 16:03:14 -08:00
Mitchell Hashimoto 1c3f7601a7
macos: pass last focused surface as env, use for focus detection
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.
2026-02-25 14:01:12 -08:00
Mitchell Hashimoto 26146f54c5
update comments 2026-02-25 09:04:20 -08:00
Mitchell Hashimoto da045d2fb3
Remove ObjCExceptionCatcher from iOS target 2026-02-25 09:00:52 -08:00
Mitchell Hashimoto 304823d560
macos: just some textual cleanup 2026-02-25 08:58:09 -08:00
Noah Gregory 58acab6c7d
Merge branch 'ghostty-org:main' into fix-tabbing-from-tab-overview 2026-02-24 20:24:18 -05:00
Noah Gregory dd4e36f921
macOS: fix crash when adding tab from tab overview 2026-02-24 18:08:45 -05:00
Mitchell Hashimoto 06084cd840
macos: various dock tile cleanups 2026-02-24 10:38:02 -08:00
Mitchell Hashimoto eaf7d8a012
macos: icon tests 2026-02-24 10:26:13 -08:00
Mitchell Hashimoto f451ea8e46
macos: move icon codable/equatable to extension 2026-02-24 10:22:49 -08:00
Lukas c72788894e
ci: fix linting and delete non-useful tests 2026-02-24 10:13:24 +01:00
Lukas f831f68f1a
macOS: update AppIcon encoding
- make `ColorizedGhosttyIcon` codable
- remove deprecated string encoding introduced in tip
2026-02-24 09:51:30 +01:00
Mitchell Hashimoto 4b1178e4f6
macos: rename a bunch of files 2026-02-24 08:58:15 +01:00
Mitchell Hashimoto 2c28c27ca5
moving lots of files, removing unused stuff 2026-02-24 08:58:15 +01:00
Lukas a79557f521
macOS: stop cycling icons when AboutWindow is closed
and start cycling with current icon
2026-02-24 08:58:15 +01:00
Lukas 45525a0a85
macOS: use `NSDockTilePlugIn` to update app icons 2026-02-24 08:58:14 +01:00
Martin Emde 40e6a6dd58 Refine spacing and header usage
This is 4pt header space, 12pt clickable frame height
2026-02-23 12:04:07 -08:00
Martin Emde 2842b18a3f Only show drag handle on hovered surface 2026-02-23 12:04:07 -08:00
Martin Emde 47577c7623 Make top visual space for surface drag handles 2026-02-23 12:03:45 -08:00
Mitchell Hashimoto 6a9a21afb6
macOS: Add inactive window tint overlay for liquid glass (#10943)
**Summary:**
- Add tint overlay to dim terminal windows when inactive, fixes
https://github.com/ghostty-org/ghostty/discussions/10040
- Refactor the liquid glass effect into a dedicated `TerminalGlassView`
class

Note: The tint overlay color and opacity values may not be ideal —
feedback is welcome.

**AI Disclosure:** I used Claude Code to read the macos repo and
understand the liquid glass implementation. Implemented basic tint
overlay mainly by hand. Refactor the code and review changes with Claude
Code.
2026-02-23 09:01:25 -08:00
Mitchell Hashimoto 51f304e9a0
macos: add AGENTS.md 2026-02-23 08:46:10 -08:00
Mitchell Hashimoto f5e2561eb7
macos: rename to TabTitleEditor 2026-02-23 08:38:10 -08:00
Mitchell Hashimoto b6a9d54e98
macos: extract inline title editing to standalone file 2026-02-23 08:38:09 -08:00
MiUPa 879d7cf337 macOS: remove dead tab title edit helper 2026-02-23 08:38:09 -08:00
MiUPa 368e190a41 macOS: defer inline tab rename start to reduce flicker 2026-02-23 08:38:09 -08:00
MiUPa f6e9b19fd5 macOS: widen inline tab title editor 2026-02-23 08:38:09 -08:00
MiUPa feee4443da macOS: add inline tab title editing 2026-02-23 08:38:09 -08:00
MiUPa daa2a9d0d5 macos: allow renaming tab title on double-click 2026-02-23 08:38:09 -08:00
miracles 81c9c81ae3 Refactor glass effect into TerminalGlassView and add inactive window tint overlay 2026-02-22 21:58:33 -08:00
Jon Parise dd29617cd3 macos: swiftlint 'multiple_closures_with_trailing_closure' rule
Also, re-enable the 'force_cast' rule, which was addressed earlier.
2026-02-21 10:17:15 -08:00
Tristan Partin 407b3c082f macos: fix new tab crash
It was introduced in 2a81d8cd2910b12fe007f0bc5fb5d6be57f0f0fe[0]. We
lost the subview. prefix of from the contains() call.

Co-authored-by: Brent Schroeter <github@brentsch.com>
Fixes: https://github.com/ghostty-org/ghostty/issues/10923
Link: 2a81d8cd29 [0]
2026-02-21 09:08:04 -06:00
Mitchell Hashimoto 2a81d8cd29
macos: swiftlint 'for_where' rule (#10909) 2026-02-20 21:06:47 -08:00
Mitchell Hashimoto ce46caeacb
macos: swiftlint 'switch_case_alignment' rule (#10908) 2026-02-20 21:02:46 -08:00
Mitchell Hashimoto 6ec8744b16
macOS: expand tilde in file paths before opening (#10863)
## Summary

Cmd-clicking a file path containing `~` (e.g. `~/Documents/file.txt`)
fails to open the file on macOS because `URL(filePath:)` treats `~` as a
literal directory name rather than the user's home directory.

This uses `NSString.expandingTildeInPath` to resolve `~` before
constructing the file URL.

## Root Cause

In `openURL()`, when the URL string has no scheme it falls through to:

```swift
url = URL(filePath: action.url)
```

Swift's `URL(filePath:)` does not perform tilde expansion. A path like
`~/Documents/file.txt` produces a URL pointing to a non-existent file,
and `NSWorkspace.open` silently fails.

## Fix

```swift
let expandedPath = NSString(string: action.url).expandingTildeInPath
url = URL(filePath: expandedPath)
```

## Reproduction

1. Have a terminal application (e.g. Claude Code) that outputs file
paths with `~` prefixes
2. Cmd-click the path in Ghostty on macOS
3. The file does not open (fails silently)

With this fix, the path resolves correctly and opens in the default
editor.
2026-02-20 20:56:27 -08:00
Alex Feijoo b65261eb66 macOS: expand tilde in file paths before opening
`URL(filePath:)` treats `~` as a literal directory name, so
cmd-clicking a path like `~/Documents/file.txt` would fail to
open because the resulting file URL doesn't point to a real file.

Use `NSString.expandingTildeInPath` to resolve `~` to the user's
home directory before constructing the file URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:37:54 -08:00
Jon Parise 2d6fa92d78 macos: swiftlint 'for_where' rule 2026-02-20 19:42:48 -05:00
Jon Parise f7e6639c43 macos: swiftlint 'switch_case_alignment' rule 2026-02-20 19:18:40 -05:00
Mitchell Hashimoto 5db9f03f62
macos: swiftlint 'no_fallthrough_only' rule (#10899)
This rule is generally trying to be helpful, but it doesn't like a few
places in our code base where we're intentionally listing out all of the
well-known cases. Given that, just disable it.

https://realm.github.io/SwiftLint/no_fallthrough_only.html
2026-02-20 13:39:31 -08:00
Mitchell Hashimoto 2ed341495f
macos: optimize secure input overlay animation (#10903)
Addresses discussion in #3729 and issues relating to #7333, #9590, and
#9617.

Rendering the Secure Keyboard Input overlay using innerShadow() can
strain the resources of the main thread, leading to elevated CPU load
and in some cases extended disruptions to the main thread's
DispatchQueue that result in lag or frozen frames. This change achieves
the same animated visual effect with ~35% lower CPU usage and resolves
most or all of the terminal rendering issues associated with the
overlay.
2026-02-20 13:39:14 -08:00
Jon Parise 3d3ea3fa59 macos: swiftlint 'no_fallthrough_only' rule
This rule is generally trying to be helpful, but it doesn't like a few
places in our code base where we're intentionally listing out all of the
well-known cases. Given that, just disable it.

https://realm.github.io/SwiftLint/no_fallthrough_only.html
2026-02-20 13:01:30 -05:00
Mitchell Hashimoto 3ba6d8174d
macos: swiftlint 'unused_enumerated' rule (#10888) 2026-02-20 09:43:38 -08:00
Mitchell Hashimoto 6ca80091c5
macos: add root-level .swiftlint.yml (#10890)
In order to support running from both the repository root and from
within Xcode project, and to keep things generally organized, our
primary .swiftlint.yml configuration file lives under macos/.

This change introduces a root-level .swiftlint.yml which limits the file
scope to macos/ and then includes macos/.swiftlint.yml for the rest of
the directives.

This unlocks a few benefits:

- We no longer need to pass an explicit `macos` path argument in any of
our invocations. SwiftLint will do the right thing when run either from
the repository root or from within the macos/ directory.
- It lets us easily exclude the macos/build/ directory (and re-enable
the 'deployment_target' rule). In the previous setup, this was more
challenging than you'd expect due to SwiftLint's path resolution rules
and required passing even more arguments like `--working-directory`.

The only downside is adding a new file to the repository root, but that
feels like the right trade-off given the benefits and conveniences.
2026-02-20 09:43:13 -08:00
Jon Parise 454d53e264 macos: ignore swiftlint 'line_length' rule
Also, there are no more outstanding 'mark' issues.
2026-02-20 10:35:10 -05:00
Jon Parise c2eab3b43d macos: add root-level .swiftlint.yml
In order to support running from both the repository root and from
within Xcode project, and to keep things generally organized, our
primary .swiftlint.yml configuration file lives under macos/.

This change introduces a root-level .swiftlint.yml which limits the file
scope to macos/ and then includes macos/.swiftlint.yml for the rest of
the directives.

This unlocks a few benefits:

- We no longer need to pass an explicit `macos` path argument in any of
  our invocations. SwiftLint will do the right thing when run either
  from the repository root or from within the macos/ directory.
- It lets us easily exclude the macos/build/ directory (and re-enable
  the 'deployment_target' rule). In the previous setup, this was more
  challenging than you'd expect due to SwiftLint's path resolution rules
  and required passing even more arguments like `--working-directory`.

The only downside is adding a new file to the repository root, but that
feels like the right trade-off given the benefits and conveniences.
2026-02-20 09:21:04 -05:00
Jon Parise e887527e59 macos: swiftlint 'unused_enumerated' rule 2026-02-20 08:03:05 -05:00
Brent Schroeter 7e90e26ae1 macos: optimize secure input overlay animation
Rendering the Secure Keyboard Input overlay using
innerShadow() can strain the resources of the main
thread, leading to elevated CPU load and in some
cases extended disruptions to the main thread's
DispatchQueue that result in lag or frozen frames.

This change achieves the same animated visual
effect with ~35% lower CPU usage and resolves most
or all of the terminal rendering issues associated
with the overlay.
2026-02-19 22:03:54 -08:00
Jon Parise dbf2e0e087 macos: swiftlint 'vertical_parameter_alignment' rule 2026-02-19 19:11:36 -05:00
Jon Parise c418e4b581 macos: swiftlint 'unused_optional_binding' rule 2026-02-19 19:10:38 -05:00
Jon Parise a7719a8db6 macos: swiftlint 'shorthand_operator' rule 2026-02-19 19:07:29 -05:00
Jon Parise 9bae26ab45 macos: swiftlint 'orphaned_doc_comment' rule 2026-02-19 19:06:09 -05:00
Jon Parise f4d70df34c macos: swiftlint 'implicit_getter' rule 2026-02-19 19:02:49 -05:00
Jon Parise 629a656e53 macos: swiftlint 'vertical_whitespace' rule 2026-02-19 18:58:28 -05:00
Jon Parise a36d2f5420 macos: swiftlint 'unused_closure_parameter' rule 2026-02-19 18:57:43 -05:00
Jon Parise 540adb0da3 macos: swiftlint 'unneeded_synthesized_initializer' rule 2026-02-19 18:57:19 -05:00
Jon Parise b532cd55d6 macos: swiftlint 'trailing_whitespace' rule 2026-02-19 18:56:43 -05:00
Jon Parise 33dce8511e macos: swiftlint 'trailing_semicolon' rule 2026-02-19 18:56:25 -05:00
Jon Parise 6af959920e macos: swiftlint 'syntactic_sugar' rule 2026-02-19 18:56:07 -05:00
Jon Parise 25b38b291e macos: swiftlint 'private_over_fileprivate' rule 2026-02-19 18:55:12 -05:00
Jon Parise 6052f664cf macos: swiftlint 'opening_brace' rule 2026-02-19 18:53:13 -05:00
Jon Parise b10dcc9629 macos: swiftlint 'legacy_constructor' rule 2026-02-19 18:43:22 -05:00
Jon Parise 32e540c248 macos: swiftlint 'legacy_constant' rule 2026-02-19 18:38:32 -05:00
Jon Parise 9287a61920 macos: swiftlint 'implicit_optional_initialization' rule 2026-02-19 18:36:38 -05:00
Jon Parise a83c8f8a9d macos: swiftlint 'empty_parentheses_with_trailing_closure' rule 2026-02-19 18:35:40 -05:00
Jon Parise 1b827e3e45 macos: swiftlint 'empty_enum_arguments' rule 2026-02-19 18:35:17 -05:00
Jon Parise 56d67ce88f macos: swiftlint 'control_statement' rule 2026-02-19 18:34:37 -05:00
Jon Parise a8903c1bb1 macos: swiftlint 'comment_spacing' rule 2026-02-19 18:34:02 -05:00
Jon Parise 6ade5df799 macos: swiftlint 'comma' rule 2026-02-19 18:33:34 -05:00
Jon Parise 786bad9774 macos: swiftlint 'colon' rule 2026-02-19 18:32:44 -05:00
benodiwal 3d0da44e15 feat(config): allow fullscreen config to specify non-native mode directly
Co-Authored-By: Sachin <sachinbeniwal0101@gmail.com>
2026-02-19 14:34:22 -08:00
Jon Parise 21ea94610a macos: lint Swift files using SwiftLint
SwiftLint <https://realm.github.io/SwiftLint/> is both a linter and
formatting. It's a popular way to spot issues and enforce a consistent
style.

Our SwiftLint configuration lives in macos/.swiftlint.yml, where is is
automatically discovered. It's very configurable, and I made an initial
pass as some basic, weakly-opinionated rules. The "TODO" section lists
rules that currently have violations but can be easily (auto)fixed in
follow-up commits.

Our integration is CLI-based. Similar to our other support tools, we
expect developers to install `swiftlint` via nix or e.g. Homebrew.
This is documented in HACKING.md.

We also have an optional Xcode integration, for in-editor feedback. When
`swiftlint` is available, it's run as a script-based Build Phase.

SwiftLint supports an auto-fix mode (--fix). Agents are aware of this
via AGENTS.md.

The rules are enforced using a (nix-based) CI job.
2026-02-19 14:42:11 -05:00
Jon Parise 303c9142dc macos: improve "Set Default Terminal"
Switch to using the existing UTType.unixExecutable constant for this
operator, which also lets us remove a failure path. Also, use the
completion-based setDefaultApplication() variant to handle errors.

This simplifies the code enough that we don't need the additional
NSWorkspace+Ghostty extension functions.
2026-02-18 11:47:30 -05:00
Mitchell Hashimoto e1f20739d0
add "Set Ghostty as Default Terminal App" on macOS (#10810)
This PR enables iTerm2-like one button "Set Ghostty as Default Terminal
App" functionality on macOS, making it easier to open a directory in
Ghostty, run shell scripts when mouse clicking, etc.
2026-02-17 21:04:55 -08:00
Mahno Kropotkinvich aee80d208d add "Set Ghostty as Default Terminal App" on macOS 2026-02-17 20:52:49 -08:00
Pieter Ouwerkerk ce66bea581
Move MockView to SplitTreeTests itself 2026-02-17 09:37:02 -08:00
Pieter Ouwerkerk 8fdedbce45
Add MockView and SplitTreeTests 2026-02-16 20:23:48 -08:00
Mitchell Hashimoto b358705b65
macos: rename shellQuoted() to Ghostty.Shell.quote() (#10765)
We already had an established Ghostty.Shell namespace (previously a
struct; now a more idiomatic enum), and locating these functions next to
each other makes it clearer how they relate to one another.
2026-02-16 12:40:13 -08:00
Jon Parise df6feba417 macos: rename shellQuoted() to Ghostty.Shell.quote()
We already had an established Ghostty.Shell namespace (previously a
struct; now a more idiomatic enum), and locating these functions next to
each other makes it clearer how they relate to one another.
2026-02-16 15:27:57 -05:00
Jon Parise d49ac65b16 macos: sort INFOPLIST_KEY_ names
Xcode wants these to be sorted and will update this list when the
project file is saved so proactively make this change before it gets
mixed up in other work.
2026-02-16 15:25:53 -05:00
Mitchell Hashimoto 99e342717b
fix: copy_title_to_clipboard respects user-overridden title (#10694)
## 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.
2026-02-16 11:10:17 -08:00
Noah Bernsohn 951cf13d7e macOS: show keyboard shortcuts in command palette 2026-02-15 10:17:01 -06:00
Priyanshu de49b7f27b rename copy_title action to copy_title_to_clipboard 2026-02-13 09:59:02 +05:30
Priyanshu b4be13ed50 fix: copy_title_to_clipboard now respects user-overridden title
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
2026-02-13 01:19:15 +05:30
Jon Parise a9e79ae74f
macos: quote input strings used for shell commands (#10583)
When we're building an input string that's explicitly meant to be used
as a shell command, quote it using the same logic as Python's
`shlex.quote` function.

This specifically addresses issues we've seen when open(1)'ing Ghostty
with filename arguments that contain spaces.

See #2633, #3030
2026-02-05 09:45:00 -05:00
Jon Parise 1ff0dd821f macos: quote input strings used for shell commands
When we're building an input string that's explicitly meant to be used
as a shell command, quote (escape) it using the same logic as Python's
shlex.quote function.

This specifically addresses issues we've seen when open(1)'ing Ghostty
with filename arguments that contain spaces.
2026-02-05 09:21:37 -05:00
Bug-Reaper 8a87378f00 👻 : Add Support For Apple's New API - Core Audio Tap API `CATap`
[Reference](https://github.com/insidegui/AudioCap). This is Apple's latest system for allowing apps to access loopback audio streams eg: Desktop-Audio, Window-Audio, etc...
2026-02-05 00:37:24 -05:00
Mitchell Hashimoto 2d02e4bb54
remove redraw_inspector message 2026-02-01 14:32:37 -08:00
Mitchell Hashimoto 020fe35c48
macos: render inspectors on timed updates, pause when occluded 2026-02-01 14:22:10 -08:00
Mitchell Hashimoto fb8cb162ce
macos: Ghostty.Inspector 2026-01-31 09:22:26 -08:00
Mitchell Hashimoto 32f5677a94
macos: slow down inspector trackpad (precision) scrolling 2026-01-27 08:34:35 -08:00
Mitchell Hashimoto 0de5f43254
macos: filter only supported commands in the command palette
This got accidentally regressed when we did the jump options.
2026-01-27 08:17:22 -08:00
Mitchell Hashimoto 6ace63acc4
macOS: xib changes from xcode
Literally just opening these on Xcode 26.2 does this, so we should
commit it lol.
2026-01-27 08:10:00 -08:00
Mitchell Hashimoto 338c9b15aa
splits: make resize_split and toggle_split_zoom non-performable with single pane (#10376)
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
2026-01-22 08:23:57 -08:00
MrConnorKenway 02d6dc0672 feat(macos): focus surface view if search box is manually closed 2026-01-22 09:25:47 +08:00
Mitchell Hashimoto 6730afe312
macOS: Add GhosttyUITests (Drafting to save some ci checks) (#9185)
### Background

~~I was trying to add a few UI test cases for
`macOS-titlebar-style`[Already in this PR]~~. In order to do this, I
need a way from `GhosttyKit` to load a temporary configuration without
messing around with users'.

### Changes

- Add `ghostty_config_load_file` using the existing
[`loadFile`](dafb9e89a3/src/config/Config.zig (L3399))
- Use `xcbeautify` to format test&build errors
**Couldn't find a way to do this in `GhosttyXcodebuild`, if you have a
better approach please let me know!**
- Add GhosttyUITests target and test cases for
`GhosttyTitlebarTabsUITests`(#2349) and `GhosttyThemeTests`(#9360)

### NOTE

Running UI tests on the runner could be **very** slow and I couldn't
find a way to guarantee success, so I made these only runnable by
manually testing in Xcode.

Better to squash this🤪

> > Some of the test cases could fail when testing all the cases
together; a rerun would succeed.
2026-01-20 09:30:39 -08:00
Lars 3fda31a66a skip checking config file 2026-01-20 09:15:14 -08:00
Lars bfe5a4be8f move config loading to Config 2026-01-20 09:15:14 -08:00
Lukas 32562e0c98 Update macos/Sources/Ghostty/Ghostty.App.swift
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-20 09:15:14 -08:00
Lars 35b2e820ce typo fix 2026-01-20 09:15:14 -08:00
Lars 4154a730ee Fix some edge cases 2026-01-20 09:15:14 -08:00
Lars 27729bf8a7 only run ui tests manually with xcode 2026-01-20 09:15:14 -08:00
Lars 85da70c98d Add more theme test cases from #9360 2026-01-20 09:15:14 -08:00
Lars 4aabd94716 add theme tests 2026-01-20 09:15:14 -08:00
Lars d9ed325818 update config explicitly 2026-01-20 09:15:14 -08:00
Lars 6ada9c7844 test: add test for mergeAllWindows 2026-01-20 09:15:14 -08:00
Lars f52013787e test: using XCTAssertEqual to get more information 2026-01-20 09:15:14 -08:00
Lars f088ce38d9 test: read config before launching XCUIApplication 2026-01-20 09:15:14 -08:00
Lars f7608d0b95 macOS: reduce press duration 2026-01-20 09:15:14 -08:00
Lars b1290dc47b macOS: add titlebar tabs tests 2026-01-20 09:15:14 -08:00
Lars bcf42dde6c build: change deployment target 2026-01-20 09:15:14 -08:00
Lars a94a6e4b36 build: fix Ghostty-iOS compiling 2026-01-20 09:15:14 -08:00
Lars 4f667520fa macOS: GhosttyUITests 2026-01-20 09:15:14 -08:00
Mitchell Hashimoto 2db80e278e
feat(macos): if the search box is empty directly close the box (#10384)
referring to the discussion:
https://github.com/ghostty-org/ghostty/discussions/9814

This is a very small change addressing the behavior for closing the
search bar. This removes an extra step when closing the search bar if
the query is empty
2026-01-20 08:33:43 -08:00
Tim Culverhouse 5ee56409c7
macos: support mouse buttons 8/9 (back/forward)
Add support for mouse buttons 4-11 in the macOS app. Previously only
left, right, and middle buttons were handled. Now otherMouseDown/Up
events properly map NSEvent.buttonNumber to the corresponding Ghostty
mouse button, enabling back/forward button support.

Fixes: https://github.com/ghostty-org/ghostty/issues/2425
Amp-Thread-ID: https://ampcode.com/threads/T-019bd74e-6b2b-731d-b43a-ac73b3460c32
Co-authored-by: Amp <amp@ampcode.com>
2026-01-19 11:59:50 -06:00
Steven Lu 6db4e437ca splits: make resize_split and toggle_split_zoom non-performable with single pane
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
2026-01-19 17:34:34 +07:00