6#include <QtCore/qcoreapplication.h>
7#include <QtCore/qsocketnotifier.h>
8#include <QtCore/qthread.h>
13
14
16 const void *,
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 == kCFSocketReadCallBack) {
30 if (socketInfo->readNotifier && socketInfo->readEnabled) {
31 socketInfo->readEnabled =
false;
32 QCoreApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent);
34 }
else if (callbackType == kCFSocketWriteCallBack) {
35 if (socketInfo->writeNotifier && socketInfo->writeEnabled) {
36 socketInfo->writeEnabled =
false;
37 QCoreApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent);
41 if (cfSocketNotifier->maybeCancelWaitForMoreEvents)
42 cfSocketNotifier->maybeCancelWaitForMoreEvents(cfSocketNotifier->eventDispatcher);
46
47
50 CFRunLoopSourceRef loopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
54 CFRunLoopAddSource(CFRunLoopGetCurrent(), loopSource, kCFRunLoopCommonModes);
59
60
64 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop, kCFRunLoopCommonModes);
65 CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
66 CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
69QCFSocketNotifier::QCFSocketNotifier()
71 , maybeCancelWaitForMoreEvents(0)
72 , enableNotifiersObserver(0)
77QCFSocketNotifier::~QCFSocketNotifier()
82void QCFSocketNotifier::setHostEventDispatcher(QAbstractEventDispatcher *hostEventDispacher)
84 eventDispatcher = hostEventDispacher;
87void QCFSocketNotifier::setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack)
89 maybeCancelWaitForMoreEvents = callBack;
92void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
95 int nativeSocket = notifier->socket();
96 int type = notifier->type();
98 if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
99 qWarning(
"QSocketNotifier: Internal error");
101 }
else if (notifier->thread() != eventDispatcher->thread()
102 || eventDispatcher->thread() != QThread::currentThread()) {
103 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
108 if (type == QSocketNotifier::Exception) {
109 qWarning(
"QSocketNotifier::Exception is not supported on iOS");
114 MacSocketInfo *socketInfo = macSockets.value(nativeSocket);
116 socketInfo =
new MacSocketInfo();
120 const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
121 CFSocketContext context = {0,
this, 0, 0, 0};
122 socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
123 if (CFSocketIsValid(socketInfo->socket) ==
false) {
124 qWarning(
"QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket");
128 CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
130 flags &= ~kCFSocketCloseOnInvalidate;
132 flags &= ~(kCFSocketAutomaticallyReenableWriteCallBack | kCFSocketAutomaticallyReenableReadCallBack);
135 flags |= kCFSocketLeaveErrors;
136 CFSocketSetSocketFlags(socketInfo->socket, flags);
138 macSockets.insert(nativeSocket, socketInfo);
141 if (type == QSocketNotifier::Read) {
142 Q_ASSERT(socketInfo->readNotifier == 0);
143 socketInfo->readNotifier = notifier;
144 socketInfo->readEnabled =
false;
145 }
else if (type == QSocketNotifier::Write) {
146 Q_ASSERT(socketInfo->writeNotifier == 0);
147 socketInfo->writeNotifier = notifier;
148 socketInfo->writeEnabled =
false;
151 if (!enableNotifiersObserver) {
154 CFRunLoopObserverContext context = {};
156 enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources,
157 true, 0, enableSocketNotifiers, &context);
158 Q_ASSERT(enableNotifiersObserver);
159 CFRunLoopAddObserver(CFRunLoopGetCurrent(), enableNotifiersObserver, kCFRunLoopCommonModes);
163void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier)
166 int nativeSocket = notifier->socket();
167 int type = notifier->type();
169 if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
170 qWarning(
"QSocketNotifier: Internal error");
172 }
else if (notifier->thread() != eventDispatcher->thread() || eventDispatcher->thread() != QThread::currentThread()) {
173 qWarning(
"QSocketNotifier: socket notifiers cannot be disabled from another thread");
178 if (type == QSocketNotifier::Exception) {
179 qWarning(
"QSocketNotifier::Exception is not supported on iOS");
182 MacSocketInfo *socketInfo = macSockets.value(nativeSocket);
184 qWarning(
"QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier");
189 if (type == QSocketNotifier::Read) {
190 Q_ASSERT(notifier == socketInfo->readNotifier);
191 socketInfo->readNotifier = 0;
192 socketInfo->readEnabled =
false;
193 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
194 }
else if (type == QSocketNotifier::Write) {
195 Q_ASSERT(notifier == socketInfo->writeNotifier);
196 socketInfo->writeNotifier = 0;
197 socketInfo->writeEnabled =
false;
198 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
202 if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) {
203 unregisterSocketInfo(socketInfo);
205 macSockets.remove(nativeSocket);
209void QCFSocketNotifier::removeSocketNotifiers()
212 for (MacSocketInfo *socketInfo : std::as_const(macSockets)) {
213 unregisterSocketInfo(socketInfo);
219 destroyRunLoopObserver();
222void QCFSocketNotifier::destroyRunLoopObserver()
224 if (!enableNotifiersObserver)
227 CFRunLoopObserverInvalidate(enableNotifiersObserver);
228 CFRelease(enableNotifiersObserver);
229 enableNotifiersObserver = 0;
232void QCFSocketNotifier::unregisterSocketInfo(MacSocketInfo *socketInfo)
234 if (socketInfo->runloop) {
235 if (CFSocketIsValid(socketInfo->socket))
236 qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
237 CFRunLoopSourceInvalidate(socketInfo->runloop);
238 CFRelease(socketInfo->runloop);
240 CFSocketInvalidate(socketInfo->socket);
241 CFRelease(socketInfo->socket);
244void QCFSocketNotifier::enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoopActivity activity,
void *info)
249 const QCFSocketNotifier *that =
static_cast<QCFSocketNotifier *>(info);
251 for (MacSocketInfo *socketInfo : that->macSockets) {
252 if (!CFSocketIsValid(socketInfo->socket))
255 if (!socketInfo->runloop) {
257 if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) {
258 qWarning(
"QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop");
259 CFSocketInvalidate(socketInfo->socket);
269 socketInfo->readEnabled = (socketInfo->readNotifier !=
nullptr);
270 if (!socketInfo->readEnabled)
271 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
272 socketInfo->writeEnabled = (socketInfo->writeNotifier !=
nullptr);
273 if (!socketInfo->writeEnabled)
274 CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
278 if (socketInfo->readNotifier && !socketInfo->readEnabled) {
279 socketInfo->readEnabled =
true;
280 CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
282 if (socketInfo->writeNotifier && !socketInfo->writeEnabled) {
283 socketInfo->writeEnabled =
true;
284 CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
Combined button and popup list for selecting options.
CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
QT_BEGIN_NAMESPACE void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef, const void *, void *info)
void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)