68 lines
2.7 KiB
Swift
68 lines
2.7 KiB
Swift
import AppKit
|
|
import Carbon.HIToolbox
|
|
|
|
struct HotkeyShortcut: Codable, Equatable {
|
|
let keyCode: UInt32
|
|
let modifiers: UInt32
|
|
|
|
static let defaultShortcut = HotkeyShortcut(
|
|
keyCode: UInt32(kVK_ANSI_S),
|
|
modifiers: UInt32(cmdKey | optionKey)
|
|
)
|
|
|
|
var displayName: String {
|
|
var result = ""
|
|
if modifiers & UInt32(controlKey) != 0 { result += "⌃" }
|
|
if modifiers & UInt32(optionKey) != 0 { result += "⌥" }
|
|
if modifiers & UInt32(shiftKey) != 0 { result += "⇧" }
|
|
if modifiers & UInt32(cmdKey) != 0 { result += "⌘" }
|
|
result += Self.keyNames[keyCode] ?? "Key \(keyCode)"
|
|
return result
|
|
}
|
|
|
|
init(keyCode: UInt32, modifiers: UInt32) {
|
|
self.keyCode = keyCode
|
|
self.modifiers = modifiers
|
|
}
|
|
|
|
init?(event: NSEvent) {
|
|
let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
|
|
var carbonModifiers: UInt32 = 0
|
|
if flags.contains(.command) { carbonModifiers |= UInt32(cmdKey) }
|
|
if flags.contains(.option) { carbonModifiers |= UInt32(optionKey) }
|
|
if flags.contains(.control) { carbonModifiers |= UInt32(controlKey) }
|
|
if flags.contains(.shift) { carbonModifiers |= UInt32(shiftKey) }
|
|
guard carbonModifiers != 0 else { return nil }
|
|
self.init(keyCode: UInt32(event.keyCode), modifiers: carbonModifiers)
|
|
}
|
|
|
|
private static let keyNames: [UInt32: String] = [
|
|
UInt32(kVK_ANSI_A): "A", UInt32(kVK_ANSI_B): "B",
|
|
UInt32(kVK_ANSI_C): "C", UInt32(kVK_ANSI_D): "D",
|
|
UInt32(kVK_ANSI_E): "E", UInt32(kVK_ANSI_F): "F",
|
|
UInt32(kVK_ANSI_G): "G", UInt32(kVK_ANSI_H): "H",
|
|
UInt32(kVK_ANSI_I): "I", UInt32(kVK_ANSI_J): "J",
|
|
UInt32(kVK_ANSI_K): "K", UInt32(kVK_ANSI_L): "L",
|
|
UInt32(kVK_ANSI_M): "M", UInt32(kVK_ANSI_N): "N",
|
|
UInt32(kVK_ANSI_O): "O", UInt32(kVK_ANSI_P): "P",
|
|
UInt32(kVK_ANSI_Q): "Q", UInt32(kVK_ANSI_R): "R",
|
|
UInt32(kVK_ANSI_S): "S", UInt32(kVK_ANSI_T): "T",
|
|
UInt32(kVK_ANSI_U): "U", UInt32(kVK_ANSI_V): "V",
|
|
UInt32(kVK_ANSI_W): "W", UInt32(kVK_ANSI_X): "X",
|
|
UInt32(kVK_ANSI_Y): "Y", UInt32(kVK_ANSI_Z): "Z",
|
|
UInt32(kVK_ANSI_0): "0", UInt32(kVK_ANSI_1): "1",
|
|
UInt32(kVK_ANSI_2): "2", UInt32(kVK_ANSI_3): "3",
|
|
UInt32(kVK_ANSI_4): "4", UInt32(kVK_ANSI_5): "5",
|
|
UInt32(kVK_ANSI_6): "6", UInt32(kVK_ANSI_7): "7",
|
|
UInt32(kVK_ANSI_8): "8", UInt32(kVK_ANSI_9): "9",
|
|
UInt32(kVK_Space): "Space", UInt32(kVK_Return): "Return",
|
|
UInt32(kVK_Tab): "Tab", UInt32(kVK_Escape): "Esc",
|
|
UInt32(kVK_F1): "F1", UInt32(kVK_F2): "F2",
|
|
UInt32(kVK_F3): "F3", UInt32(kVK_F4): "F4",
|
|
UInt32(kVK_F5): "F5", UInt32(kVK_F6): "F6",
|
|
UInt32(kVK_F7): "F7", UInt32(kVK_F8): "F8",
|
|
UInt32(kVK_F9): "F9", UInt32(kVK_F10): "F10",
|
|
UInt32(kVK_F11): "F11", UInt32(kVK_F12): "F12",
|
|
]
|
|
}
|