[gtk+/wip/otte/snapshot: 3/15] window: Implement snapshot()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/snapshot: 3/15] window: Implement snapshot()
- Date: Mon, 14 Nov 2016 03:28:39 +0000 (UTC)
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]