Search code examples
objective-ccocoansmenunsstatusitem

Listen for Actions on a NSStatusItem With a Menu


I have a NSStatusItem with a menu attached. How can I get mouse/touch events from the status item without losing the menu? I was thinking perhaps some kind of workaround where I take in the events and manually pop the menu up, but I am unsure of the feasibility.

The following example demonstrates the problem. The only major difference from this example and my actual code is I am using a menu delegate.

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    IBOutlet NSWindow *window;
    NSStatusItem* statusItem;
    NSMenu* statusMenu;
    NSMenuItem* menuItem;
}
-(IBAction)stuffHappened:(id)sender;
@end

@implementation AppDelegate

-(void)awakeFromNib{
    statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
    
    statusMenu = [[NSMenu alloc] initWithTitle:@""];
    menuItem = [[NSMenuItem alloc] initWithTitle:@"test"
                                   action:nil
                                   keyEquivalent:@""];
    statusItem.button.title = @"\U0001F410";
    
    [statusItem setMenu:statusMenu]; //commenting out this line allows the action to fire
    [statusMenu addItem:menuItem];
    
    [[statusItem button] setTarget:self];
    statusItem.button.action = @selector(stuffHappened:);
}

-(IBAction)stuffHappened:(id)sender {
    NSLog(@"Stuff happened");
}
@end

Solution

  • This solution came from a previous SO question:Highlighting NSStatusItem with attributed string and may do what you want. Unfortunately, popUpStatusItemMenu is now deprecated.

    #import <Cocoa/Cocoa.h>
    
    @interface AppDelegate : NSObject <NSApplicationDelegate> {
      NSStatusItem* statusItem;
      NSMenu* statusMenu;
      NSMenuItem* menuItem;
    }
    -(void)statusItemHandler:(id)sender;
    -(void)menuHandler:(id)sender;
    @end
    
    @implementation AppDelegate
    
    -(void)menuHandler:(id)sender {
      NSLog(@"Menu item = %@",sender);
    }
    
    -(void)statusItemHandler:(id)sender {
     NSLog(@"StatusItem hit.");
     statusMenu = [[NSMenu alloc] init];
     menuItem = [statusMenu addItemWithTitle: @"Item 1" action:@selector(menuHandler:) keyEquivalent:@""];
     menuItem = [statusMenu addItemWithTitle: @"Item 2" action:@selector(menuHandler:) keyEquivalent:@""];
     [statusMenu addItem:[NSMenuItem separatorItem]];
     menuItem = [statusMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@""]; 
     [statusItem popUpStatusItemMenu:statusMenu];
    }
    
    -(void)applicationDidFinishLaunching:(NSNotification *)notification {
     statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength]; 
     statusItem.button.title = @"\U0001F410";      
     statusItem.button.action = @selector(statusItemHandler:);
    }
    
    @end
    
    int main(){
     NSApplication *application = [NSApplication sharedApplication];
     [application setActivationPolicy:NSApplicationActivationPolicyRegular];
     AppDelegate *appDelegate = [[AppDelegate alloc] init];
     [application setDelegate:appDelegate];
     [application activateIgnoringOtherApps:YES];
     [application run];
     return 0;
    }