[gtk+] reftest: Split our more functionality



commit 2e6dd4082f1fcbc5acf39354944b13ee921cc8df
Author: Benjamin Otte <otte redhat com>
Date:   Sun Sep 21 18:33:42 2014 +0200

    reftest: Split our more functionality
    
    Split actually taking the snapshot into its own file.

 testsuite/reftests/Makefile.am        |    2 +
 testsuite/reftests/gtk-reftest.c      |  239 +----------------------------
 testsuite/reftests/gtk-reftest.h      |    1 +
 testsuite/reftests/reftest-snapshot.c |  275 +++++++++++++++++++++++++++++++++
 testsuite/reftests/reftest-snapshot.h |   29 ++++
 5 files changed, 309 insertions(+), 237 deletions(-)
---
diff --git a/testsuite/reftests/Makefile.am b/testsuite/reftests/Makefile.am
index 61135b2..50c532d 100644
--- a/testsuite/reftests/Makefile.am
+++ b/testsuite/reftests/Makefile.am
@@ -34,6 +34,8 @@ gtk_reftest_SOURCES = \
        reftest-compare.h               \
        reftest-module.c                \
        reftest-module.h                \
+       reftest-snapshot.c              \
+       reftest-snapshot.h              \
        gtk-reftest.c                   \
        gtk-reftest.h
 
diff --git a/testsuite/reftests/gtk-reftest.c b/testsuite/reftests/gtk-reftest.c
index 89cd2ad..4f5b6f4 100644
--- a/testsuite/reftests/gtk-reftest.c
+++ b/testsuite/reftests/gtk-reftest.c
@@ -208,28 +208,6 @@ remove_extra_css (GtkStyleProvider *provider)
                                                 provider);
 }
 
-static GtkWidget *
-builder_get_toplevel (GtkBuilder *builder)
-{
-  GSList *list, *walk;
-  GtkWidget *window = NULL;
-
-  list = gtk_builder_get_objects (builder);
-  for (walk = list; walk; walk = walk->next)
-    {
-      if (GTK_IS_WINDOW (walk->data) &&
-          gtk_widget_get_parent (walk->data) == NULL)
-        {
-          window = walk->data;
-          break;
-        }
-    }
-  
-  g_slist_free (list);
-
-  return window;
-}
-
 static gboolean
 quit_when_idle (gpointer loop)
 {
@@ -238,219 +216,6 @@ quit_when_idle (gpointer loop)
   return G_SOURCE_REMOVE;
 }
 
-static gint inhibit_count;
-static GMainLoop *loop;
-
-void
-reftest_inhibit_snapshot (void)
-{
-  inhibit_count++;
-}
-
-void
-reftest_uninhibit_snapshot (void)
-{
-  g_assert (inhibit_count > 0);
-  inhibit_count--;
-
-  if (inhibit_count == 0)
-    g_idle_add (quit_when_idle, loop);
-}
-
-static void
-check_for_draw (GdkEvent *event, gpointer data)
-{
-  if (event->type == GDK_EXPOSE)
-    {
-      reftest_uninhibit_snapshot ();
-      gdk_event_handler_set ((GdkEventFunc) gtk_main_do_event, NULL, NULL);
-    }
-
-  gtk_main_do_event (event);
-}
-
-static cairo_surface_t *
-snapshot_widget (GtkWidget *widget, SnapshotMode mode)
-{
-  cairo_surface_t *surface;
-  cairo_pattern_t *bg;
-  cairo_t *cr;
-
-  g_assert (gtk_widget_get_realized (widget));
-
-  loop = g_main_loop_new (NULL, FALSE);
-
-  /* We wait until the widget is drawn for the first time.
-   * We can not wait for a GtkWidget::draw event, because that might not
-   * happen if the window is fully obscured by windowed child widgets.
-   * Alternatively, we could wait for an expose event on widget's window.
-   * Both of these are rather hairy, not sure what's best.
-   *
-   * We also use an inhibit mechanism, to give module functions a chance
-   * to delay the snapshot.
-   */
-  reftest_inhibit_snapshot ();
-  gdk_event_handler_set (check_for_draw, NULL, NULL);
-  g_main_loop_run (loop);
-
-  surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
-                                               CAIRO_CONTENT_COLOR,
-                                               gtk_widget_get_allocated_width (widget),
-                                               gtk_widget_get_allocated_height (widget));
-
-  cr = cairo_create (surface);
-
-  switch (mode)
-    {
-    case SNAPSHOT_WINDOW:
-      {
-        GdkWindow *window = gtk_widget_get_window (widget);
-        if (gdk_window_get_window_type (window) == GDK_WINDOW_TOPLEVEL ||
-            gdk_window_get_window_type (window) == GDK_WINDOW_FOREIGN)
-          {
-            /* give the WM/server some time to sync. They need it.
-             * Also, do use popups instead of toplevls in your tests
-             * whenever you can. */
-            gdk_display_sync (gdk_window_get_display (window));
-            g_timeout_add (500, quit_when_idle, loop);
-            g_main_loop_run (loop);
-          }
-        gdk_cairo_set_source_window (cr, window, 0, 0);
-        cairo_paint (cr);
-      }
-      break;
-    case SNAPSHOT_DRAW:
-      bg = gdk_window_get_background_pattern (gtk_widget_get_window (widget));
-      if (bg)
-        {
-          cairo_set_source (cr, bg);
-          cairo_paint (cr);
-        }
-      gtk_widget_draw (widget, cr);
-      break;
-    default:
-      g_assert_not_reached();
-      break;
-    }
-
-  cairo_destroy (cr);
-  g_main_loop_unref (loop);
-  gtk_widget_destroy (widget);
-
-  return surface;
-}
-
-static void
-connect_signals (GtkBuilder    *builder,
-                 GObject       *object,
-                 const gchar   *signal_name,
-                 const gchar   *handler_name,
-                 GObject       *connect_object,
-                 GConnectFlags  flags,
-                 gpointer       user_data)
-{
-  ReftestModule *module;
-  const char *directory;
-  GCallback func;
-  GClosure *closure;
-  char **split;
-
-  directory = user_data;
-  split = g_strsplit (handler_name, ":", -1);
-
-  switch (g_strv_length (split))
-    {
-    case 1:
-      func = gtk_builder_lookup_callback_symbol (builder, split[0]);
-
-      if (func)
-        {
-          module = NULL;
-        }
-      else
-        {
-          module = reftest_module_new_self ();
-          if (module == NULL)
-            {
-              g_error ("glib compiled without module support.");
-              return;
-            }
-          func = reftest_module_lookup (module, split[0]);
-          if (!func)
-            {
-              g_error ("failed to lookup handler for name '%s' when connecting signals", split[0]);
-              return;
-            }
-        }
-      break;
-    case 2:
-      if (g_getenv ("REFTEST_MODULE_DIR"))
-        directory = g_getenv ("REFTEST_MODULE_DIR");
-      module = reftest_module_new (directory, split[0]);
-      if (module == NULL)
-        {
-          g_error ("Could not load module '%s' from '%s' when looking up '%s'", split[0], directory, 
handler_name);
-          return;
-        }
-      func = reftest_module_lookup (module, split[1]);
-      if (!func)
-        {
-          g_error ("failed to lookup handler for name '%s' in module '%s'", split[1], split[0]);
-          return;
-        }
-      break;
-    default:
-      g_error ("Could not connect signal handler named '%s'", handler_name);
-      return;
-    }
-
-  g_strfreev (split);
-
-  if (connect_object)
-    {
-      if (flags & G_CONNECT_SWAPPED)
-        closure = g_cclosure_new_object_swap (func, connect_object);
-      else
-        closure = g_cclosure_new_object (func, connect_object);
-    }
-  else
-    {
-      if (flags & G_CONNECT_SWAPPED)
-        closure = g_cclosure_new_swap (func, NULL, NULL);
-      else
-        closure = g_cclosure_new (func, NULL, NULL);
-    }
-  
-  if (module)
-    g_closure_add_finalize_notifier (closure, module, (GClosureNotify) reftest_module_unref);
-
-  g_signal_connect_closure (object, signal_name, closure, flags & G_CONNECT_AFTER ? TRUE : FALSE);
-}
-
-static cairo_surface_t *
-snapshot_ui_file (const char *ui_file)
-{
-  GtkWidget *window;
-  GtkBuilder *builder;
-  GError *error = NULL;
-  char *directory;
-
-  get_components_of_test_file (ui_file, &directory, NULL);
-
-  builder = gtk_builder_new ();
-  gtk_builder_add_from_file (builder, ui_file, &error);
-  g_assert_no_error (error);
-  gtk_builder_connect_signals_full (builder, connect_signals, directory);
-  window = builder_get_toplevel (builder);
-  g_object_unref (builder);
-  g_free (directory);
-  g_assert (window);
-
-  gtk_widget_show (window);
-
-  return snapshot_widget (window, SNAPSHOT_WINDOW);
-}
-
 static void
 save_image (cairo_surface_t *surface,
             const char      *test_name,
@@ -475,11 +240,11 @@ test_ui_file (GFile *file)
 
   provider = add_extra_css (ui_file, ".css");
 
-  ui_image = snapshot_ui_file (ui_file);
+  ui_image = reftest_snapshot_ui_file (ui_file);
   
   reference_file = get_test_file (ui_file, ".ref.ui", TRUE);
   if (reference_file)
-    reference_image = snapshot_ui_file (reference_file);
+    reference_image = reftest_snapshot_ui_file (reference_file);
   else
     {
       reference_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
diff --git a/testsuite/reftests/gtk-reftest.h b/testsuite/reftests/gtk-reftest.h
index aa527b6..e30c78f 100644
--- a/testsuite/reftests/gtk-reftest.h
+++ b/testsuite/reftests/gtk-reftest.h
@@ -20,6 +20,7 @@
 
 G_BEGIN_DECLS
 
+/* reftest-snapshot.c */
 void reftest_inhibit_snapshot   (void);
 void reftest_uninhibit_snapshot (void);
 
diff --git a/testsuite/reftests/reftest-snapshot.c b/testsuite/reftests/reftest-snapshot.c
new file mode 100644
index 0000000..478db4a
--- /dev/null
+++ b/testsuite/reftests/reftest-snapshot.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Author:
+ *      Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "reftest-snapshot.h"
+
+#include "reftest-module.h"
+
+#include <string.h>
+
+typedef enum {
+  SNAPSHOT_WINDOW,
+  SNAPSHOT_DRAW
+} SnapshotMode;
+
+static GtkWidget *
+builder_get_toplevel (GtkBuilder *builder)
+{
+  GSList *list, *walk;
+  GtkWidget *window = NULL;
+
+  list = gtk_builder_get_objects (builder);
+  for (walk = list; walk; walk = walk->next)
+    {
+      if (GTK_IS_WINDOW (walk->data) &&
+          gtk_widget_get_parent (walk->data) == NULL)
+        {
+          window = walk->data;
+          break;
+        }
+    }
+  
+  g_slist_free (list);
+
+  return window;
+}
+
+static gboolean
+quit_when_idle (gpointer loop)
+{
+  g_main_loop_quit (loop);
+
+  return G_SOURCE_REMOVE;
+}
+
+static gint inhibit_count;
+static GMainLoop *loop;
+
+void
+reftest_inhibit_snapshot (void)
+{
+  inhibit_count++;
+}
+
+void
+reftest_uninhibit_snapshot (void)
+{
+  g_assert (inhibit_count > 0);
+  inhibit_count--;
+
+  if (inhibit_count == 0)
+    g_idle_add (quit_when_idle, loop);
+}
+
+static void
+check_for_draw (GdkEvent *event, gpointer data)
+{
+  if (event->type == GDK_EXPOSE)
+    {
+      reftest_uninhibit_snapshot ();
+      gdk_event_handler_set ((GdkEventFunc) gtk_main_do_event, NULL, NULL);
+    }
+
+  gtk_main_do_event (event);
+}
+
+static cairo_surface_t *
+snapshot_widget (GtkWidget *widget, SnapshotMode mode)
+{
+  cairo_surface_t *surface;
+  cairo_pattern_t *bg;
+  cairo_t *cr;
+
+  g_assert (gtk_widget_get_realized (widget));
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  /* We wait until the widget is drawn for the first time.
+   * We can not wait for a GtkWidget::draw event, because that might not
+   * happen if the window is fully obscured by windowed child widgets.
+   * Alternatively, we could wait for an expose event on widget's window.
+   * Both of these are rather hairy, not sure what's best.
+   *
+   * We also use an inhibit mechanism, to give module functions a chance
+   * to delay the snapshot.
+   */
+  reftest_inhibit_snapshot ();
+  gdk_event_handler_set (check_for_draw, NULL, NULL);
+  g_main_loop_run (loop);
+
+  surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+                                               CAIRO_CONTENT_COLOR,
+                                               gtk_widget_get_allocated_width (widget),
+                                               gtk_widget_get_allocated_height (widget));
+
+  cr = cairo_create (surface);
+
+  switch (mode)
+    {
+    case SNAPSHOT_WINDOW:
+      {
+        GdkWindow *window = gtk_widget_get_window (widget);
+        if (gdk_window_get_window_type (window) == GDK_WINDOW_TOPLEVEL ||
+            gdk_window_get_window_type (window) == GDK_WINDOW_FOREIGN)
+          {
+            /* give the WM/server some time to sync. They need it.
+             * Also, do use popups instead of toplevls in your tests
+             * whenever you can. */
+            gdk_display_sync (gdk_window_get_display (window));
+            g_timeout_add (500, quit_when_idle, loop);
+            g_main_loop_run (loop);
+          }
+        gdk_cairo_set_source_window (cr, window, 0, 0);
+        cairo_paint (cr);
+      }
+      break;
+    case SNAPSHOT_DRAW:
+      bg = gdk_window_get_background_pattern (gtk_widget_get_window (widget));
+      if (bg)
+        {
+          cairo_set_source (cr, bg);
+          cairo_paint (cr);
+        }
+      gtk_widget_draw (widget, cr);
+      break;
+    default:
+      g_assert_not_reached();
+      break;
+    }
+
+  cairo_destroy (cr);
+  g_main_loop_unref (loop);
+  gtk_widget_destroy (widget);
+
+  return surface;
+}
+
+static void
+connect_signals (GtkBuilder    *builder,
+                 GObject       *object,
+                 const gchar   *signal_name,
+                 const gchar   *handler_name,
+                 GObject       *connect_object,
+                 GConnectFlags  flags,
+                 gpointer       user_data)
+{
+  ReftestModule *module;
+  const char *directory;
+  GCallback func;
+  GClosure *closure;
+  char **split;
+
+  directory = user_data;
+  split = g_strsplit (handler_name, ":", -1);
+
+  switch (g_strv_length (split))
+    {
+    case 1:
+      func = gtk_builder_lookup_callback_symbol (builder, split[0]);
+
+      if (func)
+        {
+          module = NULL;
+        }
+      else
+        {
+          module = reftest_module_new_self ();
+          if (module == NULL)
+            {
+              g_error ("glib compiled without module support.");
+              return;
+            }
+          func = reftest_module_lookup (module, split[0]);
+          if (!func)
+            {
+              g_error ("failed to lookup handler for name '%s' when connecting signals", split[0]);
+              return;
+            }
+        }
+      break;
+    case 2:
+      if (g_getenv ("REFTEST_MODULE_DIR"))
+        directory = g_getenv ("REFTEST_MODULE_DIR");
+      module = reftest_module_new (directory, split[0]);
+      if (module == NULL)
+        {
+          g_error ("Could not load module '%s' from '%s' when looking up '%s'", split[0], directory, 
handler_name);
+          return;
+        }
+      func = reftest_module_lookup (module, split[1]);
+      if (!func)
+        {
+          g_error ("failed to lookup handler for name '%s' in module '%s'", split[1], split[0]);
+          return;
+        }
+      break;
+    default:
+      g_error ("Could not connect signal handler named '%s'", handler_name);
+      return;
+    }
+
+  g_strfreev (split);
+
+  if (connect_object)
+    {
+      if (flags & G_CONNECT_SWAPPED)
+        closure = g_cclosure_new_object_swap (func, connect_object);
+      else
+        closure = g_cclosure_new_object (func, connect_object);
+    }
+  else
+    {
+      if (flags & G_CONNECT_SWAPPED)
+        closure = g_cclosure_new_swap (func, NULL, NULL);
+      else
+        closure = g_cclosure_new (func, NULL, NULL);
+    }
+  
+  if (module)
+    g_closure_add_finalize_notifier (closure, module, (GClosureNotify) reftest_module_unref);
+
+  g_signal_connect_closure (object, signal_name, closure, flags & G_CONNECT_AFTER ? TRUE : FALSE);
+}
+
+cairo_surface_t *
+reftest_snapshot_ui_file (const char *ui_file)
+{
+  GtkWidget *window;
+  GtkBuilder *builder;
+  GError *error = NULL;
+  char *directory;
+
+  directory = g_path_get_dirname (ui_file);
+
+  builder = gtk_builder_new ();
+  gtk_builder_add_from_file (builder, ui_file, &error);
+  g_assert_no_error (error);
+  gtk_builder_connect_signals_full (builder, connect_signals, directory);
+  window = builder_get_toplevel (builder);
+  g_object_unref (builder);
+  g_free (directory);
+  g_assert (window);
+
+  gtk_widget_show (window);
+
+  return snapshot_widget (window, SNAPSHOT_WINDOW);
+}
diff --git a/testsuite/reftests/reftest-snapshot.h b/testsuite/reftests/reftest-snapshot.h
new file mode 100644
index 0000000..178d2e8
--- /dev/null
+++ b/testsuite/reftests/reftest-snapshot.h
@@ -0,0 +1,29 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 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 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/>.
+ */
+
+#ifndef __REFTEST_SNAPSHOT_H__
+#define __REFTEST_SNAPSHOT_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+cairo_surface_t *       reftest_snapshot_ui_file                (const char     *ui_file);
+
+G_END_DECLS
+
+#endif /* __REFTEST_SNAPSHOT_H__ */


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