/* (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) (c) Copyright 2000-2004 Convergence (integrated media) GmbH All rights reserved. Written by Denis Oliver Kropp , Andreas Hundt , Sven Neumann , Ville Syrjälä and Claudio Ciccani . This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "idirectfbinputbuffer.h" D_DEBUG_DOMAIN( IDFBEvBuf, "IDFBEventBuffer", "IDirectFBEventBuffer Interface" ); typedef struct { DirectLink link; DFBEvent evt; } EventBufferItem; typedef struct { DirectLink link; CoreInputDevice *device; /* pointer to input core device struct */ Reaction reaction; DFBInputDeviceDescription desc; } AttachedDevice; typedef struct { DirectLink link; CoreWindow *window; /* pointer to core window struct */ Reaction reaction; } AttachedWindow; /* * private data struct of IDirectFBInputDevice */ typedef struct { int ref; /* reference counter */ EventBufferFilterCallback filter; void *filter_ctx; DirectLink *devices; /* attached devices */ DirectLink *windows; /* attached windows */ DirectLink *events; /* linked list containing events */ pthread_mutex_t events_mutex; /* mutex lock for accessing the event queue */ pthread_cond_t wait_condition; /* condition for idle wait in WaitForEvent() */ bool pipe; /* file descriptor mode? */ int pipe_fds[2]; /* read & write file descriptor */ DirectThread *pipe_thread; /* thread feeding the pipe */ DFBEventBufferStats stats; bool stats_enabled; } IDirectFBEventBuffer_data; /* * adds an event to the event queue */ static void IDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data, EventBufferItem *item ); #ifndef DIRECTFB_PURE_VOODOO static ReactionResult IDirectFBEventBuffer_InputReact( const void *msg_data, void *ctx ); static ReactionResult IDirectFBEventBuffer_WindowReact( const void *msg_data, void *ctx ); #endif static void *IDirectFBEventBuffer_Feed( DirectThread *thread, void *arg ); static void CollectEventStatistics( DFBEventBufferStats *stats, const DFBEvent *event, int incdec ); static void IDirectFBEventBuffer_Destruct( IDirectFBEventBuffer *thiz ) { IDirectFBEventBuffer_data *data = thiz->priv; AttachedDevice *device; AttachedWindow *window; EventBufferItem *item; DirectLink *n; D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); pthread_mutex_lock( &data->events_mutex ); if (data->pipe) { data->pipe = false; pthread_cond_broadcast( &data->wait_condition ); pthread_mutex_unlock( &data->events_mutex ); direct_thread_join( data->pipe_thread ); direct_thread_destroy( data->pipe_thread ); pthread_mutex_lock( &data->events_mutex ); close( data->pipe_fds[0] ); close( data->pipe_fds[1] ); } #ifndef DIRECTFB_PURE_VOODOO direct_list_foreach_safe (device, n, data->devices) { dfb_input_detach( device->device, &device->reaction ); D_FREE( device ); } direct_list_foreach_safe (window, n, data->windows) { if (window->window) { dfb_window_detach( window->window, &window->reaction ); dfb_window_unref( window->window ); } D_FREE( window ); } #endif direct_list_foreach_safe (item, n, data->events) D_FREE( item ); pthread_cond_destroy( &data->wait_condition ); pthread_mutex_destroy( &data->events_mutex ); DIRECT_DEALLOCATE_INTERFACE( thiz ); } static DirectResult IDirectFBEventBuffer_AddRef( IDirectFBEventBuffer *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); data->ref++; return DFB_OK; } static DirectResult IDirectFBEventBuffer_Release( IDirectFBEventBuffer *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); if (--data->ref == 0) IDirectFBEventBuffer_Destruct( thiz ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_Reset( IDirectFBEventBuffer *thiz ) { EventBufferItem *item; DirectLink *n; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); if (data->pipe) return DFB_UNSUPPORTED; pthread_mutex_lock( &data->events_mutex ); direct_list_foreach_safe (item, n, data->events) D_FREE( item ); data->events = NULL; pthread_mutex_unlock( &data->events_mutex ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_WaitForEvent( IDirectFBEventBuffer *thiz ) { DFBResult ret = DFB_OK; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); if (data->pipe) return DFB_UNSUPPORTED; pthread_mutex_lock( &data->events_mutex ); if (!data->events) pthread_cond_wait( &data->wait_condition, &data->events_mutex ); if (!data->events) ret = DFB_INTERRUPTED; pthread_mutex_unlock( &data->events_mutex ); return ret; } static DFBResult IDirectFBEventBuffer_WaitForEventWithTimeout( IDirectFBEventBuffer *thiz, unsigned int seconds, unsigned int milli_seconds ) { struct timespec timeout; DFBResult ret = DFB_OK; int locked = 0; long int nano_seconds = milli_seconds * 1000000; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p, %u, %u )\n", __FUNCTION__, thiz, seconds, milli_seconds ); if (data->pipe) return DFB_UNSUPPORTED; if (pthread_mutex_trylock( &data->events_mutex ) == 0) { if (data->events) { pthread_mutex_unlock ( &data->events_mutex ); return ret; } locked = 1; } direct_util_get_monotonic_pthread_timeout(&timeout, seconds, nano_seconds); if (!locked) pthread_mutex_lock( &data->events_mutex ); if (!data->events) { if (pthread_cond_timedwait( &data->wait_condition, &data->events_mutex, &timeout ) == ETIMEDOUT) ret = DFB_TIMEOUT; else if (!data->events) ret = DFB_INTERRUPTED; } pthread_mutex_unlock( &data->events_mutex ); return ret; } static DFBResult IDirectFBEventBuffer_WakeUp( IDirectFBEventBuffer *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); if (data->pipe) return DFB_UNSUPPORTED; pthread_cond_broadcast( &data->wait_condition ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_GetEvent( IDirectFBEventBuffer *thiz, DFBEvent *event ) { EventBufferItem *item; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p )\n", __FUNCTION__, thiz, event ); if (data->pipe) return DFB_UNSUPPORTED; pthread_mutex_lock( &data->events_mutex ); if (!data->events) { pthread_mutex_unlock( &data->events_mutex ); return DFB_BUFFEREMPTY; } item = (EventBufferItem*) data->events; switch (item->evt.clazz) { case DFEC_INPUT: event->input = item->evt.input; break; case DFEC_WINDOW: event->window = item->evt.window; break; case DFEC_USER: event->user = item->evt.user; break; case DFEC_VIDEOPROVIDER: event->videoprovider = item->evt.videoprovider; break; case DFEC_UNIVERSAL: direct_memcpy( event, &item->evt, item->evt.universal.size ); break; default: D_BUG("unknown event class"); } if (data->stats_enabled) CollectEventStatistics( &data->stats, &item->evt, -1 ); direct_list_remove( &data->events, &item->link ); D_FREE( item ); pthread_mutex_unlock( &data->events_mutex ); D_DEBUG_AT( IDFBEvBuf, " -> class %d, type/size %d, data/id %p\n", event->clazz, event->user.type, event->user.data ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_PeekEvent( IDirectFBEventBuffer *thiz, DFBEvent *event ) { EventBufferItem *item; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p )\n", __FUNCTION__, thiz, event ); if (data->pipe) return DFB_UNSUPPORTED; pthread_mutex_lock( &data->events_mutex ); if (!data->events) { pthread_mutex_unlock( &data->events_mutex ); return DFB_BUFFEREMPTY; } item = (EventBufferItem*) data->events; switch (item->evt.clazz) { case DFEC_INPUT: event->input = item->evt.input; break; case DFEC_WINDOW: event->window = item->evt.window; break; case DFEC_USER: event->user = item->evt.user; break; case DFEC_VIDEOPROVIDER: event->videoprovider = item->evt.videoprovider; break; case DFEC_UNIVERSAL: direct_memcpy( event, &item->evt, item->evt.universal.size ); break; default: D_BUG("unknown event class"); } pthread_mutex_unlock( &data->events_mutex ); D_DEBUG_AT( IDFBEvBuf, " -> class %d, type/size %d, data/id %p\n", event->clazz, event->user.type, event->user.data ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_HasEvent( IDirectFBEventBuffer *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p ) <- events: %p, pipe: %d\n", __FUNCTION__, thiz, data->events, data->pipe ); if (data->pipe) return DFB_UNSUPPORTED; return (data->events ? DFB_OK : DFB_BUFFEREMPTY); } static DFBResult IDirectFBEventBuffer_PostEvent( IDirectFBEventBuffer *thiz, const DFBEvent *event ) { EventBufferItem *item; int size; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [class %d, type/size %d, data/id %p] )\n", __FUNCTION__, thiz, event, event->clazz, event->user.type, event->user.data ); switch (event->clazz) { case DFEC_INPUT: case DFEC_WINDOW: case DFEC_USER: case DFEC_VIDEOPROVIDER: size = sizeof(EventBufferItem); break; case DFEC_UNIVERSAL: size = event->universal.size; if (size < sizeof(DFBUniversalEvent)) return DFB_INVARG; /* We must not exceed the union to avoid crashes in generic code (reading DFBEvents) * and to support pipe mode where each written block has to have a fixed size. */ if (size > sizeof(DFBEvent)) return DFB_INVARG; size += sizeof(DirectLink); break; default: return DFB_INVARG; } item = D_CALLOC( 1, size ); if (!item) return D_OOM(); switch (event->clazz) { case DFEC_INPUT: item->evt.input = event->input; break; case DFEC_WINDOW: item->evt.window = event->window; break; case DFEC_USER: item->evt.user = event->user; break; case DFEC_VIDEOPROVIDER: item->evt.videoprovider = event->videoprovider; break; case DFEC_UNIVERSAL: direct_memcpy( &item->evt, event, event->universal.size ); break; default: D_BUG("unexpected event class"); } IDirectFBEventBuffer_AddItem( data, item ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_CreateFileDescriptor( IDirectFBEventBuffer *thiz, int *ret_fd ) { DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); /* Check arguments. */ if (!ret_fd) return DFB_INVARG; /* Lock the event queue. */ pthread_mutex_lock( &data->events_mutex ); /* Already in pipe mode? */ if (data->pipe) { pthread_mutex_unlock( &data->events_mutex ); return DFB_BUSY; } /* Create the file descriptor(s). */ if (socketpair( PF_LOCAL, SOCK_STREAM, 0, data->pipe_fds )) { D_PERROR( "%s(): socketpair( PF_LOCAL, SOCK_STREAM, 0, fds ) failed!\n", __FUNCTION__ ); pthread_mutex_unlock( &data->events_mutex ); return errno2result( errno ); } D_DEBUG_AT( IDFBEvBuf, " -> entering pipe mode\n" ); /* Enter pipe mode. */ data->pipe = true; /* Signal any waiting processes. */ pthread_cond_broadcast( &data->wait_condition ); /* Create the feeding thread. */ data->pipe_thread = direct_thread_create( DTT_MESSAGING, IDirectFBEventBuffer_Feed, data, "EventBufferFeed" ); /* Unlock the event queue. */ pthread_mutex_unlock( &data->events_mutex ); /* Return the file descriptor for reading. */ *ret_fd = data->pipe_fds[0]; D_DEBUG_AT( IDFBEvBuf, " -> fd %d/%d\n", data->pipe_fds[0], data->pipe_fds[1] ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_EnableStatistics( IDirectFBEventBuffer *thiz, DFBBoolean enable ) { DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p, %sable )\n", __FUNCTION__, thiz, enable ? "en" : "dis" ); /* Lock the event queue. */ pthread_mutex_lock( &data->events_mutex ); /* Already enabled/disabled? */ if (data->stats_enabled == !!enable) { pthread_mutex_unlock( &data->events_mutex ); return DFB_OK; } if (enable) { EventBufferItem *item; /* Collect statistics for events already in the queue. */ direct_list_foreach (item, data->events) CollectEventStatistics( &data->stats, &item->evt, 1 ); } else { /* Clear statistics. */ memset( &data->stats, 0, sizeof(DFBEventBufferStats) ); } /* Remember state. */ data->stats_enabled = !!enable; /* Unlock the event queue. */ pthread_mutex_unlock( &data->events_mutex ); return DFB_OK; } static DFBResult IDirectFBEventBuffer_GetStatistics( IDirectFBEventBuffer *thiz, DFBEventBufferStats *ret_stats ) { DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p )\n", __FUNCTION__, thiz, ret_stats ); if (!ret_stats) return DFB_INVARG; /* Lock the event queue. */ pthread_mutex_lock( &data->events_mutex ); /* Not enabled? */ if (!data->stats_enabled) { pthread_mutex_unlock( &data->events_mutex ); return DFB_UNSUPPORTED; } /* Return current stats. */ *ret_stats = data->stats; /* Unlock the event queue. */ pthread_mutex_unlock( &data->events_mutex ); return DFB_OK; } DFBResult IDirectFBEventBuffer_Construct( IDirectFBEventBuffer *thiz, EventBufferFilterCallback filter, void *filter_ctx ) { DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBEventBuffer) D_DEBUG_AT( IDFBEvBuf, "%s( %p, filter %p, ctx %p )\n", __FUNCTION__, thiz, filter, filter_ctx ); data->ref = 1; data->filter = filter; data->filter_ctx = filter_ctx; direct_util_recursive_pthread_mutex_init( &data->events_mutex ); direct_util_monotonic_pthread_cond_init( &data->wait_condition ); thiz->AddRef = IDirectFBEventBuffer_AddRef; thiz->Release = IDirectFBEventBuffer_Release; thiz->Reset = IDirectFBEventBuffer_Reset; thiz->WaitForEvent = IDirectFBEventBuffer_WaitForEvent; thiz->WaitForEventWithTimeout = IDirectFBEventBuffer_WaitForEventWithTimeout; thiz->GetEvent = IDirectFBEventBuffer_GetEvent; thiz->PeekEvent = IDirectFBEventBuffer_PeekEvent; thiz->HasEvent = IDirectFBEventBuffer_HasEvent; thiz->PostEvent = IDirectFBEventBuffer_PostEvent; thiz->WakeUp = IDirectFBEventBuffer_WakeUp; thiz->CreateFileDescriptor = IDirectFBEventBuffer_CreateFileDescriptor; thiz->EnableStatistics = IDirectFBEventBuffer_EnableStatistics; thiz->GetStatistics = IDirectFBEventBuffer_GetStatistics; D_DEBUG_AT( IDFBEvBuf, " -> %p [%p]\n", thiz, thiz->priv ); return DFB_OK; } /* directfb internals */ #ifndef DIRECTFB_PURE_VOODOO DFBResult IDirectFBEventBuffer_AttachInputDevice( IDirectFBEventBuffer *thiz, CoreInputDevice *device ) { AttachedDevice *attached; DFBInputDeviceDescription desc; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_ASSERT( device != NULL ); dfb_input_device_description( device, &desc ); D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u - %s] )\n", __FUNCTION__, thiz, device, dfb_input_device_id(device), desc.name ); attached = D_CALLOC( 1, sizeof(AttachedDevice) ); attached->device = device; attached->desc = desc; direct_list_prepend( &data->devices, &attached->link ); dfb_input_attach( device, IDirectFBEventBuffer_InputReact, data, &attached->reaction ); return DFB_OK; } DFBResult IDirectFBEventBuffer_DetachInputDevice( IDirectFBEventBuffer *thiz, CoreInputDevice *device ) { AttachedDevice *attached; DirectLink *link; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_ASSERT( device != NULL ); D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u] )\n", __FUNCTION__, thiz, device, dfb_input_device_id(device) ); direct_list_foreach_safe (attached, link, data->devices) { if (attached->device == device) { direct_list_remove( &data->devices, &attached->link ); dfb_input_detach( attached->device, &attached->reaction ); D_FREE( attached ); return DFB_OK; } } return DFB_ITEMNOTFOUND; } DFBResult IDirectFBEventBuffer_AttachWindow( IDirectFBEventBuffer *thiz, CoreWindow *window ) { AttachedWindow *attached; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_ASSERT( window != NULL ); D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u - %d,%d-%dx%d] )\n", __FUNCTION__, thiz, window, window->id, window->config.bounds.x, window->config.bounds.y, window->config.bounds.w, window->config.bounds.h ); attached = D_CALLOC( 1, sizeof(AttachedWindow) ); attached->window = window; window->caps &= ~DWCAPS_NOFOCUS; //no focus patch PR brg36mgr#118432 dfb_window_ref( window ); direct_list_prepend( &data->windows, &attached->link ); dfb_window_attach( window, IDirectFBEventBuffer_WindowReact, data, &attached->reaction ); return DFB_OK; } DFBResult IDirectFBEventBuffer_DetachWindow( IDirectFBEventBuffer *thiz, CoreWindow *window ) { AttachedWindow *attached; DirectLink *link; DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) D_ASSERT( window != NULL ); D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u - %d,%d-%dx%d] )\n", __FUNCTION__, thiz, window, window->id, window->config.bounds.x, window->config.bounds.y, window->config.bounds.w, window->config.bounds.h ); direct_list_foreach_safe (attached, link, data->windows) { if (!attached->window || attached->window == window) { direct_list_remove( &data->windows, &attached->link ); if (attached->window) { dfb_window_detach( attached->window, &attached->reaction ); dfb_window_unref( attached->window ); } D_FREE( attached ); } } return DFB_OK; } #endif /* file internals */ static void IDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data, EventBufferItem *item ) { if (data->filter && data->filter( &item->evt, data->filter_ctx )) { D_FREE( item ); return; } pthread_mutex_lock( &data->events_mutex ); if (data->stats_enabled) CollectEventStatistics( &data->stats, &item->evt, 1 ); direct_list_append( &data->events, &item->link ); pthread_cond_broadcast( &data->wait_condition ); pthread_mutex_unlock( &data->events_mutex ); } #ifndef DIRECTFB_PURE_VOODOO static ReactionResult IDirectFBEventBuffer_InputReact( const void *msg_data, void *ctx ) { const DFBInputEvent *evt = msg_data; IDirectFBEventBuffer_data *data = ctx; EventBufferItem *item; D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p ) <- type %06x\n", __FUNCTION__, evt, data, evt->type ); if (dfb_config->discard_repeat_events && (evt->flags & DIEF_REPEAT)) { D_DEBUG_AT( IDFBEvBuf, " -> discarding repeat event!\n" ); return DFB_OK; } item = D_CALLOC( 1, sizeof(EventBufferItem) ); item->evt.input = *evt; item->evt.clazz = DFEC_INPUT; IDirectFBEventBuffer_AddItem( data, item ); return RS_OK; } static ReactionResult IDirectFBEventBuffer_WindowReact( const void *msg_data, void *ctx ) { const DFBWindowEvent *evt = msg_data; IDirectFBEventBuffer_data *data = ctx; EventBufferItem *item; D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p ) <- type %06x\n", __FUNCTION__, evt, data, evt->type ); if (dfb_config->discard_repeat_events && (evt->flags & DWEF_REPEAT)) { D_DEBUG_AT( IDFBEvBuf, " -> discarding repeat event!\n" ); return DFB_OK; } item = D_CALLOC( 1, sizeof(EventBufferItem) ); item->evt.window = *evt; item->evt.clazz = DFEC_WINDOW; IDirectFBEventBuffer_AddItem( data, item ); if (evt->type == DWET_DESTROYED) { AttachedWindow *window; direct_list_foreach (window, data->windows) { if (!window->window) continue; if (dfb_window_id( window->window ) == evt->window_id) { /* FIXME: free memory later, because reactor writes to it after we return RS_REMOVE */ dfb_window_unref( window->window ); window->window = NULL; } } return RS_REMOVE; } return RS_OK; } #endif static void * IDirectFBEventBuffer_Feed( DirectThread *thread, void *arg ) { IDirectFBEventBuffer_data *data = arg; pthread_mutex_lock( &data->events_mutex ); while (data->pipe) { while (data->events && data->pipe) { int ret; EventBufferItem *item = (EventBufferItem*) data->events; if (data->stats_enabled) CollectEventStatistics( &data->stats, &item->evt, -1 ); direct_list_remove( &data->events, &item->link ); if (item->evt.clazz == DFEC_UNIVERSAL) { D_WARN( "universal events not supported in pipe mode" ); continue; } pthread_mutex_unlock( &data->events_mutex ); D_DEBUG_AT( IDFBEvBuf, "Going to write %zu bytes to file descriptor %d...\n", sizeof(DFBEvent), data->pipe_fds[1] ); ret = write( data->pipe_fds[1], &item->evt, sizeof(DFBEvent) ); D_DEBUG_AT( IDFBEvBuf, "...wrote %d bytes to file descriptor %d.\n", ret, data->pipe_fds[1] ); D_FREE( item ); pthread_mutex_lock( &data->events_mutex ); } if (data->pipe) pthread_cond_wait( &data->wait_condition, &data->events_mutex ); } pthread_mutex_unlock( &data->events_mutex ); return NULL; } static void CollectEventStatistics( DFBEventBufferStats *stats, const DFBEvent *event, int incdec ) { stats->num_events += incdec; switch (event->clazz) { case DFEC_INPUT: stats->DFEC_INPUT += incdec; switch (event->input.type) { case DIET_KEYPRESS: stats->DIET_KEYPRESS += incdec; break; case DIET_KEYRELEASE: stats->DIET_KEYRELEASE += incdec; break; case DIET_BUTTONPRESS: stats->DIET_BUTTONPRESS += incdec; break; case DIET_BUTTONRELEASE: stats->DIET_BUTTONRELEASE += incdec; break; case DIET_AXISMOTION: stats->DIET_AXISMOTION += incdec; break; default: D_BUG( "unknown input event type 0x%08x\n", event->input.type ); } break; case DFEC_WINDOW: stats->DFEC_WINDOW += incdec; switch (event->window.type) { case DWET_POSITION: stats->DWET_POSITION += incdec; break; case DWET_SIZE: stats->DWET_SIZE += incdec; break; case DWET_CLOSE: stats->DWET_CLOSE += incdec; break; case DWET_DESTROYED: stats->DWET_DESTROYED += incdec; break; case DWET_GOTFOCUS: stats->DWET_GOTFOCUS += incdec; break; case DWET_LOSTFOCUS: stats->DWET_LOSTFOCUS += incdec; break; case DWET_KEYDOWN: stats->DWET_KEYDOWN += incdec; break; case DWET_KEYUP: stats->DWET_KEYUP += incdec; break; case DWET_BUTTONDOWN: stats->DWET_BUTTONDOWN += incdec; break; case DWET_BUTTONUP: stats->DWET_BUTTONUP += incdec; break; case DWET_MOTION: stats->DWET_MOTION += incdec; break; case DWET_ENTER: stats->DWET_ENTER += incdec; break; case DWET_LEAVE: stats->DWET_LEAVE += incdec; break; case DWET_WHEEL: stats->DWET_WHEEL += incdec; break; case DWET_POSITION_SIZE: stats->DWET_POSITION_SIZE += incdec; break; default: D_BUG( "unknown window event type 0x%08x\n", event->window.type ); } break; case DFEC_USER: stats->DFEC_USER += incdec; break; case DFEC_VIDEOPROVIDER: stats->DFEC_VIDEOPROVIDER +=incdec; switch (event->videoprovider.type) { case DVPET_STARTED: stats->DVPET_STARTED += incdec; break; case DVPET_STOPPED: stats->DVPET_STOPPED += incdec; break; case DVPET_SPEEDCHANGE: stats->DVPET_SPEEDCHANGE += incdec; break; case DVPET_STREAMCHANGE: stats->DVPET_STREAMCHANGE += incdec; break; case DVPET_FATALERROR: stats->DVPET_FATALERROR += incdec; break; case DVPET_FINISHED: stats->DVPET_FINISHED += incdec; break; case DVPET_SURFACECHANGE: stats->DVPET_SURFACECHANGE += incdec; break; case DVPET_FRAMEDECODED: stats->DVPET_FRAMEDECODED += incdec; break; case DVPET_FRAMEDISPLAYED: stats->DVPET_FRAMEDISPLAYED += incdec; break; case DVPET_DATAEXHAUSTED: stats->DVPET_DATAEXHAUSTED += incdec; break; case DVPET_VIDEOACTION: stats->DVPET_VIDEOACTION += incdec; break; case DVPET_DATALOW: stats->DVPET_DATALOW += incdec; break; case DVPET_DATAHIGH: stats->DVPET_DATAHIGH += incdec; break; case DVPET_BUFFERTIMELOW: stats->DVPET_BUFFERTIMELOW += incdec; break; case DVPET_BUFFERTIMEHIGH: stats->DVPET_BUFFERTIMEHIGH += incdec; break; default: D_BUG( "unknown video provider event type 0x%08x\n", event->videoprovider.type ); } break; case DFEC_UNIVERSAL: stats->DFEC_UNIVERSAL += incdec; break; default: D_BUG( "unknown event class 0x%08x\n", event->clazz ); } }