0

I use this code to have two different behaviors when click right or left on menu.

Click left and click right + cmd.

How can I right click without pressing cmd + click in the simplest way?

-(void)awakeFromNib {

NSImage *image = [NSImage imageNamed:@"menubar"];
NSImage *alternateImage = [NSImage imageNamed:@"menubar-white"];

statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
[statusItem setHighlightMode:YES];
[statusItem setImage:image];
[statusItem setAlternateImage:alternateImage];
[statusItem setAction:@selector(show)];
}


- (void)show {

NSLog(@"call show");

NSEvent *event = [NSApp currentEvent];
//Respond to the mouse click
if ([event modifierFlags] & NSCommandKeyMask) //Command
{
    NSLog(@"RIGHT");
    [statusItem setMenu:statusMenu];
}
else {
    NSLog(@"LEFT");
    //open window
}
}

menu click right

Thanks for your help!

Joannes
  • 81
  • 1
  • 11

2 Answers2

6

I disagree with Aaron. In general, you should avoid inspecting the instantaneous mouse or keyboard state. It might have changed in the time since the action which you're actually supposed to respond to. For example, if the user left-clicks and then releases the mouse button, +pressedMouseButtons may return 0 by the time your code gets around to calling it.

Instead, you should examine the event that triggered the current processing. For a left-click, you would get an event whose type is NSLeftMouseDown. For a right-click, you would get NSRightMouseDown. If you already know that you have some kind of mouse click event and for some reason don't wish to examine its type, you can examine its buttonNumber property.

In fact, what has invoked your -show method? I would expect that you've implemented the NSResponder method -mouseDown: somewhere. If so, that corresponds to a left-click. If the user right-clicks, a different method (-rightMouseDown:) gets called. So, you should generally code those two methods differently if you want a different response.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • I would like a menu with right click and action with the left. Could you show me an example if possible? Now my code works only the first time, but if I delete [statusItem setMenu:statusMenu]; works correctly! Thanks – Joannes May 01 '13 at 14:01
  • I think for that you need to set the `view` of the status item and have your view draw itself in the way you want. If you want it to look like the standard status item, that may be as simple as just drawing the image in your `-drawRect:` or it may be more involved than that. I don't know, I've never tried it. Anyway, once you're using a custom view, you're in control of when it displays a menu. Don't set the `menu` property. Rather, invoke `-popUpStatusItemMenu:` under whatever conditions you want (such as in `-rightMouseDown:`). – Ken Thomases May 01 '13 at 20:10
  • 1
    Yes, is need to set the custom view of the status item. This is a great example: [http://mayfleet.com/2012/12/11/custom-status-bar-item/](http://mayfleet.com/2012/12/11/custom-status-bar-item/) Thanks! – Joannes May 02 '13 at 11:43
  • You may fall prey to the user expecting ctrl+click to register as a right click. `NSResponder` handles this for you and calls `-rightMouseDown:` when the user control-clicks. But if you inspect the event yourself, it will correctly state that the left button was pressed, and that control was held. I updated the answer to include that information. – fzwo Jan 26 '15 at 13:57
  • 1
    @fzwo, this is not true. `NSResponder` does not translate a Control-click into a right click or a call to `-rightMouseDown:`. It's just that `NSView` will present a contextual menu on a Control-click (via `-mouseDown:`) as well as a right click (via `-rightMouseDown:`). Go ahead and try it. I just did. `-rightMouseDown:` is not called on a Control-click. – Ken Thomases Jan 26 '15 at 16:48
  • Oops! Thanks for calling me out on that - must have mis-remembered. Will edit tomorrow when on desktop. I still think the hint regarding control-click is valuable - actually more so than I thought. I can tell you we only noticed after a bug report from a user. – fzwo Jan 26 '15 at 20:23
  • 1
    Control-click is not **generally** supposed to be treated as equivalent to right click in OS X. Both Control-click and right click bring up contextual menus, but that's really the only thing they have in common. There's no strong reason to treat them the same other than that. An app designer can choose to do so. User feedback is a fine reason to choose that. But I wouldn't necessarily say that it's imperative in the general case. The OP seems to want to use Command-click for some alternative to right clicking, so I don't know if Control-click is meaningful. – Ken Thomases Jan 26 '15 at 20:46
  • Alright, I'll leave your revert, and won't re-edit. I still think a lot of the time, a right-click is intended when control-clicking, so I think the caveat applies. – fzwo Jan 27 '15 at 13:22
4

Inspect [NSEvent pressedMouseButtons] instead of the modifier flags. Let the system take care of deciding which button has been clicked. If you do it the way you're trying to do now you'll get weird behavior for users who are actually using multi-button mice.

You should be able to use something like this:

const NSUInteger pressedButtonMask = [NSEvent pressedMouseButtons];
const BOOL leftMouseDown = (pressedButtonMask & (1 << 0)) != 0;
const BOOL rightMouseDown = (pressedButtonMask & (1 << 1)) != 0;
fzwo
  • 9,842
  • 3
  • 37
  • 57
Aaron Golden
  • 7,092
  • 1
  • 25
  • 31
  • Something like this? -(void)show { NSUInteger pressedButtonMask = [NSEvent pressedMouseButtons]; BOOL leftMouseDown = ((pressedButtonMask & (1 << 0))) != 0; //BOOL rightMouseDown = ((pressedButtonMask & (1 << 1))) != 0; if (leftMouseDown) { NSLog(@"left"); } } – Joannes Apr 30 '13 at 21:45
  • Yea, I think that'll work. To be honest I haven't tested this code, but I think it'll do the job based on the documentation in NSEvent.h. The other thing I really should have mentioned is that if you're working with a class that inherits from `NSResponder` you can implement the `mouseDown` method to capture left mouse downs and the `rightMouseDown` method to capture right mouse downs. – Aaron Golden Apr 30 '13 at 21:50
  • Messages to Objective-C objects cannot be made constant (well, the type can, as you have it, but the results of the method cannot), due to the nature of dynamic dispatch. – CodaFi Apr 30 '13 at 22:02