native macOS codings agent orchestrator prowl.onev.cat
Something went wrong. Try again.
3.6 kB · 127 lines
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128import AppKitimport Foundationimport ProwlCLIShared
struct MirroredTerminalKey: Equatable, Sendable { enum Kind: Equatable, Sendable { case enter case backspace case deleteForward case arrowUp case arrowDown case arrowLeft case arrowRight case tab case escape case controlCharacter }
let kind: Kind let keyCode: UInt16 let characters: String let charactersIgnoringModifiers: String /// Raw value of `NSEvent.ModifierFlags` (device-independent only) to satisfy `Sendable`. let modifierFlagsRawValue: UInt let isRepeat: Bool
var modifiers: NSEvent.ModifierFlags { NSEvent.ModifierFlags(rawValue: modifierFlagsRawValue) }
/// Key codes allowed to pass through even with the Command modifier held. private static let commandAllowedKeyCodes: Set<UInt16> = [ 51, // backspace 123, // arrowLeft 124, // arrowRight 125, // arrowDown 126, // arrowUp ]
init?( kind: Kind, keyCode: UInt16, characters: String, charactersIgnoringModifiers: String, modifiers: NSEvent.ModifierFlags, isRepeat: Bool ) { if modifiers.contains(.command), !Self.commandAllowedKeyCodes.contains(keyCode) { return nil } self.kind = kind self.keyCode = keyCode self.characters = characters self.charactersIgnoringModifiers = charactersIgnoringModifiers modifierFlagsRawValue = modifiers.intersection(.deviceIndependentFlagsMask).rawValue self.isRepeat = isRepeat }
init?(event: NSEvent) { guard event.type == .keyDown else { return nil } let modifiers = event.modifierFlags.intersection(.deviceIndependentFlagsMask) if modifiers.contains(.command), !Self.commandAllowedKeyCodes.contains(event.keyCode) { return nil } guard let kind = Self.kind(for: event, modifiers: modifiers) else { return nil } self.kind = kind keyCode = event.keyCode characters = event.characters ?? "" charactersIgnoringModifiers = event.charactersIgnoringModifiers ?? event.characters ?? "" modifierFlagsRawValue = modifiers.rawValue isRepeat = event.isARepeat }
private static func kind( for event: NSEvent, modifiers: NSEvent.ModifierFlags ) -> Kind? { switch event.keyCode { case 36, 76: return .enter case 48: return .tab case 51: return .backspace case 117: return .deleteForward case 53: return .escape case 123: return .arrowLeft case 124: return .arrowRight case 125: return .arrowDown case 126: return .arrowUp default: break }
if modifiers == [.control], let charactersIgnoringModifiers = event.charactersIgnoringModifiers, !charactersIgnoringModifiers.isEmpty { return .controlCharacter }
return nil }
func keyDownEvent(windowNumber: Int) -> NSEvent? { NSEvent.keyEvent( with: .keyDown, location: .zero, modifierFlags: modifiers, timestamp: ProcessInfo.processInfo.systemUptime, windowNumber: windowNumber, context: nil, characters: characters, charactersIgnoringModifiers: charactersIgnoringModifiers, isARepeat: isRepeat, keyCode: keyCode ) }
func keyUpEvent(windowNumber: Int) -> NSEvent? { NSEvent.keyEvent( with: .keyUp, location: .zero, modifierFlags: modifiers, timestamp: ProcessInfo.processInfo.systemUptime, windowNumber: windowNumber, context: nil, characters: characters, charactersIgnoringModifiers: charactersIgnoringModifiers, isARepeat: false, keyCode: keyCode ) }}