native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051import AppKit
/// Catches the key that would undo or redo a close when no terminal surface/// can take it (docs-ai 069.002).////// A focused terminal handles Ghostty's `undo` / `redo` bindings itself. After/// the last tab of a worktree closes, the terminal area is empty and nothing/// receives ⌘Z: SwiftUI's Edit › Undo does not consult the window's undo/// manager, so a local key monitor is the one place the key can be caught./// The monitor answers only for its owning window, leaves text editing its/// own undo, and hands the event to Ghostty's app-level binding dispatch, so/// the user's real bindings decide which key it is.@MainActorfinal class TerminalCloseUndoKeyMonitor { private var monitor: Any?
/// `ownerWindow` is resolved per event: the owning view may not be in a /// window yet when the monitor is installed. `dispatch` returns `true` /// when the key undid or redid a close; only then is the event swallowed. init( ownerWindow: @escaping @MainActor () -> NSWindow?, dispatch: @escaping @MainActor (NSEvent) -> Bool ) { monitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in let handled = MainActor.assumeIsolated { () -> Bool in guard Self.shouldDispatch(event, ownerWindow: ownerWindow()) else { return false } return dispatch(event) } return handled ? nil : event } }
isolated deinit { if let monitor { NSEvent.removeMonitor(monitor) } }
/// The event must belong to the owning window, and that window's first /// responder must not own undo itself: a terminal answers the key through /// Ghostty's own binding, a text field keeps the standard text undo. static func shouldDispatch(_ event: NSEvent, ownerWindow: NSWindow?) -> Bool { guard let ownerWindow, let eventWindow = event.window, eventWindow === ownerWindow else { return false } return !firstResponderOwnsUndo(ownerWindow.firstResponder) }
nonisolated static func firstResponderOwnsUndo(_ responder: NSResponder?) -> Bool { responder is GhosttySurfaceView || responder is NSText }}