views:

616

answers:

4

I have an NSMenu popping out of an NSStatusItem using popUpStatusItemMenu. These NSMenuItems show a bunch of different links, and each one is connected with setAction: to the openLink: method of a target. This arrangement has been working fine for a long time. The user chooses a link from the menu and the openLink: method then deals with it.

Unfortunately, I recently decided to experiment with using NSMenuItem's setView: method to provide a nicer/slicker interface. Basically, I just stopped setting the title, created the NSMenuItem, and then used setView: to display a custom view. This works perfectly, the menu items look great and my custom view is displayed.

However, when the user chooses a menu item and releases the mouse, the action no longer works (i.e., openLink: isn't called). If I just simply comment out the setView: call, then the actions work again (of course, the menu items are blank, but the action is executed properly). My first question, then, is why setting a view breaks the NSMenuItem's action.

No problem, I thought, I'll fix it by detecting the mouseUp event in my custom view and calling my action method from there. I added this method to my custom view:

- (void)mouseUp:(NSEvent *)theEvent {
  NSLog(@"in mouseUp");
  }

No dice! This method is never called.

I can set tracking rects and receive mouseEntered: events, though. I put a few tests in my mouseEntered routine, as follows:

if ([[self window] ignoresMouseEvents]) {  NSLog(@"ignoring mouse events");  }
else {  NSLog(@"not ignoring mouse events");  }
if ([[self window] canBecomeKeyWindow]) {  dNSLog((@"canBecomeKeyWindow"));  }
else {  NSLog(@"not canBecomeKeyWindow");  }
if ([[self window] isKeyWindow]) {  dNSLog((@"isKeyWindow"));  }
else {  NSLog(@"not isKeyWindow");  }

And got the following responses:

not ignoring mouse events
canBecomeKeyWindow
not isKeyWindow

Is this the problem? "not isKeyWindow"? Presumably this isn't good because Apple's docs say "If the user clicks a view that isn’t in the key window, by default the window is brought forward and made key, but the mouse event is not dispatched." But there must be a way do detect these events. HOW?

Adding:

[[self window] makeKeyWindow];

has no effect, despite the fact that canBecomeKeyWindow is YES.

A: 

Hi, I've faced the same problem, do you have any progress with it? I've tried some weired ways to solve it, I've found one workaround but its terrible ugly, and after showing the menu status bar item is not highlighted, but menu is shown and fully functional.

I've set menu for status item to nil and manually control menu popup. If application is active I just call menu popup method, if no I send make application active message, and in callback I'm opening menu.

Here is some code. Again its terrible and ugly.

This does not answer the question. Moreover, you're talking about a *status item*, and the questioner is not—the question is about a view in a *menu item*.
Peter Hosey
I agree this does not answer the question. Moreover, I'm talking about NSMenuItem with NSView that added to NSMenu attached to NSStatusItem, the problem is in NSStatusItem if you do the same with normal application and NSMenu will be attached to window - there will be no problems.
A: 

Add this to your custom view and you should be fine:

  • (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { return YES; }
fabian
A: 

I added this method to my custom view, and now everything works beautifully:

- (void)viewDidMoveToWindow {
    [[self window] becomeKeyWindow];
}

Hope this helps!

Justin Voss
A: 

Add this method to your custom NSView and it will work fine with mouse events

- (void)mouseUp:(NSEvent*) event {
    NSMenuItem* mitem = [self enclosingMenuItem];
    NSMenu* m = [mitem menu];
    [m cancelTracking];
    [m performActionForItemAtIndex: [m indexOfItem: mitem]];
}

But i'm having problems with keyhandling, if you solved this problem maybe you can go to my question and help me a little bit.

Lothar