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 ) if ( m_modalSession )
{ {
NSInteger response = NSInteger response = [NSApp runModalSession:(NSModalSession)m_modalSession];
[NSApp runModalSession:(NSModalSession)m_modalSession];
switch (response) switch (response)
{ {
case NSRunContinuesResponse: case NSRunContinuesResponse:
{ {
// runModalSession is supposed to handle event dispatching, but [[NSRunLoop currentRunLoop]
// for some reason we need to dequeue and send events here as runMode:NSDefaultRunLoopMode
// well (see #17737). beforeDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000.0]];
NSEvent *event = [[NSApplication sharedApplication] if ( [[NSApplication sharedApplication]
nextEventMatchingMask: NSAnyEventMask nextEventMatchingMask: NSAnyEventMask
untilDate: [NSDate dateWithTimeIntervalSinceNow: timeout/1000.0] untilDate: nil
inMode: NSDefaultRunLoopMode inMode: NSDefaultRunLoopMode
dequeue: YES]; dequeue: NO] != nil )
return 1;
if ( event == nil )
return -1; 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;
} }
case NSRunStoppedResponse: case NSRunStoppedResponse:
case NSRunAbortedResponse: case NSRunAbortedResponse: