import Carbon import AppKit final class HotkeyManager { static let shared = HotkeyManager() /// ⌘⇧S — live capture (ScreenCaptureKit at capture time). var onTrigger: (() -> Void)? /// ⌃⇧⌘S — frozen capture (snapshot at hotkey press). var onFrozenTrigger: (() -> Void)? /// ⌃⇧⌘R — screen recording (region or window); toggles stop. var onRecordTrigger: (() -> Void)? private var hotKeyRefs: [EventHotKeyRef?] = [] private var eventHandlerRef: EventHandlerRef? private let signature: OSType = 0x4B505452 private init() {} func register() { var eventType = EventTypeSpec( eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed) ) InstallEventHandler(GetApplicationEventTarget(), { _, event, _ in var hotKeyID = EventHotKeyID() let status = GetEventParameter( event, EventParamName(kEventParamDirectObject), EventParamType(typeEventHotKeyID), nil, MemoryLayout.size, nil, &hotKeyID ) guard status == noErr else { return noErr } DispatchQueue.main.async { switch hotKeyID.id { case 1: HotkeyManager.shared.onTrigger?() case 2: HotkeyManager.shared.onFrozenTrigger?() case 3: HotkeyManager.shared.onRecordTrigger?() default: break } } return noErr }, 1, &eventType, nil, &eventHandlerRef) registerHotkey(id: 1, keyCode: UInt32(kVK_ANSI_S), modifiers: UInt32(cmdKey | shiftKey)) registerHotkey(id: 2, keyCode: UInt32(kVK_ANSI_S), modifiers: UInt32(cmdKey | shiftKey | controlKey)) registerHotkey(id: 3, keyCode: UInt32(kVK_ANSI_R), modifiers: UInt32(cmdKey | shiftKey | controlKey)) } private func registerHotkey(id: UInt32, keyCode: UInt32, modifiers: UInt32) { var ref: EventHotKeyRef? let hotKeyID = EventHotKeyID(signature: signature, id: id) RegisterEventHotKey(keyCode, modifiers, hotKeyID, GetApplicationEventTarget(), 0, &ref) hotKeyRefs.append(ref) } }