1

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?

Community
  • 1
  • 1
jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
  • When you say "`awakeFromNib` is being invoked manually from an Objective C++", are you involving `NSBundle` or `NSNib`? If not, I suspect that you need to do so. Perhaps [The Nib Object Life Cycle](http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW18) or [Loading Nib Files Programmatically](http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW24) will be helpful. – jscs Sep 19 '12 at 01:53
  • Hi @JoshCaswell, in the sample app, I think it was being called by some other process that handled loading the app, but the Firebreath framework uses C++ and some other mechanism to start the app. I'm invoking the `awakeFromNib` from an Objective C++ wrapper. I'll take a look at NSBundle and NSLib and that link. Thanks for the tip; I'll update my question as I learn more. – jamesmortensen Sep 19 '12 at 01:54
  • Keep in mind that there likely is no NSApplication and you might not be able to create one; these are the downsides to living in someone else's process. – taxilian Sep 19 '12 at 15:19
  • @taxilian - Google has a [Google Talk Chrome Extension](https://chrome.google.com/webstore/detail/chat-for-google/nckgahadagoaajjgafhacjanaoiihapd) that installs a status bar icon in both Windows and Mac OS, using NPAPI. Right click shows options, and left click loads a Chrome panel. I have the status bar icon already in place, so my thought is to try and register a click event that I can tie into. I guess I don't need full integration with the OS, in fact, throwing an event the extension can tie into would be more cross-platform compatible. So if NSApplication isn't available, I'll try this. – jamesmortensen Sep 19 '12 at 15:59
  • Ok, so it turns out that I wasn't calling alloc on the NSMenu object, and Objective C doesn't throw NPE's like Java or undefined errors like JavaScript would do in this scenario. After adding alloc, I can programmatically add items to the menu and fire a log event on click. In short, I'm completely bypassing the xib/nib, which is okay with me if it means moving onto the next challenge. – jamesmortensen Sep 19 '12 at 19:20

1 Answers1

0

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.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120