Files
transui/macos/Sources/Transui/HotkeyManager.swift
T
2026-08-29 19:58:33 +02:00

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
}