Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSMenu Pressed Mouse Button in 10.5

I’m updating (downdating?) an application I’ve written for 10.6+ to work in 10.5+. I’m struggling with capturing the currently pressed mouse button in the -(void)menuWillOpen:(NSMenu *); selector.

For 10.6+ I’m taking advantage of the [NSEvent pressedMouseButtons] which allows me to get the pressed button outside the event stream. However, this doesn’t exist in 10.5+ (it appears I need to call [theEvent buttonNumber].

How do I capture the pressed mouse button (right or left):

  1. Inside of my NSMenu delegate
  2. Preferably inside the -(void)menuWillOpen:(NSMenu *)menu selector
  3. In a manor that works in both 10.5+ and 10.6+

I really appreciate the help and know StackOverflow will help a new Objective-C programmer out!

Thanks, Dustin

like image 273
Dustin Senos Avatar asked Dec 19 '10 00:12

Dustin Senos


2 Answers

In the end I was able get the current mouse button by calling (thanks to Nick Paulson for the help):

[[[NSApplication sharedApplication] currentEvent] buttonNumber]

As ughoavgfhw pointed out a shorter way of fetching the same event is though:

[[NSApp currentEvent] buttonNumber]

like image 94
Dustin Senos Avatar answered Nov 17 '22 22:11

Dustin Senos


Another way would be to create a CGEventTap that captures mouse down events.
You then just have to remember the last event type and check that in one of your NSMenu delegate methods.
Here is some sample code:

CGEventRef MouseClickedEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon)
{
    CGPoint location = CGEventGetLocation(event);   
    switch (type) 
    {
        case kCGEventLeftMouseDown:
        {
            NSLog(@"Left Mouse pressed at %@", NSStringFromPoint(NSPointFromCGPoint(location)));
            break;
        }           
        case kCGEventRightMouseDown:
        {
            NSLog(@"Right Mouse pressed at %@", NSStringFromPoint(NSPointFromCGPoint(location)));
            break;
        }   
        case kCGEventOtherMouseDown:
        {
            NSLog(@"Other Mouse pressed at %@", NSStringFromPoint(NSPointFromCGPoint(location)));
            break;          
        }
        default:
            break;
    }
    return event;
}

- (void)applicationDidFinishLaunching:(NSNotification*)aNotification
{
    CGEventMask eventMask = CGEventMaskBit(kCGEventLeftMouseDown)|CGEventMaskBit(kCGEventRightMouseDown)|CGEventMaskBit(kCGEventOtherMouseDown);
    CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, eventMask, MouseClickedEventCallback, NULL);
    CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
    CGEventTapEnable(eventTap, true);
}

The Quartz Event Services docs state that:

Event taps receive key up and key down events if one of the following conditions is true:

  • The current process is running as the root user.
  • Access for assistive devices is enabled. In Mac OS X v10.4, you can enable this feature using System Preferences, Universal Access panel, Keyboard view.

I double checked that and it seems that you really don't have to enable assistive devices to receive mouse events.

But if [[[NSApplication sharedApplication] currentEvent] buttonNumber] does what you want, I'd definitely go with that. It's higher level and therefore less code.

like image 35
Thomas Zoechling Avatar answered Nov 17 '22 22:11

Thomas Zoechling