Как заставить NSPopover правильно следовать за указателем мыши и игнорировать события мыши?

Я хотел бы отобразить информационный NSPopover, который отслеживает курсор мыши пользователя.

Для этого я использую NSTrackingArea для обновления всплывающего окна positioningRect всякий раз, когда срабатывает событие mouseMoved.

Однако у этого есть два недостатка:

  1. Поповер следует за мышью с небольшой задержкой. Как я могу уменьшить эту задержку, чтобы всплывающее окно выглядело более «приклеенным» к указателю мыши?
  2. Когда я перемещаю указатель мыши в направлении всплывающего окна, вызывается метод mouseExited области отслеживания, который заставляет всплывающее окно «поглощать» события движения мыши, так что событие mouseMoved области отслеживания больше не срабатывает. Как я могу избежать всплывающего окна, поглощающего события мыши, или, по крайней мере, продолжать пересылать эти события?

Этот вопрос очень похож на как обойти эту причуду NSTrackingArea?, с разница в том, что я использую NSPopover, поэтому мне не на что устанавливать ignoresMouseEvents.


person MrMage    schedule 04.11.2016    source источник


Ответы (1)


Я ознакомился с вашей проблемой. Мне не удалось устранить отставание, но оно может уменьшиться, если вы установите popover.animates на false.

Неправильный подход:

Мне удалось решить проблему mouseExited вместо popover, добавив новую границу (и без теней) window поверх другой. trackingArea добавляется к прозрачному окну, поповер к исходному. В зависимости от прозрачных окон 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
}

Пользовательское окно:

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

Обновление от 11.11.2016:

Я только что прочитал вопрос по ссылке, которую вы предоставили. Есть окно для включения ignoresMouseEvents. Несмотря на то, что NSPopover наследуется от NSObject, у вас есть contentViewController, который содержит объект view, который содержит всплывающие окна window. (как описано здесь)

Так просто установить

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

после отображения popover.

person mangerlahn    schedule 10.11.2016
comment
Я уже использовал popover.animates = false, но задержка все еще заметна :-/ Я также только что попробовал источник всплывающего окна напрямую через popover.contentViewController?.view.window?.setFrameOrigin(), но это тоже не помогло, поэтому я думаю, что для этого просто нет решения. ignoresMouseEvents = true работает нормально, спасибо! - person MrMage; 14.11.2016