Cocoa: Allow widgets to receive events event when no app is running

This is necessary for QMacNativeWidget, where there exists a QApplication, but
is never executed. This directly translates in calls to the event dispatcher's
processEvents() function, whose calls we keep track. If no calls have been made,
we always allow timer and posted events to be processed.

Change-Id: Ia0062ee8c59a2572082f520a2eb85ed44a9856a7
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
This commit is contained in:
Gabriel de Dietrich 2013-09-24 19:40:44 +02:00 committed by The Qt Project
parent db9abc72ef
commit 06e7d61b68
2 changed files with 11 additions and 2 deletions

View File

@ -165,6 +165,7 @@ public:
bool currentExecIsNSAppRun; bool currentExecIsNSAppRun;
bool nsAppRunCalledByQt; bool nsAppRunCalledByQt;
bool cleanupModalSessionsNeeded; bool cleanupModalSessionsNeeded;
uint processEventsCalled;
NSModalSession currentModalSessionCached; NSModalSession currentModalSessionCached;
NSModalSession currentModalSession(); NSModalSession currentModalSession();
void updateChildrenWorksWhenModal(); void updateChildrenWorksWhenModal();

View File

@ -118,7 +118,7 @@ static Boolean runLoopSourceEqualCallback(const void *info1, const void *info2)
void QCocoaEventDispatcherPrivate::runLoopTimerCallback(CFRunLoopTimerRef, void *info) void QCocoaEventDispatcherPrivate::runLoopTimerCallback(CFRunLoopTimerRef, void *info)
{ {
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info); QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) { if (d->processEventsCalled && (d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
// processEvents() was called "manually," ignore this source for now // processEvents() was called "manually," ignore this source for now
d->maybeCancelWaitForMoreEvents(); d->maybeCancelWaitForMoreEvents();
return; return;
@ -364,6 +364,12 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
uint oldflags = d->processEventsFlags; uint oldflags = d->processEventsFlags;
d->processEventsFlags = flags; d->processEventsFlags = flags;
// Used to determine whether any eventloop has been exec'ed, and allow posted
// and timer events to be processed even if this function has never been called
// instead of being kept on hold for the next run of processEvents().
++d->processEventsCalled;
bool excludeUserEvents = d->processEventsFlags & QEventLoop::ExcludeUserInputEvents; bool excludeUserEvents = d->processEventsFlags & QEventLoop::ExcludeUserInputEvents;
bool retVal = false; bool retVal = false;
forever { forever {
@ -517,6 +523,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
} }
d->processEventsFlags = oldflags; d->processEventsFlags = oldflags;
--d->processEventsCalled;
// If we're interrupted, we need to interrupt the _current_ // If we're interrupted, we need to interrupt the _current_
// recursion as well to check if it is still supposed to be // recursion as well to check if it is still supposed to be
@ -770,6 +777,7 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
currentExecIsNSAppRun(false), currentExecIsNSAppRun(false),
nsAppRunCalledByQt(false), nsAppRunCalledByQt(false),
cleanupModalSessionsNeeded(false), cleanupModalSessionsNeeded(false),
processEventsCalled(0),
currentModalSessionCached(0), currentModalSessionCached(0),
lastSerial(-1), lastSerial(-1),
interrupt(false) interrupt(false)
@ -893,7 +901,7 @@ void QCocoaEventDispatcherPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info) void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
{ {
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info); QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) { if (d->processEventsCalled && (d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
// processEvents() was called "manually," ignore this source for now // processEvents() was called "manually," ignore this source for now
d->maybeCancelWaitForMoreEvents(); d->maybeCancelWaitForMoreEvents();
return; return;