Commit Graph

63 Commits

Author SHA1 Message Date
Mitchell Hashimoto
2de1596115 macos: normalize action working directory paths
Discussion #14048

Directory URLs no longer export a trailing slash through PWD, which
keeps zsh's %1~ prompt expansion from resolving to an empty string.

A shared URL helper removes trailing separators while preserving the
filesystem root and percent-decoding behavior. Tests cover normal,
repeated, encoded, and root paths.
2026-08-27 14:35:01 -07:00
Lukas
6229d4eb62 macOS: fix AppleScript send key for non-control keys
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 17:49:02 +02:00
Mitchell Hashimoto
1c739350c3 macOS: add test cases for ScriptKeyEventCommand (#14008)
Partial changes for #13205, known issues are marked as warnings.

### AI Disclosure

Claude generated these tests from linked pr, I cherrypicked and reviewed
myself.
2026-08-25 05:41:14 -07:00
Lukas
f1b9efed80 macOS: update default behaviour of KeyboardLayout.character(for:modifiers:) 2026-08-25 13:56:21 +02:00
Lukas
d7f5ba3b4f macOS: add test cases for ScriptKeyEventCommand
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 13:37:58 +02:00
Lukas
6a508fd5e3 macos: translate physical menu shortcuts (#13888)
Translate printable physical keybindings through the current macOS
keyboard layout before assigning menu key equivalents. Previously these
bindings could not be represented because SwiftUI shortcuts are
character-based, so actions such as `super+backquote` had no native menu
shortcut.

Keep native keycodes as dispatch identity so translated display
characters do not change physical semantics or precedence over Unicode
bindings. Refresh shortcuts when the input source changes, and prevent
AppKit from transforming equivalents that are already localized.

**AI Usage:** The approach was suggested by GPT 5.6 Sol, but I wrote
most of the code and understand it all.
2026-08-24 09:55:02 +02:00
Lukas
fd17869d15 macOS: rework for #10943
Keep the background color as it is and apply glass effect on top of it
2026-08-20 13:30:33 +02:00
Jon Parise
9886f4817c macos: enforce keyboard layout actor isolation
Text Input Sources APIs are not thread-safe, but shortcut translation could
be called outside a declared main-actor context.

Mark keyboard layout and shortcut conversion as main-actor isolated, update
their tests, and dispatch key-sequence UI notifications to the main queue
before translating their shortcuts.
2026-08-18 12:40:28 -04:00
Jon Parise
761696c349 macos: simplify menu shortcut identity
Separate menu shortcut presentation from lookup identity. Store either a
normalized key equivalent or a physical keycode in a private hashable enum,
allowing Swift to synthesize equality and hashing instead of maintaining
parallel optional-key logic.

Assign display characters directly from KeyboardShortcut and remove unused
NSMenuItem and SwiftUI conversion helpers.
2026-08-18 11:49:46 -04:00
Jon Parise
569ff3307c macos: translate physical menu shortcuts
Translate printable physical keybindings through the current macOS
keyboard layout before assigning menu key equivalents. Previously these
bindings could not be represented because SwiftUI shortcuts are
character-based, so actions such as super+backquote had no native menu
shortcut.

Keep native keycodes as dispatch identity so translated display characters
do not change physical semantics or precedence over Unicode bindings.
Refresh shortcuts when the input source changes, and prevent AppKit from
transforming equivalents that are already localized.
2026-08-18 11:27:06 -04:00
Jon Parise
5c952ac977 macos: simplify command palette sort keys
Store the Comparable ObjectIdentifier directly instead of wrapping the
only sort key type in AnySortKey.

The expected deterministic ordering of equal terminal command titles is
also now verified by a unit test.
2026-08-17 12:50:27 -04:00
Lukas
daab08ec01 macOS: drop the cross-platform check and abstraction
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 14:00:03 +02:00
Mitchell Hashimoto
8c9fd7aa79 macos: normalize command paths as file URLs
#13319
#13748

Normalize command-line file arguments as file URLs internally while
keeping the AppKit and FileManager string boundaries unchanged.

This handles relative paths, URL-sensitive characters, and trailing
directory separators consistently when matching duplicate open-file
events.
2026-08-11 09:15:05 -07:00
Mitchell Hashimoto
90154e2895 macos: ignore -e arguments as open files
Fixes #13319

AppKit treats existing positional arguments as documents, causing paths
passed to a child command after -e to open an extra terminal surface.

We now process args ourselves during openFile callbacks to ignore 
file paths after `-e`. There isn't a way to avoid this I can find
because AppKit processes argc/argv from the main entrypoint and that
can't be overridden.
2026-08-11 08:30:32 -07:00
Lukas
49e4df7833 macOS: rework for #12712 and #13645 2026-08-09 23:19:47 +02:00
Lukas
76907d8de8 macOS: remove flaky color match tests 2026-08-06 15:11:48 +02:00
Mitchell Hashimoto
e88601239d macOS: update command options match order (#13624)
Matches are sorted in the following order:
leadingColor > title > subtitle > description.

Ranking is lexicographic on (colorScore, textScore)

<img height="300" alt="image"
src="https://github.com/user-attachments/assets/1ec99e67-537e-4fc6-b595-d7eec8cbf31d"
/>


### AI Disclosure

Claude reviewed and added unit tests, also did some refactoring of my
original implementation.
2026-08-05 15:29:50 -07:00
Mitchell Hashimoto
74f01cf5df macos: prevent stale search selection crash
Fixes #13266

Keep search text and its selection range synchronized as a single
state transition.

Deleting or replacing a search term could leave a String.Index range
from the old value attached to the text field. Applying that range
could crash the app.

Clear selection before publishing new text.
2026-08-05 14:02:46 -07:00
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
Claude Fable 5
d02ad967b6 macOS: update command options match order
Matches are sorted in the following order:
leadingColor > title > subtitle > description.

Ranking is lexicographic on (colorScore, textScore)
2026-08-05 16:15:01 +02:00
Lukas
c93752a008 macOS: suppress restart tips for auto update 2026-08-05 15:15:40 +02:00
Lukas
a86c49d7af macOS: rename UpdateState.isIdle to isHidden 2026-08-04 22:38:35 +02:00
Mitchell Hashimoto
f815f84594 macos: fix quick terminal restoring stale size after display reconnect (#13250)
"Why is my quick terminal not taking up the entire top of my docked Mac
screen after I reconnect?" Boy howdy are you in the right PR.

It turns out that the quick terminal caches its last-closed window frame
per display so it can restore the user's size when reopened. The cache
entry was considered valid whenever the current screen was the same size
*or larger* than when the frame was saved ("persist when screens grow").
This has led to a pattern that was simply maddening. To wit: that rule
breaks across display changes.

When an external display is disconnected and later reconnected at a
different resolution (common after traveling with a laptop, do not even
get me started on projectors) the same display can come back larger than
when the frame was cached. The stale frame is still treated as valid and
restored, so the quick terminal no longer fills the screen (it appears
at a partial width/height). Because the cache is persisted, restarting
Ghostty does not clear it, and the user is slowly driven mad. Welcome to
madness; we have snacks.

This PR addresses this by treating a cached frame as valid when the
screen geometry matches exactly (both backing scale factor and frame
size). On any mismatch we drop the entry and fall back to the configured
quick-terminal-size. Manual resizes are still remembered across toggles
within a stable display configuration.

Fixes the regression reported in #12348.

AI disclaimer: I used AI for this. Of course I used AI for this, my code
is terrible on a good day. Specifically, Claude Code, as well as a
custom harness that has the curious tendency to write commit messages
containing conspiracy theories about the code because I am history's
greatest monster.

Fight me!
2026-07-08 10:49:39 -07:00
Claude Fable 5
acd09c0a6c macos: add tests for NSPasteboard.getOpinionatedStringContents 2026-07-03 12:53:34 +02:00
Corey Quinn
0274e7ad84 macos: fix quick terminal restoring stale size after display reconnect
The quick terminal caches its last-closed window frame per display so it
can restore the user's size when reopened. The cache entry was considered
valid whenever the current screen was the same size *or larger* than when
the frame was saved ("persist when screens grow"). This has led to a pattern
that was simply maddening. To wit:

That rule breaks across display changes. When an external display is
disconnected and later reconnected at a different resolution (common
after traveling with a laptop) the same display can come back larger
than when the frame was cached. The stale frame is still treated as valid
and restored, so the quick terminal no longer fills the screen (it appears
at a partial width/height). Because the cache is persisted, restarting
Ghostty does not clear it, and the user is slowly driven mad.

Only treat a cached frame as valid when the screen geometry matches
exactly (both backing scale factor and frame size). On any mismatch we
drop the entry and fall back to the configured quick-terminal-size. Manual
resizes are still remembered across toggles within a stable display
configuration.

Fixes the regression reported in #12348.
2026-06-29 15:31:07 -07:00
Nolin McFarland
bf716a0c39 feat: add extension to normalize OSPasteboard string interface 2026-05-18 10:12:26 -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
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
72c03e7fb8 macOS: add window restoration tests 2026-04-25 21:06:20 +02:00
Lukas
fe8a6464b9 macOS: update MenuShortcutKey 2026-04-13 19:56:56 +02:00
Lukas
18f2702225 macOS: fix Find Next/Previous button in the menu bar is not working as expected 2026-04-02 20:31:31 +02:00
Lukas
702a2b43c3 macOS: fix upper cased letter is not correctly mapped to menu shortcut 2026-04-01 14:50:53 +02:00
Lukas
1845dd26b6 macOS: extract menu shortcut syncing into MenuShortcutManager 2026-03-30 16:09:21 +02:00
Lukas
65cd31dc79 macOS: add NormalizedMenuShortcutKeyTests 2026-03-30 15:47:07 +02:00
Lukas
5c5f645b61 macOS: support reloading temporary config for testing 2026-03-30 15:47:07 +02: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
Lukas
de0f2ab22d macos: add enum type for macos-titlebar-style 2026-03-10 17:15:14 +01: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
Jon Parise
a716b9c4d4 macos: Ghostty.Shell.escape unit tests 2026-03-04 11:00:03 -05: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
Mitchell Hashimoto
eaf7d8a012 macos: icon tests 2026-02-24 10:26:13 -08:00
Lukas
c72788894e ci: fix linting and delete non-useful tests 2026-02-24 10:13:24 +01:00
Lukas
45525a0a85 macOS: use NSDockTilePlugIn to update app icons 2026-02-24 08:58:14 +01:00
Jon Parise
b532cd55d6 macos: swiftlint 'trailing_whitespace' rule 2026-02-19 18:56:43 -05: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