3

I'm developing a simple menubar app for OS X Yosemite using Swift. What is I need is to show Preferences window (when user clicks on menu item) Window should be hidden at launch, and should be shown when user calls it.

I found an example which implements the same thing that I need: http://www.johnmullins.co/blog/2014/08/08/menubar-app/

This is a piece of code from my app:

class AppDelegate: NSObject, NSApplicationDelegate {
    @IBOutlet weak var buildStatusMenu: NSMenu!
    @IBOutlet weak var preferencesWindow: NSWindow!

    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        self.preferencesWindow!.orderOut(self)
    }  

    func showPreferencesWindow(sender: AnyObject?) {
        self.preferencesWindow!.orderFront(self)
        NSLog("Show window")
    }

orderOut works correctly, and I don't see window at launch but when I try to call showPreferencesWindow(), nothing happens. (But I see a record in log) I'm sure there is no magic here, I'm just doing something wrong. Can someone help me? Thanks in advance.

Andrey Basalyha
  • 213
  • 1
  • 6
  • 1
    What is the frame of the preferences window? Also, are you sure the preferences window is not on screen but behind other windows? You may need to do `NSApplication.sharedApplication().activateIgnoringOtherApps(true)`. – Ken Thomases May 10 '15 at 15:36
  • Hi Ken. Thank you for your answer! I really don't know what is the "frame":) I'm a newbie in OS X developing, sorry for that:) but seems your recipe works perfect:) Can you please explain, what does your recipe do and what is the frame?:) – Andrey Basalyha May 10 '15 at 16:26
  • Well, those were two separate issues. The frame is the size and position of the window (x, y, width, height). I was wondering if the window was positioned outside the bounds of the screen. It sounds like it was not outside the screen because the second suggestion worked. I'll put that in an answer with a more complete explanation. – Ken Thomases May 10 '15 at 16:31

1 Answers1

5

Normally, an application with LSUIElement in its Info.plist will not be the active app. The user can't switch to it using Command-Tab or the Dock because it doesn't appear there.

When an inactive app orders a window to the front, it actually doesn't go in front of the active app. That would steal the focus and interrupt the user, which is usually undesirable. Instead, the window ends up behind the front window.

For a menubar app, however, you do want to "steal" focus. The user has just requested one of your app's windows and so it expecting your app to become active. This is one of the rare cases where it's appropriate to pass true to the activateIgnoringOtherApps() method of NSApplication. So, you should call NSApplication.sharedApplication().activateIgnoringOtherApps(true). That will make sure your window actually ends up in front.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154