mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Key events return boolean if handled
This commit is contained in:
@ -713,7 +713,7 @@ void ghostty_surface_set_color_scheme(ghostty_surface_t,
|
||||
ghostty_color_scheme_e);
|
||||
ghostty_input_mods_e ghostty_surface_key_translation_mods(ghostty_surface_t,
|
||||
ghostty_input_mods_e);
|
||||
void ghostty_surface_key(ghostty_surface_t, ghostty_input_key_s);
|
||||
bool ghostty_surface_key(ghostty_surface_t, ghostty_input_key_s);
|
||||
bool ghostty_surface_key_is_binding(ghostty_surface_t, ghostty_input_key_s);
|
||||
void ghostty_surface_text(ghostty_surface_t, const char*, uintptr_t);
|
||||
bool ghostty_surface_mouse_captured(ghostty_surface_t);
|
||||
|
@ -88,6 +88,7 @@
|
||||
A5CEAFDE29B8058B00646FDA /* SplitView.Divider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFDD29B8058B00646FDA /* SplitView.Divider.swift */; };
|
||||
A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFFE29C2410700646FDA /* Backport.swift */; };
|
||||
A5CF66D42D289CEE00139794 /* NSEvent+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CF66D32D289CEA00139794 /* NSEvent+Extension.swift */; };
|
||||
A5CF66D72D29DDB500139794 /* Ghostty.Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CF66D62D29DDB100139794 /* Ghostty.Event.swift */; };
|
||||
A5D0AF3B2B36A1DE00D21823 /* TerminalRestorable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D0AF3A2B36A1DE00D21823 /* TerminalRestorable.swift */; };
|
||||
A5D0AF3D2B37804400D21823 /* CodableBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D0AF3C2B37804400D21823 /* CodableBridge.swift */; };
|
||||
A5E112932AF73E6E00C6E0C2 /* ClipboardConfirmation.xib in Resources */ = {isa = PBXBuildFile; fileRef = A5E112922AF73E6E00C6E0C2 /* ClipboardConfirmation.xib */; };
|
||||
@ -179,6 +180,7 @@
|
||||
A5CEAFDD29B8058B00646FDA /* SplitView.Divider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitView.Divider.swift; sourceTree = "<group>"; };
|
||||
A5CEAFFE29C2410700646FDA /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; };
|
||||
A5CF66D32D289CEA00139794 /* NSEvent+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSEvent+Extension.swift"; sourceTree = "<group>"; };
|
||||
A5CF66D62D29DDB100139794 /* Ghostty.Event.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.Event.swift; sourceTree = "<group>"; };
|
||||
A5D0AF3A2B36A1DE00D21823 /* TerminalRestorable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalRestorable.swift; sourceTree = "<group>"; };
|
||||
A5D0AF3C2B37804400D21823 /* CodableBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableBridge.swift; sourceTree = "<group>"; };
|
||||
A5D4499D2B53AE7B000F5B83 /* Ghostty-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Ghostty-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@ -353,6 +355,7 @@
|
||||
A53D0C992B543F3B00305CE6 /* Ghostty.App.swift */,
|
||||
A514C8D52B54A16400493A16 /* Ghostty.Config.swift */,
|
||||
A53A6C022CCC1B7D00943E98 /* Ghostty.Action.swift */,
|
||||
A5CF66D62D29DDB100139794 /* Ghostty.Event.swift */,
|
||||
A5278A9A2AA05B2600CD3039 /* Ghostty.Input.swift */,
|
||||
A56D58852ACDDB4100508D2C /* Ghostty.Shell.swift */,
|
||||
A59630A32AF059BB00D64628 /* Ghostty.SplitNode.swift */,
|
||||
@ -621,6 +624,7 @@
|
||||
A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */,
|
||||
A5CBD0602CA0C90A0017A1AE /* QuickTerminalWindow.swift in Sources */,
|
||||
A5CBD05E2CA0C5EC0017A1AE /* QuickTerminalController.swift in Sources */,
|
||||
A5CF66D72D29DDB500139794 /* Ghostty.Event.swift in Sources */,
|
||||
A51BFC222B2FB6B400E92F16 /* AboutView.swift in Sources */,
|
||||
A5278A9B2AA05B2600CD3039 /* Ghostty.Input.swift in Sources */,
|
||||
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */,
|
||||
|
15
macos/Sources/Ghostty/Ghostty.Event.swift
Normal file
15
macos/Sources/Ghostty/Ghostty.Event.swift
Normal file
@ -0,0 +1,15 @@
|
||||
import Cocoa
|
||||
import GhosttyKit
|
||||
|
||||
extension Ghostty {
|
||||
/// A comparable event.
|
||||
struct ComparableKeyEvent: Equatable {
|
||||
let keyCode: UInt16
|
||||
let flags: NSEvent.ModifierFlags
|
||||
|
||||
init(event: NSEvent) {
|
||||
self.keyCode = event.keyCode
|
||||
self.flags = event.modifierFlags
|
||||
}
|
||||
}
|
||||
}
|
@ -773,7 +773,7 @@ extension Ghostty {
|
||||
if let list = keyTextAccumulator, list.count > 0 {
|
||||
handled = true
|
||||
for text in list {
|
||||
keyAction(action, event: event, text: text)
|
||||
_ = keyAction(action, event: event, text: text)
|
||||
}
|
||||
}
|
||||
|
||||
@ -783,29 +783,38 @@ extension Ghostty {
|
||||
// the preedit.
|
||||
if (markedText.length > 0 || markedTextBefore) {
|
||||
handled = true
|
||||
keyAction(action, event: event, preedit: markedText.string)
|
||||
_ = keyAction(action, event: event, preedit: markedText.string)
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
// No text or anything, we want to handle this manually.
|
||||
keyAction(action, event: event)
|
||||
_ = keyAction(action, event: event)
|
||||
}
|
||||
}
|
||||
|
||||
override func keyUp(with event: NSEvent) {
|
||||
keyAction(GHOSTTY_ACTION_RELEASE, event: event)
|
||||
_ = keyAction(GHOSTTY_ACTION_RELEASE, event: event)
|
||||
}
|
||||
|
||||
/// Special case handling for some control keys
|
||||
override func performKeyEquivalent(with event: NSEvent) -> Bool {
|
||||
// Only process key down events
|
||||
if (event.type != .keyDown) {
|
||||
switch (event.type) {
|
||||
case .keyDown:
|
||||
// Continue, we care about key down events
|
||||
break
|
||||
|
||||
default:
|
||||
// Any other key event we don't care about. I don't think its even
|
||||
// possible to receive any other event type.
|
||||
return false
|
||||
}
|
||||
|
||||
// Only process events if we're focused. Some key events like C-/ macOS
|
||||
// appears to send to the first view in the hierarchy rather than the
|
||||
// the first responder (I don't know why). This prevents us from handling it.
|
||||
// Besides C-/, its important we don't process key equivalents if unfocused
|
||||
// because there are other event listeners for that (i.e. AppDelegate's
|
||||
// local event handler).
|
||||
if (!focused) {
|
||||
return false
|
||||
}
|
||||
@ -819,13 +828,6 @@ extension Ghostty {
|
||||
return true
|
||||
}
|
||||
|
||||
// Only process keys when Control is active. All known issues we're
|
||||
// resolving happen only in this scenario. This probably isn't fully robust
|
||||
// but we can broaden the scope as we find more cases.
|
||||
if (!event.modifierFlags.contains(.control)) {
|
||||
return false
|
||||
}
|
||||
|
||||
let equivalent: String
|
||||
switch (event.charactersIgnoringModifiers) {
|
||||
case "/":
|
||||
@ -841,14 +843,25 @@ extension Ghostty {
|
||||
case "\r":
|
||||
// Pass C-<return> through verbatim
|
||||
// (prevent the default context menu equivalent)
|
||||
if (!event.modifierFlags.contains(.control)) {
|
||||
return false
|
||||
}
|
||||
|
||||
equivalent = "\r"
|
||||
|
||||
case ".":
|
||||
if (!event.modifierFlags.contains(.command)) {
|
||||
return false
|
||||
}
|
||||
|
||||
equivalent = "."
|
||||
|
||||
default:
|
||||
// Ignore other events
|
||||
return false
|
||||
}
|
||||
|
||||
let newEvent = NSEvent.keyEvent(
|
||||
let finalEvent = NSEvent.keyEvent(
|
||||
with: .keyDown,
|
||||
location: event.locationInWindow,
|
||||
modifierFlags: event.modifierFlags,
|
||||
@ -861,7 +874,7 @@ extension Ghostty {
|
||||
keyCode: event.keyCode
|
||||
)
|
||||
|
||||
self.keyDown(with: newEvent!)
|
||||
self.keyDown(with: finalEvent!)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -906,33 +919,38 @@ extension Ghostty {
|
||||
}
|
||||
}
|
||||
|
||||
keyAction(action, event: event)
|
||||
_ = keyAction(action, event: event)
|
||||
}
|
||||
|
||||
private func keyAction(_ action: ghostty_input_action_e, event: NSEvent) {
|
||||
guard let surface = self.surface else { return }
|
||||
|
||||
ghostty_surface_key(surface, event.ghosttyKeyEvent(action))
|
||||
private func keyAction(_ action: ghostty_input_action_e, event: NSEvent) -> Bool {
|
||||
guard let surface = self.surface else { return false }
|
||||
return ghostty_surface_key(surface, event.ghosttyKeyEvent(action))
|
||||
}
|
||||
|
||||
private func keyAction(_ action: ghostty_input_action_e, event: NSEvent, preedit: String) {
|
||||
guard let surface = self.surface else { return }
|
||||
private func keyAction(
|
||||
_ action: ghostty_input_action_e,
|
||||
event: NSEvent, preedit: String
|
||||
) -> Bool {
|
||||
guard let surface = self.surface else { return false }
|
||||
|
||||
preedit.withCString { ptr in
|
||||
return preedit.withCString { ptr in
|
||||
var key_ev = event.ghosttyKeyEvent(action)
|
||||
key_ev.text = ptr
|
||||
key_ev.composing = true
|
||||
ghostty_surface_key(surface, key_ev)
|
||||
return ghostty_surface_key(surface, key_ev)
|
||||
}
|
||||
}
|
||||
|
||||
private func keyAction(_ action: ghostty_input_action_e, event: NSEvent, text: String) {
|
||||
guard let surface = self.surface else { return }
|
||||
private func keyAction(
|
||||
_ action: ghostty_input_action_e,
|
||||
event: NSEvent, text: String
|
||||
) -> Bool {
|
||||
guard let surface = self.surface else { return false }
|
||||
|
||||
text.withCString { ptr in
|
||||
return text.withCString { ptr in
|
||||
var key_ev = event.ghosttyKeyEvent(action)
|
||||
key_ev.text = ptr
|
||||
ghostty_surface_key(surface, key_ev)
|
||||
return ghostty_surface_key(surface, key_ev)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1606,13 +1606,13 @@ pub const CAPI = struct {
|
||||
export fn ghostty_surface_key(
|
||||
surface: *Surface,
|
||||
event: KeyEvent,
|
||||
) void {
|
||||
_ = surface.app.keyEvent(
|
||||
) bool {
|
||||
return surface.app.keyEvent(
|
||||
.{ .surface = surface },
|
||||
event.keyEvent(),
|
||||
) catch |err| {
|
||||
log.warn("error processing key event err={}", .{err});
|
||||
return;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user