Fixes#5522
This commit re-dispatches command inputs that are unhandled by our macOS
app so they can be encoded to the pty and handled by the core libghostty
key callback system.
We've had a special case `cmd+period` handling in Ghostty for a very
long time (since well into the private beta). `cmd+period` by default
binds to "cancel" in macOS, so it doesn't encode to the pty. We don't
handle "cancel" in any meaningful way in Ghostty, so we special-cased it
to encode properly to the pty.
However, as shown in #5522, if the user rebinds `cmd+period` at the
system level to some other operation, then this is ignored and we encode
it still. This isn't desirable, we just want to work around not caring
about "cancel."
The callback path that AppKit takes for key events is a bit convoluted.
For command keys, it first calls `performKeyEquivalent`. If this returns
false (we want to continue standard processing), then it calls EITHER
`keyDown` or `doCommand(by:)`. It calls the latter if there is a
standard system command that matches the key event. For `cmd+period` by
default, this is "cancel." Unfortunately, from `doCommand` we can't say
"oops, we don't want to handle this, please continue processing." Its
too late.
So, this commit stores the last command key event from
`performKeyEquivalent` and if we reach `doCommand` for it without having
called `keyDown`, we re-dispatch the event and send it to keyDown.
I'm honestly pretty sus about this whole logic but it is scoped to only
command-keys and I couldn't trigger any adverse behavior in my testing.
It also definitely fixed#5522 as far as I could reproduce it before.
Fixes#5448
We previously removed the ctrl modifier for text commit (IME-style)
to workaround a libghostty quirk (as noted in the comment in the diff).
But this broke other keyboard layouts.
This commit attempts to clean this up slightly -- but not completely --
by removing that hack, and only modifying the ctrl behavior for the
UCKeyTranslate call.
Long term, I plan to remove UCKeyTranslate completely, as noted in the
todo comment already written just below this diff.
This fixes the aforementioned issue and hopefully doesn't regress any
other behavior. I tested the following:
1. Dvorak Ctrl characters
2. Ergo-L Ctrl characters
3. US standard Ctrl characters
4. Japanese IME input Ctrl input to modify IME state
Fixes#4799
This PR attempts to reduce the flash caused by the ghost emoji in the
title bar when opening new windows.
## Changes:
- Initialize `SurfaceView.title` with empty string instead of ghost
emoji
- Simplify title computation logic in `TerminalView`
- Adding a 500ms fallback timer for "👻"
- Canceling timer if title is set
## Current Status:
While these changes reduce the initial ghost emoji flash, there's still
a brief moment where a folder emoji appears alone in the title bar when
opening a new window. This suggests there might be a race condition or
timing issue with how the title is being set and updated.
https://github.com/user-attachments/assets/3688c9f3-1727-4379-b04d-0bd6ac105728
Would appreciate feedback on the remaining flash issue and suggestions
for further improvements.
Fixes: https://github.com/ghostty-org/ghostty/issues/4634#issuecomment-2573469532
This commit fixes two issues:
1. `libghostty` must not override ctrl+key inputs if we are in a preedit
state. This allows thigs like `ctrl+h` to work properly in an IME.
2. On macOS, when an IME commits text, we strip the control modifier
from the key event we send to libghostty. This is a bit of a hack but
this avoids triggering special ctrl+key handling.
Fixes#4539
AquaSKK is a Japanese IME (Input Method Editor) for macOS. It uses
keyboard inputs to switch between input modes. I don't know any other
IMEs that do this, but it's possible that there are others. Prior to
this change, the keyboard inputs to switch between input modes were
being sent to the terminal, resulting in erroneous characters being
written.
This change adds a check during keyDown events to see if the input
source changed _during the event_. If it did, we assume an IME captured
it and we don't pass the event to the terminal.
This makes AquaSKK functional in Ghostty.
Fixes#3117
On mouseExit we sent a cursor position event with (-1, -1). Negative
values are meant to indicate that the cursor is not on the surface. The
magnitude of the values are irrelevant. However, we never reset the
cursor position on mouseEnter.
This has the effect of the previous cursor position being stuck outside
the viewport which makes certain things such as `button` mouse reporting
not report until the mouse is moved.
This commit sends the correct cursor position event on mouseEnter.
Related to #2731
I'm not fully sure if this will fix this issue since I can't reproduce
it but I don't see a downside to doing this and it might fix it.
Fixes#3072
Previously, when `window-theme = auto`, the appearance was delayed
enough on the DispatchQueue that the window was already visible. This
would result in the window appearing with the wrong appearance before
switching to the correct one.
For annoying reasons, we can't set the NSApplication.shared.appearance
in `applicationDidFinishLaunching` because it results in a deadlock with
AppKit.
This commit moves to set the `NSWindow.appearance` in `windowDidLoad`
(and any config sync) to ensure that the appearance is set before the
window is visible.
This is probably the right solution anyways because this allows windows
with different background colors to each have their own distinct
appearance.
Fixes#2695
We had various issues with the pointerVisible property on macOS,
including the pointer not being hidden when it should be. Our only use
case today is mouse hide while typing so
NSCursor.setHiddenUntilMouseMoves is a better fit!
The bug: ctrl+shift+enter on macOS 15 shows a context menu and doesn't
encode to the terminal.
This avoids a system-wide keybind that shows a context menu in macOS
15+. In general Ghostty doesn't try to override system-wide keybinds
but this one is particularly annoying and not useful to terminal users.
We've discussed making this logic configurable for all system level
keybinds but for now this is a quick fix specifically for
ctrl+shift+enter.
macOS 12 is officially EOL by Apple and the project only supports
officially supported versions of macOS. Once publicly released, users on
older macOS versions will have to use older released builds.
This was recently introduced a few days ago. Unfortunately, this doesn't
work as expected. The "function" modifier is not actually the fn key
but used by macOS to represent a variety of "functional" key presses.
This breaks other bindings such as #2411.
I can't find a source on the internet that reliably tells me how we
can detect fn key presses, but I do find a number of sources that tell
us we can't.
Fixes#2370
Comparing NSScreens directly was fragile. It appears that AppKit/Cocoa
can return different instances of NSScreen for the same screen for
unknown reasons between calls to windowDidChangeScreen. I don't fully
understand why this happens.
In any case, our comparison was not safe. Instad, we now keep track of
of the CGDirectDisplayID for each screen and compare those instead.
First, this commit modifies libghostty to use a single unified action
dispatch system based on a tagged union versus the one-off callback
system that was previously in place. This change simplifies the code on
both the core and consumer sides of the library. Importantly, as we
introduce new actions, we can now maintain ABI compatibility so long as
our union size does not change (something I don't promise yet).
Second, this moves a lot more of the functions call on a surface into
the action system. This affects all apprts and continues the previous
work of introducing a more unified API for optional surface features.
Fixes#2283
macOS <= 14 crash with an invalid NSEvent error. macOS 15 seems to just
ignore the blank event. We just got lucky with this. Since we don't
override mouseEntered/Exited anymore we can remove this completely.
The regression was from: e89a4f74089b66c00043096589dc75fff5ab6674
Fixes#1547
The core change to make this work is to make the cursor position
callback support taking updated modifiers. On both macOS and GTK, cursor
position events also provide the pressed modifiers so we can pass those
in.
Fixes#2149
Previously, the way we were getting the updated surface size would use
outdated (previous) values because the resize event was not processed by
the surface before the SwiftUI view processed the resize overlay. And
since the property we used wasn't `@Published`, we didn't get notified
when we got that updated value.