]> Pileus Git - ~andy/gtk/blobdiff - gdk/directfb/gdkwindow-directfb.c
Replace a lot of idle and timeout calls by the new gdk_threads api.
[~andy/gtk] / gdk / directfb / gdkwindow-directfb.c
index ebf106df19c6b8a3bcd19fc64a522903fa036bb0..0a683de033157b9e5a684354a5e509ae82905ee6 100644 (file)
@@ -44,6 +44,7 @@
 #include "gdkinternals.h"
 #include "gdkalias.h"
 #include "cairo.h"
+#include <assert.h>
 
 static GdkRegion * gdk_window_impl_directfb_get_visible_region (GdkDrawable *drawable);
 static void        gdk_window_impl_directfb_set_colormap       (GdkDrawable *drawable,
@@ -60,11 +61,73 @@ typedef struct
 } GdkWindowChildHandlerData;
 
 
+/* Code for dirty-region queueing
+ */
+static GSList *update_windows = NULL;
+static guint update_idle = 0;
+
+static void
+gdk_window_directfb_process_all_updates (void)
+{
+  GSList *old_update_windows = update_windows;
+  GSList *tmp_list = update_windows;
+
+  if (update_idle)
+    g_source_remove (update_idle);
+  
+  update_windows = NULL;
+  update_idle = 0;
+
+  g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
+  
+  while (tmp_list)
+    {
+      GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
+      
+      if (private->update_freeze_count)
+       update_windows = g_slist_prepend (update_windows, private);
+      else
+       gdk_window_process_updates(tmp_list->data,TRUE);
+      
+      g_object_unref (tmp_list->data);
+      tmp_list = tmp_list->next;
+    }
+
+  g_slist_free (old_update_windows);
+
+}
+
+static gboolean
+gdk_window_update_idle (gpointer data)
+{
+  gdk_window_directfb_process_all_updates ();
+  
+  return FALSE;
+}
+
+static void
+gdk_window_schedule_update (GdkWindow *window)
+{
+  if (window && GDK_WINDOW_OBJECT (window)->update_freeze_count)
+    return;
+
+  if (!update_idle)
+    {
+      update_idle = gdk_threads_add_idle (GDK_PRIORITY_REDRAW,
+                                    gdk_window_update_idle, NULL, NULL);
+    }
+}
+
 
 static GdkWindow *gdk_directfb_window_containing_pointer = NULL;
 static GdkWindow *gdk_directfb_focused_window            = NULL;
 static gpointer   parent_class                           = NULL;
 GdkWindow * _gdk_parent_root = NULL;
+static void
+gdk_window_impl_directfb_paintable_init (GdkPaintableIface *iface);
+
+
+
 
 
 GType
@@ -87,9 +150,20 @@ gdk_window_impl_directfb_get_type (void)
           (GInstanceInitFunc) gdk_window_impl_directfb_init,
         };
 
+    static const GInterfaceInfo paintable_info =
+      {
+    (GInterfaceInitFunc) gdk_window_impl_directfb_paintable_init,
+    NULL,
+    NULL
+      };
+
       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_DIRECTFB,
                                             "GdkWindowImplDirectFB",
                                             &object_info, 0);
+       g_type_add_interface_static (object_type,
+                   GDK_TYPE_PAINTABLE,
+                   &paintable_info);
+
     }
 
   return object_type;
@@ -176,7 +250,7 @@ gdk_window_impl_directfb_get_visible_region (GdkDrawable *drawable)
   DFBRectangle             drect = { 0, 0, 0, 0 };
 
   if (priv->surface)
-    priv->surface->GetVisibleRectangle (priv->surface, &drect);
+  priv->surface->GetVisibleRectangle (priv->surface, &drect);
   rect.x= drect.x;
   rect.y= drect.y;
   rect.width=drect.w;
@@ -223,8 +297,9 @@ create_directfb_window (GdkWindowImplDirectFB *impl,
     }
 
   if ((desc->flags & DWDESC_CAPS) && (desc->caps & DWCAPS_INPUTONLY))
+  {
     impl->drawable.surface = NULL;
-  else
+  } else 
     window->GetSurface (window, &impl->drawable.surface);
 
   if (window_options)
@@ -258,7 +333,8 @@ _gdk_windowing_window_init (void)
   private->window_type = GDK_WINDOW_ROOT;
   private->state       = 0;
   private->children    = NULL;
-
+  impl->drawable.paint_region   = NULL;
+  impl->gdkWindow      = _gdk_parent_root;
   impl->window           = NULL;
   impl->drawable.abs_x   = 0;
   impl->drawable.abs_y   = 0;
@@ -331,6 +407,7 @@ gdk_directfb_window_new (GdkWindow              *parent,
 
   impl = GDK_WINDOW_IMPL_DIRECTFB (private->impl);
   impl->drawable.wrapper = GDK_DRAWABLE (window);
+  impl->gdkWindow      = window;
 
   private->x = x;
   private->y = y;
@@ -420,9 +497,9 @@ gdk_directfb_window_new (GdkWindow              *parent,
           impl->window=NULL;
       if (!private->input_only && parent_impl->drawable.surface)
         {
+
           DFBRectangle rect =
           { x, y, impl->drawable.width, impl->drawable.height };
-
           parent_impl->drawable.surface->GetSubSurface (parent_impl->drawable.surface,
                                                         &rect,
                                                         &impl->drawable.surface);
@@ -529,9 +606,6 @@ _gdk_windowing_window_destroy (GdkWindow *window,
   if (window == gdk_directfb_focused_window)
     gdk_directfb_change_focus (NULL);
 
-/*
-printf( " DESTROYING WINDOW %p %p %d parent=%p\n",window,impl->window,recursing,(GDK_WINDOW_OBJECT (window))->parent);
-*/
   if (!recursing && !foreign_destroy && impl->window ) {
        impl->window->SetOpacity (impl->window,0);
                impl->window->Close(impl->window);
@@ -1191,8 +1265,12 @@ _gdk_directfb_move_resize_child (GdkWindow *window,
     {
       if (impl->drawable.surface)
         {
+          GdkDrawableImplDirectFB *dimpl;
+          dimpl    = GDK_DRAWABLE_IMPL_DIRECTFB (private->impl);
           impl->drawable.surface->Release (impl->drawable.surface);
           impl->drawable.surface = NULL;
+          cairo_surface_destroy(dimpl->cairo_surface);
+          dimpl->cairo_surface= NULL;
         }
 
       parent_impl = GDK_WINDOW_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (private->parent)->impl);
@@ -1287,7 +1365,7 @@ gdk_window_move_resize (GdkWindow *window,
         }
     }
 }
-//XXX BROKE if top LEVEL WINDOW ~~~
+
 void
 gdk_window_reparent (GdkWindow *window,
                      GdkWindow *new_parent,
@@ -2345,73 +2423,6 @@ gdk_window_set_static_gravities (GdkWindow *window,
 
   return FALSE;
 }
-#if 0 
-void
-gdk_window_begin_paint_region (GdkWindow *window,
-                               GdkRegion *region)
-{
-  GdkDrawableImplDirectFB *impl;
-  gint                     i;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  impl = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
-
-  impl->buffered = TRUE;
-  impl->paint_depth++;
-
-  if (!region)
-    return;
-
-  if (impl->paint_region)
-    gdk_region_union (impl->paint_region, region);
-  else
-    impl->paint_region = gdk_region_copy (region);
-
-  for (i = 0; i < region->numRects; i++)
-    {
-      GdkRegionBox *box = &region->rects[i];
-
-      _gdk_windowing_window_clear_area (window,
-                                        box->x1,
-                                        box->y1,
-                                        box->x2 - box->x1,
-                                        box->y2 - box->y1);
-    }
-}
-
-void
-gdk_window_end_paint (GdkWindow *window)
-{
-  GdkDrawableImplDirectFB *impl;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  impl = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (window)->impl);
-
-  g_return_if_fail (impl->paint_depth > 0);
-
-  impl->paint_depth--;
-
-  if (impl->paint_depth == 0)
-    {
-      impl->buffered = FALSE;
-
-      if (impl->paint_region)
-        {
-          DFBRegion reg = { impl->paint_region->extents.x1,
-                            impl->paint_region->extents.y1,
-                            impl->paint_region->extents.x2 - 1,
-                            impl->paint_region->extents.y2 - 1 };
-
-          _gdk_directfb_update (impl, &reg);
-
-          gdk_region_destroy (impl->paint_region);
-          impl->paint_region = NULL;
-        }
-    }
-}
-#endif
 
 void
 gdk_window_begin_resize_drag (GdkWindow     *window,
@@ -2739,6 +2750,249 @@ gdk_window_set_urgency_hint (GdkWindow *window,
 
 }
 
+static void
+gdk_window_impl_directfb_invalidate_maybe_recurse (GdkPaintable *paintable,
+                         GdkRegion    *region,
+                         gboolean    (*child_func) (GdkWindow *, gpointer),
+                         gpointer      user_data)
+{
+  GdkWindow *window;
+  GdkWindowObject *private;
+  GdkWindowImplDirectFB *wimpl;
+  GdkDrawableImplDirectFB *impl;
+
+  wimpl = GDK_WINDOW_IMPL_DIRECTFB (paintable);
+  impl = (GdkDrawableImplDirectFB *)wimpl;
+  window = wimpl->gdkWindow;
+  private = (GdkWindowObject *)window;
+
+  GdkRegion *visible_region;
+  GList *tmp_list;
+
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
+    return;
+
+  visible_region = gdk_drawable_get_visible_region (window);
+  gdk_region_intersect (visible_region, region);
+
+  tmp_list = private->children;
+  while (tmp_list)
+    {
+      GdkWindowObject *child = tmp_list->data;
+      
+      if (!child->input_only)
+       {
+         GdkRegion *child_region;
+         GdkRectangle child_rect;
+         
+         gdk_window_get_position ((GdkWindow *)child,
+                                  &child_rect.x, &child_rect.y);
+         gdk_drawable_get_size ((GdkDrawable *)child,
+                                &child_rect.width, &child_rect.height);
+
+         child_region = gdk_region_rectangle (&child_rect);
+         
+         /* remove child area from the invalid area of the parent */
+         if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped)
+           gdk_region_subtract (visible_region, child_region);
+         
+         if (child_func && (*child_func) ((GdkWindow *)child, user_data))
+           {
+             gdk_region_offset (region, - child_rect.x, - child_rect.y);
+             gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
+             gdk_region_intersect (child_region, region);
+             
+             gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
+                                                  child_region, child_func, user_data);
+             
+             gdk_region_offset (region, child_rect.x, child_rect.y);
+           }
+
+         gdk_region_destroy (child_region);
+       }
+
+      tmp_list = tmp_list->next;
+    }
+  
+  if (!gdk_region_empty (visible_region))
+    {
+      
+      if (private->update_area)
+       {
+         gdk_region_union (private->update_area, visible_region);
+       }
+      else
+       {
+         update_windows = g_slist_prepend (update_windows, window);
+         private->update_area = gdk_region_copy (visible_region);
+         gdk_window_schedule_update (window);
+       }
+    }
+    gdk_region_destroy (visible_region);
+}
+
+
+static void
+gdk_window_impl_directfb_process_updates (GdkPaintable *paintable,
+                    gboolean      update_children)
+{
+  GdkWindow *window;
+  GdkWindowObject *private;
+  GdkWindowImplDirectFB *wimpl;
+  GdkDrawableImplDirectFB *impl;
+
+  wimpl = GDK_WINDOW_IMPL_DIRECTFB (paintable);
+  impl = (GdkDrawableImplDirectFB *)wimpl;
+  window = wimpl->gdkWindow;
+  private = (GdkWindowObject *)window;
+  gboolean save_region = FALSE;
+
+  /* If an update got queued during update processing, we can get a
+   * window in the update queue that has an empty update_area.
+   * just ignore it.
+   */
+  if (private->update_area)
+    {
+      GdkRegion *update_area = private->update_area;
+      private->update_area = NULL;
+      
+      if (_gdk_event_func && gdk_window_is_viewable (window))
+       {
+         GdkRectangle window_rect;
+         GdkRegion *expose_region;
+         GdkRegion *window_region;
+          gint width, height;
+         save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
+
+         if (save_region)
+           expose_region = gdk_region_copy (update_area);
+         else
+           expose_region = update_area;
+         
+          gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
+
+         window_rect.x = 0;
+         window_rect.y = 0;
+         window_rect.width = width;
+         window_rect.height = height;
+
+         window_region = gdk_region_rectangle (&window_rect);
+         gdk_region_intersect (expose_region,
+                               window_region);
+         gdk_region_destroy (window_region);
+         
+         if (!gdk_region_empty (expose_region) &&
+             (private->event_mask & GDK_EXPOSURE_MASK))
+           {
+             GdkEvent event;
+             
+             event.expose.type = GDK_EXPOSE;
+             event.expose.window = g_object_ref (window);
+             event.expose.send_event = FALSE;
+             event.expose.count = 0;
+             event.expose.region = expose_region;
+             gdk_region_get_clipbox (expose_region, &event.expose.area);
+             (*_gdk_event_func) (&event, _gdk_event_data);
+             
+             g_object_unref (window);
+           }
+
+         if (expose_region != update_area)
+           gdk_region_destroy (expose_region);
+       }
+      if (!save_region)
+       gdk_region_destroy (update_area);
+    }
+}
+
+
+static void
+gdk_window_impl_directfb_begin_paint_region (GdkPaintable *paintable,
+                                          GdkRegion    *region)
+{
+  GdkDrawableImplDirectFB *impl;
+  GdkWindowImplDirectFB *wimpl;
+  gint                     i;
+
+
+  g_assert (region != NULL );
+  wimpl = GDK_WINDOW_IMPL_DIRECTFB (paintable);
+  impl = (GdkDrawableImplDirectFB *)wimpl;
+  impl->buffered = TRUE;
+  impl->paint_depth++;
+
+  if (!region)
+    return;
+
+  if (impl->paint_region)
+    gdk_region_union (impl->paint_region, region);
+  else
+    impl->paint_region = gdk_region_copy (region);
+
+  for (i = 0; i < region->numRects; i++)
+    {
+      GdkRegionBox *box = &region->rects[i];
+
+      _gdk_windowing_window_clear_area (GDK_WINDOW(wimpl->gdkWindow),
+                                        box->x1,
+                                        box->y1,
+                                        box->x2 - box->x1,
+                                        box->y2 - box->y1);
+                                        
+    }
+}
+
+static void
+gdk_window_impl_directfb_end_paint (GdkPaintable *paintable)
+{
+  GdkDrawableImplDirectFB *impl;
+
+  impl = GDK_DRAWABLE_IMPL_DIRECTFB (paintable);
+
+  g_return_if_fail (impl->paint_depth > 0);
+
+  impl->paint_depth--;
+
+  if (impl->paint_depth == 0)
+    {
+      impl->buffered = FALSE;
+
+      if (impl->paint_region)
+        {
+          DFBRegion reg = { impl->paint_region->extents.x1,
+                            impl->paint_region->extents.y1,
+                            impl->paint_region->extents.x2 ,
+                            impl->paint_region->extents.y2 };
+
+          impl->surface->Flip(impl->surface, &reg,0);
+          gdk_region_destroy (impl->paint_region);
+          impl->paint_region = NULL;
+        }
+    }
+}
+
+
+static void
+gdk_window_impl_directfb_paintable_init (GdkPaintableIface *iface)
+{
+  iface->begin_paint_region = gdk_window_impl_directfb_begin_paint_region;
+  iface->end_paint = gdk_window_impl_directfb_end_paint;
+
+  iface->invalidate_maybe_recurse = gdk_window_impl_directfb_invalidate_maybe_recurse;
+  iface->process_updates = gdk_window_impl_directfb_process_updates;
+}
+
+void
+gdk_window_beep (GdkWindow *window)
+{
+  gdk_display_beep (gdk_display_get_default());
+}
 
 #define __GDK_WINDOW_X11_C__
 #include "gdkaliasdef.c"