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