Menu of macOS statusbar application does not appear when I force a window on top

41 Views Asked by At

I have a statusbar application that has a weird issue sometimes (not 100% reliably!) when there's a window in view, for example when onboarding. When the Window is foregrounded, the menu works. When it's not focused, the menu sometimes doesn't work.

The menu, when it works

The menu might have an issue when there is no window and I might have no issue with onboarding open, but when it does happen the issue goes away and comes back when I focus / unfocus the window by tapping the window or tapping the background.

I have the following code:

class OnboardingWindowController: NSWindowController {
    override func windowDidLoad() {
        super.windowDidLoad()

        NSApplication.shared.activate(ignoringOtherApps: true)
        window?.level = NSWindow.Level(rawValue: Int(CGWindowLevelForKey(.maximumWindow)))
    }
}

As soon as I comment out the two lines of window managing code the issue goes away.

However, I would like the onboarding window to be (one of) the most foregrounded windows as the onboarding sometimes triggers opening the settings or other windows and the user might lose the onboarding flow, leading to people not completing onboarding and not buying our product.

This is the window opening code:

@MainActor
private func showOnboardingWindow() {
    showInitialController(ofStoryboard: "Onboarding", withIdentifier: "OnboardingWindowController")
}

@MainActor
private func showInitialController(
    ofStoryboard storyboardName: String,
    withIdentifier identifier: String
) {
    closeAllWindows()

    DispatchQueue.main.async {
        let storyboard = NSStoryboard(name: storyboardName, bundle: nil)

        guard let windowController = storyboard.instantiateController(withIdentifier: identifier) as? NSWindowController else {
            self.logHandler.log(errorString: "Could not initialize NSWindowController \(identifier) on \(storyboardName)")
            return
        }

        guard let window = windowController.window else {
            self.logHandler.log(errorString: "NSWindowController \(windowController) does not have a window while opening \(identifier) on \(storyboardName)")
            return // TODO: Handle?
        }

        if #available(macOS 14.0, *) {
            NSApp.activate()
        } else {
            NSApp.activate(ignoringOtherApps: true)
        }

        DispatchQueue.main.async {
            windowController.showWindow(self)
            //window.level = NSWindow.Level.init(rawValue: 1)
            window.orderFrontRegardless()
            //window.makeKeyAndOrderFront(nil)
        }
    }
}

@MainActor
private func closeAllWindows() {
    NSApplication.shared.windows.filter { $0.contentViewController != nil }.forEach { window in
        window.close()
    }
}

What can I do to keep the user in onboarding while not messing with the menu function?

0

There are 0 best solutions below