Initial commit: Snipping Tool menu bar screenshot app

This commit is contained in:
2026-07-01 15:27:57 +02:00
commit 1c2b52fa30
25 changed files with 718 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
import Carbon.HIToolbox
import Foundation
/// Thin wrapper around the Carbon RegisterEventHotKey API to register
/// system-wide keyboard shortcuts without requiring Accessibility/Input
/// Monitoring permission.
final class HotKeyManager {
static let shared = HotKeyManager()
private var hotKeyRefs: [UInt32: EventHotKeyRef] = [:]
private var handlers: [UInt32: () -> Void] = [:]
private var eventHandlerRef: EventHandlerRef?
private static let signature: FourCharCode = {
var result: FourCharCode = 0
for byte in "SNAP".utf8 {
result = (result << 8) + FourCharCode(byte)
}
return result
}()
private init() {
installEventHandler()
}
private func installEventHandler() {
var eventType = EventTypeSpec(
eventClass: OSType(kEventClassKeyboard),
eventKind: UInt32(kEventHotKeyPressed)
)
let callback: EventHandlerUPP = { _, event, userData in
guard let event, let userData else { return noErr }
var hotKeyID = EventHotKeyID()
GetEventParameter(
event,
EventParamName(kEventParamDirectObject),
EventParamType(typeEventHotKeyID),
nil,
MemoryLayout<EventHotKeyID>.size,
nil,
&hotKeyID
)
let manager = Unmanaged<HotKeyManager>.fromOpaque(userData).takeUnretainedValue()
manager.handlers[hotKeyID.id]?()
return noErr
}
InstallEventHandler(
GetEventDispatcherTarget(),
callback,
1,
&eventType,
Unmanaged.passUnretained(self).toOpaque(),
&eventHandlerRef
)
}
@discardableResult
func register(id: UInt32, keyCode: UInt32, modifiers: UInt32, handler: @escaping () -> Void) -> Bool {
unregister(id: id)
var hotKeyRef: EventHotKeyRef?
let hotKeyID = EventHotKeyID(signature: Self.signature, id: id)
let status = RegisterEventHotKey(
keyCode,
modifiers,
hotKeyID,
GetEventDispatcherTarget(),
0,
&hotKeyRef
)
guard status == noErr, let hotKeyRef else { return false }
hotKeyRefs[id] = hotKeyRef
handlers[id] = handler
return true
}
func unregister(id: UInt32) {
if let ref = hotKeyRefs.removeValue(forKey: id) {
UnregisterEventHotKey(ref)
}
handlers.removeValue(forKey: id)
}
}