///////////////////////////////////////////////////////////////////////////// // Name: src/dfb/evtloop.cpp // Purpose: wxEventLoop implementation // Author: Vaclav Slavik // Created: 2006-08-16 // Copyright: (c) 2006 REA Elektronik GmbH // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // =========================================================================== // declarations // =========================================================================== // --------------------------------------------------------------------------- // headers // --------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #include "wx/evtloop.h" #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" #endif #include "wx/apptrait.h" #include "wx/thread.h" #include "wx/private/fdiodispatcher.h" #include "wx/dfb/private.h" #include "wx/nonownedwnd.h" #include "wx/buffer.h" #include #define TRACE_EVENTS "events" // =========================================================================== // implementation // =========================================================================== //----------------------------------------------------------------------------- // wxDFBEventsHandler //----------------------------------------------------------------------------- // This handler is installed to process input on DirectFB's events socket ( // obtained using CreateFileDescriptor()). When IDirectFBEventBuffer is used // in this mode, events are written to the file descriptor and we read them // in OnReadWaiting() below. class wxDFBEventsHandler : public wxFDIOHandler { public: wxDFBEventsHandler() : m_fd(-1), m_offset(0) {} void SetFD(int fd) { m_fd = fd; } void Reset() { m_fd = -1; m_offset = 0; } // implement wxFDIOHandler pure virtual methods virtual void OnReadWaiting(); virtual void OnWriteWaiting() { wxFAIL_MSG("OnWriteWaiting shouldn't be called"); } virtual void OnExceptionWaiting() { wxFAIL_MSG("OnExceptionWaiting shouldn't be called"); } private: // DirectFB -> wxWidgets events translation void HandleDFBEvent(const wxDFBEvent& event); int m_fd; size_t m_offset; DFBEvent m_event; }; void wxDFBEventsHandler::OnReadWaiting() { for ( ;; ) { int size = read(m_fd, ((char*)&m_event) + m_offset, sizeof(m_event) - m_offset); if ( size == 0 || (size == -1 && (errno == EAGAIN || errno == EINTR)) ) { // nothing left in the pipe (EAGAIN is expected for an FD with // O_NONBLOCK) break; } if ( size == -1 ) { wxLogSysError(_("Failed to read event from DirectFB pipe")); break; } size += m_offset; m_offset = 0; if ( size != sizeof(m_event) ) { m_offset = size; break; } HandleDFBEvent(m_event); } } void wxDFBEventsHandler::HandleDFBEvent(const wxDFBEvent& event) { switch ( event.GetClass() ) { case DFEC_WINDOW: { wxDFBWindowEvent winevent(((const DFBEvent&)event).window); wxNonOwnedWindow::HandleDFBWindowEvent(winevent); break; } case DFEC_NONE: case DFEC_INPUT: case DFEC_USER: #if wxCHECK_DFB_VERSION(0,9,23) case DFEC_UNIVERSAL: #endif { wxLogTrace(TRACE_EVENTS, "ignoring event of unsupported class %i", (int)event.GetClass()); } } } //----------------------------------------------------------------------------- // wxEventLoop initialization //----------------------------------------------------------------------------- wxIDirectFBEventBufferPtr wxGUIEventLoop::ms_buffer; int wxGUIEventLoop::ms_bufferFd; static wxDFBEventsHandler gs_DFBEventsHandler; wxGUIEventLoop::wxGUIEventLoop() { // Note that this has to be done here so that the buffer is ready when // an event loop runs; GetDirectFBEventBuffer(), which also calls // InitBuffer(), may be called before or after the first wxGUIEventLoop // instance is created. if ( !ms_buffer ) InitBuffer(); } /* static */ void wxGUIEventLoop::InitBuffer() { // create DirectFB events buffer: ms_buffer = wxIDirectFB::Get()->CreateEventBuffer(); // and setup a file descriptor that we can watch for new events: ms_buffer->CreateFileDescriptor(&ms_bufferFd); int flags = fcntl(ms_bufferFd, F_GETFL, 0); if ( flags == -1 || fcntl(ms_bufferFd, F_SETFL, flags | O_NONBLOCK) == -1 ) { wxLogSysError(_("Failed to switch DirectFB pipe to non-blocking mode")); return; } wxFDIODispatcher *dispatcher = wxFDIODispatcher::Get(); wxCHECK_RET( dispatcher, "wxDFB requires wxFDIODispatcher" ); gs_DFBEventsHandler.SetFD(ms_bufferFd); dispatcher->RegisterFD(ms_bufferFd, &gs_DFBEventsHandler, wxFDIO_INPUT); } /* static */ void wxGUIEventLoop::CleanUp() { wxFDIODispatcher *dispatcher = wxFDIODispatcher::Get(); wxCHECK_RET( dispatcher, "wxDFB requires wxFDIODispatcher" ); dispatcher->UnregisterFD(ms_bufferFd); ms_buffer.Reset(); gs_DFBEventsHandler.Reset(); } /* static */ wxIDirectFBEventBufferPtr wxGUIEventLoop::GetDirectFBEventBuffer() { if ( !ms_buffer ) InitBuffer(); return ms_buffer; } //----------------------------------------------------------------------------- // events dispatch and loop handling //----------------------------------------------------------------------------- void wxGUIEventLoop::DoYieldFor(long eventsToProcess) { // TODO: implement event filtering using the eventsToProcess mask // process all pending events: while ( Pending() ) Dispatch(); // handle timers, sockets etc. OnNextIteration(); wxEventLoopBase::DoYieldFor(eventsToProcess); } wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager() { return wxAppTraits::GetEventLoopSourcesManager(); }