// 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") }