iOS: Make the event dispatcher properly emit aboutToBlock() and awake()
This approach follows the same one used by the Cocoa event dispatcher. Change-Id: I2813b09beae07d90477c9ca506924058ace13f34 Reviewed-by: Ian Dean <ian@mediator-software.com> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
This commit is contained in:
parent
321cc1f277
commit
56083adbea
@ -134,6 +134,8 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
|
||||
, m_interrupted(false)
|
||||
, m_postedEventsRunLoopSource(this, &QEventDispatcherCoreFoundation::processPostedEvents)
|
||||
, m_blockingTimerRunLoopSource(this, &QEventDispatcherCoreFoundation::processTimers)
|
||||
, m_awakeAndBlockObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity,
|
||||
kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting)
|
||||
, m_runLoopTimerRef(0)
|
||||
{
|
||||
m_cfSocketNotifier.setHostEventDispatcher(this);
|
||||
@ -142,6 +144,8 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
|
||||
|
||||
m_blockingTimerRunLoopSource.addToMode(kCFRunLoopCommonModes);
|
||||
m_blockingTimerRunLoopSource.addToMode(CFStringRef(UITrackingRunLoopMode));
|
||||
|
||||
m_awakeAndBlockObserver.addToMode(kCFRunLoopCommonModes);
|
||||
}
|
||||
|
||||
QEventDispatcherCoreFoundation::~QEventDispatcherCoreFoundation()
|
||||
@ -168,11 +172,32 @@ void QEventDispatcherCoreFoundation::processTimers()
|
||||
maybeStartCFRunLoopTimer();
|
||||
}
|
||||
|
||||
void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity activity)
|
||||
{
|
||||
switch (activity) {
|
||||
case kCFRunLoopBeforeWaiting:
|
||||
emit aboutToBlock();
|
||||
break;
|
||||
case kCFRunLoopAfterWaiting:
|
||||
emit awake();
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
{
|
||||
m_interrupted = false;
|
||||
bool eventsProcessed = false;
|
||||
|
||||
// The documentation states that this signal is emitted after the event
|
||||
// loop returns from a function that could block, which is not the case
|
||||
// here, but all the other event dispatchers emit awake at the start of
|
||||
// processEvents, and the QEventLoop auto-test has an explicit check for
|
||||
// this behavior, so we assume it's for a good reason and do it as well.
|
||||
emit awake();
|
||||
|
||||
bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents;
|
||||
bool execFlagSet = (flags & QEventLoop::DialogExec) || (flags & QEventLoop::EventLoopExec);
|
||||
bool useExecMode = execFlagSet && !excludeUserEvents;
|
||||
|
@ -132,6 +132,48 @@ private:
|
||||
CFRunLoopSourceRef m_source;
|
||||
};
|
||||
|
||||
template <class T = QEventDispatcherCoreFoundation>
|
||||
class RunLoopObserver
|
||||
{
|
||||
public:
|
||||
typedef void (T::*CallbackFunction) (CFRunLoopActivity activity);
|
||||
|
||||
RunLoopObserver(T *delegate, CallbackFunction callback, CFOptionFlags activities)
|
||||
: m_delegate(delegate), m_callback(callback)
|
||||
{
|
||||
CFRunLoopObserverContext context = {};
|
||||
context.info = this;
|
||||
|
||||
m_observer = CFRunLoopObserverCreate(kCFAllocatorDefault, activities, true, 0, process, &context);
|
||||
Q_ASSERT(m_observer);
|
||||
}
|
||||
|
||||
~RunLoopObserver()
|
||||
{
|
||||
CFRunLoopObserverInvalidate(m_observer);
|
||||
CFRelease(m_observer);
|
||||
}
|
||||
|
||||
void addToMode(CFStringRef mode, CFRunLoopRef runLoop = 0)
|
||||
{
|
||||
if (!runLoop)
|
||||
runLoop = CFRunLoopGetCurrent();
|
||||
|
||||
CFRunLoopAddObserver(runLoop, m_observer, mode);
|
||||
}
|
||||
|
||||
private:
|
||||
static void process(CFRunLoopObserverRef, CFRunLoopActivity activity, void *info)
|
||||
{
|
||||
RunLoopObserver *self = static_cast<RunLoopObserver *>(info);
|
||||
((self->m_delegate)->*(self->m_callback))(activity);
|
||||
}
|
||||
|
||||
T *m_delegate;
|
||||
CallbackFunction m_callback;
|
||||
CFRunLoopObserverRef m_observer;
|
||||
};
|
||||
|
||||
class QEventDispatcherCoreFoundation : public QAbstractEventDispatcher
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -163,6 +205,8 @@ private:
|
||||
RunLoopSource<> m_postedEventsRunLoopSource;
|
||||
RunLoopSource<> m_blockingTimerRunLoopSource;
|
||||
|
||||
RunLoopObserver<> m_awakeAndBlockObserver;
|
||||
|
||||
QTimerInfoList m_timerInfoList;
|
||||
CFRunLoopTimerRef m_runLoopTimerRef;
|
||||
|
||||
@ -170,9 +214,12 @@ private:
|
||||
|
||||
void processPostedEvents();
|
||||
void processTimers();
|
||||
|
||||
void maybeStartCFRunLoopTimer();
|
||||
void maybeStopCFRunLoopTimer();
|
||||
|
||||
void handleRunLoopActivity(CFRunLoopActivity activity);
|
||||
|
||||
static void nonBlockingTimerRunLoopCallback(CFRunLoopTimerRef, void *info);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user