62 lines
2.4 KiB
Swift
62 lines
2.4 KiB
Swift
import Carbon
|
|
|
|
final class HotKeyManager: @unchecked Sendable {
|
|
var onLocal: (@Sendable () -> Void)?
|
|
var onCloud: (@Sendable () -> Void)?
|
|
|
|
private var localRef: EventHotKeyRef?
|
|
private var cloudRef: EventHotKeyRef?
|
|
private var handlerRef: EventHandlerRef?
|
|
private let signature: OSType = 0x574B4559 // WKEY
|
|
|
|
func register() throws {
|
|
unregister()
|
|
var eventType = EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed))
|
|
let status = InstallEventHandler(
|
|
GetApplicationEventTarget(),
|
|
{ _, event, context in
|
|
guard let context, let event else { return noErr }
|
|
let manager = Unmanaged<HotKeyManager>.fromOpaque(context).takeUnretainedValue()
|
|
var id = EventHotKeyID()
|
|
GetEventParameter(
|
|
event,
|
|
EventParamName(kEventParamDirectObject),
|
|
EventParamType(typeEventHotKeyID),
|
|
nil,
|
|
MemoryLayout<EventHotKeyID>.size,
|
|
nil,
|
|
&id
|
|
)
|
|
if id.id == 1 { manager.onLocal?() }
|
|
if id.id == 2 { manager.onCloud?() }
|
|
return noErr
|
|
},
|
|
1,
|
|
&eventType,
|
|
Unmanaged.passUnretained(self).toOpaque(),
|
|
&handlerRef
|
|
)
|
|
guard status == noErr else { throw WhisperKeyError.processFailed("Carbon handler: \(status)") }
|
|
|
|
let localID = EventHotKeyID(signature: signature, id: 1)
|
|
let cloudID = EventHotKeyID(signature: signature, id: 2)
|
|
guard RegisterEventHotKey(UInt32(kVK_F5), 0, localID, GetApplicationEventTarget(), 0, &localRef) == noErr else {
|
|
throw WhisperKeyError.processFailed("F5 уже занята. Отключите сочетание системной диктовки.")
|
|
}
|
|
guard RegisterEventHotKey(UInt32(kVK_F5), UInt32(optionKey), cloudID, GetApplicationEventTarget(), 0, &cloudRef) == noErr else {
|
|
throw WhisperKeyError.processFailed("Option+F5 уже занята.")
|
|
}
|
|
}
|
|
|
|
func unregister() {
|
|
if let localRef { UnregisterEventHotKey(localRef) }
|
|
if let cloudRef { UnregisterEventHotKey(cloudRef) }
|
|
if let handlerRef { RemoveEventHandler(handlerRef) }
|
|
localRef = nil
|
|
cloudRef = nil
|
|
handlerRef = nil
|
|
}
|
|
|
|
deinit { unregister() }
|
|
}
|