[gtk+/wip/renderops: 3/6] inspector: Add a way to snapshot rendering operations



commit 3fc2dc9a5c89466ce5719fee999b43c9d2c29bd6
Author: Benjamin Otte <otte redhat com>
Date:   Tue Jun 30 02:17:45 2015 +0200

    inspector: Add a way to snapshot rendering operations
    
    This shows the rendering broken into components for easier debugging.

 gtk/inspector/Makefile.inc               |   11 ++
 gtk/inspector/gtkrenderoperation.c       |   88 ++++++++++++
 gtk/inspector/gtkrenderoperation.h       |   69 ++++++++++
 gtk/inspector/gtkrenderoperationcairo.c  |   98 +++++++++++++
 gtk/inspector/gtkrenderoperationcairo.h  |   57 ++++++++
 gtk/inspector/gtkrenderoperationwidget.c |  123 +++++++++++++++++
 gtk/inspector/gtkrenderoperationwidget.h |   64 +++++++++
 gtk/inspector/magnifier.c                |   24 ++++
 gtk/inspector/magnifier.ui               |   11 ++
 gtk/inspector/recordingrenderops.c       |  187 +++++++++++++++++++++++++
 gtk/inspector/recordingrenderops.h       |   62 +++++++++
 gtk/inspector/snapshot.c                 |  218 ++++++++++++++++++++++++++++++
 gtk/inspector/snapshot.h                 |   66 +++++++++
 gtk/inspector/snapshot.ui                |   53 +++++++
 gtk/inspector/window.c                   |    6 +-
 gtk/inspector/window.h                   |    2 +
 16 files changed, 1136 insertions(+), 3 deletions(-)
---
diff --git a/gtk/inspector/Makefile.inc b/gtk/inspector/Makefile.inc
index 92fb1b9..cd05907 100644
--- a/gtk/inspector/Makefile.inc
+++ b/gtk/inspector/Makefile.inc
@@ -9,6 +9,9 @@ inspector_c_sources =                   \
        inspector/general.c             \
        inspector/gestures.c            \
        inspector/graphdata.c           \
+        inspector/gtkrenderoperation.c  \
+        inspector/gtkrenderoperationcairo.c   \
+        inspector/gtkrenderoperationwidget.c  \
        inspector/gtktreemodelcssnode.c \
        inspector/init.c                \
        inspector/inspect-button.c      \
@@ -19,10 +22,12 @@ inspector_c_sources =                       \
        inspector/object-tree.c         \
        inspector/prop-editor.c         \
        inspector/prop-list.c           \
+        inspector/recordingrenderops.c  \
        inspector/resource-list.c       \
        inspector/selector.c            \
        inspector/signals-list.c        \
        inspector/size-groups.c         \
+       inspector/snapshot.c            \
        inspector/statistics.c          \
        inspector/style-prop-list.c     \
        inspector/treewalk.c            \
@@ -40,6 +45,9 @@ inspector_h_sources =                         \
        inspector/general.h             \
        inspector/gestures.h            \
        inspector/graphdata.h           \
+        inspector/gtkrenderoperation.h  \
+        inspector/gtkrenderoperationcairo.h   \
+        inspector/gtkrenderoperationwidget.h  \
        inspector/gtktreemodelcssnode.h \
        inspector/init.h                \
        inspector/magnifier.h           \
@@ -49,10 +57,12 @@ inspector_h_sources =                       \
        inspector/object-tree.h         \
        inspector/prop-editor.h         \
        inspector/prop-list.h           \
+        inspector/recordingrenderops.h  \
        inspector/resource-list.h       \
        inspector/selector.h            \
        inspector/signals-list.h        \
        inspector/size-groups.h         \
+       inspector/snapshot.h            \
        inspector/statistics.h          \
        inspector/style-prop-list.h     \
        inspector/treewalk.h            \
@@ -75,6 +85,7 @@ inspector_templates =                 \
        inspector/resource-list.ui      \
        inspector/selector.ui           \
        inspector/signals-list.ui       \
+       inspector/snapshot.ui           \
        inspector/statistics.ui         \
        inspector/style-prop-list.ui    \
        inspector/visual.ui             \
diff --git a/gtk/inspector/gtkrenderoperation.c b/gtk/inspector/gtkrenderoperation.c
new file mode 100644
index 0000000..5e0520d
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperation.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright © 2011 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkrenderoperation.h"
+
+G_DEFINE_TYPE (GtkRenderOperation, gtk_render_operation, G_TYPE_OBJECT)
+
+static void
+gtk_render_operation_real_get_clip (GtkRenderOperation    *operation,
+                                    cairo_rectangle_int_t *clip)
+{
+  clip->x = clip->y = clip->width = clip->height = 0;
+}
+
+static void
+gtk_render_operation_real_get_matrix (GtkRenderOperation *operation,
+                                      cairo_matrix_t     *matrix)
+{
+  cairo_matrix_init_identity (matrix);
+}
+
+static void
+gtk_render_operation_real_draw (GtkRenderOperation *operation,
+                                cairo_t            *cr)
+{
+}
+
+static void
+gtk_render_operation_class_init (GtkRenderOperationClass *klass)
+{
+  klass->get_clip = gtk_render_operation_real_get_clip;
+  klass->get_matrix = gtk_render_operation_real_get_matrix;
+  klass->draw = gtk_render_operation_real_draw;
+}
+
+static void
+gtk_render_operation_init (GtkRenderOperation *image)
+{
+}
+
+void
+gtk_render_operation_get_clip (GtkRenderOperation    *operation,
+                               cairo_rectangle_int_t *clip)
+{
+  g_return_if_fail (GTK_IS_RENDER_OPERATION (operation));
+  g_return_if_fail (clip != NULL);
+
+  GTK_RENDER_OPERATION_GET_CLASS (operation)->get_clip (operation, clip);
+}
+
+void
+gtk_render_operation_get_matrix (GtkRenderOperation *operation,
+                                 cairo_matrix_t     *matrix)
+{
+  g_return_if_fail (GTK_IS_RENDER_OPERATION (operation));
+  g_return_if_fail (matrix != NULL);
+
+  GTK_RENDER_OPERATION_GET_CLASS (operation)->get_matrix (operation, matrix);
+}
+
+void
+gtk_render_operation_draw (GtkRenderOperation *operation,
+                           cairo_t            *cr)
+{
+  g_return_if_fail (GTK_IS_RENDER_OPERATION (operation));
+  g_return_if_fail (cr != NULL);
+
+  GTK_RENDER_OPERATION_GET_CLASS (operation)->draw (operation, cr);
+}
+
diff --git a/gtk/inspector/gtkrenderoperation.h b/gtk/inspector/gtkrenderoperation.h
new file mode 100644
index 0000000..e12f0d2
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperation.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2014 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_RENDER_OPERATION_PRIVATE_H__
+#define __GTK_RENDER_OPERATION_PRIVATE_H__
+
+#include <cairo.h>
+
+#include <gtk/gtktypes.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_RENDER_OPERATION           (gtk_render_operation_get_type ())
+#define GTK_RENDER_OPERATION(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_RENDER_OPERATION, 
GtkRenderOperation))
+#define GTK_RENDER_OPERATION_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_RENDER_OPERATION, 
GtkRenderOperationClass))
+#define GTK_IS_RENDER_OPERATION(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_RENDER_OPERATION))
+#define GTK_IS_RENDER_OPERATION_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_RENDER_OPERATION))
+#define GTK_RENDER_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_RENDER_OPERATION, 
GtkRenderOperationClass))
+
+typedef struct _GtkRenderOperation           GtkRenderOperation;
+typedef struct _GtkRenderOperationClass      GtkRenderOperationClass;
+
+struct _GtkRenderOperation
+{
+  GObject parent;
+};
+
+struct _GtkRenderOperationClass
+{
+  GObjectClass parent_class;
+
+  void          (* get_clip)                            (GtkRenderOperation      *operation,
+                                                         cairo_rectangle_int_t   *clip);
+  void          (* get_matrix)                          (GtkRenderOperation      *operation,
+                                                         cairo_matrix_t          *matrix);
+
+  void          (* draw)                                (GtkRenderOperation      *operation,
+                                                         cairo_t                 *cr);
+};
+
+GType           gtk_render_operation_get_type           (void) G_GNUC_CONST;
+
+void            gtk_render_operation_get_clip           (GtkRenderOperation      *operation,
+                                                         cairo_rectangle_int_t   *clip);
+void            gtk_render_operation_get_matrix         (GtkRenderOperation      *operation,
+                                                         cairo_matrix_t          *matrix);
+
+void            gtk_render_operation_draw               (GtkRenderOperation      *operation,
+                                                         cairo_t                 *cr);
+
+G_END_DECLS
+
+#endif /* __GTK_RENDER_OPERATION_PRIVATE_H__ */
diff --git a/gtk/inspector/gtkrenderoperationcairo.c b/gtk/inspector/gtkrenderoperationcairo.c
new file mode 100644
index 0000000..ce9e30f
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperationcairo.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2011 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkrenderoperationcairo.h"
+
+#include <math.h>
+
+G_DEFINE_TYPE (GtkRenderOperationCairo, gtk_render_operation_cairo, GTK_TYPE_RENDER_OPERATION)
+
+static void
+gtk_render_operation_cairo_get_clip (GtkRenderOperation    *operation,
+                                     cairo_rectangle_int_t *clip)
+{
+  GtkRenderOperationCairo *oper = GTK_RENDER_OPERATION_CAIRO (operation);
+  cairo_rectangle_t extents;
+  double off_x, off_y;
+
+  g_assert (cairo_surface_get_type (oper->surface) == CAIRO_SURFACE_TYPE_RECORDING);
+  cairo_recording_surface_ink_extents (oper->surface, &extents.x, &extents.y, &extents.width, 
&extents.height);
+  cairo_surface_get_device_offset (oper->surface, &off_x, &off_y);
+  extents.x -= off_x;
+  extents.y -= off_y;
+
+  clip->x = floor (extents.x);
+  clip->y = floor (extents.y);
+  clip->width = ceil (extents.x + extents.width) - clip->x;
+  clip->height = ceil (extents.y + extents.height) - clip->y;
+}
+
+static void
+gtk_render_operation_cairo_draw (GtkRenderOperation *operation,
+                                 cairo_t            *cr)
+{
+  GtkRenderOperationCairo *oper = GTK_RENDER_OPERATION_CAIRO (operation);
+
+  cairo_set_source_surface (cr, oper->surface, 0, 0);
+  cairo_paint (cr);
+}
+
+static void
+gtk_render_operation_cairo_finalize (GObject *object)
+{
+  GtkRenderOperationCairo *oper = GTK_RENDER_OPERATION_CAIRO (object);
+
+  cairo_surface_destroy (oper->surface);
+
+  G_OBJECT_CLASS (gtk_render_operation_cairo_parent_class)->finalize (object);
+}
+
+static void
+gtk_render_operation_cairo_class_init (GtkRenderOperationCairoClass *klass)
+{
+  GtkRenderOperationClass *operation_class = GTK_RENDER_OPERATION_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtk_render_operation_cairo_finalize;
+
+  operation_class->get_clip = gtk_render_operation_cairo_get_clip;
+  operation_class->draw = gtk_render_operation_cairo_draw;
+}
+
+static void
+gtk_render_operation_cairo_init (GtkRenderOperationCairo *image)
+{
+}
+
+GtkRenderOperation *
+gtk_render_operation_cairo_new (cairo_surface_t *surface)
+{
+  GtkRenderOperationCairo *result;
+
+  g_return_val_if_fail (surface != NULL, NULL);
+
+  result = g_object_new (GTK_TYPE_RENDER_OPERATION_CAIRO, NULL);
+  
+  result->surface = cairo_surface_reference (surface);
+ 
+  return GTK_RENDER_OPERATION (result);
+}
+
diff --git a/gtk/inspector/gtkrenderoperationcairo.h b/gtk/inspector/gtkrenderoperationcairo.h
new file mode 100644
index 0000000..4dde785
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperationcairo.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2014 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_RENDER_OPERATION_CAIRO_PRIVATE_H__
+#define __GTK_RENDER_OPERATION_CAIRO_PRIVATE_H__
+
+#include <cairo.h>
+
+#include "gtkrenderoperation.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_RENDER_OPERATION_CAIRO           (gtk_render_operation_cairo_get_type ())
+#define GTK_RENDER_OPERATION_CAIRO(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, 
GTK_TYPE_RENDER_OPERATION_CAIRO, GtkRenderOperationCairo))
+#define GTK_RENDER_OPERATION_CAIRO_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, 
GTK_TYPE_RENDER_OPERATION_CAIRO, GtkRenderOperationCairoClass))
+#define GTK_IS_RENDER_OPERATION_CAIRO(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, 
GTK_TYPE_RENDER_OPERATION_CAIRO))
+#define GTK_IS_RENDER_OPERATION_CAIRO_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, 
GTK_TYPE_RENDER_OPERATION_CAIRO))
+#define GTK_RENDER_OPERATION_CAIRO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GTK_TYPE_RENDER_OPERATION_CAIRO, GtkRenderOperationCairoClass))
+
+typedef struct _GtkRenderOperationCairo           GtkRenderOperationCairo;
+typedef struct _GtkRenderOperationCairoClass      GtkRenderOperationCairoClass;
+
+struct _GtkRenderOperationCairo
+{
+  GtkRenderOperation parent;
+  
+  cairo_surface_t *surface;
+};
+
+struct _GtkRenderOperationCairoClass
+{
+  GtkRenderOperationClass parent_class;
+};
+
+GType                   gtk_render_operation_cairo_get_type     (void) G_GNUC_CONST;
+
+GtkRenderOperation *    gtk_render_operation_cairo_new          (cairo_surface_t        *surface);
+
+G_END_DECLS
+
+#endif /* __GTK_RENDER_OPERATION_CAIRO_PRIVATE_H__ */
diff --git a/gtk/inspector/gtkrenderoperationwidget.c b/gtk/inspector/gtkrenderoperationwidget.c
new file mode 100644
index 0000000..c1d151b
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperationwidget.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright © 2011 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkrenderoperationwidget.h"
+
+G_DEFINE_TYPE (GtkRenderOperationWidget, gtk_render_operation_widget, GTK_TYPE_RENDER_OPERATION)
+
+static void
+gtk_render_operation_widget_get_clip (GtkRenderOperation    *operation,
+                                      cairo_rectangle_int_t *clip)
+{
+  GtkRenderOperationWidget *oper = GTK_RENDER_OPERATION_WIDGET (operation);
+
+  *clip = oper->widget_clip;
+}
+
+static void
+gtk_render_operation_widget_get_matrix (GtkRenderOperation *operation,
+                                        cairo_matrix_t     *matrix)
+{
+  GtkRenderOperationWidget *oper = GTK_RENDER_OPERATION_WIDGET (operation);
+
+  *matrix = oper->matrix;
+}
+
+static void
+gtk_render_operation_widget_draw (GtkRenderOperation *operation,
+                                  cairo_t            *cr)
+{
+  GtkRenderOperationWidget *oper = GTK_RENDER_OPERATION_WIDGET (operation);
+  cairo_matrix_t matrix;
+  GList *l;
+
+  for (l = oper->operations; l; l = l->next)
+    {
+      cairo_save (cr);
+
+      gtk_render_operation_get_matrix (l->data, &matrix);
+      cairo_transform (cr, &matrix);
+      gtk_render_operation_draw (l->data, cr);
+
+      cairo_restore (cr);
+    }
+}
+
+static void
+gtk_render_operation_widget_finalize (GObject *object)
+{
+  GtkRenderOperationWidget *oper = GTK_RENDER_OPERATION_WIDGET (object);
+
+  g_list_free_full (oper->operations, g_object_unref);
+
+  G_OBJECT_CLASS (gtk_render_operation_widget_parent_class)->finalize (object);
+}
+
+static void
+gtk_render_operation_widget_class_init (GtkRenderOperationWidgetClass *klass)
+{
+  GtkRenderOperationClass *operation_class = GTK_RENDER_OPERATION_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtk_render_operation_widget_finalize;
+
+  operation_class->get_clip = gtk_render_operation_widget_get_clip;
+  operation_class->get_matrix = gtk_render_operation_widget_get_matrix;
+  operation_class->draw = gtk_render_operation_widget_draw;
+}
+
+static void
+gtk_render_operation_widget_init (GtkRenderOperationWidget *image)
+{
+}
+
+GtkRenderOperation *
+gtk_render_operation_widget_new (GtkWidget      *widget,
+                                 cairo_matrix_t *matrix)
+
+{
+  GtkRenderOperationWidget *result;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  result = g_object_new (GTK_TYPE_RENDER_OPERATION_WIDGET, NULL);
+  
+  gtk_widget_get_allocation (widget, &result->widget_allocation);
+  gtk_widget_get_clip (widget, &result->widget_clip);
+  result->widget_clip.x -= result->widget_allocation.x;
+  result->widget_clip.y -= result->widget_allocation.y;
+  result->matrix = *matrix;
+ 
+  return GTK_RENDER_OPERATION (result);
+}
+
+void
+gtk_render_operation_widget_add_operation (GtkRenderOperationWidget *widget,
+                                           GtkRenderOperation       *oper)
+{
+  g_return_if_fail (GTK_IS_RENDER_OPERATION_WIDGET (widget));
+  g_return_if_fail (GTK_IS_RENDER_OPERATION (oper));
+
+  g_object_ref (oper);
+
+  widget->operations = g_list_append (widget->operations, oper);
+}
+
diff --git a/gtk/inspector/gtkrenderoperationwidget.h b/gtk/inspector/gtkrenderoperationwidget.h
new file mode 100644
index 0000000..652840d
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperationwidget.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2014 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_RENDER_OPERATION_WIDGET_PRIVATE_H__
+#define __GTK_RENDER_OPERATION_WIDGET_PRIVATE_H__
+
+#include "gtkrenderoperation.h"
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_RENDER_OPERATION_WIDGET           (gtk_render_operation_widget_get_type ())
+#define GTK_RENDER_OPERATION_WIDGET(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, 
GTK_TYPE_RENDER_OPERATION_WIDGET, GtkRenderOperationWidget))
+#define GTK_RENDER_OPERATION_WIDGET_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, 
GTK_TYPE_RENDER_OPERATION_WIDGET, GtkRenderOperationWidgetClass))
+#define GTK_IS_RENDER_OPERATION_WIDGET(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, 
GTK_TYPE_RENDER_OPERATION_WIDGET))
+#define GTK_IS_RENDER_OPERATION_WIDGET_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, 
GTK_TYPE_RENDER_OPERATION_WIDGET))
+#define GTK_RENDER_OPERATION_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GTK_TYPE_RENDER_OPERATION_WIDGET, GtkRenderOperationWidgetClass))
+
+typedef struct _GtkRenderOperationWidget           GtkRenderOperationWidget;
+typedef struct _GtkRenderOperationWidgetClass      GtkRenderOperationWidgetClass;
+
+struct _GtkRenderOperationWidget
+{
+  GtkRenderOperation parent;
+  
+  GtkAllocation          widget_allocation;
+  GtkAllocation          widget_clip;
+  cairo_matrix_t         matrix;
+  GList                 *operations;
+};
+
+struct _GtkRenderOperationWidgetClass
+{
+  GtkRenderOperationClass parent_class;
+};
+
+GType                   gtk_render_operation_widget_get_type    (void) G_GNUC_CONST;
+
+GtkRenderOperation *    gtk_render_operation_widget_new         (GtkWidget                      *widget,
+                                                                 cairo_matrix_t                 *matrix);
+
+void                    gtk_render_operation_widget_add_operation(GtkRenderOperationWidget      *widget,
+                                                                 GtkRenderOperation             *oper);
+
+G_END_DECLS
+
+#endif /* __GTK_RENDER_OPERATION_WIDGET_PRIVATE_H__ */
diff --git a/gtk/inspector/magnifier.c b/gtk/inspector/magnifier.c
index c7b4a5b..ee56550 100644
--- a/gtk/inspector/magnifier.c
+++ b/gtk/inspector/magnifier.c
@@ -21,7 +21,10 @@
 #include "magnifier.h"
 
 #include "gtkmagnifierprivate.h"
+#include "recordingrenderops.h"
+#include "snapshot.h"
 
+#include "gtkbutton.h"
 #include "gtklabel.h"
 
 
@@ -68,6 +71,25 @@ gtk_inspector_magnifier_set_object (GtkInspectorMagnifier *sl,
 }
 
 static void
+on_snapshot_clicked (GtkButton             *button,
+                     GtkInspectorMagnifier *sl)
+{
+  GtkRenderOperation *oper;
+  GtkRenderOps *ops;
+  GtkWidget *snapshot;
+
+  ops = gtk_recording_render_ops_new ();
+  oper = gtk_recording_render_ops_run_for_widget (GTK_RECORDING_RENDER_OPS (ops),
+                                                  GTK_WIDGET (sl->priv->object));
+  g_object_unref (ops);
+
+  snapshot = gtk_inspector_snapshot_new (oper);
+  gtk_window_present (GTK_WINDOW (snapshot));
+
+  g_object_unref (oper);
+}
+
+static void
 gtk_inspector_magnifier_class_init (GtkInspectorMagnifierClass *klass)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
@@ -75,6 +97,8 @@ gtk_inspector_magnifier_class_init (GtkInspectorMagnifierClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/magnifier.ui");
   gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMagnifier, magnifier);
   gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorMagnifier, object_title);
+
+  gtk_widget_class_bind_template_callback (widget_class, on_snapshot_clicked);
 }
 
 // vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/magnifier.ui b/gtk/inspector/magnifier.ui
index b257fdb..0f7940d 100644
--- a/gtk/inspector/magnifier.ui
+++ b/gtk/inspector/magnifier.ui
@@ -9,6 +9,17 @@
         <property name="spacing">6</property>
         <property name="margin">6</property>
         <child>
+          <object class="GtkButton" id="snapshot">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">Snapshot</property>
+            <property name="tooltip-text" translatable="yes">Take a snapshot for closer inspection</property>
+            <signal name="clicked" handler="on_snapshot_clicked"/>
+          </object>
+          <packing>
+            <property name="pack-type">start</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkScale" id="magnification">
             <property name="visible">True</property>
             <property name="orientation">horizontal</property>
diff --git a/gtk/inspector/recordingrenderops.c b/gtk/inspector/recordingrenderops.c
new file mode 100644
index 0000000..02a9fa4
--- /dev/null
+++ b/gtk/inspector/recordingrenderops.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright © 2011 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "recordingrenderops.h"
+
+#include "gtkrenderoperationcairo.h"
+#include "gtkrenderoperationwidget.h"
+#include "gtkwidget.h"
+
+G_DEFINE_TYPE (GtkRecordingRenderOps, gtk_recording_render_ops, GTK_TYPE_RENDER_OPS)
+
+static cairo_t *
+gtk_recording_render_ops_cairo_create (GtkRecordingRenderOps *ops,
+                                       GtkWidget             *widget)
+{
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  cairo_rectangle_t extents;
+  GtkAllocation clip, allocation;
+
+  gtk_widget_get_clip (widget, &clip);
+  gtk_widget_get_allocation (widget, &allocation);
+
+  extents.x = allocation.x - clip.x;
+  extents.y = allocation.y - clip.y;
+  extents.width = clip.width;
+  extents.height = clip.height;
+
+  surface = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, &extents);
+  cairo_surface_set_device_offset (surface, -extents.x, -extents.y);
+  cr = cairo_create (surface);
+  cairo_surface_destroy (surface);
+
+  gtk_cairo_set_render_ops (cr, GTK_RENDER_OPS (ops));
+
+  return cr;
+}
+
+static void
+gtk_recording_render_ops_save_snapshot (GtkRecordingRenderOps *record,
+                                        cairo_t               *cr)
+{
+  GtkRenderOperation *oper;
+  cairo_surface_t *target, *snapshot;
+  cairo_rectangle_t extents, real_extents;
+  cairo_t *copy;
+
+  target = cairo_get_target (cr);
+  g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_RECORDING);
+  cairo_recording_surface_ink_extents (target, &extents.x, &extents.y, &extents.width, &extents.height);
+  
+  /* no snapshot necessary */
+  if (extents.width <= 0 || extents.height <= 0)
+    return;
+
+  /* create snapshot */
+  g_print ("saving snapshot of %g %g %g %g\n", extents.x, extents.y, extents.width, extents.height);
+  real_extents = extents;
+  real_extents.x = real_extents.y = 0;
+  snapshot = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, &real_extents);
+  cairo_surface_set_device_offset (snapshot, -extents.x, -extents.y);
+  copy = cairo_create (snapshot);
+  cairo_set_source_surface (copy, target, 0, 0);
+  cairo_paint (copy);
+  cairo_destroy (copy);
+
+  if (extents.x > 10)
+    cairo_surface_write_to_png (snapshot, "foo.png");
+
+  /* enqueue snapshot */
+  oper = gtk_render_operation_cairo_new (snapshot);
+  cairo_surface_destroy (snapshot);
+  gtk_render_operation_widget_add_operation (record->widgets->data, oper);
+  g_object_unref (oper);
+
+  /* clear original_surface */
+  cairo_save (cr);
+  cairo_reset_clip (cr);
+  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+  cairo_paint (cr);
+  cairo_restore (cr);
+}
+
+static cairo_t *
+gtk_recording_render_ops_begin_draw_widget (GtkRenderOps *ops,
+                                            GtkWidget    *widget,
+                                            cairo_t      *cr)
+{
+  GtkRecordingRenderOps *record = GTK_RECORDING_RENDER_OPS (ops);
+  GtkRenderOperation *oper;
+  cairo_matrix_t matrix;
+
+  gtk_recording_render_ops_save_snapshot (record, cr);
+
+  g_print ("begin drawing widget %s\n", gtk_widget_get_name (widget));
+
+  cairo_get_matrix (cr, &matrix);
+
+  oper = gtk_render_operation_widget_new (widget, &matrix);
+  
+  if (record->widgets)
+    gtk_render_operation_widget_add_operation (record->widgets->data, oper);
+  record->widgets = g_list_prepend (record->widgets, oper);
+
+  return gtk_recording_render_ops_cairo_create (record, widget);
+}
+
+static void
+gtk_recording_render_ops_end_draw_widget (GtkRenderOps *ops,
+                                          GtkWidget    *widget,
+                                          cairo_t      *draw_cr,
+                                          cairo_t      *original_cr)
+{
+  GtkRecordingRenderOps *record = GTK_RECORDING_RENDER_OPS (ops);
+
+  gtk_recording_render_ops_save_snapshot (record, draw_cr);
+
+  g_print ("ended drawing widget %s\n", gtk_widget_get_name (widget));
+
+  if (record->widgets->next)
+    {
+      g_object_unref (record->widgets->data);
+      record->widgets = g_list_remove (record->widgets, record->widgets->data);
+    }
+
+  cairo_destroy (draw_cr);
+}
+
+static void
+gtk_recording_render_ops_class_init (GtkRecordingRenderOpsClass *klass)
+{
+  GtkRenderOpsClass *ops_class = GTK_RENDER_OPS_CLASS (klass);
+
+  ops_class->begin_draw_widget = gtk_recording_render_ops_begin_draw_widget;
+  ops_class->end_draw_widget = gtk_recording_render_ops_end_draw_widget;
+}
+
+static void
+gtk_recording_render_ops_init (GtkRecordingRenderOps *image)
+{
+}
+
+GtkRenderOps *
+gtk_recording_render_ops_new (void)
+{
+  return g_object_new (GTK_TYPE_RECORDING_RENDER_OPS, NULL);
+}
+
+GtkRenderOperation *
+gtk_recording_render_ops_run_for_widget (GtkRecordingRenderOps *ops,
+                                         GtkWidget             *widget)
+{
+  GtkRenderOperation *result;
+  cairo_t *cr;
+
+  g_return_val_if_fail (GTK_IS_RECORDING_RENDER_OPS (ops), NULL);
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+  cr = gtk_recording_render_ops_cairo_create (ops, widget);
+  gtk_widget_draw (widget, cr);
+  cairo_destroy (cr);
+
+  result = ops->widgets->data;
+  g_list_free (ops->widgets);
+  ops->widgets = NULL;
+
+  return result;
+}
+
diff --git a/gtk/inspector/recordingrenderops.h b/gtk/inspector/recordingrenderops.h
new file mode 100644
index 0000000..fb9955f
--- /dev/null
+++ b/gtk/inspector/recordingrenderops.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2014 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_RECORDING_RENDER_OPS_PRIVATE_H__
+#define __GTK_RECORDING_RENDER_OPS_PRIVATE_H__
+
+#include <cairo.h>
+
+#include "gtk/gtkrenderopsprivate.h"
+#include "gtkrenderoperation.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_RECORDING_RENDER_OPS           (gtk_recording_render_ops_get_type ())
+#define GTK_RECORDING_RENDER_OPS(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, 
GTK_TYPE_RECORDING_RENDER_OPS, GtkRecordingRenderOps))
+#define GTK_RECORDING_RENDER_OPS_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, 
GTK_TYPE_RECORDING_RENDER_OPS, GtkRecordingRenderOpsClass))
+#define GTK_IS_RECORDING_RENDER_OPS(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, 
GTK_TYPE_RECORDING_RENDER_OPS))
+#define GTK_IS_RECORDING_RENDER_OPS_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, 
GTK_TYPE_RECORDING_RENDER_OPS))
+#define GTK_RECORDING_RENDER_OPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GTK_TYPE_RECORDING_RENDER_OPS, GtkRecordingRenderOpsClass))
+
+typedef struct _GtkRecordingRenderOps           GtkRecordingRenderOps;
+typedef struct _GtkRecordingRenderOpsClass      GtkRecordingRenderOpsClass;
+
+struct _GtkRecordingRenderOps
+{
+  GtkRenderOps parent;
+
+  GList *widgets;
+};
+
+struct _GtkRecordingRenderOpsClass
+{
+  GtkRenderOpsClass parent_class;
+};
+
+GType                   gtk_recording_render_ops_get_type       (void) G_GNUC_CONST;
+
+GtkRenderOps *          gtk_recording_render_ops_new            (void);
+
+GtkRenderOperation *    gtk_recording_render_ops_run_for_widget (GtkRecordingRenderOps  *ops,
+                                                                 GtkWidget              *widget);
+
+
+G_END_DECLS
+
+#endif /* __GTK_RECORDING_RENDER_OPS_PRIVATE_H__ */
diff --git a/gtk/inspector/snapshot.c b/gtk/inspector/snapshot.c
new file mode 100644
index 0000000..4c9ee59
--- /dev/null
+++ b/gtk/inspector/snapshot.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015 Benjamin Otte <otte gnome org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include "snapshot.h"
+
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtklistbox.h>
+
+#include "gtkrenderoperationwidget.h"
+#include "window.h"
+
+enum {
+  PROP_0,
+  PROP_OPERATION
+};
+
+G_DEFINE_TYPE (GtkInspectorSnapshot, gtk_inspector_snapshot, GTK_TYPE_WINDOW)
+
+static void
+gtk_inspector_snapshot_set_property (GObject      *object,
+                                     guint         param_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  GtkInspectorSnapshot *snapshot = GTK_INSPECTOR_SNAPSHOT (object);
+
+  switch (param_id)
+    {
+    case PROP_OPERATION:
+      gtk_inspector_snapshot_set_operation (snapshot,
+                                            g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+static void
+gtk_inspector_snapshot_get_property (GObject    *object,
+                                     guint       param_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  GtkInspectorSnapshot *snapshot = GTK_INSPECTOR_SNAPSHOT (object);
+
+  switch (param_id)
+    {
+    case PROP_OPERATION:
+      g_value_set_object (value, snapshot->operation);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+static cairo_surface_t *
+create_surface_for_operation (GtkRenderOperation *oper)
+{
+  GtkAllocation clip;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+
+  gtk_render_operation_get_clip (oper, &clip);
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, clip.width, clip.height);
+
+  cr = cairo_create (surface);
+  cairo_translate (cr, -clip.x, -clip.y);
+  gtk_render_operation_draw (oper, cr);
+  cairo_destroy (cr);
+
+  return surface;
+}
+
+static void
+on_operation_selected (GtkListBox           *listbox,
+                       GtkListBoxRow        *row,
+                       GtkInspectorSnapshot *snapshot)
+{
+  GtkRenderOperation *oper;
+  cairo_surface_t *surface;
+
+  if (row == NULL)
+    {
+      gtk_image_clear (GTK_IMAGE (snapshot->image));
+      return;
+    }
+
+  oper = g_object_get_data (G_OBJECT (row), "operation");
+
+  surface = create_surface_for_operation (oper);
+  gtk_image_set_from_surface (GTK_IMAGE (snapshot->image), surface);
+  cairo_surface_destroy (surface);
+}
+
+static void
+gtk_inspector_snapshot_class_init (GtkInspectorSnapshotClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->set_property = gtk_inspector_snapshot_set_property;
+  object_class->get_property = gtk_inspector_snapshot_get_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_OPERATION,
+                                   g_param_spec_object ("operation",
+                                                        "Operation",
+                                                        "Operation to show",
+                                                        GTK_TYPE_RENDER_OPERATION,
+                                                        G_PARAM_READWRITE));
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/snapshot.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtkInspectorSnapshot, operations_listbox);
+  gtk_widget_class_bind_template_child (widget_class, GtkInspectorSnapshot, image);
+
+  gtk_widget_class_bind_template_callback (widget_class, on_operation_selected);
+}
+
+static void
+gtk_inspector_snapshot_init (GtkInspectorSnapshot *iw)
+{
+  gtk_widget_init_template (GTK_WIDGET (iw));
+}
+
+GtkWidget *
+gtk_inspector_snapshot_new (GtkRenderOperation *oper)
+{
+  return GTK_WIDGET (g_object_new (GTK_TYPE_INSPECTOR_SNAPSHOT,
+                                   "screen", gtk_inspector_get_screen (),
+                                   "operation", oper,
+                                   NULL));
+}
+
+static void
+gtk_inspector_snapshot_fill_listbox (GtkInspectorSnapshot *snapshot,
+                                     GtkRenderOperation   *oper,
+                                     guint                 depth)
+{
+  GtkWidget *label, *row;
+  char *text;
+
+  text = g_strdup_printf ("%*s %s", 2 * depth, "", G_OBJECT_TYPE_NAME (oper));
+  label = gtk_label_new (text);
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+  gtk_widget_show (label);
+  g_free (text);
+
+  row = gtk_list_box_row_new ();
+  gtk_container_add (GTK_CONTAINER (row), label);
+  g_object_set_data (G_OBJECT (row), "operation", oper);
+  gtk_widget_show (row);
+
+  gtk_container_add (GTK_CONTAINER (snapshot->operations_listbox), row);
+
+  if (GTK_IS_RENDER_OPERATION_WIDGET (oper))
+    {
+      GList *l;
+
+      for (l = GTK_RENDER_OPERATION_WIDGET (oper)->operations; l; l = l->next)
+        {
+          gtk_inspector_snapshot_fill_listbox (snapshot, l->data, depth + 1);
+        }
+    }
+}
+
+void
+gtk_inspector_snapshot_set_operation (GtkInspectorSnapshot *snapshot,
+                                      GtkRenderOperation   *oper)
+{
+  g_return_if_fail (GTK_IS_INSPECTOR_SNAPSHOT (snapshot));
+  g_return_if_fail (oper == NULL || GTK_IS_RENDER_OPERATION (oper));
+
+  if (snapshot->operation)
+    {
+      /* implicit version of gtk_list_box_clear(): */
+      gtk_list_box_bind_model (GTK_LIST_BOX (snapshot->operations_listbox), NULL, NULL, NULL, NULL);
+      g_object_unref (snapshot->operation);
+    }
+
+  if (oper)
+    {
+      g_object_ref (oper);
+      snapshot->operation = oper;
+      gtk_inspector_snapshot_fill_listbox (snapshot, oper, 0);
+    }
+}
+
+GtkRenderOperation *
+gtk_inspector_snapshot_get_operation (GtkInspectorSnapshot *snapshot)
+{
+  return snapshot->operation;
+}
+
+// vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/snapshot.h b/gtk/inspector/snapshot.h
new file mode 100644
index 0000000..60468cf
--- /dev/null
+++ b/gtk/inspector/snapshot.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 Benjamin Otte <otte gnome org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef _GTK_INSPECTOR_SNAPSHOT_H_
+#define _GTK_INSPECTOR_SNAPSHOT_H_
+
+#include <gtk/gtkwindow.h>
+
+#include "gtkrenderoperation.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_INSPECTOR_SNAPSHOT            (gtk_inspector_snapshot_get_type())
+#define GTK_INSPECTOR_SNAPSHOT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), 
GTK_TYPE_INSPECTOR_SNAPSHOT, GtkInspectorSnapshot))
+#define GTK_INSPECTOR_SNAPSHOT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), 
GTK_TYPE_INSPECTOR_SNAPSHOT, GtkInspectorSnapshotClass))
+#define GTK_IS_INSPECTOR_SNAPSHOT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), 
GTK_TYPE_INSPECTOR_SNAPSHOT))
+#define GTK_IS_INSPECTOR_SNAPSHOT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), 
GTK_TYPE_INSPECTOR_SNAPSHOT))
+#define GTK_INSPECTOR_SNAPSHOT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), 
GTK_TYPE_INSPECTOR_SNAPSHOT, GtkInspectorSnapshotClass))
+
+typedef struct
+{
+  GtkWindow parent;
+
+  GtkRenderOperation *operation;
+
+  GtkWidget *operations_listbox;
+  GtkWidget *image;
+} GtkInspectorSnapshot;
+
+typedef struct
+{
+  GtkWindowClass parent;
+} GtkInspectorSnapshotClass;
+
+GType                   gtk_inspector_snapshot_get_type         (void);
+
+GtkWidget *             gtk_inspector_snapshot_new              (GtkRenderOperation     *oper);
+
+void                    gtk_inspector_snapshot_set_operation    (GtkInspectorSnapshot   *snapshot,
+                                                                 GtkRenderOperation     *oper);
+GtkRenderOperation *    gtk_inspector_snapshot_get_operation    (GtkInspectorSnapshot   *snapshot);
+
+G_END_DECLS
+
+
+#endif // _GTK_INSPECTOR_SNAPSHOT_H_
+
+// vim: set et sw=2 ts=2:
diff --git a/gtk/inspector/snapshot.ui b/gtk/inspector/snapshot.ui
new file mode 100644
index 0000000..4893ef8
--- /dev/null
+++ b/gtk/inspector/snapshot.ui
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="gtk30">
+  <template class="GtkInspectorSnapshot" parent="GtkWindow">
+    <property name="default-height">500</property>
+    <property name="default-width">800</property>
+    <property name="icon">resource:///org/gtk/libgtk/inspector/logo.png</property>
+    <child type="titlebar">
+      <object class="GtkHeaderBar">
+        <property name="visible">True</property>
+        <property name="show-close-button">True</property>
+        <property name="title">Snapshot</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkPaned" id="paned">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="visible">True</property>
+            <property name="expand">True</property>
+            <property name="hscrollbar-policy">never</property>
+            <property name="vscrollbar-policy">automatic</property>
+            <child>
+              <object class="GtkListBox" id="operations_listbox">
+                <property name="visible">True</property>
+                <signal name="row-selected" handler="on_operation_selected"/>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow1">
+            <property name="visible">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkViewport" id="viewport1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkImage" id="image">
+                    <property name="visible">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c
index d7b6d22..1ee9ba0 100644
--- a/gtk/inspector/window.c
+++ b/gtk/inspector/window.c
@@ -248,8 +248,8 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass)
   gtk_widget_class_bind_template_callback (widget_class, close_object_details);
 }
 
-static GdkScreen *
-get_inspector_screen (void)
+GdkScreen *
+gtk_inspector_get_screen (void)
 {
   static GdkDisplay *display = NULL;
 
@@ -285,7 +285,7 @@ GtkWidget *
 gtk_inspector_window_new (void)
 {
   return GTK_WIDGET (g_object_new (GTK_TYPE_INSPECTOR_WINDOW,
-                                   "screen", get_inspector_screen (),
+                                   "screen", gtk_inspector_get_screen (),
                                    NULL));
 }
 
diff --git a/gtk/inspector/window.h b/gtk/inspector/window.h
index 80de702..9148653 100644
--- a/gtk/inspector/window.h
+++ b/gtk/inspector/window.h
@@ -91,6 +91,8 @@ G_BEGIN_DECLS
 GType      gtk_inspector_window_get_type    (void);
 GtkWidget *gtk_inspector_window_new         (void);
 
+GdkScreen *gtk_inspector_get_screen         (void);
+
 void       gtk_inspector_flash_widget       (GtkInspectorWindow *iw,
                                              GtkWidget          *widget);
 void       gtk_inspector_start_highlight    (GtkWidget          *widget);



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