I'm building a Mac app that only sits in the menu bar with no dock item and no key window and no main menu (it's LSUIElement
in the info.plist is set to YES
). When I first launch the app, applicationDidBecomeActive:
is called, as I expect. However, once another app gains focus, applicationDidBecomeActive:
is never called again.
This prevents a text field I have within my app from becoming the first responder. When I first open the app, the text field is editable:
But after another app comes to the foreground, the text field is not editable:
When the menu is opened, menuWillOpen:
is called on the NSMenu
's delegate. I've tried placing the following with no success:
[NSApp unhide];
[NSApp arrangeInFront:self];
[NSApp activateIgnoringOtherApps:YES];
[NSApp requestUserAttention:NSCriticalRequest];
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
[[NSRunningApplication currentApplication] unhide];
I think the issue is probably related to not having any windows to bring to the front. I feel like I'm grasping at straws here. Any help would be greatly appreciated.
Click the Apple () symbol in the menu bar and select System Preferences... in the dropdown menu. Click the Dock & Menu Bar icon in the preference pane. Make sure Dock & Menu Bar is selected in the sidebar, and under "Menu Bar," uncheck the box next to Automatically hide and show the menu bar in full screen.
If you notice that the Menu Bar at the top of your screen is missing, it is probably because you are using an app in Full Screen mode. You can customize how this works in System Preferences. You can also use Mission Control and Spaces to have the Menu Bar present for some apps and not others.
I think the issue is with that how the runloop operates when a NSMenu
is open, so you should try activating the app before you display the menu. If you're having the NSStatusItem
display it, I'd suggest doing it yourself like this:
- (void)toggleMenu:(id)sender
{
// App might already be active
if ([NSApp isActive]) {
[self.statusItem popUpStatusItemMenu:self.menu];
} else {
[NSApp activateIgnoringOtherApps:YES];
}
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
[self.statusItem popUpStatusItemMenu:self.menu];
}
That should work, but I think though in general you'll have better luck with an actual window instead of a menu.
You probably need to allow your input to -becomeFirstResponder
, maybe by overriding -canBecomeFirstResponder
or by calling the become method yourself.
You'd likely have to implement/call these methods for whatever view is housing your text input, or maybe tell your input view to become the first responder.
Either way, it smells like a responder chain issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With