[mutter] theme: Upgrade to use Cairo for painting (changes API)



commit aa65f94c672df8cc345575269d7e9dedf0e7ef24
Author: Benjamin Otte <otte redhat com>
Date:   Thu Sep 23 17:35:41 2010 +0200

    theme: Upgrade to use Cairo for painting (changes API)
    
    This commit is in preparation for the work happening in GTK3, which will
    use Cairo for drawing exclusively. So it is necessary to move all
    drawing code to Cairo. In this commit the "gtk2" code is used for both
    gtk2 and gtk3; compatibility with newer versions of gtk3 where different
    code is needed will be added subsequently.
    For compatibility with older GTK versions, the file gdk2-drawing-utils.h
    provides a compatibility layer.
    
    The commit changes the API of libmutter-private.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=630203

 src/Makefile.am          |    4 +
 src/gdk-compat.h         |   28 ++++++
 src/gdk2-drawing-utils.c |  174 ++++++++++++++++++++++++++++++++++
 src/gdk2-drawing-utils.h |   71 ++++++++++++++
 src/ui/frames.c          |    9 ++-
 src/ui/preview-widget.c  |   13 ++-
 src/ui/theme-viewer.c    |    9 ++-
 src/ui/theme.c           |  234 +++++++++++++++++++---------------------------
 src/ui/theme.h           |   27 ++----
 9 files changed, 406 insertions(+), 163 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 168bd72..1037c34 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,8 @@ mutter_SOURCES= 				\
 	compositor/tidy/tidy-texture-frame.h	\
 	gdk-compat.h				\
 	gtk-compat.h				\
+	gdk2-drawing-utils.c			\
+	gdk2-drawing-utils.h			\
 	include/compositor.h			\
 	include/mutter-plugin.h			\
 	include/mutter-window.h			\
@@ -146,6 +148,8 @@ libmutter_private_la_SOURCES=			\
 	ui/preview-widget.c			\
 	ui/preview-widget.h			\
 	include/region.h			\
+	gdk2-drawing-utils.c			\
+	gdk2-drawing-utils.h			\
 	ui/theme-parser.c			\
 	ui/theme-parser.h			\
 	ui/theme.c				\
diff --git a/src/gdk-compat.h b/src/gdk-compat.h
index 501b4f4..1554af3 100644
--- a/src/gdk-compat.h
+++ b/src/gdk-compat.h
@@ -2,6 +2,7 @@
 #define __GDK_COMPAT_H__
 
 #include <gdk/gdk.h>
+#include <math.h>
 
 /* Provide a compatibility layer for accessor function introduced
  * in GTK+ 2.22 which we need to build without deprecated GDK symbols.
@@ -15,6 +16,33 @@
 
 #endif /*GTK_CHECK_VERSION */
 
+static inline gboolean
+gdk_cairo_get_clip_rectangle (cairo_t      *cr,
+                              GdkRectangle *rect)
+{
+  double x1, y1, x2, y2;
+  gboolean clip_exists;
+
+  cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
+
+  clip_exists = x1 < x2 && y1 < y2;
+
+  if (rect)
+    {
+      x1 = floor (x1);
+      y1 = floor (y1);
+      x2 = ceil (x2);
+      y2 = ceil (y2);
+
+      rect->x      = CLAMP (x1,      G_MININT, G_MAXINT);
+      rect->y      = CLAMP (y1,      G_MININT, G_MAXINT);
+      rect->width  = CLAMP (x2 - x1, G_MININT, G_MAXINT);
+      rect->height = CLAMP (y2 - y1, G_MININT, G_MAXINT);
+    }
+
+  return clip_exists;
+}
+
 
 /* Compatibility with old GDK key symbols */
 #ifndef GDK_KEY_Escape
diff --git a/src/gdk2-drawing-utils.c b/src/gdk2-drawing-utils.c
new file mode 100644
index 0000000..558d563
--- /dev/null
+++ b/src/gdk2-drawing-utils.c
@@ -0,0 +1,174 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* 
+ * Copyright (C) 2010 Red Hat Inc.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "gdk2-drawing-utils.h"
+
+#include <math.h>
+
+#include "gdk-compat.h"
+
+static const cairo_user_data_key_t context_key;
+
+cairo_t *
+meta_cairo_create (GdkDrawable *drawable)
+{
+  cairo_t *cr;
+  
+  cr = gdk_cairo_create (drawable);
+  cairo_set_user_data (cr, &context_key, drawable, NULL);
+
+  return cr;
+}
+
+static GdkWindow *
+extract_window (cairo_t      *cr,
+                int          *dx,
+                int          *dy,
+                GdkRectangle *clip_area)
+{
+  GdkWindow *window = cairo_get_user_data (cr, &context_key);
+  cairo_matrix_t matrix;
+
+  g_assert (dx != NULL);
+  g_assert (dy != NULL);
+  g_assert (clip_area != NULL);
+
+  /* lots of stuff that mustn't happen because we can't cope with it. */
+  if (window == NULL)
+    {
+      g_error ("Could not get the GdkWindow from the cairo context passed to\n"
+               "theme drawing functions. A GdkWindow must be set on all cairo\n"
+               "context passed to theme drawing functions when using GTK2.\n"
+               "Please use meta_cairo_create() to create the Cairo context.\n");
+    }
+  cairo_get_matrix (cr, &matrix);
+  if (matrix.xx != 1.0 || matrix.yy != 1.0 ||
+      matrix.xy != 0.0 || matrix.yx != 0.0 ||
+      floor (matrix.x0) != matrix.x0 ||
+      floor (matrix.y0) != matrix.y0)
+    {
+      g_error ("GTK2 drawing requires that the matrix set on the cairo context\n"
+               "is an integer translation, however that is not the case.\n");
+    }
+
+  gdk_cairo_get_clip_rectangle (cr, clip_area);
+  clip_area->x += matrix.x0;
+  clip_area->y += matrix.y0;
+
+  *dx = matrix.x0;
+  *dy = matrix.y0;
+
+  return window;
+}
+
+void
+meta_paint_vline (GtkStyle           *style,
+                  cairo_t            *cr,
+                  GtkStateType        state_type,
+                  GtkWidget          *widget,
+                  const gchar        *detail,
+                  gint                y1_,
+                  gint                y2_,
+                  gint                x)
+{
+  int dx, dy;
+  GdkWindow *window;
+  GdkRectangle area;
+
+  window = extract_window (cr, &dx, &dy, &area);
+
+  gtk_paint_vline (style, window, state_type, &area,
+                   widget, detail, y1_ + dy, y2_ + dy, x + dx);
+}
+
+void
+meta_paint_arrow (GtkStyle           *style,
+                  cairo_t            *cr,
+                  GtkStateType        state_type,
+                  GtkShadowType       shadow_type,
+                  GtkWidget          *widget,
+                  const gchar        *detail,
+                  GtkArrowType        arrow_type,
+                  gboolean            fill,
+                  gint                x,
+                  gint                y,
+                  gint                width,
+                  gint                height)
+{
+  int dx, dy;
+  GdkWindow *window;
+  GdkRectangle area;
+
+  window = extract_window (cr, &dx, &dy, &area);
+
+  gtk_paint_arrow (style, window, state_type, shadow_type,
+                   &area, widget, detail, arrow_type,
+                   fill, x + dx, y + dy, width, height);
+}
+
+void
+meta_paint_box (GtkStyle           *style,
+                cairo_t            *cr,
+                GtkStateType        state_type,
+                GtkShadowType       shadow_type,
+                GtkWidget          *widget,
+                const gchar        *detail,
+                gint                x,
+                gint                y,
+                gint                width,
+                gint                height)
+{
+  int dx, dy;
+  GdkWindow *window;
+  GdkRectangle area;
+
+  window = extract_window (cr, &dx, &dy, &area);
+
+  gtk_paint_box (style, window, state_type, shadow_type,
+                 &area, widget, detail,
+                 x + dx, y + dy, width, height);
+}
+
+void
+meta_paint_flat_box (GtkStyle           *style,
+                     cairo_t            *cr,
+                     GtkStateType        state_type,
+                     GtkShadowType       shadow_type,
+                     GtkWidget          *widget,
+                     const gchar        *detail,
+                     gint                x,
+                     gint                y,
+                     gint                width,
+                     gint                height)
+{
+  int dx, dy;
+  GdkWindow *window;
+  GdkRectangle area;
+
+  window = extract_window (cr, &dx, &dy, &area);
+
+  gtk_paint_flat_box (style, window, state_type, shadow_type,
+                      &area, widget, detail,
+                      x + dx, y + dy, width, height);
+}
+
diff --git a/src/gdk2-drawing-utils.h b/src/gdk2-drawing-utils.h
new file mode 100644
index 0000000..d3ce302
--- /dev/null
+++ b/src/gdk2-drawing-utils.h
@@ -0,0 +1,71 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* 
+ * Copyright (C) 2010 Red Hat Inc.
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __GTK3_COMPAT_H__
+#define __GTK3_COMPAT_H__
+
+#include <gtk/gtk.h>
+
+/* This function only exists for GTK2 code. */
+cairo_t *     meta_cairo_create            (GdkDrawable        *drawable);
+
+void          meta_paint_vline             (GtkStyle           *style,
+                                            cairo_t            *cr,
+                                            GtkStateType        state_type,
+                                            GtkWidget          *widget,
+                                            const gchar        *detail,
+                                            gint                y1_,
+                                            gint                y2_,
+                                            gint                x);
+void          meta_paint_arrow             (GtkStyle           *style,
+                                            cairo_t            *cr,
+                                            GtkStateType        state_type,
+                                            GtkShadowType       shadow_type,
+                                            GtkWidget          *widget,
+                                            const gchar        *detail,
+                                            GtkArrowType        arrow_type,
+                                            gboolean            fill,
+                                            gint                x,
+                                            gint                y,
+                                            gint                width,
+                                            gint                height);
+void          meta_paint_box               (GtkStyle           *style,
+                                            cairo_t            *cr,
+                                            GtkStateType        state_type,
+                                            GtkShadowType       shadow_type,
+                                            GtkWidget          *widget,
+                                            const gchar        *detail,
+                                            gint                x,
+                                            gint                y,
+                                            gint                width,
+                                            gint                height);
+void          meta_paint_flat_box          (GtkStyle           *style,
+                                            cairo_t            *cr,
+                                            GtkStateType        state_type,
+                                            GtkShadowType       shadow_type,
+                                            GtkWidget          *widget,
+                                            const gchar        *detail,
+                                            gint                x,
+                                            gint                y,
+                                            gint                width,
+                                            gint                height);
+
+#endif /* __GTK3_COMPAT_H__ */
diff --git a/src/ui/frames.c b/src/ui/frames.c
index fa59b6a..b952cab 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -36,6 +36,7 @@
 #include "prefs.h"
 #include "ui.h"
 
+#include "gdk2-drawing-utils.h"
 #include "gtk-compat.h"
 #include "gdk-compat.h"
 
@@ -2384,6 +2385,7 @@ meta_frames_paint_to_drawable (MetaFrames   *frames,
   MetaButtonLayout button_layout;
   MetaGrabOp grab_op;
   Display *display;
+  cairo_t *cr;
   
   widget = GTK_WIDGET (frames);
   display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
@@ -2496,11 +2498,12 @@ meta_frames_paint_to_drawable (MetaFrames   *frames,
 
   meta_prefs_get_button_layout (&button_layout);
 
+  cr = meta_cairo_create (drawable);
+
   meta_theme_draw_frame_with_style (meta_theme_get_current (),
                                     frame->style,
                                     widget,
-                                    drawable,
-                                    NULL, /* &areas[i], */
+                                    cr,
                                     x_offset, y_offset,
                                     type,
                                     flags,
@@ -2510,6 +2513,8 @@ meta_frames_paint_to_drawable (MetaFrames   *frames,
                                     &button_layout,
                                     button_states,
                                     mini_icon, icon);
+
+  cairo_destroy (cr);
 }
 
 static void
diff --git a/src/ui/preview-widget.c b/src/ui/preview-widget.c
index 87229e0..87b641a 100644
--- a/src/ui/preview-widget.c
+++ b/src/ui/preview-widget.c
@@ -28,6 +28,8 @@
 #include <gtk/gtk.h>
 #include "preview-widget.h"
 
+#include "gdk2-drawing-utils.h"
+
 static void     meta_preview_size_request  (GtkWidget        *widget,
                                             GtkRequisition   *req);
 static void     meta_preview_size_allocate (GtkWidget        *widget,
@@ -220,10 +222,15 @@ meta_preview_expose (GtkWidget      *widget,
   
   if (preview->theme)
     {
+      cairo_t *cr;
+
+      cr = meta_cairo_create (gtk_widget_get_window (widget));
+      gdk_cairo_region (cr, event->region);
+      cairo_clip (cr);
+
       meta_theme_draw_frame (preview->theme,
                              widget,
-                             gtk_widget_get_window (widget),
-                             &event->area,
+                             cr,
                              allocation.x + border_width,
                              allocation.y + border_width,
                              preview->type,
@@ -235,6 +242,8 @@ meta_preview_expose (GtkWidget      *widget,
                              button_states,
                              meta_preview_get_mini_icon (),
                              meta_preview_get_icon ());
+
+      cairo_destroy (cr);
     }
 
   /* draw child */
diff --git a/src/ui/theme-viewer.c b/src/ui/theme-viewer.c
index 04a5b76..7c0d3b1 100644
--- a/src/ui/theme-viewer.c
+++ b/src/ui/theme-viewer.c
@@ -35,6 +35,8 @@
 #define _(x) dgettext (GETTEXT_PACKAGE, x)
 #define N_(x) x
 
+#include "gdk2-drawing-utils.h"
+
 /* We need to compute all different button arrangements
  * in terms of button location. We don't care about
  * different arrangements in terms of button function.
@@ -959,6 +961,7 @@ run_theme_benchmark (void)
 #define ITERATIONS 100
   int client_width;
   int client_height;
+  cairo_t *cr;
   int inc;
   
   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -1009,10 +1012,11 @@ run_theme_benchmark (void)
                                client_height + top_height + bottom_height,
                                -1);
 
+      cr = meta_cairo_create (pixmap);
+
       meta_theme_draw_frame (global_theme,
                              widget,
-                             pixmap,
-                             NULL,
+                             cr,
                              0, 0,
                              META_FRAME_TYPE_NORMAL,
                              get_flags (widget),
@@ -1024,6 +1028,7 @@ run_theme_benchmark (void)
                              meta_preview_get_mini_icon (),
                              meta_preview_get_icon ());
 
+      cairo_destroy (cr);
       g_object_unref (G_OBJECT (pixmap));
       
       ++i;
diff --git a/src/ui/theme.c b/src/ui/theme.c
index 6e51a5d..0e308a5 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -63,6 +63,8 @@
 #include <math.h>
 
 #include "gtk-compat.h"
+#include "gdk-compat.h"
+#include "gdk2-drawing-utils.h"
 
 #define GDK_COLOR_RGBA(color)                                           \
                          ((guint32) (0xff                         |     \
@@ -3448,25 +3450,17 @@ static void
 meta_draw_op_draw_with_env (const MetaDrawOp    *op,
                             GtkStyle            *style_gtk,
                             GtkWidget           *widget,
-                            GdkDrawable         *drawable,
-                            const GdkRectangle  *clip,
+                            cairo_t             *cr,
                             const MetaDrawInfo  *info,
                             MetaRectangle        rect,
                             MetaPositionExprEnv *env)
 {
   GdkColor color;
-  cairo_t *cr;
 
-  cr = gdk_cairo_create (drawable);
+  cairo_save (cr);
 
   cairo_set_line_width (cr, 1.0);
 
-  if (clip)
-    {
-      gdk_cairo_rectangle (cr, clip);
-      cairo_clip (cr);
-    }
-  
   switch (op->type)
     {
     case META_DRAW_LINE:
@@ -3716,11 +3710,10 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.gtk_arrow.width, env);
         rheight = parse_size_unchecked (op->data.gtk_arrow.height, env);
 
-        gtk_paint_arrow (style_gtk,
-                         drawable,
+        meta_paint_arrow (style_gtk,
+                         cr,
                          op->data.gtk_arrow.state,
                          op->data.gtk_arrow.shadow,
-                         (GdkRectangle*) clip,
                          widget,
                          "metacity",
                          op->data.gtk_arrow.arrow,
@@ -3738,11 +3731,10 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.gtk_box.width, env);
         rheight = parse_size_unchecked (op->data.gtk_box.height, env);
 
-        gtk_paint_box (style_gtk,
-                       drawable,
+        meta_paint_box (style_gtk,
+                       cr,
                        op->data.gtk_box.state,
                        op->data.gtk_box.shadow,
-                       (GdkRectangle*) clip,
                        widget,
                        "metacity",
                        rx, ry, rwidth, rheight);
@@ -3757,13 +3749,12 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         ry1 = parse_y_position_unchecked (op->data.gtk_vline.y1, env);
         ry2 = parse_y_position_unchecked (op->data.gtk_vline.y2, env);
         
-        gtk_paint_vline (style_gtk,
-                         drawable,
-                         op->data.gtk_vline.state,
-                         (GdkRectangle*) clip,
-                         widget,
-                         "metacity",
-                         ry1, ry2, rx);
+        meta_paint_vline (style_gtk,
+                          cr,
+                          op->data.gtk_vline.state,
+                          widget,
+                          "metacity",
+                          ry1, ry2, rx);
       }
       break;
 
@@ -3855,7 +3846,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         d_rect.height = parse_size_unchecked (op->data.op_list.height, env);
 
         meta_draw_op_list_draw_with_style (op->data.op_list.op_list,
-                                           style_gtk, widget, drawable, clip, info,
+                                           style_gtk, widget, cr, info,
                                 d_rect);
       }
       break;
@@ -3864,7 +3855,6 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
       {
         int rx, ry, rwidth, rheight;
         int tile_xoffset, tile_yoffset; 
-        GdkRectangle new_clip;
         MetaRectangle tile;
         
         rx = parse_x_position_unchecked (op->data.tile.x, env);
@@ -3872,63 +3862,58 @@ meta_draw_op_draw_with_env (const MetaDrawOp    *op,
         rwidth = parse_size_unchecked (op->data.tile.width, env);
         rheight = parse_size_unchecked (op->data.tile.height, env);
 
-        new_clip.x = rx;
-        new_clip.y = ry;
-        new_clip.width = rwidth;
-        new_clip.height = rheight;
+        cairo_save (cr);
 
-        if (clip == NULL || gdk_rectangle_intersect ((GdkRectangle*)clip, &new_clip,
-                                                     &new_clip))
-          {
-            tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env);
-            tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env);
-            /* tile offset should not include x/y */
-            tile_xoffset -= rect.x;
-            tile_yoffset -= rect.y;
-            
-            tile.width = parse_size_unchecked (op->data.tile.tile_width, env);
-            tile.height = parse_size_unchecked (op->data.tile.tile_height, env);
+        cairo_rectangle (cr, rx, ry, rwidth, rheight);
+        cairo_clip (cr);
 
-            tile.x = rx - tile_xoffset;
+        tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env);
+        tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env);
+        /* tile offset should not include x/y */
+        tile_xoffset -= rect.x;
+        tile_yoffset -= rect.y;
         
-            while (tile.x < (rx + rwidth))
-              {
-                tile.y = ry - tile_yoffset;
-                while (tile.y < (ry + rheight))
-                  {
-                    meta_draw_op_list_draw_with_style (op->data.tile.op_list,
-                                                       style_gtk, widget, drawable, &new_clip, info,
-                                            tile);
+        tile.width = parse_size_unchecked (op->data.tile.tile_width, env);
+        tile.height = parse_size_unchecked (op->data.tile.tile_height, env);
 
-                    tile.y += tile.height;
-                  }
+        tile.x = rx - tile_xoffset;
+    
+        while (tile.x < (rx + rwidth))
+          {
+            tile.y = ry - tile_yoffset;
+            while (tile.y < (ry + rheight))
+              {
+                meta_draw_op_list_draw_with_style (op->data.tile.op_list,
+                                                   style_gtk, widget, cr, info,
+                                        tile);
 
-                tile.x += tile.width;
+                tile.y += tile.height;
               }
+
+            tile.x += tile.width;
           }
+        cairo_restore (cr);
+
       }
       break;
     }
 
-  cairo_destroy (cr);
+  cairo_restore (cr);
 }
 
 void
 meta_draw_op_draw_with_style (const MetaDrawOp    *op,
                               GtkStyle            *style_gtk,
                    GtkWidget           *widget,
-                   GdkDrawable         *drawable,
-                   const GdkRectangle  *clip,
+                   cairo_t             *cr,
                    const MetaDrawInfo  *info,
                    MetaRectangle        logical_region)
 {
   MetaPositionExprEnv env;
 
-  g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable));
-
   fill_env (&env, info, logical_region);
 
-  meta_draw_op_draw_with_env (op, style_gtk, widget, drawable, clip,
+  meta_draw_op_draw_with_env (op, style_gtk, widget, cr,
                               info, logical_region,
                               &env);
 
@@ -3937,13 +3922,12 @@ meta_draw_op_draw_with_style (const MetaDrawOp    *op,
 void
 meta_draw_op_draw (const MetaDrawOp    *op,
                    GtkWidget           *widget,
-                   GdkDrawable         *drawable,
-                   const GdkRectangle  *clip,
+                   cairo_t             *cr,
                    const MetaDrawInfo  *info,
                    MetaRectangle        logical_region)
 {
   meta_draw_op_draw_with_style (op, gtk_widget_get_style (widget), widget,
-                                drawable, clip, info, logical_region);
+                                cr, info, logical_region);
 }
 
 /**
@@ -4001,18 +3985,13 @@ void
 meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
                                     GtkStyle             *style_gtk,
                          GtkWidget            *widget,
-                         GdkDrawable          *drawable,
-                         const GdkRectangle   *clip,
+                         cairo_t              *cr,
                          const MetaDrawInfo   *info,
                          MetaRectangle         rect)
 {
   int i;
-  GdkRectangle active_clip;
-  GdkRectangle orig_clip;
   MetaPositionExprEnv env;
 
-  g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable));
-
   if (op_list->n_ops == 0)
     return;
   
@@ -4029,19 +4008,8 @@ meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
    * evaluated), we make an array of those, and then fold
    * adjacent items when possible.
    */
-  if (clip)
-    {
-      orig_clip = *clip;
-    }
-  else
-    {
-      orig_clip.x = rect.x;
-      orig_clip.y = rect.y;
-      orig_clip.width = rect.width;
-      orig_clip.height = rect.height;
-    }
 
-  active_clip = orig_clip;
+  cairo_save (cr);
 
   for (i = 0; i < op_list->n_ops; i++)
     {
@@ -4049,35 +4017,39 @@ meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
       
       if (op->type == META_DRAW_CLIP)
         {
-          active_clip.x = parse_x_position_unchecked (op->data.clip.x, &env);
-          active_clip.y = parse_y_position_unchecked (op->data.clip.y, &env);
-          active_clip.width = parse_size_unchecked (op->data.clip.width, &env);
-          active_clip.height = parse_size_unchecked (op->data.clip.height, &env);
+          cairo_restore (cr);
+
+          cairo_rectangle (cr, 
+                           parse_x_position_unchecked (op->data.clip.x, &env),
+                           parse_y_position_unchecked (op->data.clip.y, &env),
+                           parse_size_unchecked (op->data.clip.width, &env),
+                           parse_size_unchecked (op->data.clip.height, &env));
+          cairo_clip (cr);
           
-          gdk_rectangle_intersect (&orig_clip, &active_clip, &active_clip);
+          cairo_save (cr);
         }
-      else if (active_clip.width > 0 &&
-               active_clip.height > 0)
+      else if (gdk_cairo_get_clip_rectangle (cr, NULL))
         {
           meta_draw_op_draw_with_env (op,
-                                      style_gtk, widget, drawable, &active_clip, info,
+                                      style_gtk, widget, cr, info,
                                       rect,
                                       &env);
         }
     }
+
+  cairo_restore (cr);
 }
 
 void
 meta_draw_op_list_draw  (const MetaDrawOpList *op_list,
                          GtkWidget            *widget,
-                         GdkDrawable          *drawable,
-                         const GdkRectangle   *clip,
+                         cairo_t              *cr,
                          const MetaDrawInfo   *info,
                          MetaRectangle         rect)
 
 {
   meta_draw_op_list_draw_with_style (op_list, gtk_widget_get_style (widget), widget,
-                                     drawable, clip, info, rect);
+                                     cr, info, rect);
 }
 
 void
@@ -4385,10 +4357,9 @@ void
 meta_frame_style_draw_with_style (MetaFrameStyle          *style,
                                   GtkStyle                *style_gtk,
                        GtkWidget               *widget,
-                       GdkDrawable             *drawable,
+                       cairo_t                 *cr,
                        int                      x_offset,
                        int                      y_offset,
-                       const GdkRectangle      *clip,
                        const MetaFrameGeometry *fgeom,
                        int                      client_width,
                        int                      client_height,
@@ -4408,8 +4379,6 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
   PangoRectangle logical_rect;
   MetaDrawInfo draw_info;
   
-  g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable));
-
   titlebar_rect.x = 0;
   titlebar_rect.y = 0;
   titlebar_rect.width = fgeom->width;
@@ -4466,7 +4435,6 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
   while (i < META_FRAME_PIECE_LAST)
     {
       GdkRectangle rect;
-      GdkRectangle combined_clip;
       
       switch ((MetaFramePiece) i)
         {
@@ -4533,17 +4501,12 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
           break;
         }
 
-      rect.x += x_offset;
-      rect.y += y_offset;
+      cairo_save (cr);
 
-      if (clip == NULL)
-        combined_clip = rect;
-      else
-        gdk_rectangle_intersect ((GdkRectangle*) clip, /* const cast */
-                                 &rect,
-                                 &combined_clip);
+      gdk_cairo_rectangle (cr, &rect);
+      cairo_clip (cr);
 
-      if (combined_clip.width > 0 && combined_clip.height > 0)
+      if (gdk_cairo_get_clip_rectangle (cr, NULL))
         {
           MetaDrawOpList *op_list;
           MetaFrameStyle *parent;
@@ -4563,17 +4526,18 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
               meta_draw_op_list_draw_with_style (op_list,
                                                  style_gtk,
                                       widget,
-                                      drawable,
-                                      &combined_clip,
+                                      cr,
                                       &draw_info,
                                       m_rect);
             }
         }
 
+      cairo_restore (cr);
 
       /* Draw buttons just before overlay */
       if ((i + 1) == META_FRAME_PIECE_OVERLAY)
         {
+          MetaDrawOpList *op_list;
           int middle_bg_offset;
 
           middle_bg_offset = 0;
@@ -4585,32 +4549,30 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
               rect.x += x_offset;
               rect.y += y_offset;
               
-              if (clip == NULL)
-                combined_clip = rect;
-              else
-                gdk_rectangle_intersect ((GdkRectangle*) clip, /* const cast */
-                                         &rect,
-                                         &combined_clip);
+              op_list = get_button (style, j, button_states[j]);
               
-              if (combined_clip.width > 0 && combined_clip.height > 0)
+              if (op_list)
                 {
-                  MetaDrawOpList *op_list;
-                  
-                  op_list = get_button (style, j, button_states[j]);
-                  
-                  if (op_list)
+                  cairo_save (cr);
+                  gdk_cairo_rectangle (cr, &rect);
+                  cairo_clip (cr);
+
+                  if (gdk_cairo_get_clip_rectangle (cr, NULL))
                     {
                       MetaRectangle m_rect;
+
                       m_rect = meta_rect (rect.x, rect.y,
                                           rect.width, rect.height);
+
                       meta_draw_op_list_draw_with_style (op_list,
                                                          style_gtk,
-                                              widget,
-                                              drawable,
-                                              &combined_clip,
-                                              &draw_info,
-                                              m_rect);
+                                                         widget,
+                                                         cr,
+                                                         &draw_info,
+                                                         m_rect);
                     }
+
+                  cairo_restore (cr);
                 }
 
               /* MIDDLE_BACKGROUND type may get drawn more than once */
@@ -4627,7 +4589,7 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
                 }
             }
         }
-      
+
       ++i;
     }
 }
@@ -4635,10 +4597,9 @@ meta_frame_style_draw_with_style (MetaFrameStyle          *style,
 void
 meta_frame_style_draw (MetaFrameStyle          *style,
                        GtkWidget               *widget,
-                       GdkDrawable             *drawable,
+                       cairo_t                 *cr,
                        int                      x_offset,
                        int                      y_offset,
-                       const GdkRectangle      *clip,
                        const MetaFrameGeometry *fgeom,
                        int                      client_width,
                        int                      client_height,
@@ -4649,8 +4610,8 @@ meta_frame_style_draw (MetaFrameStyle          *style,
                        GdkPixbuf               *icon)
 {
   meta_frame_style_draw_with_style (style, gtk_widget_get_style (widget), widget,
-                                    drawable, x_offset, y_offset,
-                                    clip, fgeom, client_width, client_height,
+                                    cr, x_offset, y_offset,
+                                    fgeom, client_width, client_height,
                                     title_layout, text_height,
                                     button_states, mini_icon, icon);
 }
@@ -5219,8 +5180,7 @@ void
 meta_theme_draw_frame_with_style (MetaTheme              *theme,
                                   GtkStyle               *style_gtk,
                        GtkWidget              *widget,
-                       GdkDrawable            *drawable,
-                       const GdkRectangle     *clip,
+                       cairo_t                *cr,
                        int                     x_offset,
                        int                     y_offset,
                        MetaFrameType           type,
@@ -5256,9 +5216,8 @@ meta_theme_draw_frame_with_style (MetaTheme              *theme,
   meta_frame_style_draw_with_style (style,
                                     style_gtk,
                                     widget,
-                                    drawable,
+                                    cr,
                                     x_offset, y_offset,
-                                    clip,
                                     &fgeom,
                                     client_width, client_height,
                                     title_layout,
@@ -5270,8 +5229,7 @@ meta_theme_draw_frame_with_style (MetaTheme              *theme,
 void
 meta_theme_draw_frame (MetaTheme              *theme,
                        GtkWidget              *widget,
-                       GdkDrawable            *drawable,
-                       const GdkRectangle     *clip,
+                       cairo_t                *cr,
                        int                     x_offset,
                        int                     y_offset,
                        MetaFrameType           type,
@@ -5286,7 +5244,7 @@ meta_theme_draw_frame (MetaTheme              *theme,
                        GdkPixbuf              *icon)
 {
   meta_theme_draw_frame_with_style (theme, gtk_widget_get_style (widget), widget,
-                                    drawable, clip, x_offset, y_offset, type,flags,
+                                    cr, x_offset, y_offset, type,flags,
                                     client_width, client_height,
                                     title_layout, text_height,
                                     button_layout, button_states,
@@ -5296,8 +5254,7 @@ meta_theme_draw_frame (MetaTheme              *theme,
 void
 meta_theme_draw_frame_by_name (MetaTheme              *theme,
                                GtkWidget              *widget,
-                               GdkDrawable            *drawable,
-                               const GdkRectangle     *clip,
+                               cairo_t                *cr,
                                int                     x_offset,
                                int                     y_offset,
                                const gchar             *style_name,
@@ -5330,9 +5287,8 @@ meta_theme_draw_frame_by_name (MetaTheme              *theme,
 
   meta_frame_style_draw (style,
                          widget,
-                         drawable,
+                         cr,
                          x_offset, y_offset,
-                         clip,
                          &fgeom,
                          client_width, client_height,
                          title_layout,
diff --git a/src/ui/theme.h b/src/ui/theme.h
index 7558ccd..cedbc12 100644
--- a/src/ui/theme.h
+++ b/src/ui/theme.h
@@ -955,8 +955,7 @@ MetaDrawOp*    meta_draw_op_new  (MetaDrawType        type);
 void           meta_draw_op_free (MetaDrawOp          *op);
 void           meta_draw_op_draw (const MetaDrawOp    *op,
                                   GtkWidget           *widget,
-                                  GdkDrawable         *drawable,
-                                  const GdkRectangle  *clip,
+                                  cairo_t             *cr,
                                   const MetaDrawInfo  *info,
                                   /* logical region being drawn */
                                   MetaRectangle        logical_region);
@@ -964,8 +963,7 @@ void           meta_draw_op_draw (const MetaDrawOp    *op,
 void           meta_draw_op_draw_with_style (const MetaDrawOp    *op,
                                              GtkStyle            *style_gtk,
                                              GtkWidget           *widget,
-                                             GdkDrawable         *drawable,
-                                             const GdkRectangle  *clip,
+                                             cairo_t             *cr,
                                              const MetaDrawInfo  *info,
                                              /* logical region being drawn */
                                              MetaRectangle        logical_region);
@@ -975,15 +973,13 @@ void            meta_draw_op_list_ref   (MetaDrawOpList       *op_list);
 void            meta_draw_op_list_unref (MetaDrawOpList       *op_list);
 void            meta_draw_op_list_draw  (const MetaDrawOpList *op_list,
                                          GtkWidget            *widget,
-                                         GdkDrawable          *drawable,
-                                         const GdkRectangle   *clip,
+                                         cairo_t              *cr,
                                          const MetaDrawInfo   *info,
                                          MetaRectangle         rect);
 void            meta_draw_op_list_draw_with_style  (const MetaDrawOpList *op_list,
                                                     GtkStyle             *style_gtk,
                                                     GtkWidget            *widget,
-                                                    GdkDrawable          *drawable,
-                                                    const GdkRectangle   *clip,
+                                                    cairo_t              *cr,
                                                     const MetaDrawInfo   *info,
                                                     MetaRectangle         rect);
 void           meta_draw_op_list_append (MetaDrawOpList       *op_list,
@@ -1013,10 +1009,9 @@ void            meta_frame_style_unref (MetaFrameStyle *style);
 
 void meta_frame_style_draw (MetaFrameStyle          *style,
                             GtkWidget               *widget,
-                            GdkDrawable             *drawable,
+                            cairo_t                 *cr,
                             int                      x_offset,
                             int                      y_offset,
-                            const GdkRectangle      *clip,
                             const MetaFrameGeometry *fgeom,
                             int                      client_width,
                             int                      client_height,
@@ -1030,10 +1025,9 @@ void meta_frame_style_draw (MetaFrameStyle          *style,
 void meta_frame_style_draw_with_style (MetaFrameStyle          *style,
                                        GtkStyle                *style_gtk,
                                        GtkWidget               *widget,
-                                       GdkDrawable             *drawable,
+                                       cairo_t                 *cr,
                                        int                      x_offset,
                                        int                      y_offset,
-                                       const GdkRectangle      *clip,
                                        const MetaFrameGeometry *fgeom,
                                        int                      client_width,
                                        int                      client_height,
@@ -1078,8 +1072,7 @@ double meta_theme_get_title_scale (MetaTheme     *theme,
 
 void meta_theme_draw_frame (MetaTheme              *theme,
                             GtkWidget              *widget,
-                            GdkDrawable            *drawable,
-                            const GdkRectangle     *clip,
+                            cairo_t                *cr,
                             int                     x_offset,
                             int                     y_offset,
                             MetaFrameType           type,
@@ -1095,8 +1088,7 @@ void meta_theme_draw_frame (MetaTheme              *theme,
 
 void meta_theme_draw_frame_by_name (MetaTheme              *theme,
                                     GtkWidget              *widget,
-                                    GdkDrawable            *drawable,
-                                    const GdkRectangle     *clip,
+                                    cairo_t                *cr,
                                     int                     x_offset,
                                     int                     y_offset,
                                     const gchar             *style_name,
@@ -1113,8 +1105,7 @@ void meta_theme_draw_frame_by_name (MetaTheme              *theme,
 void meta_theme_draw_frame_with_style (MetaTheme              *theme,
                                        GtkStyle               *style_gtk,
                                        GtkWidget              *widget,
-                                       GdkDrawable            *drawable,
-                                       const GdkRectangle     *clip,
+                                       cairo_t                *cr,
                                        int                     x_offset,
                                        int                     y_offset,
                                        MetaFrameType           type,



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