iOS: Fix logic for determining whether to exit the root event loop
Instead of trying to hook into various places where we might be in a situation where the root event loop should exit, and then enabling the runloop-observer, we always keep the observer active, and then do the relevant checks whenever the run-loop exits. The reason for checking if the event loop is running is that iOS will enter and exit the root runloop as part of normal operation, eg due to flicking a scroll view and switching the runloop mode, so we need to ensure that we're actually supposed to exit the root event loop. Change-Id: I9b84b47ee45e0c9e2b1d2ebb5a432ea92700b324 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
This commit is contained in:
parent
d2580054f9
commit
769abe8d2f
@ -54,11 +54,9 @@ public:
|
||||
explicit QIOSEventDispatcher(QObject *parent = 0);
|
||||
|
||||
bool processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE;
|
||||
void interrupt() Q_DECL_OVERRIDE;
|
||||
|
||||
void handleRunLoopExit(CFRunLoopActivity activity);
|
||||
|
||||
void checkIfEventLoopShouldExit();
|
||||
void interruptEventLoopExec();
|
||||
|
||||
private:
|
||||
|
@ -446,6 +446,8 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
|
||||
if (!m_processEventCallsAfterExec && (flags & QEventLoop::EventLoopExec)) {
|
||||
++m_processEventCallsAfterExec;
|
||||
|
||||
m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes);
|
||||
|
||||
// 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)) {
|
||||
@ -475,44 +477,18 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
|
||||
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.
|
||||
checkIfEventLoopShouldExit();
|
||||
|
||||
return processedEvents;
|
||||
}
|
||||
|
||||
void QIOSEventDispatcher::interrupt()
|
||||
{
|
||||
QEventDispatcherCoreFoundation::interrupt();
|
||||
|
||||
if (!rootLevelRunLoopIntegration())
|
||||
return;
|
||||
|
||||
// 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.
|
||||
checkIfEventLoopShouldExit();
|
||||
}
|
||||
|
||||
void QIOSEventDispatcher::checkIfEventLoopShouldExit()
|
||||
{
|
||||
if (m_processEventCallsAfterExec == 1) {
|
||||
qEventDispatcherDebug() << "Hit root runloop level, watching for runloop exit";
|
||||
m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes);
|
||||
}
|
||||
}
|
||||
|
||||
void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
|
||||
{
|
||||
Q_UNUSED(activity);
|
||||
Q_ASSERT(activity == kCFRunLoopExit);
|
||||
|
||||
m_runLoopExitObserver.removeFromMode(kCFRunLoopCommonModes);
|
||||
|
||||
interruptEventLoopExec();
|
||||
if (m_processEventCallsAfterExec == 1 && !QThreadData::current()->eventLoops.top()->isRunning()) {
|
||||
qEventDispatcherDebug() << "Root runloop level exited";
|
||||
interruptEventLoopExec();
|
||||
}
|
||||
}
|
||||
|
||||
void QIOSEventDispatcher::interruptEventLoopExec()
|
||||
@ -521,6 +497,8 @@ void QIOSEventDispatcher::interruptEventLoopExec()
|
||||
|
||||
--m_processEventCallsAfterExec;
|
||||
|
||||
m_runLoopExitObserver.removeFromMode(kCFRunLoopCommonModes);
|
||||
|
||||
// We re-set applicationProcessEventsReturnPoint here so that future
|
||||
// calls to QEventLoop::exec() will end up back here after entering
|
||||
// processEvents, instead of back in didFinishLaunchingWithOptions.
|
||||
|
Loading…
Reference in New Issue
Block a user