4

I've set a custom NSView to a NSMenuItem to do my own drawing and rendering. However the 'keyEquivalent' assigned to the NSMenuItem does not seem to respond. I understand drawing and action handling needs to be self-handled but I can't seem to be able to capture keyEquivalent request no matter what I do. I've tried subclassing NSApplication's sendEvent but that doesn't work since my app is a NSStatusBarItem (LSUIElement) and the events from the NSEventTrackingRunLoopMode (when menu is down) do not reach NSApplication's sendEvent.

Then I've tried using:

- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action

This doesn't work either as this is never called even though I've set the main menu's delegate to the controller.

Does anyone have any idea on how to capture 'keyEquivalent' events on NSMenuItems when using a custom view?

Thanks!

Jay
  • 6,572
  • 3
  • 37
  • 65
strange
  • 9,654
  • 6
  • 33
  • 47
  • I should mention the document explicitly says "Keyboard equivalents and type-select continue to use the key equivalent and title as normal." but this does not seem to be true. – strange Feb 08 '11 at 00:01

1 Answers1

1

I know this is an old post and you are probably long past this, but I was having the same problem and encountered your post multiple times when trying to find a solution, so I thought I would share what worked for me.

I was able to work around the problem by subclassing NSApplication and overriding sendEvent. You mentioned you tried this with no success, so I don't know what the difference is, but I had no problem intercepting the events from a NSMenu in a NSStatusBarItem. My key equivalents are all ints, so I validate the keys, find the appropriate item, and then explicitly invoke the NSMenuItem action.

-(void)sendEvent:(NSEvent *)theEvent
{
    if([theEvent type] == NSKeyUp){
        NSInteger mod = ([theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask);

        if(mod == NSCommandKeyMask) {
            NSInteger keyEquiv = [[theEvent characters] isEqualToString:@"0"]
            ? 10
            : [[theEvent characters] integerValue];
            if(keyEquiv > 0) {
                NSMenuItem *item = [[(MyAppDelegate *)[self delegate] myStatusMenu] itemAtIndex:(keyEquiv - 1)];
                if([[item keyEquivalent] integerValue] == keyEquiv){
                    [[item target] performSelector:[item action] withObject:item];
                }
            }
        }
    }
    [super sendEvent:theEvent];
}
Crutt
  • 524
  • 5
  • 9
  • Hmm... might work but it just doesn't sound right to me that you had to subclass `NSApplication` - that's not how Cocoa and AppKit was designed or is supposed to work. – Jay Dec 03 '12 at 16:19
  • @Jay, I need to do the same thing, and Crutt's answer seems to be the only way to achieve it. Not that I'm any more delighted than you are about having to tweak settings outside my code to implement it. Anyways, on a related note: http://stackoverflow.com/questions/27144113/subclass-nsapplication-in-swift – original_username Mar 26 '15 at 00:36