Files
Snaggle/GreenshotMac/App/HotkeyBindings.swift
T
2026-09-17 15:15:45 -05:00

87 lines
2.6 KiB
Swift

// HotkeyBindings.swift
// GreenshotMac
//
// Maps the four capture actions onto global hotkeys and keeps them registered.
import AppKit
enum HotkeyAction: String, CaseIterable {
case region
case window
case fullscreen
case lastRegion
var title: String {
switch self {
case .region: return "Capture region"
case .window: return "Capture window"
case .fullscreen: return "Capture full screen"
case .lastRegion: return "Capture last region"
}
}
var defaultsKey: String {
switch self {
case .region: return Configuration.Keys.hotkeyRegion
case .window: return Configuration.Keys.hotkeyWindow
case .fullscreen: return Configuration.Keys.hotkeyFullscreen
case .lastRegion: return Configuration.Keys.hotkeyLastRegion
}
}
var defaultSpec: HotkeySpec {
switch self {
case .region: return DefaultHotkeys.region
case .window: return DefaultHotkeys.window
case .fullscreen: return DefaultHotkeys.fullscreen
case .lastRegion: return DefaultHotkeys.lastRegion
}
}
}
final class HotkeyBindings {
static let shared = HotkeyBindings()
private var registrations: [HotkeyAction: UInt32] = [:]
private init() {}
func spec(for action: HotkeyAction) -> HotkeySpec {
Configuration.shared.hotkey(forKey: action.defaultsKey, default: action.defaultSpec)
}
func set(_ spec: HotkeySpec, for action: HotkeyAction) {
Configuration.shared.setHotkey(spec, forKey: action.defaultsKey)
registerAll()
NotificationCenter.default.post(name: .hotkeysChanged, object: nil)
}
func registerAll() {
for (_, id) in registrations { HotkeyManager.shared.unregister(id) }
registrations.removeAll()
for action in HotkeyAction.allCases {
let spec = self.spec(for: action)
guard !spec.isEmpty else { continue }
if let id = HotkeyManager.shared.register(spec, handler: { HotkeyBindings.perform(action) }) {
registrations[action] = id
}
}
}
static func perform(_ action: HotkeyAction) {
Task { @MainActor in
switch action {
case .region: CaptureCoordinator.shared.captureRegion()
case .window: CaptureCoordinator.shared.captureWindow()
case .fullscreen: CaptureCoordinator.shared.captureFullscreen()
case .lastRegion: CaptureCoordinator.shared.captureLastRegion()
}
}
}
}
extension Notification.Name {
static let hotkeysChanged = Notification.Name("GreenshotMacHotkeysChanged")
}