Skip to content

Commit

Permalink
Add new view extension
Browse files Browse the repository at this point in the history
Use solution from sindresorhus#101 (comment)

The old solution creates thousands associatedShortcut, it isn't good
  • Loading branch information
zddhub committed Apr 15, 2023
1 parent aafa286 commit a2baf16
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 0 deletions.
64 changes: 64 additions & 0 deletions Sources/KeyboardShortcuts/Shortcut.swift
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,72 @@ extension View {

}

@available(macOS 11.0, *)
extension KeyboardShortcuts.Shortcut {
func toKeyEquivalent() -> KeyEquivalent? {
let carbonKeyCode = UInt16(self.carbonKeyCode)
let maxNameLength = 4
var nameBuffer = [UniChar](repeating: 0, count : maxNameLength)
var nameLength = 0

let modifierKeys = UInt32(alphaLock >> 8) & 0xFF // Caps Lock
var deadKeys: UInt32 = 0
let keyboardType = UInt32(LMGetKbdType())

let source = TISCopyCurrentKeyboardLayoutInputSource().takeRetainedValue()
guard let ptr = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData) else {
NSLog("Could not get keyboard layout data")
return nil
}
let layoutData = Unmanaged<CFData>.fromOpaque(ptr).takeUnretainedValue() as Data
let osStatus = layoutData.withUnsafeBytes {
UCKeyTranslate($0.bindMemory(to: UCKeyboardLayout.self).baseAddress, carbonKeyCode, UInt16(kUCKeyActionDown),
modifierKeys, keyboardType, UInt32(kUCKeyTranslateNoDeadKeysMask),
&deadKeys, maxNameLength, &nameLength, &nameBuffer)
}
guard osStatus == noErr else {
NSLog("Code: 0x%04X Status: %+i", carbonKeyCode, osStatus);
return nil
}

return KeyEquivalent(Character(String(utf16CodeUnits: nameBuffer, count: nameLength)))
}

func toEventModifiers() -> SwiftUI.EventModifiers {
var modifiers: SwiftUI.EventModifiers = []

if self.modifiers.contains(NSEvent.ModifierFlags.command) {
modifiers.update(with: EventModifiers.command)
}

if self.modifiers.contains(NSEvent.ModifierFlags.control) {
modifiers.update(with: EventModifiers.control)
}

if self.modifiers.contains(NSEvent.ModifierFlags.option) {
modifiers.update(with: EventModifiers.option)
}

if self.modifiers.contains(NSEvent.ModifierFlags.shift) {
modifiers.update(with: EventModifiers.shift)
}

if self.modifiers.contains(NSEvent.ModifierFlags.capsLock) {
modifiers.update(with: EventModifiers.capsLock)
}

if self.modifiers.contains(NSEvent.ModifierFlags.numericPad) {
modifiers.update(with: EventModifiers.numericPad)
}

return modifiers
}

}

// MARK: - SwiftUI ShortcutViewModifier

@available(*, deprecated, message: "Deprecated because associatedShortcut is created thousands times in the project")
@available(iOS 14.0, macOS 12.0, *)
struct ShortcutViewModifier: ViewModifier {
class AssociatedShortcut: ObservableObject {
Expand Down
9 changes: 9 additions & 0 deletions Sources/KeyboardShortcuts/ViewModifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,13 @@ extension View {
public func keyboardShortcut(for name: KeyboardShortcuts.Name) -> some View {
modifier(ShortcutViewModifier(for: name))
}

public func onKeyboardShortcut(for name: KeyboardShortcuts.Name) -> some View {
if let shortcut = name.shortcut {
if let keyEquivalent = shortcut.toKeyEquivalent() {
return AnyView(self.keyboardShortcut(keyEquivalent, modifiers: shortcut.toEventModifiers()))
}
}
return AnyView(self)
}
}

0 comments on commit a2baf16

Please sign in to comment.