224 lines
6.2 KiB
C++
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();
|
|
}
|