Commit Graph

1923 Commits (main)

Author SHA1 Message Date
YuWiz ef68e96400 macos: fix GHOSTTY_QUICK_TERMINAL not set for quick terminal splits 2026-06-02 16:48:36 +08:00
Claude Opus 4.7 eb5c1c7220
fix(macos): mark Swift os.Logger interpolations as public 2026-05-31 16:35:11 +02:00
Jon Parise e32d7abe6e macos: fix swiftlint opening_brace issue 2026-05-31 10:00:24 -04:00
Jon Parise 33adb58bee macos: remove unneeded initializers
These will be automatically synthesized (they only do memberwise
initialization) and do not need to be manually defined.
2026-05-31 09:54:41 -04:00
Mitchell Hashimoto 3103ae8838
macos: avoid duplicate appearance sync on tab focus (#12828)
Close #12825

Skip the initial emissions from the focused surface appearance
publishers after a tab focus change. The focused surface is already
synced immediately, so the initial Combine values only repeat the same
titlebar and background updates. Subsequent derived config and OSC
background changes still resync the window appearance.



https://github.com/user-attachments/assets/f229fb95-4b4c-4040-85ac-0acfcc54ca82



Assigned to Codex GPT 5.5(medium)
PS: Sry for I don't write zig and let AI write this.
2026-05-27 07:52:42 -07:00
Tunglies 5368adcd29
macos: avoid duplicate appearance sync on tab focus
Close #12825

Skip the initial emissions from the focused surface appearance publishers after a tab focus change. The focused surface is already synced immediately, so the initial Combine values only repeat the same titlebar and background updates. Subsequent derived config and OSC background changes still resync the window appearance.
2026-05-27 19:43:41 +08:00
Adam Bouker 57d202066d macOS: clear stale OSC 11 background cache on config change
SurfaceView caches the background color set by OSC 11 in
backgroundColor. TerminalWindow.preferredBackgroundColor consults
that cache before falling back to derivedConfig.backgroundColor,
so once OSC 11 has fired the cached value masks any later config
change. After a light/dark theme auto-switch this leaves the
window chrome on the previous theme's color until the application
next emits OSC 11.

In ghosttyConfigDidChange, after updating derivedConfig, drop the
cache when it no longer matches the new config-derived background.
A subsequent ghosttyColorDidChange repopulates it as before, so
within-config OSC 11 behavior is unchanged.
2026-05-26 14:11:45 -05:00
minorcell da541bea63 fix stray brace from conflict resolution 2026-05-23 16:33:33 +08:00
minorcell 7a346dd8d4 macOS: fix search bar Enter key blocking IME composition
Use onSubmit for the plain Enter → next-match behavior, which respects
IME composition state. Keep onKeyPress only for Shift+Enter (previous
match), returning .ignored for plain Enter so the IME can process it.
2026-05-23 16:09:48 +08:00
Mitchell Hashimoto 3e3705b932
macOS: fix surface focus/render state after dragging in to to another window/tab (#12338)
Fixes 2 bugs

1. After dragging a non-focused surface from window A to window B
**quickly without making B the key window**, the focused surface in
window A is not receiving `keyDown` events.


https://github.com/user-attachments/assets/a8861c0a-9300-470d-bf7e-0f32a9ab2cd1

2. #12343 After dragging a surface from tab A to tab B within the same
window, the dragged surface is not rendering input correctly.
> The reason the thread is stuck is because the surface's occlusion
state is set to invisible after target tab's activate while dragging,
since the dragged surface is still in previous tree before dropping, and
after dropping the occlusion state of this surface is not updated to
visible, which causing the surface is accepting input but not rendering.



https://github.com/user-attachments/assets/d67f5dba-8609-4f67-a956-921982faf796
2026-05-22 09:05:11 -07:00
Mitchell Hashimoto b78174a68f
macOS: update window appearance for About and ConfigurationErrors (#12601)
<img width="1224" height="696" alt="Xnip2026-05-06_19-13-31"
src="https://github.com/user-attachments/assets/ab090dc0-7c06-4a01-8e7c-5d48ca6ccca3"
/>
2026-05-22 08:58:26 -07:00
Mitchell Hashimoto 7e24f0e0bc
macOS: use find pasteboard for search needle (#12712)
Fixes the issue described in #12516.

### What
- Inject an `OSPasteboard` into `SearchState`
- Add `OSPasteboard` extension to normalize working with strings between
UIPasteboard/NSPasteboard
- Add `BackportSelectionTextField` which supports text selection for
MacOS 15/iOS 18 and up.
- Read from the pasteboard when the overlay opens and when the app
becomes active
- Write to the pasteboard when the search needle changes
- Annotate `SearchState` as MainActor. `NSPasteboard` isn't thread safe,
and since `SearchState` is already accessed from the main thread,
MainActor enforces our writes be thread safe
- Add SearchState unit tests

### Why
Consistent with other macOS apps, the Find bar's search needle should
persist when re-opened and should sync to the Find bar in other apps.
For example, see Xcode, Notes, Terminal, and Safari.


https://github.com/user-attachments/assets/b6a55a4a-a52c-45bc-ac38-c9df452c11cb
2026-05-22 08:57:45 -07:00
Mitchell Hashimoto afe4819920
macOS: Re-enable global keybinds after event tap disable events (#12714)
While testing https://github.com/ghostty-org/ghostty/pull/9857, I
encountered the behavior mentioned below. It's pretty frustrating to
encounter, so I've been actually compiling this fix into my test builds
for last month or so, and the issue has not come back. I exclusively use
the QuickTerminal, so my workflow depends on global keybinds working
reliably.

Issue: https://github.com/ghostty-org/ghostty/issues/12294

The solution includes listening to two events that are fired when a tap
is disabled:
- tapDisabledByTimeout
- tapDisabledByUserInput

When these are fired, we re-enable the tap.

Apple's Docs:
https://developer.apple.com/documentation/coregraphics/cgeventtype?language=swift

Related Discussions:
- https://github.com/ghostty-org/ghostty/discussions/11819
- https://github.com/ghostty-org/ghostty/discussions/12091
2026-05-22 08:56:16 -07:00
Lukas 00a989774e
macOS: add review windows when quitting
Inspired by Terminal.app
2026-05-19 20:01:32 +02:00
Lukas 8f9b86afa8
macOS: add confirmCloseAsync to return the actual response 2026-05-19 20:00:10 +02:00
Lukas 7f5c233492
macOS: add `windowCanBeClosedWithoutConfirmation` without any side effects 2026-05-19 19:56:09 +02:00
Lukas 3ac7562791
macOS: set error when there is no directory to open with 2026-05-19 09:58:44 +02:00
Lukas fdf84ef7ce
macOS: check the resource the URL refers to.
Fixes #12727. [`NSURL.hasDirectoryPath` doesn't do this](https://developer.apple.com/documentation/foundation/nsurl/hasdirectorypath).

We don't need to check this in NewTerminalIntent since AppIntent already appends `/` to the directory.
2026-05-19 09:58:44 +02:00
Nolin McFarland bf716a0c39 feat: add extension to normalize OSPasteboard string interface 2026-05-18 10:12:26 -04:00
Nolin McFarland ed52160612 feat: support BackportSelectionTextField on iOS 18 2026-05-17 12:33:56 -04:00
Nolin McFarland 69cab3d808 feat: select needle when reading from pasteboard 2026-05-17 11:26:32 -04:00
Nolin McFarland 8fa42c6ec0 feat: add search state unit tests 2026-05-16 20:05:11 -04:00
Nolin McFarland 59eece9a8e feat: use find pasteboard to store search needle 2026-05-16 19:59:20 -04:00
Lukas b6c6f7630a
macos: opacity-toggle setting persists between tabs in a window and to a newly created window (#11583) 2026-05-17 00:45:24 +02:00
Lukas 0226bcf034
macOS: update window appearance for About and ConfigurationErrors 2026-05-12 09:20:08 +02:00
Lukas 2c6dd59406
macOS: fix render_thread "stuck" after dragging surface to another tab within the same window
The reason the thread is stuck is because the surface's occlusion state is set to invisible after target tab's activate while dragging, since the dragged surface is still in previous tree before dropping, and after dropping the occlusion state of this surface is not updated to visible, which causing the surface is accepting input but not rendering.
2026-05-12 09:18:52 +02:00
Lukas 366c34831a
macOS: fix first responder after dragging a non-focused surface
This fixes a bug: after dragging a non-focused surface from window A to window B **quickly without making B the key window**, the focused surface in window A is not receiving `keyDown` events.
2026-05-12 09:18:51 +02:00
Jon Parise 2b48045731 macos: simplify workingDirectory setter
This is a minor improvement to the computed property's `set` logic: we
can just use `.map {}` to unify the two optional paths.
2026-05-09 14:37:43 -04:00
Lukas 607152ec6d
macOS: normalize working directory paths with FilePath
This fixes for nuShell when opening Ghostty via Finder service and Shortcuts, also makes path parsing more robust in AppleScript.
2026-05-09 12:47:46 +02:00
Akinori Musha d60a16c146 macos: avoid replaying keys that commit preedit
Refs #10460
Related: #12518

When an input method commits all or part of marked text during keyDown,
AppKit returns the committed text through insertText. Treat that as
text committed by the input method instead of replaying the original key
event to the terminal.

Previously this path only handled arrow-key commits specially. A
control-key shortcut that commits preedit text could still be encoded as
the original control input after composition, such as ctrl+j becoming LF.

Send committed preedit text as a text-only event for any key that causes
the commit. Only replay arrow navigation keys that the existing Korean
IME handling expects, and keep plain left-arrow suppressed because AppKit
already leaves the caret in place.

AI usage: OpenAI Codex helped investigate, implement, test, and refine
this change. I reviewed and tested the resulting code.
2026-05-01 23:18:42 +09:00
Mitchell Hashimoto 4dcb09ada0
macos: suppress control-char input while composing (#12518)
macos: suppress control-char input while composing

When AppKit delivers a single C0 control character during marked-text
composition, Ghostty should treat it as input consumed by the composing
state instead of forwarding it to the terminal.

This prevents control-key IME actions, such as Japanese input shortcuts
like ctrl+h/j/m/n, from leaking into the terminal while composition is
still active. Printable text and non-composing control input continue
through the normal key path.

Refs #10460
Related: #2628, #4539
Vouched in #12169

Testing:
- xcodebuild test -scheme Ghostty -destination platform=macOS
-only-testing:GhosttyTests/SurfaceViewAppKitTests
- Manually tested Japanese IME control-key shortcuts on macOS

AI usage:
- OpenAI Codex helped investigate, implement, test, and refine this
change. I reviewed and tested the resulting code.
2026-04-30 06:48:58 -07:00
Mitchell Hashimoto 95b56eb525
macOS: fix focus state when toggling command palette from inline title editor (#12524)
A bug found while recording that menu fix.
> ~~Will link to an open issue if there is one.~~

When toggling the command palette from the inline title editor, the
first responder state of the surface is changed quickly from true to
false.

`makeFirstResponder:` is called by the title editor when finishing, but
it happens **after** the command palette is shown, so the `focused` is
set to `true` while the command palette is shown. (Could be an AppKit
issue as well, since the resign is not called after but the command
palette is receiving `keyDown`.)

Since `performKeyEquivalent(with:)` is called on all of the subviews
until one of the return `true` so the paste action is consumed by the
surface instead of the first responder (command palette).
2026-04-30 06:42:12 -07:00
Mitchell Hashimoto 1623daf21c
macOS: enable copy only when there’s actual selected text (#12521)
This matches the `peformable` definition and the default behaviors of
text editing on macOS.
2026-04-30 06:41:04 -07:00
Lukas 61595b5ec9
macOS: fix focus state when toggling command palette from inline title editor 2026-04-29 22:41:18 +02:00
Lukas 6fdca6bb53
macOS: enable copy only when there’s actual selected text 2026-04-29 19:33:09 +02:00
Lukas dbffe994db
chore: remove Ghostty.xctestplan in project tree.
`lastKnownFileType = file` will change to `text` if you checking out branches with Xcode opened. But this was generated by Xcode in the first place.

Anyway we don't need it to be in the project tree to run the tests, and you can still open the test plan in scheme editor.
2026-04-29 19:24:03 +02:00
Akinori Musha a43cc02ebd macos: suppress control-char input while composing
When AppKit delivers a single C0 control character during
marked-text composition, Ghostty should treat it as input consumed by
the composing state instead of forwarding it to the terminal.

This prevents control-key IME actions, such as Japanese input
shortcuts like ctrl+h/j/m/n, from leaking into the terminal while
composition is still active. Printable text and non-composing control
input continue through the normal key path.

AI usage: OpenAI Codex helped investigate, implement, test, and refine
this change. I reviewed and tested the resulting code.
2026-04-29 22:50:35 +09:00
Lukas 97c5a21aba
macOS: fix ending search in menu bar does focus on surface 2026-04-27 19:03:06 +02:00
Lukas 1df7a5d3f3
macOS: update keybind for end_search 2026-04-27 18:55:31 +02:00
Lukas df365baf18
test: add test plan and override default config when running tests 2026-04-26 14:49:20 +02:00
Lukas a7eaecf929
test: always use temporary config when running ui tests 2026-04-26 13:53:36 +02:00
Lukas b66258806e
test: only change themes in theme tests 2026-04-26 13:53:36 +02:00
Mitchell Hashimoto 0e0bcafed5
macOS: remove manual invalidateRestorableState() (#12464)
This should be safe to delete now after #12461.

I tested saving 27 tabs, 4 with 2 splits,
`TerminalRestorable.encode(with:` finished successfully.

And I check the breakpoints when the Sparkle sends
`-[NSRunningApplication treminate]`. The call stack at `-[NSResponder
invalidateRestorableState]` is pretty much the same as quitting via
`cmd+q`.
2026-04-25 13:16:08 -07:00
Mitchell Hashimoto aedf39f3bd
macOS: support migrations when restoring window state (#12461)
First two commits fix the issue when upgrading from 1.2.x to 1.3.x.
(#11304)

> To double check if this pr really fixes the issue, you can either
archive a release build, sign with the same profile, and override
manually.
> 
> Or you can find the `savedState` files (located in `~/Library/Daemon\
Containers/<uuid>`), can copy them the local build dir (which is what I
did), and run the debug build.

Following commits add tests for migrations and some logs.

**Currently the minimum version is set to 1.2.x**, since there's a lot
changes comparing to 1.1.x. It will be difficult to restore
`Ghostty.SplitNode` -> `SplitTree<Ghostty.SurfaceView>` without
introducing a lot of checks.
2026-04-25 13:15:50 -07:00
Lukas 385376185c
macOS: remove manual invalidateRestorableState() 2026-04-25 21:25:38 +02:00
Lukas 231f6f4c75
macOS: move the restoration logs 2026-04-25 21:06:20 +02:00
Lukas 72c03e7fb8
macOS: add window restoration tests 2026-04-25 21:06:20 +02:00
Lukas bfe07bb99e
macOS: add InternalState to cover migrations 2026-04-25 20:25:17 +02:00
Lukas 5b89671d51
macOS: make terminal restorable state compatible with 1.2.3(v5) 2026-04-25 20:22:59 +02:00
Lukas 8ebf4f70e5
macOS: make tab color optional 2026-04-25 20:09:55 +02:00