Skip to content

Commit 428ee65

Browse files
Support for setting NSMenuItem shortcut with nameless shortcut (#38)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
1 parent f617225 commit 428ee65

File tree

1 file changed

+41
-20
lines changed

1 file changed

+41
-20
lines changed

Sources/KeyboardShortcuts/NSMenuItem++.swift

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ extension NSMenuItem {
55
static let observer = ObjectAssociation<NSObjectProtocol>()
66
}
77

8+
private func clearShortcut() {
9+
keyEquivalent = ""
10+
keyEquivalentModifierMask = []
11+
}
12+
813
// TODO: Make this a getter/setter. We must first add the ability to create a `Shortcut` from a `keyEquivalent`.
914
/**
1015
Show a recorded keyboard shortcut in a `NSMenuItem`.
@@ -35,20 +40,48 @@ extension NSMenuItem {
3540
- Important: You will have to disable the global keyboard shortcut while the menu is open, as otherwise, the keyboard events will be buffered up and triggered when the menu closes. This is because `NSMenu` puts the thread in tracking-mode, which prevents the keyboard events from being received. You can listen to whether a menu is open by implementing `NSMenuDelegate#menuWillOpen` and `NSMenuDelegate#menuDidClose`. You then use `KeyboardShortcuts.disable` and `KeyboardShortcuts.enable`.
3641
*/
3742
public func setShortcut(for name: KeyboardShortcuts.Name?) {
38-
func clear() {
39-
keyEquivalent = ""
40-
keyEquivalentModifierMask = []
41-
}
42-
4343
guard let name = name else {
44-
clear()
44+
clearShortcut()
4545
AssociatedKeys.observer[self] = nil
4646
return
4747
}
4848

4949
func set() {
50-
guard let shortcut = KeyboardShortcuts.Shortcut(name: name) else {
51-
clear()
50+
let shortcut = KeyboardShortcuts.Shortcut(name: name)
51+
setShortcut(shortcut)
52+
}
53+
54+
set()
55+
56+
// TODO: Use Combine when targeting macOS 10.15.
57+
AssociatedKeys.observer[self] = NotificationCenter.default.addObserver(forName: .shortcutByNameDidChange, object: nil, queue: nil) { notification in
58+
guard
59+
let nameInNotification = notification.userInfo?["name"] as? KeyboardShortcuts.Name,
60+
nameInNotification == name
61+
else {
62+
return
63+
}
64+
65+
set()
66+
}
67+
}
68+
69+
/**
70+
Add a keyboard shortcut to a `NSMenuItem`.
71+
72+
This method is only recommended for dynamic shortcuts. In general, it's preferred to create a static shortcut name and use `NSMenuItem.setShortcut(for:)` instead.
73+
74+
Pass in `nil` to clear the keyboard shortcut.
75+
76+
This method overrides `.keyEquivalent` and `.keyEquivalentModifierMask`.
77+
78+
- Important: You will have to disable the global keyboard shortcut while the menu is open, as otherwise, the keyboard events will be buffered up and triggered when the menu closes. This is because `NSMenu` puts the thread in tracking-mode, which prevents the keyboard events from being received. You can listen to whether a menu is open by implementing `NSMenuDelegate#menuWillOpen` and `NSMenuDelegate#menuDidClose`. You then use `KeyboardShortcuts.disable` and `KeyboardShortcuts.enable`.
79+
*/
80+
@_disfavoredOverload
81+
public func setShortcut(_ shortcut: KeyboardShortcuts.Shortcut?) {
82+
func set() {
83+
guard let shortcut = shortcut else {
84+
clearShortcut()
5285
return
5386
}
5487

@@ -64,17 +97,5 @@ extension NSMenuItem {
6497
} else {
6598
set()
6699
}
67-
68-
// TODO: Use Combine when targeting macOS 10.15.
69-
AssociatedKeys.observer[self] = NotificationCenter.default.addObserver(forName: .shortcutByNameDidChange, object: nil, queue: nil) { notification in
70-
guard
71-
let nameInNotification = notification.userInfo?["name"] as? KeyboardShortcuts.Name,
72-
nameInNotification == name
73-
else {
74-
return
75-
}
76-
77-
set()
78-
}
79100
}
80101
}

0 commit comments

Comments
 (0)