summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm72
2 files changed, 57 insertions, 23 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index a4a1286fab..f286b632fb 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -116,7 +116,6 @@ public:
explicit QCocoaEventDispatcher(QObject *parent = 0);
~QCocoaEventDispatcher();
-
bool processEvents(QEventLoop::ProcessEventsFlags flags);
bool hasPendingEvents();
@@ -154,9 +153,11 @@ public:
// timer handling
QTimerInfoList timerInfoList;
CFRunLoopTimerRef runLoopTimerRef;
+ CFRunLoopSourceRef activateTimersSourceRef;
void maybeStartCFRunLoopTimer();
void maybeStopCFRunLoopTimer();
- static void activateTimer(CFRunLoopTimerRef, void *info);
+ static void runLoopTimerCallback(CFRunLoopTimerRef, void *info);
+ static void activateTimersSourceCallback(void *info);
// Set 'blockSendPostedEvents' to true if you _really_ need
// to make sure that qt events are not posted while calling
@@ -188,8 +189,7 @@ public:
int lastSerial;
bool interrupt;
- static Boolean postedEventSourceEqualCallback(const void *info1, const void *info2);
- static void postedEventsSourcePerformCallback(void *info);
+ static void postedEventsSourceCallback(void *info);
static void waitingObserverCallback(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void *info);
static void firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info);
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 77cccac0b4..f2927d32c1 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -104,12 +104,28 @@ static inline CFRunLoopRef mainRunLoop()
return CFRunLoopGetMain();
}
+static Boolean runLoopSourceEqualCallback(const void *info1, const void *info2)
+{
+ return info1 == info2;
+}
+
/*****************************************************************************
Timers stuff
*****************************************************************************/
/* timer call back */
-void QCocoaEventDispatcherPrivate::activateTimer(CFRunLoopTimerRef, void *info)
+void QCocoaEventDispatcherPrivate::runLoopTimerCallback(CFRunLoopTimerRef, void *info)
+{
+ QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
+ if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
+ // processEvents() was called "manually," ignore this source for now
+ d->maybeCancelWaitForMoreEvents();
+ return;
+ }
+ CFRunLoopSourceSignal(d->activateTimersSourceRef);
+}
+
+void QCocoaEventDispatcherPrivate::activateTimersSourceCallback(void *info)
{
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
(void) d->timerInfoList.activateTimers();
@@ -145,7 +161,7 @@ void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer()
CFRunLoopTimerContext info = { 0, this, 0, 0, 0 };
// create the timer with a large interval, as recommended by the CFRunLoopTimerSetNextFireDate()
// documentation, since we will adjust the timer's time-to-fire as needed to keep Qt timers working
- runLoopTimerRef = CFRunLoopTimerCreate(0, ttf, oneyear, 0, 0, QCocoaEventDispatcherPrivate::activateTimer, &info);
+ runLoopTimerRef = CFRunLoopTimerCreate(0, ttf, oneyear, 0, 0, QCocoaEventDispatcherPrivate::runLoopTimerCallback, &info);
Q_ASSERT(runLoopTimerRef != 0);
CFRunLoopAddTimer(mainRunLoop(), runLoopTimerRef, kCFRunLoopCommonModes);
@@ -513,10 +529,10 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
emit awake();
- bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents;
- bool retVal = false;
uint oldflags = d->processEventsFlags;
d->processEventsFlags = flags;
+ bool excludeUserEvents = d->processEventsFlags & QEventLoop::ExcludeUserInputEvents;
+ bool retVal = false;
forever {
if (d->interrupt)
break;
@@ -544,8 +560,9 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
// Finally, if we are to exclude user input events, we cannot call [NSApp run]
// as we then loose control over which events gets dispatched:
const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
- const bool canExec_Qt = !excludeUserEvents &&
- (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec) ;
+ const bool canExec_Qt = (!excludeUserEvents
+ && ((d->processEventsFlags & QEventLoop::DialogExec)
+ || (d->processEventsFlags & QEventLoop::EventLoopExec)));
if (canExec_Qt && canExec_3rdParty) {
// We can use exec-mode, meaning that we can stay in a tight loop until
@@ -632,9 +649,11 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
}
} while (!d->interrupt && event != nil);
- if ((flags & QEventLoop::WaitForMoreEvents) == 0) {
- // when called "manually", always send posted events
+ if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
+ // when called "manually", always send posted events and timers
d->processPostedEvents();
+ retVal = d->timerInfoList.activateTimers() > 0 || retVal;
+ d->maybeStartCFRunLoopTimer();
}
// be sure to return true if the posted event source fired
@@ -651,12 +670,12 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
bool canWait = (d->threadData->canWait
&& !retVal
&& !d->interrupt
- && (flags & QEventLoop::WaitForMoreEvents));
+ && (d->processEventsFlags & QEventLoop::WaitForMoreEvents));
if (canWait) {
// INVARIANT: We haven't processed any events yet. And we're told
// to stay inside this function until at least one event is processed.
qt_mac_waitForMoreEvents();
- flags &= ~QEventLoop::WaitForMoreEvents;
+ d->processEventsFlags &= ~QEventLoop::WaitForMoreEvents;
} else {
// Done with event processing for now.
// Leave the function:
@@ -904,15 +923,28 @@ QCocoaEventDispatcher::QCocoaEventDispatcher(QObject *parent)
: QAbstractEventDispatcher(*new QCocoaEventDispatcherPrivate, parent)
{
Q_D(QCocoaEventDispatcher);
+
+ // keep our sources running when modal loops are running
+ CFRunLoopAddCommonMode(mainRunLoop(), (CFStringRef) NSModalPanelRunLoopMode);
+
CFRunLoopSourceContext context;
bzero(&context, sizeof(CFRunLoopSourceContext));
context.info = d;
- context.equal = QCocoaEventDispatcherPrivate::postedEventSourceEqualCallback;
- context.perform = QCocoaEventDispatcherPrivate::postedEventsSourcePerformCallback;
- d->postedEventsSource = CFRunLoopSourceCreate(0, 0, &context);
+ context.equal = runLoopSourceEqualCallback;
+
+ // source used to activate timers
+ context.perform = QCocoaEventDispatcherPrivate::activateTimersSourceCallback;
+ d->activateTimersSourceRef = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ Q_ASSERT(d->activateTimersSourceRef);
+ CFRunLoopAddSource(mainRunLoop(), d->activateTimersSourceRef, kCFRunLoopCommonModes);
+
+ // source used to send posted events
+ context.perform = QCocoaEventDispatcherPrivate::postedEventsSourceCallback;
+ d->postedEventsSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
Q_ASSERT(d->postedEventsSource);
CFRunLoopAddSource(mainRunLoop(), d->postedEventsSource, kCFRunLoopCommonModes);
+ // observer to emit aboutToBlock() and awake()
CFRunLoopObserverContext observerContext;
bzero(&observerContext, sizeof(CFRunLoopObserverContext));
observerContext.info = this;
@@ -948,11 +980,6 @@ void QCocoaEventDispatcherPrivate::waitingObserverCallback(CFRunLoopObserverRef,
emit static_cast<QCocoaEventDispatcher*>(info)->awake();
}
-Boolean QCocoaEventDispatcherPrivate::postedEventSourceEqualCallback(const void *info1, const void *info2)
-{
- return info1 == info2;
-}
-
void QCocoaEventDispatcherPrivate::processPostedEvents()
{
if (blockSendPostedEvents) {
@@ -1017,9 +1044,14 @@ void QCocoaEventDispatcherPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
static_cast<QCocoaEventDispatcherPrivate *>(info)->processPostedEvents();
}
-void QCocoaEventDispatcherPrivate::postedEventsSourcePerformCallback(void *info)
+void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
{
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
+ if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
+ // processEvents() was called "manually," ignore this source for now
+ d->maybeCancelWaitForMoreEvents();
+ return;
+ }
d->processPostedEvents();
d->maybeCancelWaitForMoreEvents();
}
@@ -1069,6 +1101,8 @@ QCocoaEventDispatcher::~QCocoaEventDispatcher()
qDeleteAll(d->timerInfoList);
d->maybeStopCFRunLoopTimer();
+ CFRunLoopRemoveSource(mainRunLoop(), d->activateTimersSourceRef, kCFRunLoopCommonModes);
+ CFRelease(d->activateTimersSourceRef);
// Remove CFSockets from the runloop.
for (MacSocketHash::ConstIterator it = d->macSockets.constBegin(); it != d->macSockets.constEnd(); ++it) {