summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/eventdispatchers
diff options
context:
space:
mode:
authorIan Dean <ian@mediator-software.com>2013-04-18 11:36:34 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-06-13 12:41:05 +0200
commit71b8f12aaa7b6195b27bdb8633191415d744322a (patch)
treeb22d95ba4b5d0ca286633bcd02887548526c57d1 /src/platformsupport/eventdispatchers
parentc172ae81c93ed8de8e8c080b849a6c7ba66a71d2 (diff)
Correct implementation of nested runloop to match UIApplicationMain()
The previous implementation of the nested runloop was derived from the Mac Cocoa implementation(?), and did not correctly deal with UI animations and other UIKit functions which are run in a different mode to the default mode. This version corrects that (in most cases) and switches the implementation to use CoreFoundation instead of NextStep APIs. Change-Id: I45802d22044465749a1e5b6207d745268f6ae8a1 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
Diffstat (limited to 'src/platformsupport/eventdispatchers')
-rw-r--r--src/platformsupport/eventdispatchers/qioseventdispatcher.mm46
1 files changed, 40 insertions, 6 deletions
diff --git a/src/platformsupport/eventdispatchers/qioseventdispatcher.mm b/src/platformsupport/eventdispatchers/qioseventdispatcher.mm
index f8f8cc15ad..ab3036143d 100644
--- a/src/platformsupport/eventdispatchers/qioseventdispatcher.mm
+++ b/src/platformsupport/eventdispatchers/qioseventdispatcher.mm
@@ -117,7 +117,9 @@ void QIOSEventDispatcher::maybeStartCFRunLoopTimer()
m_runLoopTimerRef = CFRunLoopTimerCreate(0, ttf, oneyear, 0, 0, QIOSEventDispatcher::nonBlockingTimerRunLoopCallback, &info);
Q_ASSERT(m_runLoopTimerRef != 0);
- CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimerRef, kCFRunLoopCommonModes);
+ CFRunLoopRef mainRunLoop = CFRunLoopGetMain();
+ CFRunLoopAddTimer(mainRunLoop, m_runLoopTimerRef, kCFRunLoopCommonModes);
+ CFRunLoopAddTimer(mainRunLoop, m_runLoopTimerRef, (CFStringRef) UITrackingRunLoopMode);
} else {
struct timespec tv;
// Calculate when the next timer should fire:
@@ -167,6 +169,7 @@ QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
m_blockingTimerRunLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
Q_ASSERT(m_blockingTimerRunLoopSource);
CFRunLoopAddSource(mainRunLoop, m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopAddSource(mainRunLoop, m_blockingTimerRunLoopSource, (CFStringRef) UITrackingRunLoopMode);
// source used to handle posted events:
context.perform = QIOSEventDispatcher::postedEventsRunLoopCallback;
@@ -183,7 +186,9 @@ QIOSEventDispatcher::~QIOSEventDispatcher()
qDeleteAll(m_timerInfoList);
maybeStopCFRunLoopTimer();
- CFRunLoopRemoveSource(CFRunLoopGetMain(), m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+
+ CFRunLoopRemoveSource(mainRunLoop, m_blockingTimerRunLoopSource, kCFRunLoopCommonModes);
+ CFRunLoopRemoveSource(mainRunLoop, m_blockingTimerRunLoopSource, (CFStringRef) UITrackingRunLoopMode);
CFRelease(m_blockingTimerRunLoopSource);
m_cfSocketNotifier.removeSocketNotifiers();
@@ -198,14 +203,42 @@ bool QIOSEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
bool execFlagSet = (flags & QEventLoop::DialogExec) || (flags & QEventLoop::EventLoopExec);
bool useExecMode = execFlagSet && !excludeUserEvents;
+ CFTimeInterval distantFuture = CFTimeInterval(3600. * 24. * 365. * 10.);
+ SInt32 result;
+
if (useExecMode) {
- NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
- while ([runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] && !m_interrupted);
+ while (!m_interrupted) {
+ // Run a single pass on the runloop to unblock it
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
+
+ // Run the default runloop until interrupted (by Qt or UIKit)
+ if (result != kCFRunLoopRunFinished)
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, distantFuture, false);
+
+ // App has quit or Qt has interrupted?
+ if (result == kCFRunLoopRunFinished || m_interrupted)
+ break;
+
+ // Runloop was interrupted by UIKit?
+ if (result == kCFRunLoopRunStopped && !m_interrupted) {
+ // Run runloop in UI tracking mode
+ if (CFRunLoopRunInMode((CFStringRef) UITrackingRunLoopMode,
+ distantFuture, false) == kCFRunLoopRunFinished)
+ break;
+ }
+ }
eventsProcessed = true;
} else {
if (!(flags & QEventLoop::WaitForMoreEvents))
wakeUp();
- eventsProcessed = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+
+ // Run runloop in default mode
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, distantFuture, true);
+ if (result != kCFRunLoopRunFinished) {
+ // Run runloop in UI tracking mode
+ CFRunLoopRunInMode((CFStringRef) UITrackingRunLoopMode, distantFuture, false);
+ }
+ eventsProcessed = (result == kCFRunLoopRunHandledSource);
}
return eventsProcessed;
}
@@ -308,8 +341,9 @@ void QIOSEventDispatcher::wakeUp()
void QIOSEventDispatcher::interrupt()
{
- wakeUp();
+ // Stop the runloop, which will cause processEvents() to exit
m_interrupted = true;
+ CFRunLoopStop(CFRunLoopGetMain());
}
void QIOSEventDispatcher::flush()