summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@digia.com>2013-10-01 17:30:52 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-09 11:50:53 +0200
commit2043adf97ce90b70a98e03e85513387e49ed66d0 (patch)
treeb75e8c117a685af5f72b9c7cb18ca13bc7ab1ee7 /src
parent54c5a79fd0d711dd30c8813b7c5b3ce23e7429ef (diff)
iOS: Generalize jumping event-dispatcher to handle QEventLoop:exec()
We already supported re-entering QApplication::exec(), so adding support for handling a generalized QEventLoop::exec() was nothing more than removing the qApplication->in_exec condition in processEvents() and the QThreadData::current()->quitNow condition when interrupting the event loop. Everything else is just renaming and rewording, now that the feature is not specific to QApplication::exec(). This means dialogs such as QFileDialog opened in the main() function will show something on screen, as we then fall back to the iOS root run-loop handling, while at the same time supporting QApplication exec once the dialog closes. We still don't hadle recursive QEventLoop:exec() at the root level, as that would require multiple stacks and detailed application knowledge about when to create them. Change-Id: I334a362d85796341a343ce82f3104ff5866bdc3f Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.h6
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm66
2 files changed, 33 insertions, 39 deletions
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h
index 83267e80ea..f2272ecd68 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.h
+++ b/src/plugins/platforms/ios/qioseventdispatcher.h
@@ -58,11 +58,11 @@ public:
void handleRunLoopExit(CFRunLoopActivity activity);
- void checkIfApplicationShouldQuit();
- void interruptQApplicationExec();
+ void checkIfEventLoopShouldExit();
+ void interruptEventLoopExec();
private:
- uint m_processEventCallsAfterAppExec;
+ uint m_processEventCallsAfterExec;
RunLoopObserver<QIOSEventDispatcher> m_runLoopExitObserver;
};
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index 24f6210f97..f7df792362 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -244,7 +244,7 @@ enum SetJumpResult
{
kJumpPointSetSuccessfully = 0,
kJumpedFromEventDispatcherProcessEvents,
- kJumpedFromQApplicationExecInterrupt,
+ kJumpedFromEventLoopExecInterrupt,
kJumpedFromUserMainTrampoline,
};
@@ -395,9 +395,9 @@ static const char kApplicationWillTerminateExitCode = SIGTERM | 0x80;
// The runloop will not exit when the application is about to terminate,
// so we'll never see the exit activity and have a chance to return from
- // QApplication::exec(). We initiate the return manually as a workaround.
- qEventDispatcherDebug() << "Manually triggering return from QApp exec";
- static_cast<QIOSEventDispatcher *>(qApp->eventDispatcher())->interruptQApplicationExec();
+ // QEventLoop::exec(). We initiate the return manually as a workaround.
+ qEventDispatcherDebug() << "Manually triggering return from event loop exec";
+ static_cast<QIOSEventDispatcher *>(qApp->eventDispatcher())->interruptEventLoopExec();
break;
case kJumpedFromUserMainTrampoline:
// The user's main has returned, so we're ready to let iOS terminate the application
@@ -415,7 +415,7 @@ QT_USE_NAMESPACE
QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
: QEventDispatcherCoreFoundation(parent)
- , m_processEventCallsAfterAppExec(0)
+ , m_processEventCallsAfterExec(0)
, m_runLoopExitObserver(this, &QIOSEventDispatcher::handleRunLoopExit, kCFRunLoopExit)
{
}
@@ -432,27 +432,22 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
return false;
}
- QCoreApplicationPrivate *qApplication = static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(qApp));
- if (!m_processEventCallsAfterAppExec && qApplication->in_exec) {
- Q_ASSERT(flags & QEventLoop::EventLoopExec);
+ if (!m_processEventCallsAfterExec && (flags & QEventLoop::EventLoopExec)) {
+ ++m_processEventCallsAfterExec;
- // We know that app->in_exec is set just before executing the main event loop,
- // so the first processEvents call after that will be the main event loop.
- ++m_processEventCallsAfterAppExec;
-
- // We set a new jump point here that we can return to when the Qt application
- // is asked to exit, so that we can return from QCoreApplication::exec().
+ // We set a new jump point here that we can return to when the event loop
+ // is asked to exit, so that we can return from QEventLoop::exec().
switch (setjmp(processEventExitJumpPoint)) {
case kJumpPointSetSuccessfully:
- qEventDispatcherDebug() << "QApplication exec detected, jumping back to native runloop";
+ qEventDispatcherDebug() << "QEventLoop exec detected, jumping back to native runloop";
longjmp(processEventEnterJumpPoint, kJumpedFromEventDispatcherProcessEvents);
break;
- case kJumpedFromQApplicationExecInterrupt:
- // QCoreApplication has quit (either by the hand of the user, or the iOS termination
+ case kJumpedFromEventLoopExecInterrupt:
+ // The event loop has exited (either by the hand of the user, or the iOS termination
// signal), and we jumped back though processEventExitJumpPoint. We return from processEvents,
- // which will emit aboutToQuit and then return to the user's main, which can do
- // whatever it wants, including calling exec() on the application again.
- qEventDispatcherDebug() << "kJumpedFromQApplicationExecInterrupt, returning with eventsProcessed = true";
+ // which will emit aboutToQuit if it's QApplication's event loop, and then return to the user's
+ // main, which can do whatever it wants, including calling exec() on the application again.
+ qEventDispatcherDebug() << "kJumpedFromEventLoopExecInterrupt, returning with eventsProcessed = true";
return true;
default:
qFatal("Unexpected jump result in event loop integration");
@@ -461,19 +456,19 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
Q_UNREACHABLE();
}
- if (m_processEventCallsAfterAppExec)
- ++m_processEventCallsAfterAppExec;
+ if (m_processEventCallsAfterExec)
+ ++m_processEventCallsAfterExec;
bool processedEvents = QEventDispatcherCoreFoundation::processEvents(flags);
- if (m_processEventCallsAfterAppExec)
- --m_processEventCallsAfterAppExec;
+ if (m_processEventCallsAfterExec)
+ --m_processEventCallsAfterExec;
// If we're running with nested event loops and the application is quit,
// then the forwarded interrupt call will happen while our processEvent
// counter is still 2, and we won't detect that we're about to fall down
// to the root iOS run-loop. We do an extra check here to catch that case.
- checkIfApplicationShouldQuit();
+ checkIfEventLoopShouldExit();
return processedEvents;
}
@@ -488,12 +483,12 @@ void QIOSEventDispatcher::interrupt()
// If an interrupt happens as part of a non-nested event loop, that is,
// by processing an event or timer in the root iOS run-loop, we'll be
// able to detect it here.
- checkIfApplicationShouldQuit();
+ checkIfEventLoopShouldExit();
}
-void QIOSEventDispatcher::checkIfApplicationShouldQuit()
+void QIOSEventDispatcher::checkIfEventLoopShouldExit()
{
- if (QThreadData::current()->quitNow && m_processEventCallsAfterAppExec == 1) {
+ if (m_processEventCallsAfterExec == 1) {
qEventDispatcherDebug() << "Hit root runloop level, watching for runloop exit";
m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes);
}
@@ -505,26 +500,25 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
m_runLoopExitObserver.removeFromMode(kCFRunLoopCommonModes);
- interruptQApplicationExec();
+ interruptEventLoopExec();
}
-void QIOSEventDispatcher::interruptQApplicationExec()
+void QIOSEventDispatcher::interruptEventLoopExec()
{
- Q_ASSERT(QThreadData::current()->quitNow);
- Q_ASSERT(m_processEventCallsAfterAppExec == 1);
+ Q_ASSERT(m_processEventCallsAfterExec == 1);
- --m_processEventCallsAfterAppExec;
+ --m_processEventCallsAfterExec;
// We re-set applicationProcessEventsReturnPoint here so that future
- // calls to QApplication::exec() will end up back here after entering
+ // calls to QEventLoop::exec() will end up back here after entering
// processEvents, instead of back in didFinishLaunchingWithOptions.
switch (setjmp(processEventEnterJumpPoint)) {
case kJumpPointSetSuccessfully:
qEventDispatcherDebug() << "Jumping back to processEvents";
- longjmp(processEventExitJumpPoint, kJumpedFromQApplicationExecInterrupt);
+ longjmp(processEventExitJumpPoint, kJumpedFromEventLoopExecInterrupt);
break;
case kJumpedFromEventDispatcherProcessEvents:
- // QCoreApplication was re-executed
+ // QEventLoop was re-executed
qEventDispatcherDebug() << "kJumpedFromEventDispatcherProcessEvents";
break;
default: