macos: enter and shift+enter move the results

pull/9709/head
Mitchell Hashimoto 2025-11-25 17:25:01 -08:00
parent efc05523e0
commit cfbc219f5c
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 43 additions and 16 deletions

View File

@ -405,21 +405,24 @@ extension Ghostty {
get: { searchState?.needle ?? "" }, get: { searchState?.needle ?? "" },
set: { searchState?.needle = $0 } set: { searchState?.needle = $0 }
)) ))
.textFieldStyle(.plain) .textFieldStyle(.plain)
.frame(width: 180) .frame(width: 180)
.padding(.horizontal, 8) .padding(.horizontal, 8)
.padding(.vertical, 6) .padding(.vertical, 6)
.background(Color.primary.opacity(0.1)) .background(Color.primary.opacity(0.1))
.cornerRadius(6) .cornerRadius(6)
.focused($isSearchFieldFocused) .focused($isSearchFieldFocused)
.onSubmit { .onExitCommand {
guard let surface = surfaceView.surface else { return } Ghostty.moveFocus(to: surfaceView)
let action = "navigate_search:next" }
ghostty_surface_binding_action(surface, action, UInt(action.count)) .backport.onKeyPress(.return) { modifiers in
} guard let surface = surfaceView.surface else { return .ignored }
.onExitCommand { let action = modifiers.contains(.shift)
Ghostty.moveFocus(to: surfaceView) ? "navigate_search:previous"
} : "navigate_search:next"
ghostty_surface_binding_action(surface, action, UInt(action.count))
return .handled
}
Button(action: { Button(action: {
guard let surface = surfaceView.surface else { return } guard let surface = surfaceView.surface else { return }
@ -526,7 +529,7 @@ extension Ghostty {
} }
} }
} }
/// A surface is terminology in Ghostty for a terminal surface, or a place where a terminal is actually drawn /// A surface is terminology in Ghostty for a terminal surface, or a place where a terminal is actually drawn
/// and interacted with. The word "surface" is used because a surface may represent a window, a tab, /// and interacted with. The word "surface" is used because a surface may represent a window, a tab,
/// a split, a small preview pane, etc. It is ANYTHING that has a terminal drawn to it. /// a split, a small preview pane, etc. It is ANYTHING that has a terminal drawn to it.

View File

@ -18,6 +18,12 @@ extension Backport where Content: Scene {
// None currently // None currently
} }
/// Result type for backported onKeyPress handler
enum BackportKeyPressResult {
case handled
case ignored
}
extension Backport where Content: View { extension Backport where Content: View {
func pointerVisibility(_ v: BackportVisibility) -> some View { func pointerVisibility(_ v: BackportVisibility) -> some View {
#if canImport(AppKit) #if canImport(AppKit)
@ -42,6 +48,24 @@ extension Backport where Content: View {
return content return content
#endif #endif
} }
/// Backported onKeyPress that works on macOS 14+ and is a no-op on macOS 13.
func onKeyPress(_ key: KeyEquivalent, action: @escaping (EventModifiers) -> BackportKeyPressResult) -> some View {
#if canImport(AppKit)
if #available(macOS 14, *) {
return content.onKeyPress(key, phases: .down, action: { keyPress in
switch action(keyPress.modifiers) {
case .handled: return .handled
case .ignored: return .ignored
}
})
} else {
return content
}
#else
return content
#endif
}
} }
enum BackportVisibility { enum BackportVisibility {