Import Coucou 0.1.9 (Louis-CFM/coucou@83708fe), Mac app only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
maksarsanjeev
2026-10-06 19:34:32 +03:00
commit 53b4f60da1
158 changed files with 29442 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
import AppKit
import Carbon.HIToolbox
// MARK: - C-level event handler
//
// Carbon's InstallEventHandler requires a top-level C-compatible function.
// We store state in nonisolated(unsafe) globals — safe because all mutations
// happen on the main thread (Carbon dispatches hot-key events on the main thread).
private nonisolated(unsafe) var gHotKeyHandler: EventHandlerRef? = nil
private nonisolated(unsafe) var gHotKeyTable: [UInt32: ShortcutAction] = [:]
private nonisolated(unsafe) var gOnAction: ((ShortcutAction) -> Void)? = nil
private func coucouHotKeyEventHandler(
_: EventHandlerCallRef?,
_ event: EventRef?,
_: UnsafeMutableRawPointer?
) -> OSStatus {
guard let event else { return OSStatus(eventNotHandledErr) }
var hkid = EventHotKeyID()
let err = GetEventParameter(
event,
EventParamName(kEventParamDirectObject),
EventParamType(typeEventHotKeyID),
nil,
MemoryLayout<EventHotKeyID>.size,
nil,
&hkid
)
guard err == noErr, let action = gHotKeyTable[hkid.id] else {
return OSStatus(eventNotHandledErr)
}
// Carbon events are dispatched on the main thread.
MainActor.assumeIsolated { gOnAction?(action) }
return noErr
}
// MARK: - HotKeyCenter
/// Manages all global keyboard shortcuts via Carbon `RegisterEventHotKey`.
///
/// - No Accessibility permission required.
/// - Works in the App Store sandbox.
/// - The hot-key event is consumed and never forwarded to the front application.
@MainActor
final class HotKeyCenter {
static let shared = HotKeyCenter()
private init() {}
// "COUC" in big-endian — unique signature for Coucou's hot-key IDs
private let kSignature = OSType(0x434F5543)
// Live registered refs (action → EventHotKeyRef)
private var refs: [ShortcutAction: EventHotKeyRef] = [:]
/// Actions whose `RegisterEventHotKey` call failed (system conflict).
private(set) var conflicts: Set<ShortcutAction> = []
// MARK: - Lifecycle
/// Start the hot-key engine and fire `onAction` whenever the user presses a registered shortcut.
/// Safe to call more than once — the handler is installed only once.
func start(onAction: @escaping @MainActor (ShortcutAction) -> Void) {
gOnAction = onAction
if gHotKeyHandler == nil {
var spec = EventTypeSpec(
eventClass: OSType(kEventClassKeyboard),
eventKind: UInt32(kEventHotKeyPressed)
)
InstallEventHandler(
GetApplicationEventTarget(),
coucouHotKeyEventHandler,
1, &spec,
nil, &gHotKeyHandler
)
}
registerAll()
}
/// Unregister every hot key. Called on app quit.
func unregisterAll() {
for (action, ref) in refs {
UnregisterEventHotKey(ref)
let idx = UInt32(ShortcutAction.allCases.firstIndex(of: action)!)
gHotKeyTable.removeValue(forKey: idx)
}
refs.removeAll()
}
/// Re-register all shortcuts from the current UserDefaults state.
func registerAll() {
unregisterAll()
conflicts.removeAll()
for action in ShortcutAction.allCases {
#if APPSTORE
if action.isNonAppStore { continue }
#endif
if !ShortcutLogic.isEnabled(action) { continue }
registerOne(action)
}
}
/// Re-register a single action (called after a setting change).
func reregister(_ action: ShortcutAction) {
// Remove old registration if present
if let ref = refs[action] {
UnregisterEventHotKey(ref)
let idx = UInt32(ShortcutAction.allCases.firstIndex(of: action)!)
gHotKeyTable.removeValue(forKey: idx)
refs.removeValue(forKey: action)
}
conflicts.remove(action)
#if APPSTORE
if action.isNonAppStore { return }
#endif
if !ShortcutLogic.isEnabled(action) { return }
registerOne(action)
}
// MARK: - Private
private func registerOne(_ action: ShortcutAction) {
let spec = ShortcutLogic.hotKey(for: action)
let carbon = ShortcutLogic.carbonModifiers(fromNS: spec.nsFlags)
let idx = UInt32(ShortcutAction.allCases.firstIndex(of: action)!)
let hkid = EventHotKeyID(signature: kSignature, id: idx)
var ref: EventHotKeyRef?
let status = RegisterEventHotKey(
UInt32(spec.keyCode),
carbon,
hkid,
GetApplicationEventTarget(),
0,
&ref
)
if status == noErr, let ref {
refs[action] = ref
gHotKeyTable[idx] = action
} else {
conflicts.insert(action)
}
}
}