Recording: Ctrl+Shift+Cmd+R (or the menu) opens the same selection flow — a marquee records that region, clicking a window records it (following moves). Video is H.264 .mov at 60fps via SCStream -> AVAssetWriter with the cursor included, auto-saved to ~/Movies and revealed in Finder on stop. A red border and a floating timer/stop bar show during recording, both excluded from the video. Audio is wired behind a flag for later. The result window gains a Crop button (crop to the selection; annotations translate and stay editable) and is restyled after Cap: sliding-pill Screenshot/Text switcher, capsule buttons in Cap blue, circular icon buttons, and the content on a rounded card — light and dark. Generated with OpenCode Assisted-by: Kimi:k3
60 lines
2.2 KiB
Swift
60 lines
2.2 KiB
Swift
import Carbon
|
|
import AppKit
|
|
|
|
final class HotkeyManager {
|
|
static let shared = HotkeyManager()
|
|
|
|
/// ⌘⇧S — live capture (ScreenCaptureKit at capture time).
|
|
var onTrigger: (() -> Void)?
|
|
/// ⌃⇧⌘S — frozen capture (snapshot at hotkey press).
|
|
var onFrozenTrigger: (() -> Void)?
|
|
/// ⌃⇧⌘R — screen recording (region or window); toggles stop.
|
|
var onRecordTrigger: (() -> Void)?
|
|
|
|
private var hotKeyRefs: [EventHotKeyRef?] = []
|
|
private var eventHandlerRef: EventHandlerRef?
|
|
private let signature: OSType = 0x4B505452
|
|
|
|
private init() {}
|
|
|
|
func register() {
|
|
var eventType = EventTypeSpec(
|
|
eventClass: OSType(kEventClassKeyboard),
|
|
eventKind: UInt32(kEventHotKeyPressed)
|
|
)
|
|
InstallEventHandler(GetApplicationEventTarget(), { _, event, _ in
|
|
var hotKeyID = EventHotKeyID()
|
|
let status = GetEventParameter(
|
|
event,
|
|
EventParamName(kEventParamDirectObject),
|
|
EventParamType(typeEventHotKeyID),
|
|
nil,
|
|
MemoryLayout<EventHotKeyID>.size,
|
|
nil,
|
|
&hotKeyID
|
|
)
|
|
guard status == noErr else { return noErr }
|
|
DispatchQueue.main.async {
|
|
switch hotKeyID.id {
|
|
case 1: HotkeyManager.shared.onTrigger?()
|
|
case 2: HotkeyManager.shared.onFrozenTrigger?()
|
|
case 3: HotkeyManager.shared.onRecordTrigger?()
|
|
default: break
|
|
}
|
|
}
|
|
return noErr
|
|
}, 1, &eventType, nil, &eventHandlerRef)
|
|
|
|
registerHotkey(id: 1, keyCode: UInt32(kVK_ANSI_S), modifiers: UInt32(cmdKey | shiftKey))
|
|
registerHotkey(id: 2, keyCode: UInt32(kVK_ANSI_S), modifiers: UInt32(cmdKey | shiftKey | controlKey))
|
|
registerHotkey(id: 3, keyCode: UInt32(kVK_ANSI_R), modifiers: UInt32(cmdKey | shiftKey | controlKey))
|
|
}
|
|
|
|
private func registerHotkey(id: UInt32, keyCode: UInt32, modifiers: UInt32) {
|
|
var ref: EventHotKeyRef?
|
|
let hotKeyID = EventHotKeyID(signature: signature, id: id)
|
|
RegisterEventHotKey(keyCode, modifiers, hotKeyID, GetApplicationEventTarget(), 0, &ref)
|
|
hotKeyRefs.append(ref)
|
|
}
|
|
}
|