[gtk+/wip/ebassi/frame-marker: 6/12] Simplify the widget rendering entry point



commit bdc74bd96e98977e6affc7029ba1d475b4247406
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Fri May 20 16:59:51 2016 +0100

    Simplify the widget rendering entry point
    
    Now that GDK has the appropriate API, we can simplify the widget drawing
    code into a single function.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=766675

 gtk/gtkmain.c          |   27 +-----------
 gtk/gtkwidget.c        |  114 ++++++++++++++++++++++++++++-------------------
 gtk/gtkwidgetprivate.h |    5 ++
 3 files changed, 74 insertions(+), 72 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index f104f16..d0d91ef 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1804,32 +1804,7 @@ gtk_main_do_event (GdkEvent *event)
 
     case GDK_EXPOSE:
       if (event->any.window)
-        {
-          gboolean is_double_buffered;
-
-          G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
-          is_double_buffered = gtk_widget_get_double_buffered (event_widget);
-          G_GNUC_END_IGNORE_DEPRECATIONS;
-
-          if (is_double_buffered)
-            {
-              /* We handle exposes only on native windows, relying on the
-               * draw() handler to propagate down to non-native windows.
-               * This is ok now that child windows are always considered
-               * (semi)transparent.
-               */
-              if (gdk_window_has_native (event->expose.window))
-                {
-                  gdk_window_begin_paint_region (event->any.window, event->expose.region);
-                  gtk_widget_send_expose (event_widget, event);
-                  gdk_window_end_paint (event->any.window);
-                }
-            }
-          else
-            {
-              gtk_widget_send_expose (event_widget, event);
-            }
-        }
+        gtk_widget_render (event_widget, event->any.window, event->expose.region);
       break;
 
     case GDK_PROPERTY_NOTIFY:
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 006be5e..2751a4d 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -6883,21 +6883,22 @@ gtk_widget_real_mnemonic_activate (GtkWidget *widget,
   return TRUE;
 }
 
-static const cairo_user_data_key_t event_window_key;
+static const cairo_user_data_key_t mark_for_draw_key;
 
-static GdkWindow *
-gtk_cairo_get_event_window (cairo_t *cr)
+static gboolean
+gtk_cairo_is_marked_for_draw (cairo_t *cr)
 {
-  g_return_val_if_fail (cr != NULL, NULL);
-
-  return cairo_get_user_data (cr, &event_window_key);
+  return cairo_get_user_data (cr, &mark_for_draw_key) != NULL;
 }
 
 static void
-gtk_cairo_set_event_window (cairo_t        *cr,
-                           GdkWindow *event_window)
+gtk_cairo_set_marked_for_draw (cairo_t  *cr,
+                               gboolean  marked)
 {
-  cairo_set_user_data (cr, &event_window_key, event_window, NULL);
+  if (marked)
+    cairo_set_user_data (cr, &mark_for_draw_key, GINT_TO_POINTER (1), NULL);
+  else
+    cairo_set_user_data (cr, &mark_for_draw_key, NULL, NULL);
 }
 
 /**
@@ -6919,25 +6920,28 @@ gtk_cairo_set_event_window (cairo_t        *cr,
  * Returns: %TRUE if @window should be drawn
  *
  * Since: 3.0
- **/
+ */
 gboolean
-gtk_cairo_should_draw_window (cairo_t *cr,
+gtk_cairo_should_draw_window (cairo_t   *cr,
                               GdkWindow *window)
 {
-  GdkWindow *event_window;
+  GdkWindow *tmp;
 
   g_return_val_if_fail (cr != NULL, FALSE);
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  event_window = gtk_cairo_get_event_window (cr);
+  if (gtk_cairo_is_marked_for_draw (cr))
+    return TRUE;
 
-  if (event_window == NULL)
+  tmp = gdk_cairo_get_window (cr);
+
+  if (tmp == NULL)
     return TRUE;
 
   while (!gdk_window_has_native (window))
     window = gdk_window_get_parent (window);
 
-  return event_window == window;
+  return tmp == window;
 }
 
 void
@@ -6964,9 +6968,19 @@ gtk_widget_draw_internal (GtkWidget *widget,
       gboolean result;
       gboolean push_group;
 
-      event_window = gtk_cairo_get_event_window (cr);
-      if (event_window)
-        gdk_window_mark_paint_from_clip (event_window, cr);
+      /* If this was a cairo_t passed via gtk_widget_draw() then we don't
+       * require a window
+       */
+      if (gtk_cairo_is_marked_for_draw (cr))
+        {
+          event_window = NULL;
+        }
+      else
+        {
+          event_window = gdk_cairo_get_window (cr);
+          if (event_window != NULL)
+            gdk_window_mark_paint_from_clip (event_window, cr);
+        }
 
       push_group =
         widget->priv->alpha != 255 &&
@@ -7077,7 +7091,7 @@ void
 gtk_widget_draw (GtkWidget *widget,
                  cairo_t   *cr)
 {
-  GdkWindow *tmp_event_window;
+  gboolean was_marked;
 
   g_return_if_fail (GTK_IS_WIDGET (widget));
   g_return_if_fail (!widget->priv->alloc_needed);
@@ -7086,17 +7100,18 @@ gtk_widget_draw (GtkWidget *widget,
 
   cairo_save (cr);
 
-  /* We have to reset the event here so that draw functions can call
-   * gtk_widget_draw() on random other widgets and get the desired
-   * effect: Drawing all contents, not just the current window.
+  was_marked = gtk_cairo_is_marked_for_draw (cr);
+
+  /* We mark the window so that gtk_cairo_should_draw_window()
+   * will always return TRUE, and all GdkWindows get drawn
    */
-  tmp_event_window = gtk_cairo_get_event_window (cr);
-  gtk_cairo_set_event_window (cr, NULL);
+  gtk_cairo_set_marked_for_draw (cr, TRUE);
 
   gtk_widget_draw_internal (widget, cr, TRUE);
 
+  gtk_cairo_set_marked_for_draw (cr, was_marked);
+
   cairo_restore (cr);
-  gtk_cairo_set_event_window (cr, tmp_event_window);
 }
 
 static gboolean
@@ -7506,32 +7521,12 @@ gint
 gtk_widget_send_expose (GtkWidget *widget,
                        GdkEvent  *event)
 {
-  cairo_t *cr;
-  int x, y;
-  gboolean do_clip;
-
   g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
   g_return_val_if_fail (gtk_widget_get_realized (widget), TRUE);
   g_return_val_if_fail (event != NULL, TRUE);
   g_return_val_if_fail (event->type == GDK_EXPOSE, TRUE);
 
-  cr = gdk_cairo_create (event->expose.window);
-  gtk_cairo_set_event_window (cr, event->expose.window);
-
-  gdk_cairo_region (cr, event->expose.region);
-  cairo_clip (cr);
-
-  do_clip = _gtk_widget_get_translation_to_window (widget,
-                                                   event->expose.window,
-                                                   &x, &y);
-  cairo_translate (cr, -x, -y);
-
-  gtk_widget_draw_internal (widget, cr, do_clip);
-
-  /* unset here, so if someone keeps a reference to cr we
-   * don't leak the window. */
-  gtk_cairo_set_event_window (cr, NULL);
-  cairo_destroy (cr);
+  gtk_widget_render (widget, event->any.window, event->expose.region);
 
   return FALSE;
 }
@@ -17439,3 +17434,30 @@ gtk_widget_reset_controllers (GtkWidget *widget)
       gtk_event_controller_reset (controller_data->controller);
     }
 }
+
+void
+gtk_widget_render (GtkWidget            *widget,
+                   GdkWindow            *window,
+                   const cairo_region_t *region)
+{
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+  gboolean do_clip;
+  cairo_t *cr;
+  int x, y;
+
+  if (priv->double_buffered)
+    {
+      /* We only render double buffered on native windows */
+      if (!gdk_window_has_native (window))
+        return;
+    }
+
+  cr = gdk_window_begin_draw_frame (window, region);
+
+  do_clip = _gtk_widget_get_translation_to_window (widget, window, &x, &y);
+  cairo_translate (cr, -x, -y);
+
+  gtk_widget_draw_internal (widget, cr, do_clip);
+
+  gdk_window_end_draw_frame (window, cr);
+}
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index e51dd39..aa7dba6 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -302,6 +302,11 @@ gboolean          gtk_widget_query_tooltip                 (GtkWidget  *widget,
                                                             gboolean    keyboard_mode,
                                                             GtkTooltip *tooltip);
 
+void              gtk_widget_render                        (GtkWidget            *widget,
+                                                            GdkWindow            *window,
+                                                            const cairo_region_t *region);
+
+
 /* inline getters */
 
 static inline gboolean


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