NSApp.activate() does not work with menu bar (background) apps

NSApp(ignoringOtherApps:) is deprecated but there is no other working alternative for menu bar apps. NSApp.activate() does not work when no app windows are active and we want to show a window from a menu bar application. Making it impossible for the app to open a window and make it active.

Is it really an intended behavior?

Here is a sample project showing the issue: https://github.com/wojciech-kulik/macos-menu-bar-bug

Steps to reproduce:

  1. Run the app.
  2. Focus some other app like Finder or Safari.
  3. Click on the app's menu bar icon and select "Open".

The app window will appear below the other app's window, instead of being brought to the front. NSApp(ignoringOtherApps: true) works as expected though.

I also created a feedback ticket: FB23508310

Thank you for the post. Very interesting post.

The strictness of the new window activation model is intended, I believe the goal was to stop apps from aggressively stealing focus from the user while they are typing or working in another app. Because of this, NSApp.activate(ignoringOtherApps:) was deprecated. https://developer.apple.com/documentation/appkit/nsapplication/activate(ignoringotherapps:)

You should use https://developer.apple.com/documentation/appkit/nsapplication/activate()

If you are using SwiftUI lifecycle with MenuBarExtra and WindowGroup, relying on the environment's openWindow to handles the underlying activation better than bridging to AppKit:

@Environment(\.openWindow) var openWindow

// Inside your MenuBarExtra... 
Button("Open") {
    openWindow(id: "my-main-window")
}

My code is for reference only as I don't validate it with Xcode.

If the behavior deviates from your expectations, the bug filed as an enhancement will be forwarded to the relevant team for evaluation of your requirements. The team will then propose a more effective workaround to address your needs than me.

Also invite other engineers to provide suggestions on your workflow.

Albert  WWDR

Hi, thank you for the quick reply!

I wanted to call out a specific user experience issue with this approach regarding menu bar apps.

Currently, if a user clicks an item in the menu bar expecting a window to open, that window appears behind the currently active window. Because it's hidden from view, the user might assume the app is broken or didn't respond. It's hard to imagine that this is the intended behavior. Bringing the newly opened window to the foreground would be the expected behavior in this case.

It seems like the new NSApp.activate() was designed for regular apps and did not take menu bar apps into account.

This behavior is the same when using NSApp.activate() and SwiftUI openWindow.

For now, all menu bar apps still rely on the deprecated NSApp.activate(ignoringOtherApps:), but removing this function would result in breaking thousands of apps. That's why I think there should be an alternative to NSApp.activate(ignoringOtherApps:) or the behavior of NSApp.activate() should be changed when the activation policy is set to NSApp.setActivationPolicy(.accessory).

Please see the video presenting this issue: https://github.com/user-attachments/assets/cc1748da-3a18-4254-b730-e8fa844158d6

@maxik Thank you for providing the feedback and the description to keep that API for being deprecated. Please add that reasoning to the bug for the team to review and provide you with an answer.

Albert  WWDR

Yeah if NSApplication's -activateIgnoringOtherApps: method stops working this will be a problem for my app as well.

I briefly replaced the to be deprecated method with -activate at some point (last year I think) but after discovering the same issue I had to revert back to -activateIgnoringOtherApps:YES

[@Macho Man Randy Savage](https://developer.apple.com/forums/profile/Macho Man Randy Savage)

Can you also file a bug with your description for the team? I'm sure the team has a workaround and a way to accomplish what you need. This feedback will produce a better documentation moving forward.

Thanks

Albert  WWDR

NSApp.activate() does not work with menu bar (background) apps
 
 
Q