Show NSWindow below your NSStatusItem

Often, showing a simple menu in your status bar application is not sufficient enough. This short tutorial explains how you can show your own window right below of your status item. Inspired was this blog post by the following question on StackOverflow.

  1. For the basic setup of your status bar application you should have a look at our previous blog post How to create a Mac OS X status bar application.
  2. Instead of adding a NSMenu  control to the status item, we want to call our own action. Therefore we set the target  and action  property of NSStatusItem . In this case the target will be the app delegate itself.
    // Code for creating status item
    ...
    
    // Setting target and action
    [self.statusItem setTarget:self];
    [self.statusItem setAction:@selector(statusItemAction:)];
  3. Now add your custom action method statusItemAction:  to your app delegate.
    - (void) statusItemAction:(id) sender
    {
    }
  4. Prepare the window you want to show below your status item. The best way to do this is to create a new NSWindowController  subclass including a xib  file. Customize your window as you like and add a new propertyto your app delegate for your window controller.
    @property(strong, nonatomic) StatusWindowController *windowController;
  5. The next things I will summarize up a little bit. You need to get the frame of your status item, create your window controller, get the window reference, calculate the window position and finally displaying the window. This is shown in the following code snippet of the statusItemAction:  method.
    - (void) statusItemAction:(id) sender
    {
        // Get the frame and origin of the control of the current event
        // (= our NSStatusItem)
        CGRect eventFrame = [[[NSApp currentEvent] window] frame];
        CGPoint eventOrigin = eventFrame.origin;
        CGSize eventSize = eventFrame.size;
    
        // Create a window controller from your xib file
        // and get the window reference
        if(self.windowController == nil)
            self.windowController = [[StatusWindowController alloc] initWithWindowNibName:@"StatusWindow"];
        NSWindow *window = [self.windowController window];
    
        // Calculate the position of the window to
        // place it centered below of the status item
        CGRect windowFrame = window.frame;
        CGSize windowSize = windowFrame.size;
        CGPoint windowTopLeftPosition = CGPointMake(eventOrigin.x + eventSize.width/2.f - windowSize.width/2.f, eventOrigin.y - 20);
    
        // Set position of the window and display it
        [window setFrameTopLeftPoint:windowTopLeftPosition];
        [window makeKeyAndOrderFront:self];
    
        // Show your window in front of all other apps
        [NSApp activateIgnoringOtherApps:YES];
    }

That’s it. Run your application and click the status item. The window should appear right below and centered to your status item.

2 responses to “Show NSWindow below your NSStatusItem”

  1. Thank you for your blog post. Also I have one question… can you provide the full project source code? Thanks.

  2. Hi ! This works if you click on the status item on the menu bar. But how can i make it work for short cut keys. I don’t know how to get the correct position of the status item. Any suggestion?

Leave a Reply

Your email address will not be published. Required fields are marked *