--------- Co-authored-by: intelligence <intelligence@debian.local> Co-authored-by: jourintown <jourintown@proton.me> Reviewed-on: #2
71 lines
1.9 KiB
Swift
71 lines
1.9 KiB
Swift
import Carbon.HIToolbox
|
|
import Foundation
|
|
|
|
final class HotkeyManager {
|
|
private var hotkey: EventHotKeyRef?
|
|
private var handler: EventHandlerRef?
|
|
private var action: (() -> Void)?
|
|
|
|
init() {
|
|
var type = EventTypeSpec(
|
|
eventClass: OSType(kEventClassKeyboard),
|
|
eventKind: UInt32(kEventHotKeyPressed)
|
|
)
|
|
InstallEventHandler(
|
|
GetApplicationEventTarget(),
|
|
{ _, event, context in
|
|
guard let event, let context else { return noErr }
|
|
var identifier = EventHotKeyID()
|
|
let status = GetEventParameter(
|
|
event,
|
|
EventParamName(kEventParamDirectObject),
|
|
EventParamType(typeEventHotKeyID),
|
|
nil,
|
|
MemoryLayout<EventHotKeyID>.size,
|
|
nil,
|
|
&identifier
|
|
)
|
|
guard status == noErr, identifier.id == 1 else { return status }
|
|
let manager = Unmanaged<HotkeyManager>.fromOpaque(context).takeUnretainedValue()
|
|
DispatchQueue.main.async { manager.action?() }
|
|
return noErr
|
|
},
|
|
1,
|
|
&type,
|
|
Unmanaged.passUnretained(self).toOpaque(),
|
|
&handler
|
|
)
|
|
}
|
|
|
|
deinit {
|
|
unregister()
|
|
if let handler { RemoveEventHandler(handler) }
|
|
}
|
|
|
|
@discardableResult
|
|
func register(_ shortcut: HotkeyShortcut, action: @escaping () -> Void) -> Bool {
|
|
let identifier = EventHotKeyID(signature: Self.signature, id: 1)
|
|
var candidate: EventHotKeyRef?
|
|
let status = RegisterEventHotKey(
|
|
shortcut.keyCode,
|
|
shortcut.modifiers,
|
|
identifier,
|
|
GetApplicationEventTarget(),
|
|
0,
|
|
&candidate
|
|
)
|
|
guard status == noErr, let candidate else { return false }
|
|
unregister()
|
|
hotkey = candidate
|
|
self.action = action
|
|
return true
|
|
}
|
|
|
|
private func unregister() {
|
|
if let hotkey { UnregisterEventHotKey(hotkey) }
|
|
hotkey = nil
|
|
}
|
|
|
|
private static let signature: OSType = 0x5452_5549 // TRUI
|
|
}
|