Files
transui/macos/Sources/Transui/HotkeyShortcut.swift
jourintownandintelligence 32e7f32e0a
Android / build-android (release) Successful in 2m18s
Build / build-amd64 (release) Successful in 34s
Build / build-arm64 (release) Canceled after 0s
Feat macos (#2)
---------

Co-authored-by: intelligence <intelligence@debian.local>
Co-authored-by: jourintown <jourintown@proton.me>
Reviewed-on: #2
2026-08-29 20:30:30 +02:00

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",
]
}