Files
wxWidgets/src/dfb/evtloop.cpp
2018-09-19 22:03:00 +02:00

224 lines
6.2 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// 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 <errno.h>
#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();
}