Cocoa: Post event to "show()" a modal window

The way we were doing it, we may have interferred with other
events in the CFRunLoop source and call processEvents() at
the wrong moment or for the wrong reason. By using a posted
event, we make the notification channel unambiguous.

This ammends ff3dcc49c4.

Task-number: QTBUG-38214
Change-Id: I94f7e89cf4c9803289749394f85119cba62ef0e7
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
This commit is contained in:
Gabriel de Dietrich 2014-04-09 13:26:57 +02:00 committed by The Qt Project
parent bab494e4d0
commit a9cbddf473
2 changed files with 16 additions and 12 deletions

View File

@ -134,6 +134,8 @@ public:
void interrupt();
void flush();
bool event(QEvent *);
friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher);
};
@ -163,7 +165,6 @@ public:
// The following variables help organizing modal sessions:
QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
bool currentExecIsNSAppRun;
bool modalSessionOnNSAppRun;
bool nsAppRunCalledByQt;
bool cleanupModalSessionsNeeded;
uint processEventsCalled;

View File

@ -734,13 +734,25 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
updateChildrenWorksWhenModal();
currentModalSessionCached = 0;
if (currentExecIsNSAppRun) {
modalSessionOnNSAppRun = true;
q->wakeUp();
QEvent *e = new QEvent(QEvent::User);
qApp->postEvent(q, e, Qt::HighEventPriority);
} else {
q->interrupt();
}
}
bool QCocoaEventDispatcher::event(QEvent *e)
{
Q_D(QCocoaEventDispatcher);
if (e->type() == QEvent::User) {
d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents);
return true;
}
return QObject::event(e);
}
void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
{
Q_Q(QCocoaEventDispatcher);
@ -777,7 +789,6 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
runLoopTimerRef(0),
blockSendPostedEvents(false),
currentExecIsNSAppRun(false),
modalSessionOnNSAppRun(false),
nsAppRunCalledByQt(false),
cleanupModalSessionsNeeded(false),
processEventsCalled(0),
@ -908,14 +919,6 @@ 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();