From 4a83fd4696cd9c238d64a93e834264d5471cf977 Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Sun, 4 Dec 2016 08:56:49 -0800 Subject: [PATCH] Dequeue and dispatch events in modal event loops This should be a no-op, as runModalSession's documentation states that it will handle dispatch event for the modal's window. However, in practice, it does not seem to be doing so frequently enough for modal UI to keep up with two-finger scroll events. Dequeuing and manually dispatching the next event seems to mitigate this. Note that we only dispatch events that are associated with the modal dialog's window, or with no window at all, to prevent other windows from responding to inputs while the modal is present. Closes #17737 Closes https://github.com/wxWidgets/wxWidgets/pull/365 --- src/osx/cocoa/evtloop.mm | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/osx/cocoa/evtloop.mm b/src/osx/cocoa/evtloop.mm index cf9f46ed0c..12d52c0466 100644 --- a/src/osx/cocoa/evtloop.mm +++ b/src/osx/cocoa/evtloop.mm @@ -210,20 +210,34 @@ 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: { - if ( [[NSApplication sharedApplication] + // 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] nextEventMatchingMask: NSAnyEventMask untilDate: [NSDate dateWithTimeIntervalSinceNow: timeout/1000.0] inMode: NSDefaultRunLoopMode - dequeue: NO] != nil ) - return 1; - - return -1; + 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; } case NSRunStoppedResponse: case NSRunAbortedResponse: