I'd like to create an NSMenu
containing an NSMenuItem
which is hidden by default, and only appears while the user is holding a keyboard modifier key.
Basically, I'm looking for the same behaviour as the 'Library' option in the Finder's 'Go' Menu:
I already tried installing a key listener using [NSEvent addGlobalMonitorForEventsMatchingMask: handler:]
to hide and unhide the NSMenuItem
programmatically by setting it's hidden
property. This kind of worked, but the problem is that the hiding/unhiding wouldn't work while the NSMenu
was open. Apparently an NSMenu
completely takes over the event processing loop while it's open, preventing the key listener from working.
I could probably use a CGEventTap to still receive events while the NSMenu
is open, but that seems like complete overkill.
Another thing I discovered which does a similar thing to what I want is the 'alternate' mechanism of NSMenu
. But I could only get it to switch out NSMenuItems
, not hide/unhide them.
Any help would be greatly appreciated. Thanks!
I found a solution that behaves perfectly!
On the NSMenuItem
you want hidable, set the alternate
property to YES
, and set the keyEquivalentModifierMask
property to the keyboard modifiers which you want to unhide the item.
In your NSMenu
, right before the NSMenuItem
which you want to be hideable, insert another NSMenuItem
that has height 0.
In Objc, you can create an NSMenuItem
with height 0 like this:
NSMenuItem *i = [[NSMenuItem alloc] init];
i.view = [[NSView alloc] initWithFrame:NSZeroRect];
The hideable NSMenuItem
will now be 'alternate' to the zero-height NSMenuItem
preceding it. The zero-height item will display by default, but while you hold the keyboard modifier(s) you specified, the zero-height item will be swapped out with the hideable item. Because the zero-height item is invisible, this has the effect of unhiding the hideable item.