import Foundation
|
|
public struct ShortcutModifiers: OptionSet, Equatable, Sendable {
|
public let rawValue: UInt
|
|
public init(rawValue: UInt) {
|
self.rawValue = rawValue
|
}
|
|
public static let option = ShortcutModifiers(rawValue: 1 << 0)
|
public static let command = ShortcutModifiers(rawValue: 1 << 1)
|
public static let shift = ShortcutModifiers(rawValue: 1 << 2)
|
public static let control = ShortcutModifiers(rawValue: 1 << 3)
|
}
|
|
public struct KeyboardShortcut: Equatable, Sendable {
|
public let keyCode: UInt16
|
public let modifiers: ShortcutModifiers
|
|
public init(keyCode: UInt16, modifiers: ShortcutModifiers) {
|
self.keyCode = keyCode
|
self.modifiers = modifiers
|
}
|
}
|
|
public enum TriggerKeyCode {
|
public static let tab: UInt16 = 48
|
public static let escape: UInt16 = 53
|
public static let returnKey: UInt16 = 36
|
public static let keypadEnter: UInt16 = 76
|
public static let leftArrow: UInt16 = 123
|
public static let rightArrow: UInt16 = 124
|
public static let downArrow: UInt16 = 125
|
public static let upArrow: UInt16 = 126
|
}
|
|
public enum TriggerDefaults {
|
public static let quickSwitchShortcut = KeyboardShortcut(
|
keyCode: TriggerKeyCode.tab,
|
modifiers: [.option]
|
)
|
|
public static let forceQuitShortcut = KeyboardShortcut(
|
keyCode: TriggerKeyCode.escape,
|
modifiers: [.command, .option]
|
)
|
}
|
|
public enum TriggerEventDecision: Equatable, Sendable {
|
case quickSwitch(consumeEvent: Bool)
|
case passThrough
|
}
|
|
public enum TriggerEventPolicy {
|
public static func decision(
|
for shortcut: KeyboardShortcut,
|
configuredQuickSwitch: KeyboardShortcut = TriggerDefaults.quickSwitchShortcut,
|
overlayVisible: Bool,
|
consumeInitialQuickSwitch: Bool = false
|
) -> TriggerEventDecision {
|
guard shortcut != TriggerDefaults.forceQuitShortcut else {
|
return .passThrough
|
}
|
|
guard shortcut == configuredQuickSwitch else {
|
return .passThrough
|
}
|
|
return .quickSwitch(consumeEvent: overlayVisible || consumeInitialQuickSwitch)
|
}
|
}
|
|
@MainActor
|
public final class ManualTriggerService: TriggerServiceProtocol {
|
public var onQuickSwitch: (() -> Void)?
|
public private(set) var isRunning = false
|
|
public init() {}
|
|
public func start() {
|
isRunning = true
|
}
|
|
public func stop() {
|
isRunning = false
|
}
|
|
public func triggerQuickSwitch() {
|
guard isRunning else { return }
|
onQuickSwitch?()
|
}
|
}
|