NSMenuItem custom view does not respond to keyEquivalent

1.1k views Asked by At

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!

1

There are 1 answers

2
Crutt On BEST ANSWER

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];
}