The problem is that when the status bar isn't visible the statusItem / button has a weird position so it's in the left side of the screen.
A possibly solution to this could be to save the position when the popover is first opened and keep showing it relative to that point. In this answer they place the popover relative to an invisible window. This we need because when we display the popover relative to the statusItem / button, the position is weird if the status is not visible.
So if you save the window as a variable and show the popover relative to this you will end up with something like this:
static let popover = NSPopover()
var invisibleWindow: NSWindow!
func showPopover(sender: Any?) {
if let button = AppDelegate.statusItem.button {
if (invisibleWindow == nil) {
invisibleWindow = NSWindow(contentRect: NSMakeRect(0, 0, 20, 1), styleMask: .borderless, backing: .buffered, defer: false)
invisibleWindow.backgroundColor = .red
invisibleWindow.alphaValue = 0
// find the coordinates of the statusBarItem in screen space
let buttonRect:NSRect = button.convert(button.bounds, to: nil)
let screenRect:NSRect = button.window!.convertToScreen(buttonRect)
// calculate the bottom center position (10 is the half of the window width)
let posX = screenRect.origin.x + (screenRect.width / 2) - 10
let posY = screenRect.origin.y
// position and show the window
invisibleWindow.setFrameOrigin(NSPoint(x: posX, y: posY))
invisibleWindow.makeKeyAndOrderFront(self)
}
AppDelegate.popover.show(relativeTo: invisibleWindow.contentView!.frame, of: invisibleWindow.contentView!, preferredEdge: NSRectEdge.minY)
NSApp.activate(ignoringOtherApps: true)
}
}