+#if wxUSE_EVENTLOOP_SOURCE
+
+namespace
+{
+
+void EnableDescriptorCallBacks(CFFileDescriptorRef cffd, int flags)
+{
+ if ( flags & wxEVENT_SOURCE_INPUT )
+ CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack);
+ if ( flags & wxEVENT_SOURCE_OUTPUT )
+ CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack);
+}
+
+void
+wx_cffiledescriptor_callback(CFFileDescriptorRef cffd,
+ CFOptionFlags flags,
+ void *ctxData)
+{
+ wxLogTrace(wxTRACE_EVT_SOURCE,
+ "CFFileDescriptor callback, flags=%d", flags);
+
+ wxCFEventLoopSource * const
+ source = static_cast<wxCFEventLoopSource *>(ctxData);
+
+ wxEventLoopSourceHandler * const
+ handler = source->GetHandler();
+ if ( flags & kCFFileDescriptorReadCallBack )
+ handler->OnReadWaiting();
+ if ( flags & kCFFileDescriptorWriteCallBack )
+ handler->OnWriteWaiting();
+
+ // we need to re-enable callbacks to be called again
+ EnableDescriptorCallBacks(cffd, source->GetFlags());
+}
+
+} // anonymous namespace
+
+class wxCFEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
+{
+public:
+ wxEventLoopSource *
+ AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags)
+ {
+ wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
+
+ wxScopedPtr<wxCFEventLoopSource>
+ source(new wxCFEventLoopSource(handler, flags));
+
+ CFFileDescriptorContext ctx = { 0, source.get(), NULL, NULL, NULL };
+ wxCFRef<CFFileDescriptorRef>
+ cffd(CFFileDescriptorCreate
+ (
+ kCFAllocatorDefault,
+ fd,
+ true, // close on invalidate
+ wx_cffiledescriptor_callback,
+ &ctx
+ ));
+ if ( !cffd )
+ return NULL;
+
+ wxCFRef<CFRunLoopSourceRef>
+ cfsrc(CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0));
+ if ( !cfsrc )
+ return NULL;
+
+ CFRunLoopRef cfloop = CFRunLoopGetCurrent();
+ CFRunLoopAddSource(cfloop, cfsrc, kCFRunLoopDefaultMode);
+
+ // Enable the callbacks initially.
+ EnableDescriptorCallBacks(cffd, source->GetFlags());
+
+ source->SetFileDescriptor(cffd.release());
+
+ return source.release();
+ }
+};
+
+wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager()
+{
+ static wxCFEventLoopSourcesManager s_eventLoopSourcesManager;
+
+ return &s_eventLoopSourcesManager;
+}
+
+#endif // wxUSE_EVENTLOOP_SOURCE
+