--- src/gui/kernel/qeventdispatcher_mac_p.h 2013-06-07 01:16:59.000000000 -0400 +++ src/gui/kernel/qeventdispatcher_mac_p_new-8184b49c12d887928921ed5b695c8c6f04a07514.h 2013-12-08 14:31:01.000000000 -0500 @@ -173,6 +173,7 @@ #ifdef QT_MAC_USE_COCOA // The following variables help organizing modal sessions: static QStack cocoaModalSessionStack; + static QStack cocoaModalSessionStackPendingEnd; static bool currentExecIsNSAppRun; static bool nsAppRunCalledByQt; static bool cleanupModalSessionsNeeded; @@ -180,6 +181,7 @@ static NSModalSession currentModalSession(); static void updateChildrenWorksWhenModal(); static void temporarilyStopAllModalSessions(); + static void stopAllPendingEndModalSessions(); static void beginModalSession(QWidget *widget); static void endModalSession(QWidget *widget); static void cancelWaitForMoreEvents(); --- src/gui/kernel/qeventdispatcher_mac.mm 2013-06-07 01:16:59.000000000 -0400 +++ src/gui/kernel/qeventdispatcher_mac_new-833e02de99494686f8dd7a567f6e19e847508f11.mm 2013-12-08 14:30:59.000000000 -0500 @@ -603,6 +603,9 @@ while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt) qt_mac_waitForMoreModalSessionEvents(); + // stop all pending end modal sessions + d->stopAllPendingEndModalSessions(); + if (!d->interrupt && session == d->currentModalSessionCached) { // Someone called [NSApp stopModal:] from outside the event // dispatcher (e.g to stop a native dialog). But that call wrongly stopped @@ -678,6 +681,9 @@ if (!d->interrupt) QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); + // stop all pending end modal sessions + d->stopAllPendingEndModalSessions(); + // Since the window that holds modality might have changed while processing // events, we we need to interrupt when we return back the previous process // event recursion to ensure that we spin the correct modal session. @@ -781,6 +787,7 @@ #ifdef QT_MAC_USE_COCOA QStack QEventDispatcherMacPrivate::cocoaModalSessionStack; +QStack QEventDispatcherMacPrivate::cocoaModalSessionStackPendingEnd; bool QEventDispatcherMacPrivate::currentExecIsNSAppRun = false; bool QEventDispatcherMacPrivate::nsAppRunCalledByQt = false; bool QEventDispatcherMacPrivate::cleanupModalSessionsNeeded = false; @@ -828,6 +835,20 @@ currentModalSessionCached = 0; } +void QEventDispatcherMacPrivate::stopAllPendingEndModalSessions() +{ + // stop all modal sessions pending end + int stackSize = cocoaModalSessionStackPendingEnd.size(); + for (int i=stackSize-1; i>=0; --i) { + QCocoaModalSessionInfo &info = cocoaModalSessionStackPendingEnd[i]; + cocoaModalSessionStackPendingEnd.remove(i); + if (info.session) { + [NSApp endModalSession:info.session]; + [(NSWindow *)info.nswindow release]; + } + } +} + NSModalSession QEventDispatcherMacPrivate::currentModalSession() { // If we have one or more modal windows, this function will create @@ -925,10 +946,12 @@ } cocoaModalSessionStack.remove(i); currentModalSessionCached = 0; - if (info.session) { - [NSApp endModalSession:info.session]; - [(NSWindow *)info.nswindow release]; - } + + // Cannot stop the sessions here since we might still be inside a + // [NSApp runModalSession:] call. Add the session to the pending end stack and + // process the stack after the call to [NSApp runModalSession:] returns. + if (info.session) + cocoaModalSessionStackPendingEnd.push(info); } updateChildrenWorksWhenModal();