Fixes#7286
Previously, when using the "New Ghostty Window/Tab Here" macOS service
on a file, the new terminal window/tab would incorrectly open in the
user's home directory. This was because the service handler only
expected directory paths.
This commit updates the service handler to check if the provided path is
a file. If it is, the handler now uses the file's parent
directory as the working directory for the new Ghostty window or tab,
aligning with user expectations. If the path is a directory, it's used
directly as before.
Fixes#7337
AppKit encodes functional keys as PUA codepoints. We don't want to send
that down as valid text encoding for a key event because KKP uses that
in particular to change the encoding with associated text.
I think there may be a more specific solution to this by only doing this
within the KKP encoding part of KeyEncoder but that was filled with edge
cases and I didn't want to risk breaking anything else.
Fixes#7236
Supersedes #7249
This removes all of our `focusedValue`-based tracking of the surface
title and moves it completely to the window controller. The window
controller now sets up event listeners (via Combine) when the focused
surface changes and updates the window title accordingly.
There is some complicated logic here to handle when we lose focus to
something other than a surface. In this case, we want our title to be
the last focused surface so long as it exists.
Fixes#6999
It appears that at some point one of the operations causes focus to move
away for non-native fullscreen. We previously relied on the delegate
method to restore this but a better approach appears to handle this
directly in the fullscreen implementations. This fixes the linked issue.
I still think long term all the `Ghostty.moveFocus` stuff is a code
smell and we should be auditing all that code to see if we can
eliminate it. But this is a step in the right direction, and removes one
of those uses.
Fixes#7114
Supercedes #7271
This fixes a crash that could occur with non-native fullscreen and
`fullscreen = true` set at once.
The "windowNumber" can be `<= 0` if the window "doesn't have a
window device." I don't fully know all the scenarios this is true but it
is true when the window is not visible, at least.
#7173
(1) The command palette no longer has any selection by default.
If and when we introduce most recently used commands, defaulting to that
would make sense. A selection only appears when the arrow keys are used
or the user starts typing.
(2) The selection with arrow keys now wraps, so if you press "down" on
the last option, it will wrap to the first option, and if you press "up"
on the first option, it will wrap to the last option. This matches both
VSCode and Zed.
Removes the withAnimation closure which caused flashing when scrolling
up or down with arrow keys. Also removes the center anchor to behave
more like other command palletes (e.g., Zed, Raycast).
This introduces a command palette (inspired by @pluiedev's work in
#5681, but not using it as a base) for macOS.
The command palette is available in the `View` menu and also bindable
via `toggle_command_palette`, default binding is `cmd+shift+p` to match
VSCode.
The commands in the command palette must map to a _bindable_ action,
though they may not have an associated keybinding. This means that any
new binding actions we add in the future can be represented here and
also makes it easy in the future to add configuration to add new custom
entries to the command palette. For this initial PR, the available
commands are hardcoded (`src/input/commands.zig`).
I've noticed in other programs (VSCode, Zed), the command palette
contains pretty much _all available actions_ even if they're basically
useless in the context of a command palette. For example, Zed has the
"toggle command palette" action in the command palette and it... does
nothing (it probably should hide the palette). I followed @pluiedev's
lead and made this subjective in this PR but I wonder if we should
actually force all binding actions to be available.
There are various other improvements I'd like to make but omitted from
this PR for the sake of limiting scope:
* Instead of an entry with no matches doing nothing, we can allow users
to manually input _any_ configurable binding.
* Localization, since macOS doesn't have any yet. But for Linux when we
port this we probably have to change our strings extraction.
## Demo
https://github.com/user-attachments/assets/a2155cfb-d86b-4c1a-82b5-74ba927e4d69
Resolves#7108
This PR adds visual notification badges to the Ghostty dock icon when
bell events are triggered while the application is in the background.
This complements the existing dock bounce notification, making it easier
for users to notice when a terminal needs attention.
https://github.com/user-attachments/assets/b54c881f-fea8-4085-8614-432d9e5847b9
Fixes a regression where `C-S-c` stopped working properly in both legacy
and Kitty modes (although the Kitty mode side only affected alternates
and not the key itself so it probably worked fine in most programs).
The issue is that `charactersIgnoringModifiers` changes behavior if
`control` is pressed, so it doesn't really ignore all modifiers. We have
to use `characters(byApplyingModifiers:)` to get the proper unshifted
codepoint when `control` is pressed.
This replaces the use of our custom `Ghostty.KeyEquivalent` with the
SwiftUI `KeyboardShortcut` type. This is a more standard way to
represent keyboard shortcuts and lets us more tightly integrate with
SwiftUI/AppKit when necessary over our custom type.
This PR should have no user impact. This is just some cleanup for future
work.
Note that not all Ghostty triggers can be represented as
KeyboardShortcut values because macOS itself does not support binding
keys such as function keys (e.g. F1-F12) to KeyboardShortcuts.
This isn't an issue since all input also passes through a lower level
libghostty API which can handle all key events, we just can't show these
keyboard shortcuts on things like the menu bar. This was already true
before this commit.
Fixes a regression where `C-S-c` stopped working properly in both legacy
and Kitty modes (although the Kitty mode side only affected alternates
and not the key itself so it probably worked fine in most programs).
The issue is that `charactersIgnoringModifiers` changes behavior if
`control` is pressed, so it doesn't really ignore all modifiers. We have
to use `characters(byApplyingModifiers:)` to get the proper unshifted codepoint
when `control` is pressed.
This replaces the use of our custom `Ghostty.KeyEquivalent` with
the SwiftUI `KeyboardShortcut` type. This is a more standard way to
represent keyboard shortcuts and lets us more tightly integrate with
SwiftUI/AppKit when necessary over our custom type.
Note that not all Ghostty triggers can be represented as
KeyboardShortcut values because macOS itself does not support
binding keys such as function keys (e.g. F1-F12) to KeyboardShortcuts.
This isn't an issue since all input also passes through a lower level
libghostty API which can handle all key events, we just can't show these
keyboard shortcuts on things like the menu bar. This was already true
before this commit.