Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qeventdispatcher_cf_p.h
Go to the documentation of this file.
1// Copyright (c) 2007-2008, Apple, Inc.
2// SPDX-License-Identifier: BSD-3-Clause
3
4#ifndef QEVENTDISPATCHER_CF_P_H
5#define QEVENTDISPATCHER_CF_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qabstracteventdispatcher.h>
19#include <QtCore/private/qtimerinfo_unix_p.h>
20#include <QtCore/private/qcfsocketnotifier_p.h>
21#include <QtCore/private/qcore_mac_p.h>
22#include <QtCore/qloggingcategory.h>
23
24#include <CoreFoundation/CoreFoundation.h>
25
26Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker));
27
28QT_BEGIN_NAMESPACE
29
30namespace QtPrivate {
33}
34
35class QEventDispatcherCoreFoundation;
36
37template <class T = QEventDispatcherCoreFoundation>
39{
40public:
41 typedef bool (T::*CallbackFunction)();
42
43 enum { kHighestPriority = 0 } RunLoopSourcePriority;
44
45 RunLoopSource(T *delegate, CallbackFunction callback)
46 : m_delegate(delegate), m_callback(callback)
47 {
48 CFRunLoopSourceContext context = {};
49 context.info = this;
50 context.perform = RunLoopSource::process;
51
52 m_source = CFRunLoopSourceCreate(kCFAllocatorDefault, kHighestPriority, &context);
53 Q_ASSERT(m_source);
54 }
55
57 {
58 CFRunLoopSourceInvalidate(m_source);
59 CFRelease(m_source);
60 }
61
62 void addToMode(CFStringRef mode, CFRunLoopRef runLoop = 0)
63 {
64 if (!runLoop)
65 runLoop = CFRunLoopGetCurrent();
66
67 CFRunLoopAddSource(runLoop, m_source, mode);
68 }
69
70 void signal() { CFRunLoopSourceSignal(m_source); }
71
72private:
73 static void process(void *info)
74 {
75 RunLoopSource *self = static_cast<RunLoopSource *>(info);
76 ((self->m_delegate)->*(self->m_callback))();
77 }
78
79 T *m_delegate;
80 CallbackFunction m_callback;
81 CFRunLoopSourceRef m_source;
82};
83
84template <class T = QEventDispatcherCoreFoundation>
86{
87public:
88 typedef void (T::*CallbackFunction) (CFRunLoopActivity activity);
89
90 RunLoopObserver(T *delegate, CallbackFunction callback, CFOptionFlags activities)
91 : m_delegate(delegate), m_callback(callback)
92 {
93 CFRunLoopObserverContext context = {};
94 context.info = this;
95
96 m_observer = CFRunLoopObserverCreate(kCFAllocatorDefault, activities, true, 0, process, &context);
97 Q_ASSERT(m_observer);
98 }
99
101 {
102 CFRunLoopObserverInvalidate(m_observer);
103 CFRelease(m_observer);
104 }
105
106 void addToMode(CFStringRef mode, CFRunLoopRef runLoop = 0)
107 {
108 if (!runLoop)
109 runLoop = CFRunLoopGetCurrent();
110
111 if (!CFRunLoopContainsObserver(runLoop, m_observer, mode))
112 CFRunLoopAddObserver(runLoop, m_observer, mode);
113 }
114
115 void removeFromMode(CFStringRef mode, CFRunLoopRef runLoop = 0)
116 {
117 if (!runLoop)
118 runLoop = CFRunLoopGetCurrent();
119
120 if (CFRunLoopContainsObserver(runLoop, m_observer, mode))
121 CFRunLoopRemoveObserver(runLoop, m_observer, mode);
122 }
123
124private:
125 static void process(CFRunLoopObserverRef, CFRunLoopActivity activity, void *info)
126 {
127 RunLoopObserver *self = static_cast<RunLoopObserver *>(info);
128 ((self->m_delegate)->*(self->m_callback))(activity);
129 }
130
131 T *m_delegate;
132 CallbackFunction m_callback;
133 CFRunLoopObserverRef m_observer;
134};
135
136class Q_CORE_EXPORT QEventDispatcherCoreFoundation : public QAbstractEventDispatcherV2
137{
138 Q_OBJECT
139
140public:
141 explicit QEventDispatcherCoreFoundation(QObject *parent = nullptr);
142 void startingUp() override;
143 ~QEventDispatcherCoreFoundation();
144
145 bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
146
147 void registerSocketNotifier(QSocketNotifier *notifier) override;
148 void unregisterSocketNotifier(QSocketNotifier *notifier) override;
149
150 void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType,
151 QObject *object) override final;
152 bool unregisterTimer(Qt::TimerId timerId) override final;
153 bool unregisterTimers(QObject *object) override final;
154 QList<TimerInfoV2> timersForObject(QObject *object) const override final;
155 Duration remainingTime(Qt::TimerId timerId) const override final;
156
157 void wakeUp() override;
158 void interrupt() override;
159
160protected:
161 QEventLoop *currentEventLoop() const;
162
163 virtual bool processPostedEvents();
164
165 struct ProcessEventsState
166 {
167 ProcessEventsState(QEventLoop::ProcessEventsFlags f)
168 : flags(f.toInt()), wasInterrupted(false)
169 , processedPostedEvents(false), processedTimers(false)
170 , deferredWakeUp(false), deferredUpdateTimers(false) {}
171
172 ProcessEventsState(const ProcessEventsState &other)
173 : flags(other.flags.loadAcquire())
174 , wasInterrupted(other.wasInterrupted.loadAcquire())
175 , processedPostedEvents(other.processedPostedEvents.loadAcquire())
176 , processedTimers(other.processedTimers.loadAcquire())
177 , deferredWakeUp(other.deferredWakeUp.loadAcquire())
178 , deferredUpdateTimers(other.deferredUpdateTimers) {}
179
180 ProcessEventsState &operator=(const ProcessEventsState &other)
181 {
182 flags.storeRelease(other.flags.loadAcquire());
183 wasInterrupted.storeRelease(other.wasInterrupted.loadAcquire());
184 processedPostedEvents.storeRelease(other.processedPostedEvents.loadAcquire());
185 processedTimers.storeRelease(other.processedTimers.loadAcquire());
186 deferredWakeUp.storeRelease(other.deferredWakeUp.loadAcquire());
187 deferredUpdateTimers = other.deferredUpdateTimers;
188 return *this;
189 }
190
191 QAtomicInt flags;
192 QAtomicInteger<char> wasInterrupted;
193 QAtomicInteger<char> processedPostedEvents;
194 QAtomicInteger<char> processedTimers;
195 QAtomicInteger<char> deferredWakeUp;
196 bool deferredUpdateTimers;
197 };
198
199 ProcessEventsState m_processEvents;
200
201private:
202 RunLoopSource<> m_postedEventsRunLoopSource;
203 RunLoopObserver<> m_runLoopActivityObserver;
204
205 QT_MANGLE_NAMESPACE(RunLoopModeTracker) *m_runLoopModeTracker;
206
207 QTimerInfoList m_timerInfoList;
208 CFRunLoopTimerRef m_runLoopTimer;
209 CFRunLoopTimerRef m_blockedRunLoopTimer;
210 QCFType<CFRunLoopRef> m_runLoop;
211 bool m_overdueTimerScheduled;
212
213 QCFSocketNotifier m_cfSocketNotifier;
214
215 void processTimers(CFRunLoopTimerRef);
216
217 void handleRunLoopActivity(CFRunLoopActivity activity);
218
219 void updateTimers();
220 void invalidateTimer();
221};
222
223QT_END_NAMESPACE
224
225#endif // QEVENTDISPATCHER_CF_P_H
void(T::* CallbackFunction)(CFRunLoopActivity activity)
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
RunLoopObserver(T *delegate, CallbackFunction callback, CFOptionFlags activities)
void removeFromMode(CFStringRef mode, CFRunLoopRef runLoop=0)
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
RunLoopSource(T *delegate, CallbackFunction callback)
bool(T::* CallbackFunction)()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
#define Q_ENUM_PRINTER(enumName)
#define Q_MIRROR_ENUM(name)
static const CFTimeInterval kCFTimeIntervalMinimum
static const CFTimeInterval kCFTimeIntervalDistantFuture
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker))
QDebug operator<<(QDebug debug, QIODevice::OpenMode modes)