[gtk+/rendering-cleanup: 19/31] gdk: Rewrite background handling



commit 95f63cb4ba47774b4d2dbb673b1363b37666467b
Author: Benjamin Otte <otte redhat com>
Date:   Sun Aug 15 13:49:30 2010 +0200

    gdk: Rewrite background handling
    
    Now the window background is a cairo_pattern_t. The backends will try to
    set this as good as they can on the windowing system, but no guarantees
    are made on wether the windowing system supports the pattern.
    
    Also gets rid of GDK_NO_BG as undefined behavior is not a good idea to
    support, and GDK_NO_BG effectively made the window's contents undefined.
    It wasn't effectively used in GTK anyway.

 docs/reference/gdk/gdk3-sections.txt |    4 +-
 gdk/directfb/gdkwindow-directfb.c    |   58 +------------
 gdk/gdk.symbols                      |    1 +
 gdk/gdkinternals.h                   |    3 +-
 gdk/gdkoffscreenwindow.c             |   48 +----------
 gdk/gdkwindow.c                      |  162 +++++++++++++---------------------
 gdk/gdkwindow.h                      |    8 +-
 gdk/gdkwindowimpl.h                  |    4 +-
 gdk/quartz/gdkwindow-quartz.c        |   60 +++----------
 gdk/win32/gdkgeometry-win32.c        |   12 ---
 gdk/win32/gdkwindow-win32.c          |   19 +----
 gdk/x11/gdkwindow-x11.c              |  114 +++++++++++++++---------
 12 files changed, 158 insertions(+), 335 deletions(-)
---
diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt
index 9ed6ec3..536b05d 100644
--- a/docs/reference/gdk/gdk3-sections.txt
+++ b/docs/reference/gdk/gdk3-sections.txt
@@ -474,9 +474,7 @@ gdk_window_merge_child_input_shapes
 gdk_window_set_static_gravities
 gdk_window_set_title
 gdk_window_set_background
-gdk_window_get_background
-gdk_window_set_back_pixmap
-gdk_window_get_back_pixmap
+gdk_window_set_background_pattern
 GDK_PARENT_RELATIVE
 gdk_window_set_cursor
 gdk_window_get_cursor
diff --git a/gdk/directfb/gdkwindow-directfb.c b/gdk/directfb/gdkwindow-directfb.c
index cc6f0b1..8904902 100644
--- a/gdk/directfb/gdkwindow-directfb.c
+++ b/gdk/directfb/gdkwindow-directfb.c
@@ -1607,63 +1607,8 @@ gdk_window_set_transient_for (GdkWindow *window,
 
 static void
 gdk_directfb_window_set_background (GdkWindow *window,
-                                    const GdkColor  *color)
+                                    cairo_pattern_t *pattern)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  g_return_if_fail (color != NULL);
-
-  D_DEBUG_AT( GDKDFB_Window, "%s( %p, %d,%d,%d )\n", G_STRFUNC, window, color->red, color->green, color->blue );
-
-  private = GDK_WINDOW_OBJECT (window);
-  private->bg_color = *color;
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  private->bg_pixmap = NULL;
-}
-
-static void
-gdk_directfb_window_set_back_pixmap (GdkWindow *window,
-                                     GdkPixmap *pixmap)
-{
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  D_DEBUG_AT( GDKDFB_Window, "%s( %p, %p )\n", G_STRFUNC,
-              window, pixmap);
-
-  private = GDK_WINDOW_OBJECT (window);
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    {
-      g_object_unref (private->bg_pixmap);
-    }
-
-  if (pixmap == GDK_PARENT_RELATIVE_BG)
-    {
-      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
-    }
-  else
-    {
-      if (pixmap)
-        {
-          g_object_ref (pixmap);
-          private->bg_pixmap = pixmap;
-        }
-      else
-        {
-          private->bg_pixmap = GDK_NO_BG;
-        }
-    }
 }
 
 static void
@@ -2855,7 +2800,6 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->lower = gdk_window_directfb_lower;
   iface->move_resize = gdk_directfb_window_move_resize;
   iface->set_background = gdk_directfb_window_set_background;
-  iface->set_back_pixmap = gdk_directfb_window_set_back_pixmap;
   iface->reparent = gdk_directfb_window_reparent;
   iface->set_cursor = gdk_directfb_window_set_cursor;
   iface->get_geometry = gdk_directfb_window_get_geometry;
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index f3faade..4a8b364 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -592,6 +592,7 @@ gdk_window_get_support_multidevice
 gdk_window_has_native
 gdk_window_set_background
 gdk_window_set_back_pixmap
+gdk_window_set_background_pattern
 gdk_window_set_cursor
 gdk_window_shape_combine_region
 gdk_window_set_child_shapes
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 12e36c9..5ba2309 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -207,8 +207,7 @@ struct _GdkWindowObject
   GList *filters;
   GList *children;
 
-  GdkColor bg_color;
-  GdkPixmap *bg_pixmap;
+  cairo_pattern_t *background;
   
   GSList *paint_stack;
   
diff --git a/gdk/gdkoffscreenwindow.c b/gdk/gdkoffscreenwindow.c
index bbf18e9..15aaa96 100644
--- a/gdk/gdkoffscreenwindow.c
+++ b/gdk/gdkoffscreenwindow.c
@@ -35,7 +35,6 @@
 #include "gdktypes.h"
 #include "gdkscreen.h"
 #include "gdkcolor.h"
-#include "gdkcursor.h"
 
 
 /* LIMITATIONS:
@@ -53,7 +52,6 @@ struct _GdkOffscreenWindow
   GdkDrawable parent_instance;
 
   GdkWindow *wrapper;
-  GdkCursor *cursor;
   GdkColormap *colormap;
   GdkScreen *screen;
 
@@ -88,11 +86,6 @@ gdk_offscreen_window_finalize (GObject *object)
 {
   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
 
-  if (offscreen->cursor)
-    gdk_cursor_unref (offscreen->cursor);
-
-  offscreen->cursor = NULL;
-
   g_object_unref (offscreen->pixmap);
 
   G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
@@ -636,46 +629,8 @@ gdk_offscreen_window_set_events (GdkWindow       *window,
 
 static void
 gdk_offscreen_window_set_background (GdkWindow      *window,
-				     const GdkColor *color)
+				     cairo_pattern_t *pattern)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  private->bg_color = *color;
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  private->bg_pixmap = NULL;
-}
-
-static void
-gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
-				      GdkPixmap *pixmap)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  if (pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG &&
-      !gdk_drawable_get_colormap (pixmap))
-    {
-      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
-      return;
-    }
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  private->bg_pixmap = pixmap;
-
-  if (pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_ref (pixmap);
 }
 
 static void
@@ -867,7 +822,6 @@ gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->lower = gdk_offscreen_window_lower;
   iface->move_resize = gdk_offscreen_window_move_resize;
   iface->set_background = gdk_offscreen_window_set_background;
-  iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
   iface->get_events = gdk_offscreen_window_get_events;
   iface->set_events = gdk_offscreen_window_set_events;
   iface->reparent = gdk_offscreen_window_reparent;
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 482d60e..0447efa 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -1407,10 +1407,8 @@ gdk_window_new (GdkWindow     *parent,
       private->input_only = FALSE;
       private->depth = visual->depth;
 
-      private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
-      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
-
-      private->bg_pixmap = NULL;
+      /* XXX: Cache this somehow? */
+      private->background = cairo_pattern_create_rgb (0, 0, 0);
     }
   else
     {
@@ -1901,9 +1899,7 @@ gdk_window_ensure_native (GdkWindow *window)
 
   if (!private->input_only)
     {
-      impl_iface->set_background (window, &private->bg_color);
-      if (private->bg_pixmap != NULL)
-	impl_iface->set_back_pixmap (window, private->bg_pixmap);
+      impl_iface->set_background (window, private->background);
     }
 
   impl_iface->input_shape_combine_region (window,
@@ -2059,13 +2055,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
 
 	  gdk_window_free_paint_stack (window);
 
-	  if (private->bg_pixmap &&
-	      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-	      private->bg_pixmap != GDK_NO_BG)
-	    {
-	      g_object_unref (private->bg_pixmap);
-	      private->bg_pixmap = NULL;
-	    }
+          gdk_window_set_background_pattern (window, NULL);
 
 	  if (private->window_type == GDK_WINDOW_FOREIGN)
 	    g_assert (private->children == NULL);
@@ -3656,7 +3646,7 @@ setup_backing_rect (GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo
   GdkWindowObject *private = (GdkWindowObject *)window;
   cairo_t *cr;
 
-  if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+  if (private->background == NULL && private->parent)
     {
       GdkWindowPaint tmp_paint;
 
@@ -3669,33 +3659,18 @@ setup_backing_rect (GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo
 
       cr = setup_backing_rect (GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
     }
-  else if (private->bg_pixmap &&
-	   private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-	   private->bg_pixmap != GDK_NO_BG)
-    {
-      cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
-      cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
-      cairo_surface_destroy (surface);
-
-      if (x_offset_cairo != 0 || y_offset_cairo != 0)
-	{
-	  cairo_matrix_t matrix;
-	  cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
-	  cairo_pattern_set_matrix (pattern, &matrix);
-	}
-
-      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
-
-      cr = cairo_create (paint->surface);
-
-      cairo_set_source (cr, pattern);
-      cairo_pattern_destroy (pattern);
-    }
   else
     {
       cr = cairo_create (paint->surface);
 
-      gdk_cairo_set_source_color (cr, &private->bg_color);
+      if (private->background)
+        {
+          cairo_translate (cr, - x_offset_cairo, - y_offset_cairo);
+          cairo_set_source (cr, private->background);
+          cairo_translate (cr, x_offset_cairo, y_offset_cairo);
+        }
+      else
+        cairo_set_source_rgba (cr, 0, 0, 0, 0);
     }
 
   return cr;
@@ -4297,8 +4272,7 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
 
 	  g_object_unref (window);
 	}
-      else if (private->bg_pixmap != GDK_NO_BG &&
-	       private->window_type != GDK_WINDOW_FOREIGN)
+      else if (private->window_type != GDK_WINDOW_FOREIGN)
 	{
 	  /* No exposure mask set, so nothing will be drawn, the
 	   * app relies on the background being what it specified
@@ -6964,108 +6938,96 @@ gdk_window_move_region (GdkWindow       *window,
 /**
  * gdk_window_set_background:
  * @window: a #GdkWindow
- * @color: an allocated #GdkColor
+ * @color: a #GdkColor
  *
  * Sets the background color of @window. (However, when using GTK+,
  * set the background of a widget with gtk_widget_modify_bg() - if
  * you're an application - or gtk_style_set_background() - if you're
  * implementing a custom widget.)
  *
- * See also gdk_window_set_background_pixmap().
+ * See also gdk_window_set_background_pattern().
  */
 void
 gdk_window_set_background (GdkWindow      *window,
 			   const GdkColor *color)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  cairo_pattern_t *pattern;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
+  pattern = cairo_pattern_create_rgb (color->red   / 65535.,
+                                      color->green / 65535.,
+                                      color->blue  / 65535.);
 
-  private->bg_color = *color;
+  gdk_window_set_background_pattern (window, pattern);
 
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
+  cairo_pattern_destroy (pattern);
+}
 
-  private->bg_pixmap = NULL;
+/* NB: This is more or less a hack now and about to go away. */
+void
+gdk_window_set_back_pixmap (GdkWindow *window,
+                            GdkPixmap *pixmap,
+                            gboolean   parent_relative)
+{
+  cairo_pattern_t *pattern;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (pixmap == NULL || !parent_relative);
 
-  if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_window_has_impl (private) &&
-      !private->input_only)
+  if (parent_relative || pixmap == NULL)
+    pattern = NULL;
+  else
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->set_background (window, &private->bg_color);
+      static cairo_user_data_key_t key;
+      cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (pixmap);
+      pattern = cairo_pattern_create_for_surface (surface);
+      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+      g_object_ref (pixmap);
+      cairo_pattern_set_user_data (pattern, &key, pixmap, g_object_unref);
     }
+
+  gdk_window_set_background_pattern (window, pattern);
+
+  if (pattern)
+    cairo_pattern_destroy (pattern);
 }
 
 /**
- * gdk_window_set_back_pixmap:
+ * gdk_window_set_background_pattern:
  * @window: a #GdkWindow
- * @pixmap: (allow-none): a #GdkPixmap, or %NULL
- * @parent_relative: whether the tiling origin is at the origin of
- *   @window's parent
- *
- * Sets the background pixmap of @window. May also be used to set a
- * background of "None" on @window, by setting a background pixmap
- * of %NULL.
+ * @pattern: (allow-none): a pattern to use, or %NULL
  *
- * A background pixmap will be tiled, positioning the first tile at
- * the origin of @window, or if @parent_relative is %TRUE, the tiling
- * will be done based on the origin of the parent window (useful to
- * align tiles in a parent with tiles in a child).
+ * Sets the background of @window.
  *
- * A background pixmap of %NULL means that the window will have no
- * background.  A window with no background will never have its
- * background filled by the windowing system, instead the window will
- * contain whatever pixels were already in the corresponding area of
- * the display.
+ * A background of %NULL means that the window will inherit its
+ * background form its parent window.
  *
  * The windowing system will normally fill a window with its background
  * when the window is obscured then exposed, and when you call
  * gdk_window_clear().
  */
 void
-gdk_window_set_back_pixmap (GdkWindow *window,
-			    GdkPixmap *pixmap,
-			    gboolean   parent_relative)
+gdk_window_set_background_pattern (GdkWindow *window,
+                                   cairo_pattern_t *pattern)
 {
   GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (pixmap == NULL || !parent_relative);
-  g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
 
   private = (GdkWindowObject *) window;
 
-  if (pixmap && !gdk_drawable_get_colormap (pixmap))
-    {
-      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
-      return;
-    }
+  if (pattern)
+    cairo_pattern_reference (pattern);
+  if (private->background)
+    cairo_pattern_destroy (private->background);
+  private->background = pattern;
 
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  if (parent_relative)
-    private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
-  else if (pixmap)
-    private->bg_pixmap = g_object_ref (pixmap);
-  else
-    private->bg_pixmap = GDK_NO_BG;
-
-  if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_window_has_impl (private) &&
+  if (gdk_window_has_impl (private) &&
       !private->input_only)
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->set_back_pixmap (window, private->bg_pixmap);
+      GdkWindowImplIface *impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+      impl_iface->set_background (window, pattern);
     }
 }
 
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 70f8b13..23dddea 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -677,9 +677,11 @@ void          gdk_window_set_transient_for (GdkWindow     *window,
 					    GdkWindow     *parent);
 void	      gdk_window_set_background	 (GdkWindow	  *window,
 					  const GdkColor  *color);
-void	      gdk_window_set_back_pixmap (GdkWindow	  *window,
-					  GdkPixmap	  *pixmap,
-					  gboolean	   parent_relative);
+void          gdk_window_set_back_pixmap (GdkWindow       *window,
+                                          GdkPixmap       *pixmap,
+                                          gboolean         parent_relative);
+void	      gdk_window_set_background_pattern (GdkWindow	 *window,
+                                                 cairo_pattern_t *pattern);
 void	      gdk_window_set_cursor	 (GdkWindow	  *window,
 					  GdkCursor	  *cursor);
 GdkCursor    *gdk_window_get_cursor      (GdkWindow       *window);
diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h
index 6e480aa..8edb21b 100644
--- a/gdk/gdkwindowimpl.h
+++ b/gdk/gdkwindowimpl.h
@@ -62,9 +62,7 @@ struct _GdkWindowImplIface
                                          gint             width,
                                          gint             height);
   void         (* set_background)       (GdkWindow       *window,
-                                         const GdkColor  *color);
-  void         (* set_back_pixmap)      (GdkWindow       *window,
-                                         GdkPixmap       *pixmap);
+                                         cairo_pattern_t *pattern);
 
   GdkEventMask (* get_events)           (GdkWindow       *window);
   void         (* set_events)           (GdkWindow       *window,
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index f5d7010..d4389e0 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -228,13 +228,10 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
 					   const cairo_region_t *region)
 {
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
-  GdkWindowObject *private = (GdkWindowObject*)window;
-  GdkPixmap *bg_pixmap;
+  GdkWindowObject *private = (GdkWindowObject*) window;
   cairo_region_t *clipped_and_offset_region;
   cairo_t *cr;
 
-  bg_pixmap = private->bg_pixmap;
-
   clipped_and_offset_region = cairo_region_copy (region);
 
   cairo_region_intersect (clipped_and_offset_region,
@@ -249,8 +246,7 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
 
   impl->begin_paint_count++;
 
-  if (bg_pixmap == GDK_NO_BG ||
-      cairo_region_is_empty (clipped_and_offset_region))
+  if (cairo_region_is_empty (clipped_and_offset_region))
     goto done;
 
   cr = gdk_cairo_create (window);
@@ -260,40 +256,16 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
   gdk_cairo_region (cr, clipped_and_offset_region);
   cairo_clip (cr);
 
-  if (bg_pixmap == NULL)
+  while (private->pattern == NULL && private->parent)
     {
-      gdk_cairo_set_source_color (cr, &private->bg_color);
+      cairo_translate (cr, -private->x, private->y);
+      private = private->parent;
     }
+  
+  if (private->pattern)
+    cairo_set_source (cr, private->pattern);
   else
-    {
-      int x_offset, y_offset;
-
-      x_offset = y_offset = 0;
-
-      while (window && bg_pixmap == GDK_PARENT_RELATIVE_BG)
-        {
-          /* If this window should have the same background as the parent,
-           * fetch the parent. (And if the same goes for the parent, fetch
-           * the grandparent, etc.)
-           */
-          x_offset += ((GdkWindowObject *) window)->x;
-          y_offset += ((GdkWindowObject *) window)->y;
-          window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
-          bg_pixmap = ((GdkWindowObject *) window)->bg_pixmap;
-        }
-
-      /* If we have a parent relative background or we don't have a pixmap,
-       * clear the area to transparent.
-       */ 
-      if (bg_pixmap == NULL || bg_pixmap == GDK_NO_BG || bg_pixmap == GDK_PARENT_RELATIVE_BG)
-        {
-          cairo_destroy (cr);
-          goto done;
-        }
-
-      gdk_cairo_set_source_pixmap (cr, bg_pixmap, x_offset, y_offset);
-      cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
-    }
+    cairo_set_source_rgba (cr, 0, 0, 0, 0);
 
   /* Can use cairo_paint() here, we clipped above */
   cairo_paint (cr);
@@ -1650,8 +1622,8 @@ gdk_window_quartz_restack_toplevel (GdkWindow *window,
 }
 
 static void
-gdk_window_quartz_set_background (GdkWindow      *window,
-                                  const GdkColor *color)
+gdk_window_quartz_set_background (GdkWindow       *window,
+                                  cairo_pattern_t *pattern)
 {
   /* FIXME: We could theoretically set the background color for toplevels
    * here. (Currently we draw the background before emitting expose events)
@@ -1659,15 +1631,6 @@ gdk_window_quartz_set_background (GdkWindow      *window,
 }
 
 static void
-gdk_window_quartz_set_back_pixmap (GdkWindow *window,
-                                   GdkPixmap *pixmap)
-{
-  /* FIXME: Could theoretically set some background image here. (Currently
-   * the back pixmap is drawn before emitting expose events.
-   */
-}
-
-static void
 gdk_window_quartz_set_device_cursor (GdkWindow *window,
                                      GdkDevice *device,
                                      GdkCursor *cursor)
@@ -3037,7 +3000,6 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->restack_toplevel = gdk_window_quartz_restack_toplevel;
   iface->move_resize = gdk_window_quartz_move_resize;
   iface->set_background = gdk_window_quartz_set_background;
-  iface->set_back_pixmap = gdk_window_quartz_set_back_pixmap;
   iface->reparent = gdk_window_quartz_reparent;
   iface->set_device_cursor = gdk_window_quartz_set_device_cursor;
   iface->get_geometry = gdk_window_quartz_get_geometry;
diff --git a/gdk/win32/gdkgeometry-win32.c b/gdk/win32/gdkgeometry-win32.c
index a94b81e..947095e 100644
--- a/gdk/win32/gdkgeometry-win32.c
+++ b/gdk/win32/gdkgeometry-win32.c
@@ -152,18 +152,6 @@ tmp_unset_bg (GdkWindow *window)
   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
 
   impl->no_bg = TRUE;
-
-  /*
-   * The X version sets background = None to avoid updateing for a moment.
-   * Not sure if this could really emulate it.
-   */
-  if (obj->bg_pixmap != GDK_NO_BG)
-    {
-      ///* handled in WM_ERASEBKGRND proceesing */;
-
-      //HDC hdc = GetDC (GDK_WINDOW_HWND (window));
-      //erase_background (window, hdc);
-    }
 }
 
 static void
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index 2379e96..a56d1be 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -1807,23 +1807,9 @@ _gdk_modal_current (void)
 }
 
 static void
-gdk_win32_window_set_background (GdkWindow      *window,
-				 const GdkColor *color)
+gdk_win32_window_set_background (GdkWindow       *window,
+				 cairo_pattern_t *pattern)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  
-  GDK_NOTE (MISC, g_print ("gdk_win32_window_set_background: %p: %s\n",
-			   GDK_WINDOW_HWND (window), 
-			   _gdk_win32_color_to_string (color)));
-
-  private->bg_color = *color;
-}
-
-static void
-gdk_win32_window_set_back_pixmap (GdkWindow *window,
-				  GdkPixmap *pixmap)
-{
-  /* TODO_CSW? but win32 has no XSetWindowBackgroundPixmap */
 }
 
 static void
@@ -3342,7 +3328,6 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->restack_toplevel = gdk_win32_window_restack_toplevel;
   iface->move_resize = gdk_win32_window_move_resize;
   iface->set_background = gdk_win32_window_set_background;
-  iface->set_back_pixmap = gdk_win32_window_set_back_pixmap;
   iface->reparent = gdk_win32_window_reparent;
   iface->set_device_cursor = gdk_win32_window_set_device_cursor;
   iface->get_geometry = gdk_win32_window_get_geometry;
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 8115d56..71c7814 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -35,6 +35,8 @@
 #include <X11/XKBlib.h>
 #endif
 
+#include <cairo-xlib.h>
+
 #include <netinet/in.h>
 #include <unistd.h>
 
@@ -106,6 +108,8 @@ static void     set_wm_name                       (GdkDisplay  *display,
 						   Window       xwindow,
 						   const gchar *name);
 static void     move_to_current_desktop           (GdkWindow *window);
+static void     gdk_window_x11_set_background     (GdkWindow      *window,
+                                                   cairo_pattern_t *pattern);
 
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
@@ -228,9 +232,8 @@ tmp_unset_bg (GdkWindow *window)
 
   impl->no_bg = TRUE;
 
-  if (obj->bg_pixmap != GDK_NO_BG)
-    XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
-				GDK_DRAWABLE_XID (window), None);
+  XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
+                              GDK_DRAWABLE_XID (window), None);
 }
 
 static void
@@ -244,27 +247,7 @@ tmp_reset_bg (GdkWindow *window)
 
   impl->no_bg = FALSE;
 
-  if (obj->bg_pixmap == GDK_NO_BG)
-    return;
-  
-  if (obj->bg_pixmap)
-    {
-      Pixmap xpixmap;
-
-      if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
-	xpixmap = ParentRelative;
-      else 
-	xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);
-
-      XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
-				  GDK_DRAWABLE_XID (window), xpixmap);
-    }
-  else
-    {
-      XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
-			    GDK_DRAWABLE_XID (window),
-			    obj->bg_color.pixel);
-    }
+  gdk_window_x11_set_background (window, obj->background);
 }
 
 /* Unsetting and resetting window backgrounds.
@@ -754,7 +737,7 @@ _gdk_window_impl_new (GdkWindow     *window,
             }
 	}
       
-      xattributes.background_pixel = private->bg_color.pixel;
+      xattributes.background_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
 
       xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
       xattributes_mask |= CWBorderPixel | CWBackPixel;
@@ -2603,8 +2586,8 @@ gdk_window_set_transient_for (GdkWindow *window,
 }
 
 static void
-gdk_window_x11_set_background (GdkWindow      *window,
-                               const GdkColor *color)
+gdk_window_x11_set_back_color (GdkWindow *window,
+                               GdkColor *color)
 {
   GdkColor allocated = *color;
 
@@ -2619,22 +2602,70 @@ gdk_window_x11_set_background (GdkWindow      *window,
   gdk_colormap_free_colors (gdk_drawable_get_colormap (window), &allocated, 1);
 }
 
+static gboolean
+matrix_is_identity (cairo_matrix_t *matrix)
+{
+  return matrix->xx == 1.0 && matrix->yy == 1.0 &&
+    matrix->yx == 0.0 && matrix->xy == 0.0 &&
+    matrix->x0 == 0.0 && matrix->y0 == 0.0;
+}
+
 static void
-gdk_window_x11_set_back_pixmap (GdkWindow *window,
-                                GdkPixmap *pixmap)
+gdk_window_x11_set_background (GdkWindow      *window,
+                               cairo_pattern_t *pattern)
 {
-  Pixmap xpixmap;
-  
-  if (pixmap == GDK_PARENT_RELATIVE_BG)
-    xpixmap = ParentRelative;
-  else if (pixmap == GDK_NO_BG)
-    xpixmap = None;
-  else
-    xpixmap = GDK_PIXMAP_XID (pixmap);
-  
-  if (!GDK_WINDOW_DESTROYED (window))
-    XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
-				GDK_WINDOW_XID (window), xpixmap);
+  GdkColor color = { 0, };
+  double r, g, b, a;
+  cairo_surface_t *surface;
+  cairo_matrix_t matrix;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (pattern == NULL)
+    {
+      XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
+                                  GDK_WINDOW_XID (window), None);
+      return;
+    }
+
+  switch (cairo_pattern_get_type (pattern))
+    {
+    case CAIRO_PATTERN_TYPE_SOLID:
+      cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
+      color.red = r * 65535;
+      color.green = g * 65535;
+      color.blue = b * 65535;
+      break;
+    case CAIRO_PATTERN_TYPE_SURFACE:
+      cairo_pattern_get_matrix (pattern, &matrix);
+      if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
+          matrix_is_identity (&matrix) &&
+          cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
+          cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
+        {
+          double x, y;
+
+          cairo_surface_get_device_offset (surface, &x, &y);
+          /* XXX: This still bombs for non-pixmaps, but there's no way to
+           * detect we're not a pixmap in Cairo... */
+          if (x == 0.0 && y == 0.0)
+            {
+              XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
+                                          GDK_WINDOW_XID (window),
+                                          cairo_xlib_surface_get_drawable (surface));
+              return;
+            }
+        }
+      /* fall through */
+    case CAIRO_PATTERN_TYPE_LINEAR:
+    case CAIRO_PATTERN_TYPE_RADIAL:
+    default:
+      /* fallback: just use black */
+      break;
+    }
+
+  gdk_window_x11_set_back_color (window, &color);
 }
 
 static void
@@ -5514,7 +5545,6 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->restack_toplevel = gdk_window_x11_restack_toplevel;
   iface->move_resize = gdk_window_x11_move_resize;
   iface->set_background = gdk_window_x11_set_background;
-  iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
   iface->reparent = gdk_window_x11_reparent;
   iface->set_device_cursor = gdk_window_x11_set_device_cursor;
   iface->get_geometry = gdk_window_x11_get_geometry;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]