macosswiftuiappkitcolor-pickerlsuielement

SwiftUI ColorPicker Fails In Background (Menubar) App


Context

I have an app that runs only from the macOS menubar. (The LSUIElement property in info.plist is set to YES).

Instead of a menu, this app shows an NSPopover when the menubar button is clicked. The popover holds an NSHostingView which has an extremely simple SwiftUI view:

struct PopoverContentView: View
{
    @State private var color: CGColor = .white

    var body: some View
    {
        ColorPicker(selection: $color) {
            Text("Pick a Color:")
        }
    }
}

Problem

Clicking on the ColorPicker() does not open the macOS color picker window. The UI of the ColorPicker() button changes, to show the "selected" border state but the color-picker window never appears.

However, if I change LSUIElement to be NO and then make the app active by clicking its Dock icon (so that it takes over the menubar), THEN clicking on the ColorPicker() in the popover actually reveals the color-picker window.

Do you know of a way to force macOS to show the color-picker window for a background application?


Solution

  • The answer turned out to be simple. In the AppKit ViewController that opens the popover when the menubar button is clicked (PopoverController, for me), I simply did this:

    extension PopoverController: NSPopoverDelegate
    {
        func popoverWillShow(_ notification: Notification)
        {
            NSApp.activate(ignoringOtherApps: true)
        }
    }
    

    The ColorPicker now correctly shows the standard macOS system color panel on click.