6#include <QtCore/qcoreapplication.h>
7#include <QtCore/qsocketnotifier.h>
8#include <QtCore/qthread.h>
13
14
16 const void *data,
void *info)
19 QCFSocketNotifier *cfSocketNotifier =
static_cast<QCFSocketNotifier *>(info);
20 int nativeSocket = CFSocketGetNative(s);
21 MacSocketInfo *socketInfo = cfSocketNotifier->macSockets.value(nativeSocket);
22 QEvent notifierEvent(QEvent::SockAct);
29 if (callbackType == kCFSocketConnectCallBack) {
32 if (socketInfo->readNotifier)
33 QCoreApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent);
34 if (socketInfo->writeNotifier)
35 QCoreApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent);
37 }
else if (callbackType == kCFSocketReadCallBack) {
38 if (socketInfo->readNotifier && socketInfo->readEnabled) {
39 socketInfo->readEnabled =
false;
40 QCoreApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent);
42 }
else if (callbackType == kCFSocketWriteCallBack) {
43 if (socketInfo->writeNotifier && socketInfo->writeEnabled) {
44 socketInfo->writeEnabled =
false;
45 QCoreApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent);
49 if (cfSocketNotifier->maybeCancelWaitForMoreEvents)
50 cfSocketNotifier->maybeCancelWaitForMoreEvents(cfSocketNotifier->eventDispatcher);
54
55
58 CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
62 CFRunLoopAddSource(CFRunLoopGetCurrent(), loopSource, kCFRunLoopCommonModes);
67
68
72 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop, kCFRunLoopCommonModes);
73 CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
74 CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
77QCFSocketNotifier::QCFSocketNotifier()
79 , maybeCancelWaitForMoreEvents(0)
80 , enableNotifiersObserver(0)
85QCFSocketNotifier::~QCFSocketNotifier()
90void QCFSocketNotifier::setHostEventDispatcher(QAbstractEventDispatcher *hostEventDispacher)
92 eventDispatcher = hostEventDispacher;
95void QCFSocketNotifier::setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack)
97 maybeCancelWaitForMoreEvents = callBack;
100void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
103 int nativeSocket = notifier->socket();
104 int type = notifier->type();
106 if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
107 qWarning(
"QSocketNotifier: Internal error");
109 }
else if (notifier->thread() != eventDispatcher->thread()
110 || eventDispatcher->thread() != QThread::currentThread()) {
111 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
116 if (type == QSocketNotifier::Exception) {
117 qWarning(
"QSocketNotifier::Exception is not supported on iOS");
122 MacSocketInfo *socketInfo = macSockets.value(nativeSocket);
124 socketInfo =
new MacSocketInfo();
128 const int callbackTypes = kCFSocketConnectCallBack | kCFSocketReadCallBack | kCFSocketWriteCallBack;
129 CFSocketContext context = {0,
this, 0, 0, 0};
130 socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
131 if (CFSocketIsValid(socketInfo->socket) ==
false) {
132 qWarning(
"QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket");
136 CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
138 flags &= ~kCFSocketCloseOnInvalidate;
140 flags &= ~(kCFSocketAutomaticallyReenableWriteCallBack | kCFSocketAutomaticallyReenableReadCallBack);
141 CFSocketSetSocketFlags(socketInfo->socket, flags);
143 macSockets.insert(nativeSocket, socketInfo);
146 if (type == QSocketNotifier::Read) {
147 Q_ASSERT(socketInfo->readNotifier == 0);
148 socketInfo->readNotifier = notifier;
149 socketInfo->readEnabled =
false;
150 }
else if (type == QSocketNotifier::Write) {
151 Q_ASSERT(socketInfo->writeNotifier == 0);
152 socketInfo->writeNotifier = notifier;
153 socketInfo->writeEnabled =
false;
156 if (!enableNotifiersObserver) {
159 CFRunLoopObserverContext context = {};
161 enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources,
162 true, 0, enableSocketNotifiers, &context);
163 Q_ASSERT(enableNotifiersObserver);
164 CFRunLoopAddObserver(CFRunLoopGetCurrent(), enableNotifiersObserver, kCFRunLoopCommonModes);
168void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier)
171 int nativeSocket = notifier->socket();
172 int type = notifier->type();
174 if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
175 qWarning(
"QSocketNotifier: Internal error");
177 }
else if (notifier->thread() != eventDispatcher->thread() || eventDispatcher->thread() != QThread::currentThread()) {
178 qWarning(
"QSocketNotifier: socket notifiers cannot be disabled from another thread");
183 if (type == QSocketNotifier::Exception) {
184 qWarning(
"QSocketNotifier::Exception is not supported on iOS");
187 MacSocketInfo *socketInfo = macSockets.value(nativeSocket);
189 qWarning(
"QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier");
194 if (type == QSocketNotifier::Read) {
195 Q_ASSERT(notifier == socketInfo->readNotifier);
196 socketInfo->readNotifier = 0;
197 socketInfo->readEnabled =
false;
198 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
199 }
else if (type == QSocketNotifier::Write) {
200 Q_ASSERT(notifier == socketInfo->writeNotifier);
201 socketInfo->writeNotifier = 0;
202 socketInfo->writeEnabled =
false;
203 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
207 if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) {
208 unregisterSocketInfo(socketInfo);
210 macSockets.remove(nativeSocket);
214void QCFSocketNotifier::removeSocketNotifiers()
217 for (MacSocketInfo *socketInfo : std::as_const(macSockets)) {
218 unregisterSocketInfo(socketInfo);
224 destroyRunLoopObserver();
227void QCFSocketNotifier::destroyRunLoopObserver()
229 if (!enableNotifiersObserver)
232 CFRunLoopObserverInvalidate(enableNotifiersObserver);
233 CFRelease(enableNotifiersObserver);
234 enableNotifiersObserver = 0;
237void QCFSocketNotifier::unregisterSocketInfo(MacSocketInfo *socketInfo)
239 if (socketInfo->runloop) {
240 if (CFSocketIsValid(socketInfo->socket))
241 qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
242 CFRunLoopSourceInvalidate(socketInfo->runloop);
243 CFRelease(socketInfo->runloop);
245 CFSocketInvalidate(socketInfo->socket);
246 CFRelease(socketInfo->socket);
249void QCFSocketNotifier::enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoopActivity activity,
void *info)
254 const QCFSocketNotifier *that =
static_cast<QCFSocketNotifier *>(info);
256 for (MacSocketInfo *socketInfo : that->macSockets) {
257 if (!CFSocketIsValid(socketInfo->socket))
260 if (!socketInfo->runloop) {
262 if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) {
263 qWarning(
"QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop");
264 CFSocketInvalidate(socketInfo->socket);
274 socketInfo->readEnabled = (socketInfo->readNotifier !=
nullptr);
275 if (!socketInfo->readEnabled)
276 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
277 socketInfo->writeEnabled = (socketInfo->writeNotifier !=
nullptr);
278 if (!socketInfo->writeEnabled)
279 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
283 if (socketInfo->readNotifier && !socketInfo->readEnabled) {
284 socketInfo->readEnabled =
true;
285 CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
287 if (socketInfo->writeNotifier && !socketInfo->writeEnabled) {
288 socketInfo->writeEnabled =
true;
289 CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
Combined button and popup list for selecting options.
CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
QT_BEGIN_NAMESPACE void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef, const void *data, void *info)