Really fix event dispatching in Mac modal event loops

Manually dispatching events to eligible windows is error-prone and
should really be the responsibility of the system. But the old
approach of blocking in nextEventMatchingMask:untilDate:inMode:dequeue
seems to fail because while this blocks, events can't even enter the
queue.

Thus, revert to the old logic, but instead of blocking in
nextEventMatchingMask, first block on processing the input source via
[NSRunLoop runMode:beforeDate].

This resolves the original problem which was also fixed by the commit
4a83fd4696 but doesn't seem to introduce any
regressions, and seems to be a much cleaner fix overall.

See #17737.

Closes https://github.com/wxWidgets/wxWidgets/pull/365
This commit is contained in:
Jeff Davidson 2016-12-22 01:23:37 -08:00 committed by Vadim Zeitlin
parent 59d26b0bad
commit 6293d7427c

View File

@ -210,34 +210,23 @@ int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout)
if ( m_modalSession )
{
NSInteger response =
[NSApp runModalSession:(NSModalSession)m_modalSession];
NSInteger response = [NSApp runModalSession:(NSModalSession)m_modalSession];
switch (response)
{
case NSRunContinuesResponse:
{
// runModalSession is supposed to handle event dispatching, but
// for some reason we need to dequeue and send events here as
// well (see #17737).
NSEvent *event = [[NSApplication sharedApplication]
[[NSRunLoop currentRunLoop]
runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000.0]];
if ( [[NSApplication sharedApplication]
nextEventMatchingMask: NSAnyEventMask
untilDate: [NSDate dateWithTimeIntervalSinceNow: timeout/1000.0]
untilDate: nil
inMode: NSDefaultRunLoopMode
dequeue: YES];
if ( event == nil )
return -1;
// Only dispatch events for the modal window, or events not
// associated with any window, as other windows should not be
// responsive to inputs when a modal is present.
NSWindow *modalWindow =
m_modalWindow->MacGetTopLevelWindowRef();
if ( event.window == nil || event.window == modalWindow )
[NSApp sendEvent: event];
return 1;
dequeue: NO] != nil )
return 1;
return -1;
}
case NSRunStoppedResponse:
case NSRunAbortedResponse: