How to open a NSPopover at a distance from the system bar?

£可爱£侵袭症+ 提交于 2019-12-01 00:27:11

First, the reason why button.bounds.offsetBy(dx: 0.0, dy: -20.0) didn't work is because those coordinate fell outside the "window" of the status bar item which is the status bar itself. So anything outside of it was cropped.

I solved this problem by collecting information here and there:

  1. Create an invisible window.
  2. Find the coordinates in the screen of the status bar item and position the invisible window under it.
  3. Show the NSPopover in relation to the invisible window and not the status bar item.

The red thing is the invisible window (for demonstration purposes).

Swift 4 (Xcode 9.2)

// Create a window
let invisibleWindow = NSWindow(contentRect: NSMakeRect(0, 0, 20, 5), styleMask: .borderless, backing: .buffered, defer: false)
invisibleWindow.backgroundColor = .red
invisibleWindow.alphaValue = 0

if let button = statusBarItem.button {
    // 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)

    // position and show the NSPopover
    mainPopover.show(relativeTo: invisibleWindow.contentView!.frame, of: invisibleWindow.contentView!, preferredEdge: NSRectEdge.minY)
    NSApp.activate(ignoringOtherApps: true)
}

I was trying to use show(relativeTo: invisibleWindow.frame ...) and the popup wasn't showing up because NSWindow is not an NSView. For the popup to be displayed a view has to be passed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!