Cocoa: fix unresponsive dialogs causes application to hang
authorRichard Moe Gustavsen <richard.gustavsen@digia.com>
Wed, 5 Dec 2012 10:36:25 +0000 (11:36 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 5 Dec 2012 16:29:46 +0000 (17:29 +0100)
The reason for this bug seems to be related to how we wait for
more events in the event dispatcher. We use the nextEventMatchingMask
function, which already in Qt4 showed to have problems when telling
it to not dequeue the event. The solution back then was to
tell it to dequeue the event, and instead repost in front again.
Why this was changed in Qt5 is uncertain (other than it being tempting)
but moving the same code back in will solve the bug.

Note that this bug might also stem from the fact that the run loop
sources we add in the event dispatcher fires before the application
is really ready to show modal dialogs. E.g refusing to execute a
modal dialog before NSAppDelegate applicationWillFinishLaunching
is called will also fix the problem. But this code change is to big
atm, and can easily introduce other unforeseen regressions.

Task-number: QTBUG-28283
Change-Id: I07cd109568c2b9c782cf5120a9eb2ac71128cada
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm

index 7aa365d..80c9e22 100644 (file)
@@ -510,14 +510,16 @@ static bool IsMouseOrKeyEvent( NSEvent* event )
 
 static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRunLoopMode)
 {
-    // If no event exist in the cocoa event que, wait
-    // (and free up cpu time) until at least one event occur.
-    // This implementation is a bit on the edge, but seems to
-    // work fine:
-    [NSApp nextEventMatchingMask:NSAnyEventMask
-                       untilDate:[NSDate distantFuture]
-                          inMode:runLoopMode
-                         dequeue:NO];
+    // If no event exist in the cocoa event que, wait (and free up cpu time) until
+    // at least one event occur. Setting 'dequeuing' to 'no' in the following call
+    // causes it to hang under certain circumstances (QTBUG-28283), so we tell it
+    // to dequeue instead, just to repost the event again:
+    NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
+        untilDate:[NSDate distantFuture]
+        inMode:runLoopMode
+        dequeue:YES];
+    if (event)
+        [NSApp postEvent:event atStart:YES];
 }
 
 bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)