Switching properly from a status menu only state to a normal foreground application state programmatically could be tricky on macOS, here is one possible solution of the problem.
(works 10.7+)
- DO NOT USE LSBackgroundOnly NOR LSUIElement in the app plist
- Add and init your menu and NSStatusBar menu
- After app initialized but not yet shown any window take a place
where you might want to show the first window if any. We use
applicationDidFinishLaunching.
- If you do not want to show any window yet after app initialized use
[NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
on 10.9+ you can use at last the otherwise much correct
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
- If you should open any window after app init finished than simply show the main window
- If you do not want to show any window yet after app initialized use
- Maintain your list of windows
- If last window closed, call
[NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
on 10.9+ you can use at last the otherwise much correct
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
- When your first window shown next time, call
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps:YES];
[[self window] makeKeyAndOrderFront:nil];
Known issues:
- The first step is important because without that if a system
modal dialog suspends your startup (f.e. your app is downloaded from the
net and become quarantined a confirmation dialog might appear at first
startup depending on your security settings) your menubar might not be
owned by your app after your first app window shown.
Workaround: Starting as normal app (step 1.) would solve this problem, but will cause another small one, your app icon might appear for a moment in the dock at startup even if you would like to startup without any window shown. (but we can deal with this, not owning the menubar was a bigger problem for us, so we chose this instead)
- Changing between NSApplicationActivationPolicyRegular and
NSApplicationActivationPolicyAccessory (or
NSApplicationActivationPolicyProhibited on OSes bellow 10.9) will kill
your tooltip of status bar menu element, the tooltip will be shown
initially but will not ever after the second call of
NSApplicationActivationPolicyAccessory ->
NSApplicationActivationPolicyProhibited
Workaround: We could not find a working workaround for this and reported to Apple as a bug.
- Changing from NSApplicationActivationPolicyRegular to
NSApplicationActivationPolicyAccessory has other problems on some OS
versions like there might be no more mouse events in visible app windows
sometimes
Workaround: switch first to NSApplicationActivationPolicyProhibited (take care this leads to unwanted app messages, like NSApplicationWillResignActiveNotification, NSWindowDidResignMainNotification, etc. !)
- Changing from NSApplicationActivationPolicyAccessory to NSApplicationActivationPolicyRegular is bogus as on some OS versions
- the app main menu is frozen till the first app front status change
- the app activated after this policy not always get placed front in the application order