-
-
Notifications
You must be signed in to change notification settings - Fork 181
-
-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add as SwiftUI .keyboardShortcut()
helper
#101
Comments
For anyone interested I needed it because I wanted to display shortcuts in my menu bar items so I implemented it manually thanks to this answer on StackOverflow https://stackoverflow.com/a/35138823. Maybe there's a cleaner way to implement the View extension and import KeyboardShortcuts
import SwiftUI
import Carbon
extension View {
public func keyboardShortcut(_ shortcut: KeyboardShortcuts.Name) -> some View {
if let shortcut = shortcut.shortcut {
if let keyEquivalent = shortcut.toKeyEquivalent() {
return AnyView(self.keyboardShortcut(keyEquivalent, modifiers: shortcut.toEventModifiers()))
}
}
return AnyView(self)
}
}
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
}
} Example implementation : struct SomeView: View {
var body: some View {
return Button("Shortcut") {
print("clicked")
}.keyboardShortcut(KeyboardShortcuts.Name("..."))
}
} |
Use solution from sindresorhus#101 (comment) The old solution creates thousands associatedShortcut, it isn't good
Thanks, @mbenoukaiss! 🙏 How would you extend this so the menu bar item is updated dynamically? You currently have to restart the app for changes to take effect. |
This is a necessity when using this package with |
I agree, this is exactly where I'm at as well |
i found a short fix, you could notify the user, whenever a change in the keyboard-shortcut is made the app would restart, and you could programatically restart like this:- func relaunch(afterDelay seconds: TimeInterval = 0.5) -> Never {
let task = Process()
task.launchPath = "/bin/sh"
task.arguments = ["-c", "sleep \(seconds); open \"\(Bundle.main.bundlePath)\""]
task.launch()
NSApp.terminate(self)
exit(0)
} |
Use solution from sindresorhus#101 (comment) The old solution creates thousands associatedShortcut, it isn't good
A little late to the party, but I've just raised a PR that solves this (same idea, different SwiftUI wrapper, which auto updates based on changes to the Shortcut state) see: #181 |
For anyone who needs it quickly! I've forked this project because I wanted this change this weekend 🙂 -> https://github.com/aueangpanit/KeyboardShortcuts Example usage: In case it's helpful, all of the changes for this feature in this file: https://github.com/aueangpanit/KeyboardShortcuts/blob/main/Sources/KeyboardShortcuts/View%2B%2B.swift Hopefully, we have it in the main project soon! ❤️ |
#69
The text was updated successfully, but these errors were encountered: