As of OS X 10.10 most of NSStatusItem has been deprecated in favour of the button
property, which consists of an NSStatusBarButton. It should work like a norma
Struggling with this issue myself, I discovered that overwriting mouseDown:
in a category on NSStatusBarButton
works:
#import "MUTargetClass.h"
@implementation NSStatusBarButton (Additions)
- (void)mouseDown:(NSEvent *)theEvent
{
// Relay CTRL+Click to perform a right click action
if(theEvent.modifierFlags & NSControlKeyMask)
{
[self rightMouseDown:theEvent];
return;
}
// Handle highlighting
[self setHighlighted:YES];
// Perform action on target
[(MUTargetClass *)self.target actionSelector:self];
}
@end
MUTargetClass
could then for example implement:
#import "NSStatusBarButton+Additions.h"
@implementation MUTargetClass
[…]
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
NSStatusBarButton *button = [self.statusItem button];
[button setTarget:self];
[…]
- (void)actionSelector:(id)sender
{
// Whatever behavior a click on the button should invoke
}
[…]
// Reset button's highlighting status when done
[[self.statusItem button] setHighlighted:NO];
[…]
@end
Note that the functionality of CTRL+clicking the button is getting lost in the mouseDown:
-override. As shown above, it can be restored by relaying the event to rightMouseDown:
.
A simpler way of having the action called would be something along the lines of [self.target performSelector:self.action]
in the category and [self.statusItem setAction:@selector(actionSelector:)]
in the target class, however this may cause a leak in ARC projects.
Edit: This works on El Capitan, too.
Anton's solution is perfect. Here it is in Swift 3:
NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown) { [weak self] event in
if event.window == self?.statusItem.button?.window {
// Your action:
self?.togglePopover(self?.statusItem.button)
return nil
}
return event
}
I added an observer for NSApplicationWillResignActive
to close the popover and set the button's isHighlighted
to false
.
I added a subview to the status item, and inside that view I added event handlers for mouseDown etc. which called [[statusItem button] highlight:true]. As it turns out setHighlighted: doesn't do the same thing as highlight:.
NSArray *array = [NSArray arrayWithObjects:[statusItem button], [self statusItemView], nil];
[[[statusItem button] superview] setSubviews:array];
//Highlight like so:
[[statusItem button] highlight:true];
EDIT: As of El Capitan this method no longer works, and neither does statusItem.button.highlight = true
either