Hello, here are:

1)
patch (against CVS) for adding shaped window support for colokeyed windows,
seems to work :-)

2) 
patch (against CVS) to avoid additional threads, i used it for some time and 
it looks stable.
The master works the old way.

I fixed also the master and slave code in order to be (almost) safe against 
"pthread_cancel" during WaitForEvent(WithTimeout).
I say "almost" because it is not safe when a thread is pthread_cancel'ed at 
the very beginning of WaitForEvent(WithTimeout), but you have to be quite 
unlucky :-)

I have also seen the addition in cvs of the WakeUp method in EventBuffer, and 
i implemented it for the thread that is "selecting" /dev/fusion with a 
SIGCONT signal that terminates the "select".
I did not know wich signal to use, i decided SIGCONT because it is very little 
used. If you don't like it, just change the SIG_AWAKE macro

3)
a couple of programs to test shaped windows, pthread_cancels and
WakeUps

Please test and let me know if it works for you :-)

                                         Ciao
                                         Maurizio
Index: DirectFB/src/core/windows.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/windows.c,v
retrieving revision 1.160
diff -u -r1.160 windows.c
--- DirectFB/src/core/windows.c	28 Jul 2003 14:21:52 -0000	1.160
+++ DirectFB/src/core/windows.c	3 Aug 2003 12:38:07 -0000
@@ -1671,63 +1671,125 @@
                int wx = x - w->x;
                int wy = y - w->y;
 
-               if (((w->options & (DWOP_ALPHACHANNEL|DWOP_SHAPED)) != 
-                    (DWOP_ALPHACHANNEL|DWOP_SHAPED)) || !w->surface ||
-                   ((w->options & DWOP_OPAQUE_REGION) &&
-                    (wx >= w->opaque.x1  &&  wx <= w->opaque.x2 &&
-                     wy >= w->opaque.y1  &&  wy <= w->opaque.y2)))
+               if ( !(w->options & DWOP_SHAPED)  ||
+                        !(w->options &(DWOP_ALPHACHANNEL|DWOP_COLORKEYING))
+                        || !w->surface ||
+                        ((w->options & DWOP_OPAQUE_REGION) &&
+                        (wx >= w->opaque.x1  &&  wx <= w->opaque.x2 &&
+                        wy >= w->opaque.y1  &&  wy <= w->opaque.y2)))
                {
                     return w;
                }
-               else {
+               else
+               {
                     void        *data;
                     int          pitch;
                     CoreSurface *surface = w->surface;
 
-                    if (DFB_PIXELFORMAT_HAS_ALPHA( surface->format ) &&
-                        dfb_surface_soft_lock( surface, DSLF_READ,
-                                               &data, &pitch, true ) == DFB_OK)
+                    if( dfb_surface_soft_lock( surface, DSLF_READ,
+                                               &data, &pitch, true ) == DFB_OK )
                     {
-                         int alpha = -1;
+                        if(w->options & DWOP_ALPHACHANNEL)
+                        {
+                            int alpha = -1;
+                            
+                            DFB_ASSERT( DFB_PIXELFORMAT_HAS_ALPHA( surface->format ) );
+                            
+                            switch (surface->format) 
+                            {
+                                case DSPF_ARGB:
+                                    alpha = *(__u32*)(data +
+                                                        4 * wx + pitch * wy) >> 24;
+                                    break;
+                                case DSPF_ARGB1555:
+                                    alpha = *(__u16*)(data + 2 * wx +
+                                                        pitch * wy) & 0x8000;
+                                    alpha = alpha ? 0xff : 0x00;
+                                    break;
+                                case DSPF_ALUT44:
+                                    alpha = *(__u8*)(data +
+                                                        wx + pitch * wy) & 0xf0;
+                                    alpha |= alpha >> 4;
+                                    break;
+                                case DSPF_LUT8: {
+                                    CorePalette *palette = surface->palette;
+                                    __u8         pix     = *((__u8*) data + wx +
+                                                                pitch * wy);
+
+                                    if (palette && pix < palette->num_entries) {
+                                            alpha = palette->entries[pix].a;
+                                            break;
+                                    }
+
+                                    /* fall through */
+                                }
+
+                                default:
+                                    break;
+                            }
 
-                         switch (surface->format) {
-                              case DSPF_ARGB:
-                                   alpha = *(__u32*)(data +
-                                                     4 * wx + pitch * wy) >> 24;
-                                   break;
-                              case DSPF_ARGB1555:
-                                   alpha = *(__u16*)(data + 2 * wx +
-                                                     pitch * wy) & 0x8000;
-                                   alpha = alpha ? 0xff : 0x00;
-                                   break;
-                              case DSPF_ALUT44:
-                                   alpha = *(__u8*)(data +
-                                                    wx + pitch * wy) & 0xf0;
-                                   alpha |= alpha >> 4;
-                                   break;
-                              case DSPF_LUT8: {
-                                   CorePalette *palette = surface->palette;
-                                   __u8         pix     = *((__u8*) data + wx +
-                                                            pitch * wy);
-                                   
-                                   if (palette && pix < palette->num_entries) {
-                                        alpha = palette->entries[pix].a;
-                                        break;
-                                   }
-                                   
-                                   /* fall through */
-                              }
-
-                              default:
-                                   break;
-                         }
-
-                         if (alpha) { /* alpha == -1 on error */
-                              dfb_surface_unlock( surface, true );
-                              return w;
-                         }
+                            if (alpha) /* alpha == -1 on error */
+                            { 
+                                dfb_surface_unlock( surface, true );
+                                return w;
+                            }
 
-                         dfb_surface_unlock( surface, true );
+                        }
+                        if(w->options & DWOP_COLORKEYING)
+                        {
+                            int pixel = 0;
+                            
+                            switch (surface->format) 
+                            {
+                                case DSPF_ARGB:
+                                case DSPF_RGB32:
+                                    pixel = *(__u32*)(data +
+                                                        4 * wx + pitch * wy)
+                                                        & 0x00ffffff;
+                                    break;
+                                    
+                                case DSPF_RGB24:   //endianess? boh...
+                                    pixel = (*(__u32*)(data +
+                                                        3 * wx + pitch * wy))
+                                                        & 0x00ffffff;
+                                    break;
+                                    
+                                case DSPF_RGB16:
+                                    pixel = *(__u16*)(data + 2 * wx +
+                                                        pitch * wy);
+                                    break;
+                                    
+                                case DSPF_ARGB1555:
+                                    pixel = *(__u16*)(data + 2 * wx +
+                                                        pitch * wy)
+                                                        & 0x7fff;
+                                    break;
+                                    
+                                case DSPF_RGB332:
+                                case DSPF_LUT8:
+                                    pixel = *(__u8*)(data +
+                                                        wx + pitch * wy);
+                                    break;
+                                    
+                                case DSPF_ALUT44:
+                                    pixel = *(__u8*)(data +
+                                                        wx + pitch * wy)
+                                                        & 0x0f;
+                                    break;
+                                    
+                                default:
+                                    break;
+                            }
+                            
+                            if ( pixel != w->color_key ) 
+                            { 
+                                dfb_surface_unlock( surface, true );
+                                return w;
+                            }
+                        
+                        }
+                        
+                        dfb_surface_unlock( surface, true );
                     }
                }
           }
Index: DirectFB/include/directfb.h
===================================================================
RCS file: /cvs/directfb/DirectFB/include/directfb.h,v
retrieving revision 1.186
diff -u -r1.186 directfb.h
--- DirectFB/include/directfb.h	2 Aug 2003 19:35:40 -0000	1.186
+++ DirectFB/include/directfb.h	3 Aug 2003 12:38:21 -0000
@@ -2989,8 +2989,9 @@
                                            window's alpha channel */
      DWOP_OPAQUE_REGION  = 0x00000004,  /* overrides DWOP_ALPHACHANNEL for the
                                            region set by SetOpaqueRegion() */
-     DWOP_SHAPED         = 0x00000008,  /* Do not send events if alpha==0, can
-                                           be used with DWOP_ALPHACHANNEL */
+     DWOP_SHAPED         = 0x00000008,  /* window doesn't receive mouse events for 
+                                           invisible regions, must be used with 
+                                           DWOP_ALPHACHANNEL or DWOP_COLORKEYING */
      DWOP_KEEP_POSITION  = 0x00000010,  /* window can't be moved
                                            with the mouse */
      DWOP_KEEP_SIZE      = 0x00000020,  /* window can't be resized
Index: DirectFB/src/core/fusion/fusion.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/fusion/fusion.c,v
retrieving revision 1.41
diff -u -r1.41 fusion.c
--- DirectFB/src/core/fusion/fusion.c	9 Jul 2003 15:43:08 -0000	1.41
+++ DirectFB/src/core/fusion/fusion.c	3 Aug 2003 13:15:16 -0000
@@ -67,13 +67,14 @@
 int           _fusion_fd    = -1;
 FusionShared *_fusion_shared = NULL;
 
-static CoreThread *read_loop;
+static CoreThread *read_loop = NULL;
 
 /****************
  *  Public API  *
  ****************/
 
 int _fusion_id = 0;  /* non-zero if Fusion is initialized */
+int dfb_is_master = 0;
 
 int
 fusion_init( int world, int *world_ret )
@@ -148,12 +149,13 @@
           fusion_skirmish_init( &_fusion_shared->arenas_lock );
 
           gettimeofday( &_fusion_shared->start_time, NULL );
+          
+          dfb_is_master = 1;
+          read_loop = dfb_thread_create( CTT_MESSAGING, fusion_read_loop, NULL );
      }
      else
           _fusion_shared = __shmalloc_get_root();
 
-     read_loop = dfb_thread_create( CTT_MESSAGING, fusion_read_loop, NULL );
-
      if (world_ret)
           *world_ret = world;
 
@@ -186,8 +188,11 @@
      }
 
      /* Wait for its termination. */
+     if(dfb_is_master && read_loop)
+     {
      dfb_thread_join( read_loop );
      dfb_thread_destroy( read_loop );
+     }
 
      /* Master has to deinitialize shared data. */
      if (_fusion_id == 1) {
@@ -252,9 +257,9 @@
             (tv.tv_usec - _fusion_shared->start_time.tv_usec) / 1000;
 }
 
-/*****************************
- *  File internal functions  *
- *****************************/
+/*
+ *  File internal functions (keep this for master use only)
+ */
 
 static void *
 fusion_read_loop( CoreThread *thread, void *arg )
@@ -288,7 +293,7 @@
                switch (header->msg_type) {
                     case FMT_SEND:
                          if (!fusion_refs)
-                              return NULL;
+                              return NULL;;
                          break;
                     case FMT_CALL:
                          _fusion_call_process( header->msg_id, data );
@@ -309,6 +314,97 @@
      FPERROR( "reading from fusion device failed\n" );
 
      return NULL;
+}
+
+/*
+ * functions to implement slave polling
+ */
+
+void
+fusion_read_pending( )
+{
+     int    len = 0;
+     char   buf[1024];
+     char  *buf_p = buf;
+
+     len = read (_fusion_fd, buf, 1024);
+     
+     buf_p = buf;   
+     while (buf_p < buf + len) 
+     {
+          FusionReadMessage *header = (FusionReadMessage*) buf_p;
+          void              *data   = buf_p + sizeof(FusionReadMessage);
+
+          switch (header->msg_type) {
+               case FMT_SEND:
+                    if (!fusion_refs)
+                         return;
+                    break;
+               case FMT_CALL:
+                    _fusion_call_process( header->msg_id, data );
+                    break;
+               case FMT_REACTOR:
+                    _fusion_reactor_process_message( header->msg_id, data );
+                    break;
+               default:
+                    FDEBUG( "discarding message of unknown type '%d'\n",
+                         header->msg_type );
+                    break;
+          }
+
+          buf_p = data + header->msg_size;
+     }
+     return;
+}
+
+
+void 
+fusion_read_iteration( )
+{
+     int    result;
+     fd_set set;
+
+     FD_ZERO(&set);
+     FD_SET(_fusion_fd,&set);
+
+     result = select (_fusion_fd+1, &set, NULL, NULL, NULL);
+     
+     if (result <= 0)
+          FPERROR( "reading from fusion device failed\n" );
+}
+
+//return 1 on timeout reached
+int 
+fusion_read_iteration_timeout( struct timeval tv )
+{
+     int    result;
+     fd_set set;
+     struct timeval now;
+
+     FD_ZERO(&set);
+     FD_SET(_fusion_fd,&set);
+     
+     gettimeofday( &now, NULL );
+     tv.tv_sec  -= now.tv_sec;
+     tv.tv_usec -= now.tv_usec;
+   
+     if(tv.tv_usec<0)
+     {
+          tv.tv_usec += 1000000;
+          tv.tv_sec  -= 1;
+     }
+   
+     if(tv.tv_sec<0)
+          return 1;
+
+     result = select (_fusion_fd+1, &set, NULL, NULL, &tv);
+     
+     if (result < 0)
+          FPERROR( "reading from fusion device failed\n" ); //error
+     else if(result == 0)
+          return 1;
+
+     return 0;
 }
 
 #else
Index: DirectFB/src/core/fusion/fusion.h
===================================================================
RCS file: /cvs/directfb/DirectFB/src/core/fusion/fusion.h,v
retrieving revision 1.8
diff -u -r1.8 fusion.h
--- DirectFB/src/core/fusion/fusion.h	7 Jul 2003 17:25:36 -0000	1.8
+++ DirectFB/src/core/fusion/fusion.h	3 Aug 2003 13:15:17 -0000
@@ -60,6 +60,13 @@
  */
 long long fusion_get_millis();
 
+/*
+     to implement slave polling
+*/
+void fusion_read_pending( );
+void fusion_read_iteration( );
+int fusion_read_iteration_timeout( struct timeval );
+
 
 #ifdef __cplusplus
 }
Index: DirectFB/src/input/idirectfbinputbuffer.c
===================================================================
RCS file: /cvs/directfb/DirectFB/src/input/idirectfbinputbuffer.c,v
retrieving revision 1.38
diff -u -r1.38 idirectfbinputbuffer.c
--- DirectFB/src/input/idirectfbinputbuffer.c	2 Aug 2003 19:35:40 -0000	1.38
+++ DirectFB/src/input/idirectfbinputbuffer.c	3 Aug 2003 13:15:21 -0000
@@ -37,6 +37,7 @@
 
 #include <core/fusion/reactor.h>
 #include <core/fusion/list.h>
+#include <core/fusion/fusion.h>
 
 #include <directfb.h>
 #include <directfb_internals.h>
@@ -93,9 +94,105 @@
 
      pthread_cond_t                wait_condition;/* condition used for idle
                                                      wait in WaitForEvent() */
+                                                     
+     int                           interrupted;   /* signal interruption */
 } IDirectFBEventBuffer_data;
 
 /*
+ *  Structures and functions to know about
+ *  thread that are in pthread_cond_wait
+ *  and could be awaken to select /dev/fusion
+ */
+
+typedef struct _waiting_thread
+{
+     struct _waiting_thread *next;
+     pthread_cond_t *cond;   //to awake the thread...
+     pthread_mutex_t *mutex;
+}waiting_thread;
+                                             
+static waiting_thread *waiting_threads_list = NULL; 
+static pthread_mutex_t fusion_lock;
+static pthread_mutex_t wtlist_lock;
+static int mutexes_init = 0;
+static pid_t fusion_pid = 0;
+static IDirectFBEventBuffer_data *fusion_data = NULL;
+extern int dfb_is_master;
+
+/*
+ *  function to handle the list of waiting threads
+ */
+
+static waiting_thread *
+put_in_waiting_thread_list( pthread_cond_t *cond, pthread_mutex_t *mtx)
+{
+     waiting_thread *newitem = (waiting_thread*)malloc(sizeof(waiting_thread));
+     pthread_mutex_lock( &wtlist_lock );
+     newitem->cond = cond;
+     newitem->mutex = mtx;     
+     newitem->next = waiting_threads_list; 
+     waiting_threads_list = newitem;       
+     pthread_mutex_unlock( &wtlist_lock );   
+
+     return newitem;
+}
+
+static void 
+take_from_waiting_thread_list(waiting_thread *item)
+{
+     waiting_thread **tmp;
+     pthread_mutex_lock( &wtlist_lock );
+     tmp = &waiting_threads_list;
+     while(*tmp)
+     {
+          if(*tmp == item)
+          {
+               *tmp = (*tmp)->next;
+               break;
+          }   
+          tmp = &((*tmp)->next);  
+     }
+     free(item);
+     pthread_mutex_unlock( &wtlist_lock ); 
+}
+
+//check if waiting_thread points to something died...
+static void 
+waiting_thread_wake()
+{
+     pthread_mutex_lock( &wtlist_lock );
+     if(waiting_threads_list)
+          pthread_cond_broadcast( waiting_threads_list->cond );
+     pthread_mutex_unlock( &wtlist_lock ); 
+}
+
+/*
+  cleanups for thread if pthread_cancel'ed
+*/
+static void 
+selector_cleanup(void* ign)
+{
+     pthread_mutex_unlock( &fusion_lock ); 
+     fusion_pid = 0;
+     waiting_thread_wake();
+}
+
+static void waiter_cleanup(void* it)
+{
+     waiting_thread *item = it;
+     pthread_mutex_unlock( item->mutex );     
+     take_from_waiting_thread_list(item);
+}
+
+/*
+     sighandler to enable wakeup of who is selecting /dev/fusion
+*/
+#define SIG_AWAKE SIGCONT
+static void dummy(int g)
+{
+}
+
+/*
  * adds an event to the event queue
  */
 static void IDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data,
@@ -108,7 +205,6 @@
                                                         void       *ctx );
 
 
-
 static void
 IDirectFBEventBuffer_Destruct( IDirectFBEventBuffer *thiz )
 {
@@ -190,13 +286,264 @@
      return DFB_OK;
 }
 
+/*
+ * this functions are implemented separatley for master and slave
+ */
+
 static DFBResult
-IDirectFBEventBuffer_WaitForEvent( IDirectFBEventBuffer *thiz )
+IDirectFBEventBuffer_WaitForEvent_slave( 
+                              IDirectFBEventBuffer *thiz )
+{
+     INTERFACE_GET_DATA(IDirectFBEventBuffer)    
+
+     if(data->events)
+          return DFB_OK;
+     data->interrupted = 0;
+         
+     //someone else is selecting
+     if(pthread_mutex_trylock( &fusion_lock )!=0) 
+     {
+          waiting_thread *me;
+          
+          //please let me know if you go away...
+          me = put_in_waiting_thread_list(&(data->wait_condition),
+               &(data->events_mutex));  
+          
+          do
+          {                   
+               //let me know if you go away *OR* there is something for me.               
+               pthread_cleanup_push(waiter_cleanup,me);
+               pthread_mutex_lock( &data->events_mutex );
+                
+               pthread_cond_wait( &data->wait_condition, 
+                                   &data->events_mutex );
+                    
+               pthread_mutex_unlock( &data->events_mutex ); 
+               pthread_cleanup_pop(0);
+                              
+               //there is really something for me!
+               if(data->events||data->interrupted)
+               {
+                    //clenup signal condition
+                    take_from_waiting_thread_list(me);
+                    
+                    //before going away, it may happen that
+                    //i (b) was awaken by (a) to select **AND**
+                    //there are messages for me, so if i 
+                    //return immediatly (c) could fuck up...
+                    if(waiting_threads_list &&
+                         pthread_mutex_trylock( &fusion_lock )==0)
+                    {
+                         //so lets awake (c) :-)
+                         pthread_mutex_unlock( &fusion_lock );      
+                         waiting_thread_wake();
+                    } 
+
+                    return (data->interrupted) ? DFB_INTERRUPTED : DFB_OK;                        
+               }
+               else
+               {     
+                    if(pthread_mutex_trylock( &fusion_lock )==0)
+                         break; 
+                         
+                    //d'oh, i was awaken and a brother quicker then me
+                    //got the mutex ... -> continue waiting,   
+                    //or congrats to the selector thread for being so fast 
+                    //to process events and select before i could react! 
+               }
+               
+          }
+          while(1);
+          
+          //cleanup signal condition
+          take_from_waiting_thread_list(me);
+     }
+     
+     //if i die someone will remember me :-)
+     pthread_cleanup_push(selector_cleanup,NULL);
+     fusion_data = data;
+          
+     //select main loop
+     do
+     {       
+          fusion_read_pending( ); 
+           
+          if(data->events || data->interrupted)
+               break;
+               
+          signal(SIG_AWAKE,dummy);
+          fusion_pid = getpid( );
+          fusion_read_iteration( ); 
+          fusion_pid = 0;
+          signal(SIG_AWAKE,SIG_DFL);
+     }
+     while (1);
+     
+     pthread_mutex_unlock( &fusion_lock );
+     pthread_cleanup_pop(0);
+
+     //i go away, someone else has to be awaken, maybe...
+     waiting_thread_wake();
+
+     return (data->interrupted) ? DFB_INTERRUPTED : DFB_OK;
+}
+
+static DFBResult
+IDirectFBEventBuffer_WaitForEventWithTimeout_slave( 
+                    IDirectFBEventBuffer *thiz,
+                    unsigned int          seconds,
+                    unsigned int          milli_seconds )
+{     
+     DFBResult retval = DFB_OK;
+     struct timeval tv;
+     struct timespec ts;
+     INTERFACE_GET_DATA(IDirectFBEventBuffer)    
+
+     if(data->events)
+          return DFB_OK;
+     data->interrupted = 0;
+         
+     gettimeofday(&tv,NULL);
+     tv.tv_sec += seconds;
+     tv.tv_usec += milli_seconds * 1000;
+     if(tv.tv_usec>=1000)
+     {
+          tv.tv_sec += 1;
+          tv.tv_sec -= 1000;
+     }
+     ts.tv_sec = tv.tv_sec;
+     ts.tv_nsec = tv.tv_usec * 1000;
+          
+     //someone else is selecting
+     if(pthread_mutex_trylock( &fusion_lock )!=0) 
+     {
+          waiting_thread *me;
+          
+          //please let me know if you go away...
+          me = put_in_waiting_thread_list(&(data->wait_condition),
+               &(data->events_mutex));  
+          
+          do
+          {                   
+               //let me know if you go away *OR* there is something for me.               
+               pthread_cleanup_push(waiter_cleanup,me);
+               pthread_mutex_lock( &data->events_mutex );
+                
+               if(pthread_cond_timedwait( &data->wait_condition, 
+                                   &data->events_mutex, &ts ))
+                    retval = DFB_TIMEOUT;
+                                   
+               pthread_mutex_unlock( &data->events_mutex ); 
+               pthread_cleanup_pop(0);
+                              
+               //there is really something for me! (or just a timeout)
+               if( data->events || data->interrupted || retval == DFB_TIMEOUT)
+               {
+                    //clenup signal condition
+                    take_from_waiting_thread_list(me);
+                    
+                    //before going away, it may happen that
+                    //i (b) was awaken by (a) to select **AND**
+                    //there are messages for me, so if i 
+                    //return immediatly (c) could fuck up...
+                    if(waiting_threads_list &&
+                         pthread_mutex_trylock( &fusion_lock )==0)
+                    {
+                         //so lets awake (c) :-)
+                         pthread_mutex_unlock( &fusion_lock );      
+                         waiting_thread_wake();
+                    } 
+
+
+                    return (data->interrupted) ? DFB_INTERRUPTED : retval; 
+               }
+               else
+               {     
+                    if(pthread_mutex_trylock( &fusion_lock )==0)
+                         break; 
+                         
+                    //d'oh, i was awaken and a brother quicker then me
+                    //got the 35/*mutex 35/*... -> continue waiting   
+                    //or congrats to the selector for being so fast 
+                    //to process events! 
+               }
+               
+          }
+          while(1);
+          
+          //cleanup signal condition
+          take_from_waiting_thread_list(me);
+     }
+     
+     //if i die someone will remember me :-)
+     pthread_cleanup_push(selector_cleanup,NULL);
+     fusion_data = data;
+          
+     //select mainfusion_pid loop
+     do
+     {       
+          fusion_read_pending(); 
+           
+          if(data->events || data->interrupted)
+               break;
+                         
+          signal(SIG_AWAKE,dummy);
+          fusion_pid = getpid( );
+          if(fusion_read_iteration_timeout( tv ));
+          {
+               fusion_pid = 0;
+               signal(SIG_AWAKE,SIG_DFL);
+               retval = DFB_TIMEOUT;
+               break;
+          }
+          fusion_pid = 0;
+          signal(SIG_AWAKE,SIG_DFL);
+     }
+     while (1);
+     
+     pthread_mutex_unlock( &fusion_lock );
+     pthread_cleanup_pop(0);
+
+     //i go away, someone else has to be awaken, maybe...
+     waiting_thread_wake();
+
+     return DFB_OK;
+}
+
+static DFBResult
+IDirectFBEventBuffer_HasEvent_slave( IDirectFBEventBuffer *thiz )
+{
+     INTERFACE_GET_DATA(IDirectFBEventBuffer)
+
+     //noone else is reading for us...              
+     pthread_cleanup_push( (void(*)(void*))pthread_mutex_unlock ,
+                    (void*)&fusion_lock );
+     
+     if(pthread_mutex_trylock( &fusion_lock )==0)
+     {
+          fusion_read_pending();
+          pthread_mutex_unlock( &fusion_lock );
+     }
+      
+     pthread_cleanup_pop(0);
+     
+     return (data->events ? DFB_OK : DFB_BUFFEREMPTY);
+}
+
+/*
+ * keep the old functions to make work the master
+ */
+ 
+ static DFBResult
+IDirectFBEventBuffer_WaitForEvent_master( 
+                              IDirectFBEventBuffer *thiz )
 {
      DFBResult ret = DFB_OK;
 
      INTERFACE_GET_DATA(IDirectFBEventBuffer)
 
+     pthread_cleanup_push( (void(*)(void*))pthread_mutex_unlock,
+                         (void*)&(data->events_mutex) );     
      pthread_mutex_lock( &data->events_mutex );
 
      if (!data->events)
@@ -204,13 +551,15 @@
      if (!data->events)
           ret = DFB_INTERRUPTED;
 
-     pthread_mutex_unlock( &data->events_mutex );
+     pthread_mutex_unlock( &data->events_mutex );     
+     pthread_cleanup_pop(0);
 
      return ret;
 }
 
 static DFBResult
-IDirectFBEventBuffer_WaitForEventWithTimeout( IDirectFBEventBuffer *thiz,
+IDirectFBEventBuffer_WaitForEventWithTimeout_master( 
+                              IDirectFBEventBuffer *thiz,
                                               unsigned int          seconds,
                                               unsigned int          milli_seconds )
 {
@@ -218,48 +567,70 @@
      struct timespec timeout;
      DFBResult       ret    = DFB_OK;
      int             locked = 0;
+     int             hasevents = 0;
      long int        nano_seconds = milli_seconds * 1000000;
 
      INTERFACE_GET_DATA(IDirectFBEventBuffer)
 
+     pthread_cleanup_push( (void(*)(void*))pthread_mutex_unlock,
+                         (void*)&(data->events_mutex));   
+     
      if (pthread_mutex_trylock( &data->events_mutex ) == 0) {
-          if (data->events) {
-               pthread_mutex_unlock ( &data->events_mutex );
-               return ret;
-          }
+          if (data->events) 
+               hasevents = 1;
           locked = 1;
      }
 
-     gettimeofday( &now, NULL );
-
-     timeout.tv_sec  = now.tv_sec + seconds;
-     timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds;
-
-     timeout.tv_sec  += timeout.tv_nsec / 1000000000;
-     timeout.tv_nsec %= 1000000000;
-
-     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;
+     if(!hasevents)
+     {
+          gettimeofday( &now, NULL );
+
+          timeout.tv_sec  = now.tv_sec + seconds;
+          timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds;
+
+          timeout.tv_sec  += timeout.tv_nsec / 1000000000;
+          timeout.tv_nsec %= 1000000000;
+
+          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 );
+     
+     pthread_mutex_unlock( &data->events_mutex );    
+     pthread_cleanup_pop(0);
 
      return ret;
 }
 
 static DFBResult
+IDirectFBEventBuffer_HasEvent_master( 
+                              IDirectFBEventBuffer *thiz )
+{
+     INTERFACE_GET_DATA(IDirectFBEventBuffer)
+
+     return (data->events ? DFB_OK : DFB_BUFFEREMPTY);
+}
+ 
+/*
+ * end master functions
+ */
+
+static DFBResult
 IDirectFBEventBuffer_WakeUp( IDirectFBEventBuffer *thiz )
 {
      INTERFACE_GET_DATA(IDirectFBEventBuffer)
 
+     data->interrupted = 1;   //has no meaning for the master :-)
+     if(fusion_pid && fusion_data == data)
+          kill(fusion_pid,SIG_AWAKE);
      pthread_cond_broadcast( &data->wait_condition );
      
      return DFB_OK;
@@ -343,14 +714,6 @@
 }
 
 static DFBResult
-IDirectFBEventBuffer_HasEvent( IDirectFBEventBuffer *thiz )
-{
-     INTERFACE_GET_DATA(IDirectFBEventBuffer)
-
-     return (data->events ? DFB_OK : DFB_BUFFEREMPTY);
-}
-
-static DFBResult
 IDirectFBEventBuffer_PostEvent( IDirectFBEventBuffer *thiz,
                                 DFBEvent             *event )
 {
@@ -382,19 +745,44 @@
      data->filter     = filter;
      data->filter_ctx = filter_ctx;
 
+     if(dfb_is_master && mutexes_init==0) //if master skip mutex
+          mutexes_init++;
+     if(mutexes_init==0)
+     {          
+          pthread_mutex_init( &fusion_lock, NULL );
+          pthread_mutex_init( &wtlist_lock, NULL ); 
+     }
+     mutexes_init++;
+     
      pthread_mutex_init( &data->events_mutex, NULL );
      pthread_cond_init( &data->wait_condition, NULL );
-
-     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;
+     
+     if(dfb_is_master)
+     {
+          thiz->WaitForEvent = 
+               IDirectFBEventBuffer_WaitForEvent_master;
+          thiz->WaitForEventWithTimeout =
+               IDirectFBEventBuffer_WaitForEventWithTimeout_master;
+          thiz->HasEvent = 
+               IDirectFBEventBuffer_HasEvent_master;
+     }
+     else
+     {
+          thiz->WaitForEvent = 
+               IDirectFBEventBuffer_WaitForEvent_slave;
+          thiz->WaitForEventWithTimeout =
+               IDirectFBEventBuffer_WaitForEventWithTimeout_slave;
+          thiz->HasEvent = 
+               IDirectFBEventBuffer_HasEvent_slave;
+     }
+     
+     thiz->AddRef = IDirectFBEventBuffer_AddRef;
+     thiz->Release = IDirectFBEventBuffer_Release;
+     thiz->Reset = IDirectFBEventBuffer_Reset;
+     thiz->GetEvent  = IDirectFBEventBuffer_GetEvent;
+     thiz->PeekEvent = IDirectFBEventBuffer_PeekEvent;
+     thiz->PostEvent = IDirectFBEventBuffer_PostEvent;
+     thiz->WakeUp    = IDirectFBEventBuffer_WakeUp;
 
      return DFB_OK;
 }
#include <directfb.h>
#include <pthread.h>
#include <signal.h>

IDirectFB *d;
IDirectFBDisplayLayer *l;
IDirectFBWindow *w1;
IDirectFBWindow *w2;
IDirectFBWindow *w3;
IDirectFBSurface *s1;
IDirectFBSurface *s2;
IDirectFBSurface *s3;
IDirectFBEventBuffer *e1;
IDirectFBEventBuffer *e2;
IDirectFBEventBuffer *e3;
pthread_t dummy;

void * illkillyou(void *a)
{
	while(1)
	{
	char k;
	scanf("%c",&k);
	if(k=='k')
		{
		printf("killing brother :-)\n");
		printf("i wish you a bloody continue, ha ha ha...\n");
		pthread_cancel(dummy);
		}
	}
}

void * async_shit(void *a)
{
     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
     printf("child pid %d\n",getpid());
     while(2)
     {
          DFBWindowEvent ev;
          e2->WaitForEvent( e2 );
          e2->GetEvent( e2, DFB_EVENT(&ev) );
          if(ev.type == DWET_MOTION)
          {
               DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
               s2->FillRectangle(s2,ev.x-5,ev.y-5,10,10); 
               s2->Flip(s2,&r,0);
          }
     }
};

void * async_shit3(void *a)
{
     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
     printf("child pid %d\n",getpid());
     while(3)
     {
          DFBWindowEvent ev;
          e3->WaitForEvent( e3 );
          e3->GetEvent( e3, DFB_EVENT(&ev) );
          if(ev.type == DWET_MOTION)
          {
               DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
               s3->FillRectangle(s3,ev.x-5,ev.y-5,10,10); 
               s3->Flip(s3,&r,0);
          }
     }
};

#define TRE

int main(int argc,char *argv[])
{
	int i;
	DirectFBInit(&argc,&argv);
	DirectFBCreate(&d);
	d->GetDisplayLayer(d, DLID_PRIMARY, &l );

	{
        DFBWindowDescription desc;
        desc.flags= (DFBWindowDescriptionFlags)
	            (DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|
	            DWDESC_POSX|DWDESC_POSY|DWDESC_PIXELFORMAT);
	desc.caps = DWCAPS_ALPHACHANNEL;
	desc.pixelformat = DSPF_ARGB;
	desc.posx = 40;
	desc.posy = 40;
	desc.height = 300;
	desc.width = 300;
	l->CreateWindow( l, &desc, &w1 );
	desc.posx = 100;
	desc.posy = 300;
	l->CreateWindow( l, &desc, &w2 );
#ifdef TRE
	desc.posx = 300;
	desc.posy = 100;
	l->CreateWindow( l, &desc, &w3 );
#endif
	}
	w1->SetOpacity( w1, 0xff );
	w1->GetSurface( w1, &s1 );    
	w1->SetOptions(w1,DWOP_ALPHACHANNEL|DWOP_SHAPED);
     w1->CreateEventBuffer( w1, &e1 );
     s1->Clear(s1,0xff,0xff,0xff,0xff);
     s1->SetColor(s1,0,0,0,0);
     s1->FillRectangle(s1,100,0,150,250);
     s1->SetColor(s1,0,0,0,0xff);
     s1->Flip(s1,0,0);
	w2->SetOpacity( w2, 0xff );
	w2->GetSurface( w2, &s2 );     
	w2->SetOptions(w2,DWOP_NONE);
     w2->CreateEventBuffer( w2, &e2 );
     s2->Clear(s2,0,0xff,0xff,0);
     s2->SetColor(s2,0xff,0,0,0);
     s2->Flip(s2,0,0);
#ifdef TRE
	w3->SetOpacity( w3, 0xff );
	w3->GetSurface( w3, &s3 );     
	w3->SetOptions(w3,DWOP_COLORKEYING|DWOP_SHAPED);
	w3->SetColorKey(w3,6,6,6);
     w3->CreateEventBuffer( w3, &e3 );
     s3->Clear(s3,6,6,6,7);
     s3->SetColor(s3,0xff,0xff,0,0xff);
     s3->FillTriangle(s3,300,0,0,150,300,300);
     s3->SetColor(s3,0xff,0,0xff,0);
     s3->Flip(s3,0,0);
#endif
     
     pthread_create(&dummy,NULL,illkillyou,NULL);
#ifdef TRE
     pthread_create(&dummy,NULL,async_shit3,NULL);
#endif
     pthread_create(&dummy,NULL,async_shit,NULL);
    
     printf("write k<enter> to murder a thread\n");
     
     while(1)
     {
          DFBWindowEvent ev;
          e1->WaitForEvent( e1 );
          e1->GetEvent( e1, DFB_EVENT(&ev) );
          if(ev.type == DWET_MOTION)
          {
               DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
               s1->FillRectangle(s1,ev.x-5,ev.y-5,10,10); 
               s1->Flip(s1,&r,0);
          }
     }
	return 0;
}
#include <directfb.h>
#include <pthread.h>
#include <signal.h>

IDirectFB *d;
IDirectFBDisplayLayer *l;
IDirectFBWindow *w1;
IDirectFBWindow *w2;
IDirectFBWindow *w3;
IDirectFBSurface *s1;
IDirectFBSurface *s2;
IDirectFBSurface *s3;
IDirectFBEventBuffer *e1;
IDirectFBEventBuffer *e2;
IDirectFBEventBuffer *e3;
pthread_t dummy;

void * illkillyou(void *a)
{
	while(1)
	{
	char k;
	scanf("%c",&k);
	if(k=='k')
		{
		printf("awaking brother :-)\n");
		printf("it is so sleepy, d'oh...\n");
		e1->WakeUp(e1);
		}
	}
}

int main(int argc,char *argv[])
{
	int i;
	DirectFBInit(&argc,&argv);
	DirectFBCreate(&d);
	d->GetDisplayLayer(d, DLID_PRIMARY, &l );

	{
        DFBWindowDescription desc;
        desc.flags= (DFBWindowDescriptionFlags)
	            (DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_CAPS|
	            DWDESC_POSX|DWDESC_POSY|DWDESC_PIXELFORMAT);
	desc.pixelformat = DSPF_ARGB;
	desc.caps = DWCAPS_ALPHACHANNEL;
	desc.posx = 40;
	desc.posy = 40;
	desc.height = 300;
	desc.width = 300;
	l->CreateWindow( l, &desc, &w1 );
	}
	w1->SetOpacity( w1, 0xff);
     w1->CreateEventBuffer( w1, &e1 );
     w1->SetOptions(w1,DWOP_ALPHACHANNEL|DWOP_SHAPED);
     w1->GetSurface( w1, &s1 );    
     s1->Clear(s1,0xff,0xff,0xff,0xff);
     s1->SetColor(s1,0,0,0,0);
     s1->FillRectangle(s1,100,0,100,250);
     s1->SetColor(s1,0xff,0x80,0,0xff);
     s1->Flip(s1,0,0);
	
     
     pthread_create(&dummy,NULL,illkillyou,NULL);
    
     printf("write k<enter> to wakeup the buffer\n");
     
     while(1)
     {
          DFBWindowEvent ev;
          DFBResult e;
          e = e1->WaitForEvent( e1 );
          if(e==DFB_INTERRUPTED)
               printf("awaken :-)\n");
          else
          {
               e1->GetEvent( e1, DFB_EVENT(&ev) );
               if(ev.type == DWET_MOTION)
               {
                    DFBRegion r = {ev.x-5,ev.y-5,ev.x+5,ev.y+5};
                    s1->FillRectangle(s1,ev.x-5,ev.y-5,10,10); 
                    s1->Flip(s1,&r,0);
               }
          }
     }
	return 0;
}

Reply via email to