6#include <QtCore/qdebug.h>
7#include <QtCore/qmetaobject.h>
8#include <QtCore/qthread.h>
9#include <QtCore/private/qcoreapplication_p.h>
10#include <QtCore/private/qcore_unix_p.h>
11#include <QtCore/private/qthread_p.h>
16# include <AppKit/NSApplication.h>
17#elif defined(Q_OS_WATCHOS)
18# include <WatchKit/WatchKit.h>
20# include <UIKit/UIApplication.h>
65#if !defined(Q_OS_WATCHOS)
67 [[NSNotificationCenter defaultCenter]
68 addObserver:self selector:@selector(receivedNotification:)
69 name:nil object:qt_apple_sharedApplication()];
79 [NSNotificationCenter.defaultCenter removeObserver:self];
84static CFStringRef runLoopMode(NSDictionary *
dictionary)
87 if (CFStringHasSuffix((CFStringRef)
key, CFSTR(
"RunLoopMode")))
94- (
void)receivedNotification:(NSNotification *)notification
96 if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR(
"RunLoopModePushNotification"))) {
97 if (CFStringRef
mode = runLoopMode(notification.userInfo))
100 qCWarning(lcEventDispatcher) <<
"Encountered run loop push notification without run loop mode!";
102 }
else if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR(
"RunLoopModePopNotification"))) {
103 CFStringRef
mode = runLoopMode(notification.userInfo);
104 if (CFStringCompare(
mode,
self.currentMode, 0) == kCFCompareEqualTo)
107 qCWarning(lcEventDispatcher) <<
"Tried to pop run loop mode"
108 <<
qPrintable(QString::fromCFString(
mode)) <<
"that was never pushed!";
114- (CFStringRef)currentMode
132 #define Q_MIRROR_ENUM(name) name = name
151#define Q_ENUM_PRINTER(enumName) \
152 static const char* qPrintable##enumName(int value) \
154 return RunLoopDebugger::staticMetaObject.enumerator(RunLoopDebugger::staticMetaObject.indexOfEnumerator(#enumName)).valueToKey(value); \
169#pragma mark - Class definition
176 , m_runLoopModeTracker([[RunLoopModeTracker alloc]
init])
178 , m_blockedRunLoopTimer(0)
179 , m_overdueTimerScheduled(
false)
191 m_postedEventsRunLoopSource.
addToMode(kCFRunLoopCommonModes);
192 m_runLoopActivityObserver.
addToMode(kCFRunLoopCommonModes);
232 bool eventsProcessed =
false;
235 qCWarning(lcEventDispatcher) <<
"processEvents() flags" <<
flags <<
"not supported on iOS";
237 qCDebug(lcEventDispatcher) <<
"Processing events with flags" <<
flags;
239 if (m_blockedRunLoopTimer) {
240 Q_ASSERT(m_blockedRunLoopTimer == m_runLoopTimer);
242 qCDebug(lcEventDispatcher) <<
"Recursing from blocked timer" << m_blockedRunLoopTimer;
251 m_postedEventsRunLoopSource.
signal();
254 qCDebug(lcEventDispatcher) <<
"Processed deferred wake-up";
270 CFStringRef
mode = [m_runLoopModeTracker currentMode];
275 qCDebug(lcEventDispatcher) <<
"Calling CFRunLoopRunInMode =" <<
qPrintable(QString::fromCFString(
mode))
276 <<
"for" << duration <<
"ms, processing single source =" << returnAfterSingleSourceHandled;
278 SInt32
result = CFRunLoopRunInMode(
mode, duration, returnAfterSingleSourceHandled);
280 qCDebug(lcEventDispatcher) <<
"result =" << qPrintableResult(
result);
282 eventsProcessed |= (
result == kCFRunLoopRunHandledSource
286 if (
result == kCFRunLoopRunFinished) {
304 qCDebug(lcEventDispatcher) <<
"Top level event loop was exited";
307 qCDebug(lcEventDispatcher) <<
"Top level event loop still running, making another pass";
312 qCDebug(lcEventDispatcher) <<
"Top level processEvents was interrupted";
327 if (
result == kCFRunLoopRunHandledSource) {
341 qCDebug(lcEventDispatcher) <<
"Manually processing timers due to overdue timer";
343 eventsProcessed =
true;
350 if (m_blockedRunLoopTimer) {
352 m_runLoopTimer = m_blockedRunLoopTimer;
359 m_postedEventsRunLoopSource.
signal();
360 qCDebug(lcEventDispatcher) <<
"Processed deferred wake-up";
368 if (wasInterrupted) {
373 qCDebug(lcEventDispatcher) <<
"Forwarding interrupt in case of nested processEvents";
377 qCDebug(lcEventDispatcher) <<
"Returning with eventsProcessed =" << eventsProcessed;
379 return eventsProcessed;
387 qCDebug(lcEventDispatcher) <<
"Already processed events this pass";
393 qCDebug(lcEventDispatcher) <<
"Sending posted events for"
400void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef
timer)
405 qCDebug(lcEventDispatcher) <<
"Already processed timers this pass";
410 qCDebug(lcEventDispatcher) <<
"CFRunLoopTimer" <<
timer <<
"fired, activating Qt timers";
421 CFRunLoopTimerRef previouslyBlockedRunLoopTimer = m_blockedRunLoopTimer;
423 m_blockedRunLoopTimer =
timer;
425 m_blockedRunLoopTimer = previouslyBlockedRunLoopTimer;
436 qCDebug(lcEventDispatcherActivity) <<
"Runloop entered activity" << qPrintableActivity(activity);
439 case kCFRunLoopBeforeWaiting:
440 if (m_processEvents.processedTimers
452 case kCFRunLoopAfterWaiting:
455 case kCFRunLoopEntry:
456 case kCFRunLoopBeforeTimers:
457 case kCFRunLoopBeforeSources:
477 qCDebug(lcEventDispatcher) <<
"Already processed posted events, deferring wakeUp";
481 m_postedEventsRunLoopSource.
signal();
483 CFRunLoopWakeUp(m_runLoop);
485 qCDebug(lcEventDispatcher) <<
"Signaled posted event run-loop source";
490 qCDebug(lcEventDispatcher) <<
"Marking current processEvent as interrupted";
492 CFRunLoopStop(m_runLoop);
495#pragma mark - Socket notifiers
511 qCDebug(lcEventDispatcherTimers) <<
"Registering timer with id =" << timerId <<
"interval =" << interval
512 <<
"type =" << timerType <<
"object =" <<
object;
514 Q_ASSERT(timerId > 0 && interval >= 0 &&
object);
517 m_timerInfoList.
registerTimer(timerId, interval, timerType,
object);
528 qCDebug(lcEventDispatcherTimers) <<
"Unegistered timer with id =" << timerId <<
"Timers left:" << m_timerInfoList.
size();
540 qCDebug(lcEventDispatcherTimers) <<
"Unegistered timers for object =" <<
object <<
"Timers left:" << m_timerInfoList.
size();
558static double timespecToSeconds(
const timespec &spec)
560 static double nanosecondsPerSecond = 1.0 * 1000 * 1000 * 1000;
561 return spec.tv_sec + (spec.tv_nsec / nanosecondsPerSecond);
564void QEventDispatcherCoreFoundation::updateTimers()
566 if (m_timerInfoList.
size() > 0) {
569 timespec tv = { -1, -1 };
570 CFAbsoluteTime timeToFire = m_timerInfoList.
timerWait(tv) ?
572 CFAbsoluteTimeGetCurrent() + timespecToSeconds(tv)
574 : kCFTimeIntervalDistantFuture;
576 if (!m_runLoopTimer) {
577 m_runLoopTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault,
579 processTimers(
timer);
582 CFRunLoopAddTimer(m_runLoop, m_runLoopTimer, kCFRunLoopCommonModes);
583 qCDebug(lcEventDispatcherTimers) <<
"Created new CFRunLoopTimer" << m_runLoopTimer;
586 CFRunLoopTimerSetNextFireDate(m_runLoopTimer, timeToFire);
587 qCDebug(lcEventDispatcherTimers) <<
"Re-scheduled CFRunLoopTimer" << m_runLoopTimer;
590 m_overdueTimerScheduled = !timespecToSeconds(tv);
592 qCDebug(lcEventDispatcherTimers) <<
"Next timeout in" << tv <<
"seconds";
598 m_overdueTimerScheduled =
false;
602void QEventDispatcherCoreFoundation::invalidateTimer()
604 if (!m_runLoopTimer || (m_runLoopTimer == m_blockedRunLoopTimer))
607 CFRunLoopTimerInvalidate(m_runLoopTimer);
608 qCDebug(lcEventDispatcherTimers) <<
"Invalidated CFRunLoopTimer" << m_runLoopTimer;
610 CFRelease(m_runLoopTimer);
616#include "qeventdispatcher_cf.moc"
617#include "moc_qeventdispatcher_cf_p.cpp"
DarwinBluetooth::LECBManagerNotifier * notifier
void awake()
This signal is emitted after the event loop returns from a function that could block.
T loadRelaxed() const noexcept
void unregisterSocketNotifier(QSocketNotifier *notifier)
void removeSocketNotifiers()
void registerSocketNotifier(QSocketNotifier *notifier)
void setHostEventDispatcher(QAbstractEventDispatcher *hostEventDispacher)
static QCFType constructFromGet(const T &t)
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
~QEventDispatcherCoreFoundation()
void interrupt() override
Interrupts event dispatching.
virtual bool processPostedEvents()
ProcessEventsState m_processEvents
QList< QAbstractEventDispatcher::TimerInfo > registeredTimers(QObject *object) const override
Returns a list of registered timers for object.
void registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object) override
Register a timer with the specified timerId, interval, and timerType for the given object.
void registerSocketNotifier(QSocketNotifier *notifier) override
Registers notifier with the event loop.
bool processEvents(QEventLoop::ProcessEventsFlags flags) override
Processes pending events that match flags until there are no more events to process.
void wakeUp() override
\threadsafe
bool unregisterTimers(QObject *object) override
Unregisters all the timers associated with the given object.
QEventDispatcherCoreFoundation(QObject *parent=nullptr)
void unregisterSocketNotifier(QSocketNotifier *notifier) override
Unregisters notifier from the event dispatcher.
void startingUp() override
bool unregisterTimer(int timerId) override
Unregisters the timer with the given timerId.
QEventLoop * currentEventLoop() const
int remainingTime(int timerId) override
Returns the remaining time in milliseconds with the given timerId.
qsizetype size() const noexcept
QThread * thread() const
Returns the thread in which the object lives.
T & top()
Returns a reference to the stack's top item.
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
QStack< QEventLoop * > eventLoops
static QThread * currentThread()
bool timerWait(timespec &)
qint64 timerRemainingTime(int timerId)
bool unregisterTimers(QObject *object)
void registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
QList< QAbstractEventDispatcher::TimerInfo > registeredTimers(QObject *object) const
bool unregisterTimer(int timerId)
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
QTextStream & reset(QTextStream &stream)
Calls QTextStream::reset() on stream and returns stream.
bool qt_apple_isApplicationExtension()
#define QT_APPLE_SCOPED_LOG_ACTIVITY(...)
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
#define Q_ENUM_PRINTER(enumName)
static const CFTimeInterval kCFTimeIntervalMinimum
QStack< CFStringRef > m_runLoopModes
static const CFTimeInterval kCFTimeIntervalDistantFuture
QDebug operator<<(QDebug s, timespec tv)
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define qPrintable(string)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
QTextStreamManipulator qSetPadChar(QChar ch)
QTextStreamManipulator qSetFieldWidth(int width)
QFuture< QSet< QString > > dictionary
QAtomicInteger< char > processedPostedEvents
bool deferredUpdateTimers
QAtomicInteger< char > deferredWakeUp
QAtomicInteger< char > wasInterrupted
QAtomicInteger< char > processedTimers
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent