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
512 qCDebug(lcEventDispatcherTimers) <<
"Registering timer with id =" << int(timerId) <<
"interval =" << interval
513 <<
"type =" << timerType <<
"object =" <<
object;
518 m_timerInfoList.
registerTimer(timerId, interval, timerType,
object);
530 <<
"Timers left:" << m_timerInfoList.
size();
542 qCDebug(lcEventDispatcherTimers) <<
"Unegistered timers for object =" <<
object <<
"Timers left:" << m_timerInfoList.
size();
548QList<QAbstractEventDispatcher::TimerInfoV2>
562void QEventDispatcherCoreFoundation::updateTimers()
564 if (m_timerInfoList.
size() > 0) {
567 using namespace std::chrono_literals;
568 using DoubleSeconds = std::chrono::duration<double, std::ratio<1>>;
570 CFAbsoluteTime timeToFire;
572 DoubleSeconds secs{};
575 secs = DoubleSeconds{*
opt};
576 timeToFire = CFAbsoluteTimeGetCurrent() + secs.
count();
582 if (!m_runLoopTimer) {
583 m_runLoopTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault,
585 processTimers(
timer);
588 CFRunLoopAddTimer(m_runLoop, m_runLoopTimer, kCFRunLoopCommonModes);
589 qCDebug(lcEventDispatcherTimers) <<
"Created new CFRunLoopTimer" << m_runLoopTimer;
592 CFRunLoopTimerSetNextFireDate(m_runLoopTimer, timeToFire);
593 qCDebug(lcEventDispatcherTimers) <<
"Re-scheduled CFRunLoopTimer" << m_runLoopTimer;
596 m_overdueTimerScheduled = secs > 0
s;
598 qCDebug(lcEventDispatcherTimers) <<
"Next timeout in" << secs;
604 m_overdueTimerScheduled =
false;
608void QEventDispatcherCoreFoundation::invalidateTimer()
610 if (!m_runLoopTimer || (m_runLoopTimer == m_blockedRunLoopTimer))
613 CFRunLoopTimerInvalidate(m_runLoopTimer);
614 qCDebug(lcEventDispatcherTimers) <<
"Invalidated CFRunLoopTimer" << m_runLoopTimer;
616 CFRelease(m_runLoopTimer);
622#include "qeventdispatcher_cf.moc"
623#include "moc_qeventdispatcher_cf_p.cpp"
DarwinBluetooth::LECBManagerNotifier * notifier
std::chrono::nanoseconds Duration
A {std::chrono::duration} type that is used in various API in this class.
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
void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object) override final
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
QEventDispatcherCoreFoundation(QObject *parent=nullptr)
QList< TimerInfoV2 > timersForObject(QObject *object) const override final
bool unregisterTimer(Qt::TimerId timerId) override final
void unregisterSocketNotifier(QSocketNotifier *notifier) override
Unregisters notifier from the event dispatcher.
void startingUp() override
QEventLoop * currentEventLoop() const
Duration remainingTime(Qt::TimerId timerId) const override final
Returns the remaining time of the timer with the given timerId.
bool unregisterTimers(QObject *object) override final
Unregisters all the timers associated with the given object.
QThread * thread() const
Returns the thread in which the object lives.
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
static QThread * currentThread()
bool unregisterTimer(Qt::TimerId timerId)
Duration remainingDuration(Qt::TimerId timerId) const
bool unregisterTimers(QObject *object)
std::optional< Duration > timerWait()
void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object)
QList< TimerInfo > registeredTimers(QObject *object) const
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
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,...)
GLenum GLenum GLsizei count
#define qPrintable(string)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
QTextStreamManipulator qSetPadChar(QChar ch)
QTextStreamManipulator qSetFieldWidth(int width)
QT_BEGIN_NAMESPACE constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
QFuture< QSet< QString > > dictionary
QAtomicInteger< char > processedPostedEvents
bool deferredUpdateTimers
QAtomicInteger< char > deferredWakeUp
QAtomicInteger< char > wasInterrupted
QAtomicInteger< char > processedTimers