Skip to content

Instantly share code, notes, and snippets.

@rsfinn
Last active April 9, 2016 23:48
Show Gist options
  • Save rsfinn/ad04fed80d88630205cc15c4e66fecb1 to your computer and use it in GitHub Desktop.
Save rsfinn/ad04fed80d88630205cc15c4e66fecb1 to your computer and use it in GitHub Desktop.
Notes on NSPopover (from Chromium bug report)
From <https://bugs.chromium.org/p/chromium/issues/detail?id=116179#c14>:
In 10.8, -[NSWindow _sharesParentKeyState] has changed meaning to also include when a window has resigned key state
(which makes sense). This means that the parent window of the bubble (the BrowserWindowController's window) has to
resign key in order for the bubble to lose key via -[NSWindow _changeKeyAndMainLimitedOK:]. Note that there's also
a method -[NSWindow(NSWindowSharedFirstResponder) _setSharesParentFirstResponder:], which may or may not do the same
thing as overriding |-_sharesParentKeyState|, but the former is how popovers get this behavior.
Popovers get closed when key state changes in three ways, set up in _NSPopoverRegisterForEvents. The first is an event
tap via +[NSEvent addGlobalMonitorForEventsMatchingMask:handler:] that watches on (NSLeftMouseDownMask | NSLeftMouseUpMask)
and causes all popovers to close when the handler is invoked. Secondly, they register for NSWindowDidResignKeyNotification
notifications on nil (all objects) and again close all popovers when this is called. Finally, in
-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:], they peek each event and call _NSPopoverPreProcessLocalEvent.
This lets them dismiss popovers on scroll events and anything else they like (which we don't need to do/"can't" do).
To fix this in Chrome, I'll do something similar with the event monitor and notification. Yuck, but it's the "right thing" to do.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment