Search code examples
objective-cmacosxibnpapifirebreath

How to connect NSMenu to NSStatusItem in a Firebreath NPAPI plugin so the menu appears when clicking the StatusBar Item?


I'm working on getting a Status icon with a menu to appear in the Mac OS Status Bar, as part of an NPAPI Chrome browser plugin.

Firebreath uses C++, while most of the libraries for Mac OS development utilize Objective C. I overcame that hurdle thanks to the response on this question. I also had to adjust my CMake settings in order to compile an XIB file to NIB.

After trial and error, I was able to get the status bar option to appear in the status bar, but when I click on it, the menu will not expand. I'm not sure what I need to do to get the menu to display. It works in a Cocoa application, but not in the Firebreath application.

I've imported the Foundation and Cocoa libraries as well.

I suspect the problem is either in my MainMenu.xib file or in AppDelegate.m.

AppDelegate.m:

#import "AppDelegate.h"   

@implementation AppDelegate

-(void)awakeFromNib {
    NSLog(@"calling awakeFromNib...");

    NSStatusBar *bar = [NSStatusBar systemStatusBar];
    statusItem = [[bar statusItemWithLength:NSVariableStatusItemLength ] retain];


   // statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    //[statusItem retain];
    NSMenuItem *menuItem;


    menuItem = [[[NSMenuItem alloc] initWithTitle:@"Test" action:NULL keyEquivalent:@""] retain];
//    [menuItem setView: myView];
    statusMenu = [statusMenu initWithTitle:@"WTF"];
    [statusMenu addItem:menuItem];

    [menuItem retain];
    [statusItem setTitle: NSLocalizedString(@"StatusMenu",@"")];
    [statusItem setHighlightMode:YES];
    [statusItem setMenu:statusMenu];
    [statusItem setEnabled:YES];

    [statusMenu retain];

    // this was needed to get the icon to display
    [statusItem retain];
    //[window retain];
}

- (IBAction)settings:(id)sender {
    NSLog(@"Invoking the settings from the menu...");

}

//@synthesize window;
@end

This file was snagged from the sample app, and awakeFromNib is being invoked manually from an Objective C++ wrapper class. As per the logs, and the fact that I see "StatusMenu" in the Status Bar, I know this function is being called.

I also include a screenshot of the MainMenu.xib:

MainMenu.xib:

MainMenu.xib

The last thing I've tried is adding NSStatusItem as an IBOutlet to see if I can connect it to something in the xib file, but I'm not really sure this is the right direction to go.

What is it that needs to be done to get the menu to show when clicking the Status Menu option?


Solution

  • The problem here is that the Firebreath project and the NPAPI plugin architecture don't support automatic reference counting (ARC), which is generally turned on by default in XCode projects.

    Additionally, because of the craziness of mixing Objective C with C++, XCode isn't really able to report on errors as easily as if the code was written purely in Objective C. Thus, the error message is suppressed. In order to avoid the errors, the developer working with the NPAPI plugin architecture must manage memory explicitly by invoking alloc on the NSMenu object.

    As long as alloc is called on these objects, they'll be properly retained. This fixes the problem.