如何让 NSPopover 正确跟随鼠标指针并忽略鼠标事件?

How to make NSPopover properly follow the mouse pointer and ignore mouse events?

我想显示跟踪用户鼠标光标的信息NSPopover

为此,每当 mouseMoved 事件触发时,我使用 NSTrackingArea 更新弹出窗口的 positioningRect

但是,这有两个缺点:

  1. 弹出窗口跟随鼠标稍有延迟。我怎样才能减少这个延迟,使弹出窗口看起来更 "glued" 到鼠标指针?
  2. 当我在弹出窗口的方向移动鼠标指针时,跟踪区域的 mouseExited 方法被调用,这导致弹出窗口 "absorb" 鼠标移动事件,因此跟踪区域的mouseMoved 事件不再触发。我怎样才能避免弹出窗口吸收鼠标事件,或者至少继续转发这些事件?

这个问题和Any way around this NSTrackingArea quirk?非常相似,不同的是我用的是NSPopover,所以我没有设置ignoresMouseEvents

我看了你的问题。我无法消除延迟,但如果将 popover.animates 设置为 false 可能会减少延迟。

错误的做法:

我能够通过在另一个边框之上添加新边框(和无阴影)window 来解决 mouseExited 超过 popover 的问题。 trackingArea被添加到透明window,popover到原来的。根据透明 windows level,它位于弹出窗口上方,因此它们不会相互干扰。 在下面的 gif 中,您可以看到我的测试结果:

这是我的一些代码:

鼠标跟踪:

override func mouseMoved(with event: NSEvent) {
    let location = self.view.convert(event.locationInWindow, from: nil)
    popover.positioningRect.origin.x = location.x
    popover.positioningRect.origin.y = location.y
}

自定义window:

transparentWindow.backgroundColor = NSColor.clear
transparentWindow.isOpaque = false
transparentWindow.styleMask = .borderless
transparentWindow.makeKeyAndOrderFront(nil)

2016 年 11 月 11 日更新

我刚刚阅读了您提供的 link 中的问题。有一个 window 可以设置 ignoresMouseEvents。尽管 NSPopover 继承自 NSObject,但您有一个 contentViewController,它包含一个 view 对象,该对象包含弹出窗口 window。 (如解释here

所以只需设置

popover.contentViewController?.view.window?.ignoresMouseEvents = true

显示 popover 之后。