]> git.saurik.com Git - wxWidgets.git/blob - src/dfb/evtloop.cpp
No changes, just use wxRecursionGuard instead of manual boolean flag.
[wxWidgets.git] / src / dfb / evtloop.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/dfb/evtloop.cpp
3 // Purpose: wxEventLoop implementation
4 // Author: Vaclav Slavik
5 // Created: 2006-08-16
6 // Copyright: (c) 2006 REA Elektronik GmbH
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // ===========================================================================
11 // declarations
12 // ===========================================================================
13
14 // ---------------------------------------------------------------------------
15 // headers
16 // ---------------------------------------------------------------------------
17
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20
21 #include "wx/evtloop.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/app.h"
25 #include "wx/log.h"
26 #endif
27
28 #include "wx/thread.h"
29 #include "wx/private/fdiodispatcher.h"
30 #include "wx/dfb/private.h"
31 #include "wx/nonownedwnd.h"
32 #include "wx/buffer.h"
33
34 #include <errno.h>
35
36 #define TRACE_EVENTS "events"
37
38 // ===========================================================================
39 // implementation
40 // ===========================================================================
41
42 //-----------------------------------------------------------------------------
43 // wxDFBEventsHandler
44 //-----------------------------------------------------------------------------
45
46 // This handler is installed to process input on DirectFB's events socket (
47 // obtained using CreateFileDescriptor()). When IDirectFBEventBuffer is used
48 // in this mode, events are written to the file descriptor and we read them
49 // in OnReadWaiting() below.
50 class wxDFBEventsHandler : public wxFDIOHandler
51 {
52 public:
53 wxDFBEventsHandler()
54 : m_fd(-1), m_offset(0)
55 {}
56
57 void SetFD(int fd) { m_fd = fd; }
58
59 void Reset()
60 {
61 m_fd = -1;
62 m_offset = 0;
63 }
64
65 // implement wxFDIOHandler pure virtual methods
66 virtual void OnReadWaiting();
67 virtual void OnWriteWaiting()
68 { wxFAIL_MSG("OnWriteWaiting shouldn't be called"); }
69 virtual void OnExceptionWaiting()
70 { wxFAIL_MSG("OnExceptionWaiting shouldn't be called"); }
71
72 private:
73 // DirectFB -> wxWidgets events translation
74 void HandleDFBEvent(const wxDFBEvent& event);
75
76 int m_fd;
77 size_t m_offset;
78 DFBEvent m_event;
79 };
80
81 void wxDFBEventsHandler::OnReadWaiting()
82 {
83 for ( ;; )
84 {
85 int size = read(m_fd,
86 ((char*)&m_event) + m_offset,
87 sizeof(m_event) - m_offset);
88
89 if ( size == 0 || (size == -1 && (errno == EAGAIN || errno == EINTR)) )
90 {
91 // nothing left in the pipe (EAGAIN is expected for an FD with
92 // O_NONBLOCK)
93 break;
94 }
95
96 if ( size == -1 )
97 {
98 wxLogSysError(_("Failed to read event from DirectFB pipe"));
99 break;
100 }
101
102 size += m_offset;
103 m_offset = 0;
104
105 if ( size != sizeof(m_event) )
106 {
107 m_offset = size;
108 break;
109 }
110
111 HandleDFBEvent(m_event);
112 }
113 }
114
115 void wxDFBEventsHandler::HandleDFBEvent(const wxDFBEvent& event)
116 {
117 switch ( event.GetClass() )
118 {
119 case DFEC_WINDOW:
120 {
121 wxDFBWindowEvent winevent(((const DFBEvent&)event).window);
122 wxNonOwnedWindow::HandleDFBWindowEvent(winevent);
123 break;
124 }
125
126 case DFEC_NONE:
127 case DFEC_INPUT:
128 case DFEC_USER:
129 #if wxCHECK_DFB_VERSION(0,9,23)
130 case DFEC_UNIVERSAL:
131 #endif
132 {
133 wxLogTrace(TRACE_EVENTS,
134 "ignoring event of unsupported class %i",
135 (int)event.GetClass());
136 }
137 }
138 }
139
140 //-----------------------------------------------------------------------------
141 // wxEventLoop initialization
142 //-----------------------------------------------------------------------------
143
144 wxIDirectFBEventBufferPtr wxGUIEventLoop::ms_buffer;
145 int wxGUIEventLoop::ms_bufferFd;
146 static wxDFBEventsHandler gs_DFBEventsHandler;
147
148 wxGUIEventLoop::wxGUIEventLoop()
149 {
150 // Note that this has to be done here so that the buffer is ready when
151 // an event loop runs; GetDirectFBEventBuffer(), which also calls
152 // InitBuffer(), may be called before or after the first wxGUIEventLoop
153 // instance is created.
154 if ( !ms_buffer )
155 InitBuffer();
156 }
157
158 /* static */
159 void wxGUIEventLoop::InitBuffer()
160 {
161 // create DirectFB events buffer:
162 ms_buffer = wxIDirectFB::Get()->CreateEventBuffer();
163
164 // and setup a file descriptor that we can watch for new events:
165
166 ms_buffer->CreateFileDescriptor(&ms_bufferFd);
167 int flags = fcntl(ms_bufferFd, F_GETFL, 0);
168 if ( flags == -1 || fcntl(ms_bufferFd, F_SETFL, flags | O_NONBLOCK) == -1 )
169 {
170 wxLogSysError(_("Failed to switch DirectFB pipe to non-blocking mode"));
171 return;
172 }
173
174 wxFDIODispatcher *dispatcher = wxFDIODispatcher::Get();
175 wxCHECK_RET( dispatcher, "wxDFB requires wxFDIODispatcher" );
176
177 gs_DFBEventsHandler.SetFD(ms_bufferFd);
178 dispatcher->RegisterFD(ms_bufferFd, &gs_DFBEventsHandler, wxFDIO_INPUT);
179 }
180
181 /* static */
182 void wxGUIEventLoop::CleanUp()
183 {
184 wxFDIODispatcher *dispatcher = wxFDIODispatcher::Get();
185 wxCHECK_RET( dispatcher, "wxDFB requires wxFDIODispatcher" );
186 dispatcher->UnregisterFD(ms_bufferFd);
187
188 ms_buffer.Reset();
189 gs_DFBEventsHandler.Reset();
190 }
191
192 /* static */
193 wxIDirectFBEventBufferPtr wxGUIEventLoop::GetDirectFBEventBuffer()
194 {
195 if ( !ms_buffer )
196 InitBuffer();
197
198 return ms_buffer;
199 }
200
201 //-----------------------------------------------------------------------------
202 // events dispatch and loop handling
203 //-----------------------------------------------------------------------------
204
205 bool wxGUIEventLoop::YieldFor(long eventsToProcess)
206 {
207 #if wxUSE_THREADS
208 if ( !wxThread::IsMain() )
209 return true; // can't process events from other threads
210 #endif // wxUSE_THREADS
211
212 m_isInsideYield = true;
213 m_eventsToProcessInsideYield = eventsToProcess;
214
215 #if wxUSE_LOG
216 wxLog::Suspend();
217 #endif // wxUSE_LOG
218
219 // TODO: implement event filtering using the eventsToProcess mask
220
221 // process all pending events:
222 while ( Pending() )
223 Dispatch();
224
225 // handle timers, sockets etc.
226 OnNextIteration();
227
228 // it's necessary to call ProcessIdle() to update the frames sizes which
229 // might have been changed (it also will update other things set from
230 // OnUpdateUI() which is a nice (and desired) side effect)
231 while ( ProcessIdle() ) {}
232
233 #if wxUSE_LOG
234 wxLog::Resume();
235 #endif // wxUSE_LOG
236
237 m_isInsideYield = false;
238
239 return true;
240 }