[gtk+/rendering-cleanup-next: 14/199] API: Add gtk_cairo_should_draw_window()



commit 3ab29d6e669c23958fb1aae86c2cdf246a216e5f
Author: Benjamin Otte <otte redhat com>
Date:   Thu Sep 2 23:26:13 2010 +0200

    API: Add gtk_cairo_should_draw_window()
    
    See the function documentation for its purpose and the next commit(s)
    for examples on how to use it.

 gtk/gtk.symbols |    1 +
 gtk/gtkwidget.c |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 16fa21c..6e43d6f 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -4177,6 +4177,7 @@ gtk_vseparator_new
 
 #if IN_HEADER(__GTK_WIDGET_H__)
 #if IN_FILE(__GTK_WIDGET_C__)
+gtk_cairo_should_draw_window
 gtk_requisition_copy
 gtk_requisition_free
 gtk_requisition_get_type G_GNUC_CONST
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 7ed8c44..b33d858 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -5070,10 +5070,59 @@ gtk_widget_real_mnemonic_activate (GtkWidget *widget,
   return TRUE;
 }
 
+static const cairo_user_data_key_t window_key;
+
+static GdkWindow *
+gtk_cairo_get_window (cairo_t *cr)
+{
+  g_return_val_if_fail (cr != NULL, NULL);
+
+  return cairo_get_user_data (cr, &window_key);
+}
+
+/**
+ * gtk_cairo_should_draw_window:
+ * @cr: a cairo context
+ * @window: the window to check
+ *
+ * This function is supposed to be called in GtkWidget::draw
+ * implementations for widgets that support multiple windows.
+ * @cr must be untransformed from invoking of the draw function.
+ * This function will return %TRUE if the contents of the given
+ * @window are supposed to be drawn and %FALSE otherwise. Note
+ * that when the drawing was not initiated by the windowing
+ * system this function will return %TRUE for all windows, so
+ * you need to draw the bottommost window first. Also, do not
+ * use "else if" statements to check which window should be drawn.
+ *
+ * Returns: %TRUE if @window should be drawn
+ **/
+gboolean
+gtk_cairo_should_draw_window (cairo_t *cr,
+                              GdkWindow *window)
+{
+  GdkWindow *cairo_window;
+
+  g_return_val_if_fail (cr != NULL, FALSE);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  cairo_window = gtk_cairo_get_window (cr);
+  
+  return cairo_window == NULL ||
+         cairo_window == window;
+}
+
+static void
+gtk_cairo_set_window (cairo_t   *cr,
+                      GdkWindow *window)
+{
+  cairo_set_user_data (cr, &window_key, window, NULL);
+}
 static gboolean
 gtk_widget_real_expose_event (GtkWidget      *widget,
 			      GdkEventExpose *expose)
 {
+  GdkWindow *window;
   gboolean result = FALSE;
   cairo_t *cr;
 
@@ -5081,9 +5130,34 @@ gtk_widget_real_expose_event (GtkWidget      *widget,
     return FALSE;
 
   cr = gdk_cairo_create (expose->window);
+  gtk_cairo_set_window (cr, expose->window);
+
   gdk_cairo_region (cr, expose->region);
   cairo_clip (cr);
 
+  /* translate cairo context properly */
+  window = gtk_widget_get_window (widget);
+  if (window != expose->window)
+    {
+      int x, y;
+
+      if (gdk_window_get_parent (expose->window) == window)
+        {
+          gdk_window_get_position (expose->window, &x, &y);
+        }
+      else
+        {
+          int ex, ey;
+          gdk_window_get_origin (expose->window, &ex, &ey);
+          gdk_window_get_origin (window, &x, &y);
+          x = ex - x;
+          y = ey - y;
+        }
+
+      cairo_translate (cr, -x, -y);
+    }
+
+
   if (!gtk_widget_get_has_window (widget))
     {
       cairo_translate (cr,
@@ -5094,7 +5168,10 @@ gtk_widget_real_expose_event (GtkWidget      *widget,
   g_signal_emit (widget, widget_signals[DRAW], 
                  0, cr,
                  &result);
-                
+
+  /* unset here, so if someone keeps a reference to cr we
+   * don't leak the window. */
+  gtk_cairo_set_window (cr, NULL);
   cairo_destroy (cr);
 
   return result;



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