summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@digia.com>2014-03-17 19:21:49 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-27 17:51:21 +0100
commitff3dcc49c4a1912189091e35e87cb61af2f62d47 (patch)
treed40451c04017174c3432bb3b3ccaa0657f5ead8f /src/plugins
parent9a9feab102019d810a1120ef9953c15b48f24640 (diff)
Cocoa: Don't stop NSApp when showing a modal dialog
We manage embedded modal sessions with a stack and only run the top-most session. We also stop the last modal session before starting a new one. However, if there is no modal session running yet, we end up stopping NSApp. This seems to cause ill side effects on OS X 10.9. Notably, starting a new modal session outside QCocoaEventDispatcher, like when opening a native file dialog, makes this last modal session impossible for the user to quit. In this patch, we make sure NSApp is kept running if there's no modal session running yet, akin to calling QDialog::exec() at the event dispatcher level. The behavior for ensuing modal sessions remains unchanged. Task-number: QTBUG-34677 Change-Id: I6a23b191e4dce18514504b8e953f8caa7fad8731 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm16
2 files changed, 16 insertions, 1 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 33d7dcbcf4..0274ed8201 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -163,6 +163,7 @@ public:
// The following variables help organizing modal sessions:
QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
bool currentExecIsNSAppRun;
+ bool modalSessionOnNSAppRun;
bool nsAppRunCalledByQt;
bool cleanupModalSessionsNeeded;
uint processEventsCalled;
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 91b631bff9..495a54cac4 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -721,7 +721,6 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
// setting currentModalSessionCached to zero, so that interrupt() calls
// [NSApp abortModal] if another modal session is currently running
Q_Q(QCocoaEventDispatcher);
- q->interrupt();
// Add a new, empty (null), NSModalSession to the stack.
// It will become active the next time QEventDispatcher::processEvents is called.
@@ -734,6 +733,12 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
cocoaModalSessionStack.push(info);
updateChildrenWorksWhenModal();
currentModalSessionCached = 0;
+ if (currentExecIsNSAppRun) {
+ modalSessionOnNSAppRun = true;
+ q->wakeUp();
+ } else {
+ q->interrupt();
+ }
}
void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
@@ -772,6 +777,7 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
runLoopTimerRef(0),
blockSendPostedEvents(false),
currentExecIsNSAppRun(false),
+ modalSessionOnNSAppRun(false),
nsAppRunCalledByQt(false),
cleanupModalSessionsNeeded(false),
processEventsCalled(0),
@@ -902,6 +908,14 @@ void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
// processEvents() was called "manually," ignore this source for now
d->maybeCancelWaitForMoreEvents();
return;
+ } else if (d->modalSessionOnNSAppRun) {
+ // We're about to spawn the 1st modal session on top of the main runloop.
+ // Instead of calling processPostedEvents(), which would need us stop
+ // NSApp, we just re-enter processEvents(). This is equivalent to calling
+ // QDialog::exec() except that it's done in a non-blocking way.
+ d->modalSessionOnNSAppRun = false;
+ d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents);
+ return;
}
d->processPostedEvents();
d->maybeCancelWaitForMoreEvents();