Refactor wxEventLoopSource-related code.
[wxWidgets.git] / src / osx / core / evtloop_cf.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/evtloop_cf.cpp
3 // Purpose: wxEventLoop implementation common to both Carbon and Cocoa
4 // Author: Vadim Zeitlin
5 // Created: 2009-10-18
6 // RCS-ID: $Id: wxhead.cpp,v 1.10 2009-06-29 10:23:04 zeitlin Exp $
7 // Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #include "wx/evtloop.h"
27
28 #if wxUSE_EVENTLOOP_SOURCE
29
30 #include "wx/evtloopsrc.h"
31
32 #include "wx/scopedptr.h"
33
34 #include "wx/osx/private.h"
35 #include "wx/osx/core/cfref.h"
36
37 // ============================================================================
38 // wxCFEventLoopSource and wxCFEventLoop implementation
39 // ============================================================================
40
41 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
42 namespace
43 {
44
45 void EnableDescriptorCallBacks(CFFileDescriptorRef cffd, int flags)
46 {
47 if ( flags & wxEVENT_SOURCE_INPUT )
48 CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack);
49 if ( flags & wxEVENT_SOURCE_OUTPUT )
50 CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack);
51 }
52
53 void
54 wx_cffiledescriptor_callback(CFFileDescriptorRef cffd,
55 CFOptionFlags flags,
56 void *ctxData)
57 {
58 wxLogTrace(wxTRACE_EVT_SOURCE,
59 "CFFileDescriptor callback, flags=%d", flags);
60
61 wxCFEventLoopSource * const
62 source = static_cast<wxCFEventLoopSource *>(ctxData);
63
64 wxEventLoopSourceHandler * const
65 handler = source->GetHandler();
66 if ( flags & kCFFileDescriptorReadCallBack )
67 handler->OnReadWaiting();
68 if ( flags & kCFFileDescriptorWriteCallBack )
69 handler->OnWriteWaiting();
70
71 // we need to re-enable callbacks to be called again
72 EnableDescriptorCallBacks(cffd, source->GetFlags());
73 }
74
75 } // anonymous namespace
76
77 wxEventLoopSource *
78 wxCFEventLoop::AddSourceForFD(int fd,
79 wxEventLoopSourceHandler *handler,
80 int flags)
81 {
82 wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
83
84 wxScopedPtr<wxCFEventLoopSource>
85 source(new wxCFEventLoopSource(handler, flags));
86
87 CFFileDescriptorContext ctx = { 0, source.get(), NULL, NULL, NULL };
88 wxCFRef<CFFileDescriptorRef>
89 cffd(CFFileDescriptorCreate
90 (
91 kCFAllocatorDefault,
92 fd,
93 true, // close on invalidate
94 wx_cffiledescriptor_callback,
95 &ctx
96 ));
97 if ( !cffd )
98 return NULL;
99
100 source->SetFileDescriptor(cffd.release());
101
102 wxCFRef<CFRunLoopSourceRef>
103 cfsrc(CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0));
104 if ( !cfsrc )
105 return NULL;
106
107 CFRunLoopRef cfloop = CFGetCurrentRunLoop();
108 CFRunLoopAddSource(cfloop, cfsrc, kCFRunLoopDefaultMode);
109
110 return source.release();
111 }
112
113 void wxCFEventLoopSource::SetFileDescriptor(CFFileDescriptorRef cffd)
114 {
115 wxASSERT_MSG( !m_cffd, "shouldn't be called more than once" );
116
117 m_cffd = cffd;
118 }
119
120 wxCFEventLoopSource::~wxCFEventLoopSource()
121 {
122 if ( m_cffd )
123 CFRelease(m_cffd);
124 }
125
126 #else // OS X < 10.5
127
128 wxEventLoopSource *
129 wxCFEventLoop::AddSourceForFD(int WXUNUSED(fd),
130 wxEventLoopSourceHandler * WXUNUSED(handler),
131 int WXUNUSED(flags))
132 {
133 return NULL;
134 }
135
136 #endif // MAC_OS_X_VERSION_MAX_ALLOWED
137
138 #endif // wxUSE_EVENTLOOP_SOURCE