[gtk+/wip/otte/snapshot: 3/15] window: Implement snapshot()



commit a26f4f5d03cfece8ad29ce9debd4d85ba1efe8dc
Author: Benjamin Otte <otte redhat com>
Date:   Tue Nov 8 01:42:06 2016 +0100

    window: Implement snapshot()

 gtk/gtkcontainer.c           |  117 +++++++++++++++++++++++++++++-------------
 gtk/gtkcontainerprivate.h    |    4 ++
 gtk/gtkdebugupdates.c        |    9 ++--
 gtk/gtkdebugupdatesprivate.h |    4 +-
 gtk/gtksnapshot.c            |   13 +++++
 gtk/gtksnapshotprivate.h     |   10 ++++
 gtk/gtkwidget.c              |    3 +
 gtk/gtkwindow.c              |   30 +++++++----
 8 files changed, 137 insertions(+), 53 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index a68fa87..893b1e4 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -42,6 +42,7 @@
 #include "gtkmarshalers.h"
 #include "gtksizerequest.h"
 #include "gtksizerequestcacheprivate.h"
+#include "gtksnapshotprivate.h"
 #include "gtkwidgetprivate.h"
 #include "gtkwindow.h"
 #include "gtkassistant.h"
@@ -3158,47 +3159,16 @@ gtk_container_get_children_clip (GtkContainer  *container,
   gtk_container_forall (container, union_with_clip, out_clip);
 }
 
-/**
- * gtk_container_propagate_draw:
- * @container: a #GtkContainer
- * @child: a child of @container
- * @cr: Cairo context as passed to the container. If you want to use @cr
- *   in container’s draw function, consider using cairo_save() and
- *   cairo_restore() before calling this function.
- *
- * When a container receives a call to the draw function, it must send
- * synthetic #GtkWidget::draw calls to all children that don’t have their
- * own #GdkWindows. This function provides a convenient way of doing this.
- * A container, when it receives a call to its #GtkWidget::draw function,
- * calls gtk_container_propagate_draw() once for each child, passing in
- * the @cr the container received.
- *
- * gtk_container_propagate_draw() takes care of translating the origin of @cr,
- * and deciding whether the draw needs to be sent to the child. It is a
- * convenient and optimized way of getting the same effect as calling
- * gtk_widget_draw() on the child directly.
- *
- * In most cases, a container can simply either inherit the
- * #GtkWidget::draw implementation from #GtkContainer, or do some drawing
- * and then chain to the ::draw implementation from #GtkContainer.
- **/
-void
-gtk_container_propagate_draw (GtkContainer *container,
-                              GtkWidget    *child,
-                              cairo_t      *cr)
+static void
+gtk_container_get_translation_to_child (GtkContainer *container,
+                                        GtkWidget    *child,
+                                        int          *x_out,
+                                        int          *y_out)
 {
   GtkAllocation allocation;
   GdkWindow *window, *w;
   int x, y;
 
-  g_return_if_fail (GTK_IS_CONTAINER (container));
-  g_return_if_fail (GTK_IS_WIDGET (child));
-  g_return_if_fail (cr != NULL);
-  g_return_if_fail (_gtk_widget_get_parent (child) == GTK_WIDGET (container));
-
-  if (!gtk_container_should_propagate_draw (container, child, cr))
-    return;
-
   /* translate coordinates. Ugly business, that. */
   if (!_gtk_widget_get_has_window (GTK_WIDGET (container)))
     {
@@ -3235,6 +3205,51 @@ gtk_container_propagate_draw (GtkContainer *container,
       y += allocation.y;
     }
 
+  *x_out = x;
+  *y_out = y;
+}
+
+/**
+ * gtk_container_propagate_draw:
+ * @container: a #GtkContainer
+ * @child: a child of @container
+ * @cr: Cairo context as passed to the container. If you want to use @cr
+ *   in container’s draw function, consider using cairo_save() and
+ *   cairo_restore() before calling this function.
+ *
+ * When a container receives a call to the draw function, it must send
+ * synthetic #GtkWidget::draw calls to all children that don’t have their
+ * own #GdkWindows. This function provides a convenient way of doing this.
+ * A container, when it receives a call to its #GtkWidget::draw function,
+ * calls gtk_container_propagate_draw() once for each child, passing in
+ * the @cr the container received.
+ *
+ * gtk_container_propagate_draw() takes care of translating the origin of @cr,
+ * and deciding whether the draw needs to be sent to the child. It is a
+ * convenient and optimized way of getting the same effect as calling
+ * gtk_widget_draw() on the child directly.
+ *
+ * In most cases, a container can simply either inherit the
+ * #GtkWidget::draw implementation from #GtkContainer, or do some drawing
+ * and then chain to the ::draw implementation from #GtkContainer.
+ **/
+void
+gtk_container_propagate_draw (GtkContainer *container,
+                              GtkWidget    *child,
+                              cairo_t      *cr)
+{
+  int x, y;
+
+  g_return_if_fail (GTK_IS_CONTAINER (container));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+  g_return_if_fail (cr != NULL);
+  g_return_if_fail (_gtk_widget_get_parent (child) == GTK_WIDGET (container));
+
+  if (!gtk_container_should_propagate_draw (container, child, cr))
+    return;
+
+  gtk_container_get_translation_to_child (container, child, &x, &y);
+
   cairo_save (cr);
   cairo_translate (cr, x, y);
 
@@ -3243,6 +3258,36 @@ gtk_container_propagate_draw (GtkContainer *container,
   cairo_restore (cr);
 }
 
+void
+gtk_container_snapshot_child (GtkContainer      *container,
+                              GskRenderNode     *container_node,
+                              GtkWidget         *child,
+                              const GtkSnapshot *snapshot)
+{
+  GtkSnapshot child_snapshot;
+  GskRenderNode *child_node;
+  int x, y;
+
+  g_return_if_fail (GTK_IS_CONTAINER (container));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+  g_return_if_fail (_gtk_widget_get_parent (child) == GTK_WIDGET (container));
+  g_return_if_fail (GSK_IS_RENDER_NODE (container_node));
+  g_return_if_fail (snapshot != NULL);
+
+  gtk_container_get_translation_to_child (container, child, &x, &y);
+
+  gtk_snapshot_init_translate (&child_snapshot, snapshot, x, y);
+  child_node = gtk_widget_snapshot (child, &child_snapshot);
+
+  if (child_node)
+    {
+      gsk_render_node_append_child (container_node, child_node);
+      gsk_render_node_unref (child_node);
+    }
+
+  gtk_snapshot_finish (&child_snapshot);
+}
+
 /**
  * gtk_container_get_path_for_child:
  * @container: a #GtkContainer
diff --git a/gtk/gtkcontainerprivate.h b/gtk/gtkcontainerprivate.h
index c106ab8..7b0b9e4 100644
--- a/gtk/gtkcontainerprivate.h
+++ b/gtk/gtkcontainerprivate.h
@@ -50,6 +50,10 @@ void      gtk_container_propagate_render_node_for_child   (GtkContainer  *contai
                                                            GtkWidget     *child,
                                                            GskRenderer   *renderer,
                                                            GskRenderNode *parent_node);
+void      gtk_container_snapshot_child          (GtkContainer      *container,
+                                                 GskRenderNode     *container_node,
+                                                 GtkWidget         *child,
+                                                 const GtkSnapshot *snapshot);
 
 G_END_DECLS
 
diff --git a/gtk/gtkdebugupdates.c b/gtk/gtkdebugupdates.c
index 42e89b6..752a9c4 100644
--- a/gtk/gtkdebugupdates.c
+++ b/gtk/gtkdebugupdates.c
@@ -265,8 +265,8 @@ gtk_debug_updates_queue_get_extents (GQueue       *updates,
 }
 
 GskRenderNode *
-gtk_debug_updates_get_render_node (GtkWidget   *widget,
-                                   GskRenderer *renderer)
+gtk_debug_updates_snapshot (GtkWidget         *widget,
+                            const GtkSnapshot *snapshot)
 {
   GQueue *updates;
   GskRenderNode *node;
@@ -287,12 +287,11 @@ gtk_debug_updates_get_render_node (GtkWidget   *widget,
   
   gtk_debug_updates_print (updates, NULL, "Painting at %lli", (long long) timestamp);
 
-  node = gsk_renderer_create_render_node (renderer);
-  gsk_render_node_set_name (node, "Debug Updates");
+  node = gtk_snapshot_create_render_node (snapshot, "Debug Updates");
   gtk_debug_updates_queue_get_extents (updates, &rect);
   gsk_render_node_set_bounds (node, &(graphene_rect_t) GRAPHENE_RECT_INIT(rect.x, rect.y, rect.width, 
rect.height));
 
-  cr = gsk_render_node_get_draw_context (node, renderer);
+  cr = gsk_render_node_get_draw_context (node, gtk_snapshot_get_renderer (snapshot));
 
   for (l = g_queue_peek_head_link (updates); l != NULL; l = l->next)
     {
diff --git a/gtk/gtkdebugupdatesprivate.h b/gtk/gtkdebugupdatesprivate.h
index 7134119..2e55ea4 100644
--- a/gtk/gtkdebugupdatesprivate.h
+++ b/gtk/gtkdebugupdatesprivate.h
@@ -31,8 +31,8 @@ void            gtk_debug_updates_set_enabled_for_display       (GdkDisplay
 
 void            gtk_debug_updates_add                           (GtkWidget              *widget,
                                                                  const cairo_region_t   *region);
-GskRenderNode * gtk_debug_updates_get_render_node               (GtkWidget              *widget,
-                                                                 GskRenderer            *renderer);
+GskRenderNode * gtk_debug_updates_snapshot                      (GtkWidget              *widget,
+                                                                 const GtkSnapshot      *snapshot);
 
 
 G_END_DECLS
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 0dbc3d1..d250745 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -32,6 +32,19 @@ gtk_snapshot_init (GtkSnapshot             *state,
 }
 
 void
+gtk_snapshot_init_translate (GtkSnapshot             *state,
+                             const GtkSnapshot       *parent,
+                             int                      x,
+                             int                      y)
+{
+  graphene_matrix_t matrix;
+
+  graphene_matrix_init_translate (&matrix, &(graphene_point3d_t) GRAPHENE_POINT3D_INIT (x, y, 0));
+
+  gtk_snapshot_init (state, parent, &matrix);
+}
+
+void
 gtk_snapshot_init_root (GtkSnapshot *state,
                         GskRenderer *renderer)
 {
diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h
index 5b238b7..bb8df07 100644
--- a/gtk/gtksnapshotprivate.h
+++ b/gtk/gtksnapshotprivate.h
@@ -33,9 +33,19 @@ struct _GtkSnapshot {
 void            gtk_snapshot_init               (GtkSnapshot             *state,
                                                  const GtkSnapshot       *parent,
                                                  const graphene_matrix_t *transform);
+void            gtk_snapshot_init_translate     (GtkSnapshot             *state,
+                                                 const GtkSnapshot       *parent,
+                                                 int                      x,
+                                                 int                      y);
 void            gtk_snapshot_init_root          (GtkSnapshot             *state,
                                                  GskRenderer             *renderer);
 
+static inline const graphene_matrix_t *
+gtk_snapshot_get_transform (const GtkSnapshot *snapshot)
+{
+  return &snapshot->transform;
+}
+
 void            gtk_snapshot_finish             (GtkSnapshot             *state);
 
 G_END_DECLS
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 562c5ee..e35e663 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -15742,6 +15742,9 @@ gtk_widget_snapshot (GtkWidget         *widget,
         }
     }
 
+  if (node)
+    gsk_render_node_set_transform (node, gtk_snapshot_get_transform (snapshot));
+
   return node;
 }
 
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 28b68af..4478a9b 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -447,8 +447,8 @@ static void gtk_window_real_activate_focus   (GtkWindow         *window);
 static void gtk_window_keys_changed          (GtkWindow         *window);
 static gboolean gtk_window_enable_debugging  (GtkWindow         *window,
                                               gboolean           toggle);
-static GskRenderNode *gtk_window_get_render_node (GtkWidget   *widget,
-                                                  GskRenderer *renderer);
+static GskRenderNode *gtk_window_snapshot          (GtkWidget         *widget,
+                                                    const GtkSnapshot *snapshot);
 static void gtk_window_unset_transient_for         (GtkWindow  *window);
 static void gtk_window_transient_parent_realized   (GtkWidget  *parent,
                                                    GtkWidget  *window);
@@ -776,7 +776,7 @@ gtk_window_class_init (GtkWindowClass *klass)
   widget_class->measure = gtk_window_measure;
   widget_class->state_flags_changed = gtk_window_state_flags_changed;
   widget_class->style_updated = gtk_window_style_updated;
-  widget_class->get_render_node = gtk_window_get_render_node;
+  widget_class->snapshot = gtk_window_snapshot;
   widget_class->queue_draw_region = gtk_window_queue_draw_region;
 
   container_class->remove = gtk_window_remove;
@@ -9370,8 +9370,8 @@ gtk_window_compute_hints (GtkWindow   *window,
  ***********************/
 
 static GskRenderNode *
-gtk_window_get_render_node (GtkWidget   *widget,
-                            GskRenderer *renderer)
+gtk_window_snapshot (GtkWidget         *widget,
+                     const GtkSnapshot *snapshot)
 {
   GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
   GtkStyleContext *context;
@@ -9383,6 +9383,7 @@ gtk_window_get_render_node (GtkWidget   *widget,
   graphene_matrix_t m;
   graphene_point3d_t p;
   cairo_t *cr;
+  GList *l;
 
   context = gtk_widget_get_style_context (widget);
 
@@ -9392,12 +9393,11 @@ gtk_window_get_render_node (GtkWidget   *widget,
   graphene_rect_init (&bounds, allocation.x, allocation.y, allocation.width, allocation.height);
   graphene_matrix_init_translate (&m, graphene_point3d_init (&p, allocation.x, allocation.y, 0.));
 
-  node = gsk_renderer_create_render_node (renderer);
-  gsk_render_node_set_name (node, "Window Decoration");
+  node = gtk_snapshot_create_render_node (snapshot, "Window Decoration");
   gsk_render_node_set_bounds (node, &bounds);
   gsk_render_node_set_transform (node, &m);
 
-  cr = gsk_render_node_get_draw_context (node, renderer);
+  cr = gsk_render_node_get_draw_context (node, gtk_snapshot_get_renderer (snapshot));
 
   if (priv->client_decorated &&
       priv->decorated &&
@@ -9464,9 +9464,19 @@ gtk_window_get_render_node (GtkWidget   *widget,
 
   cairo_destroy (cr);
 
-  gtk_container_propagate_render_node (GTK_CONTAINER (widget), renderer, node);
+  if (priv->title_box != NULL)
+    gtk_container_snapshot_child (GTK_CONTAINER (widget), node, priv->title_box, snapshot);
+
+  if (gtk_bin_get_child (GTK_BIN (widget)))
+    gtk_container_snapshot_child (GTK_CONTAINER (widget), node, gtk_bin_get_child (GTK_BIN (widget)), 
snapshot);
+
+  for (l = priv->popovers; l; l = l->next)
+    {
+      GtkWindowPopover *data = l->data;
+      gtk_container_snapshot_child (GTK_CONTAINER (widget), node, data->widget, snapshot);
+    }
 
-  updates_node = gtk_debug_updates_get_render_node (widget, renderer);
+  updates_node = gtk_debug_updates_snapshot (widget, snapshot);
   if (updates_node)
     {
       gsk_render_node_append_child (node, updates_node);


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