[glib: 1/2] gsignal: Allow return types for RUN_FIRST-only signals too




commit 3581eda9a2ed8d7731ce80d16bb03d84ad251e92
Author: Sebastian Dröge <sebastian centricular com>
Date:   Thu Feb 16 09:57:48 2012 +0100

    gsignal: Allow return types for RUN_FIRST-only signals too
    
    Also adds a test that checks that the G_SIGNAL_RUN flags are handled
    correctly and the class signal handler is called at the right times.
    
    Fixes https://gitlab.gnome.org/GNOME/glib/issues/513

 gobject/gsignal.c       |   9 ----
 gobject/tests/signals.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+), 9 deletions(-)
---
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index c3b453de7..d8a4cd9d9 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -1771,15 +1771,6 @@ g_signal_newv (const gchar       *signal_name,
       SIGNAL_UNLOCK ();
       return 0;
     }
-  if (return_type != G_TYPE_NONE &&
-      (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST)
-    {
-      g_warning (G_STRLOC ": signal \"%s::%s\" has return type '%s' and is only G_SIGNAL_RUN_FIRST",
-                type_debug_name (itype), name, type_debug_name (return_type));
-      g_free (signal_name_copy);
-      SIGNAL_UNLOCK ();
-      return 0;
-    }
   
   /* setup permanent portion of signal node */
   if (!node)
diff --git a/gobject/tests/signals.c b/gobject/tests/signals.c
index 37d06a237..ea9a778bf 100644
--- a/gobject/tests/signals.c
+++ b/gobject/tests/signals.c
@@ -186,6 +186,8 @@ struct _Test
 
 static void all_types_handler (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong 
ul, MyEnum e, MyFlags f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test 
*obj, GVariant *var, gint64 i64, guint64 ui64);
 static gboolean accumulator_sum (GSignalInvocationHint *ihint, GValue *return_accu, const GValue 
*handler_return, gpointer data);
+static gboolean accumulator_concat_string (GSignalInvocationHint *ihint, GValue *return_accu, const GValue 
*handler_return, gpointer data);
+static gchar * accumulator_class (Test *test);
 
 struct _TestClass
 {
@@ -194,6 +196,7 @@ struct _TestClass
   void (* variant_changed) (Test *, GVariant *);
   void (* all_types) (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong ul, MyEnum 
e, MyFlags f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test *obj, 
GVariant *var, gint64 i64, guint64 ui64);
   void (* all_types_null) (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong ul, 
MyEnum e, MyFlags f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test 
*obj, GVariant *var, gint64 i64, guint64 ui64);
+  gchar * (*accumulator_class) (Test *test);
 };
 
 static GType test_get_type (void);
@@ -213,6 +216,7 @@ test_class_init (TestClass *klass)
   flags_type = g_flags_register_static ("MyFlag", my_flag_values);
 
   klass->all_types = all_types_handler;
+  klass->accumulator_class = accumulator_class;
 
   simple_id = g_signal_new ("simple",
                 G_TYPE_FROM_CLASS (klass),
@@ -247,6 +251,54 @@ test_class_init (TestClass *klass)
                 NULL,
                 G_TYPE_INT,
                 0);
+  g_signal_new ("accumulator-class-first",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_FIRST,
+                G_STRUCT_OFFSET (TestClass, accumulator_class),
+                accumulator_concat_string, NULL,
+                NULL,
+                G_TYPE_STRING,
+                0);
+  g_signal_new ("accumulator-class-last",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_LAST,
+                G_STRUCT_OFFSET (TestClass, accumulator_class),
+                accumulator_concat_string, NULL,
+                NULL,
+                G_TYPE_STRING,
+                0);
+  g_signal_new ("accumulator-class-cleanup",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_CLEANUP,
+                G_STRUCT_OFFSET (TestClass, accumulator_class),
+                accumulator_concat_string, NULL,
+                NULL,
+                G_TYPE_STRING,
+                0);
+  g_signal_new ("accumulator-class-first-last",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
+                G_STRUCT_OFFSET (TestClass, accumulator_class),
+                accumulator_concat_string, NULL,
+                NULL,
+                G_TYPE_STRING,
+                0);
+  g_signal_new ("accumulator-class-first-last-cleanup",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
+                G_STRUCT_OFFSET (TestClass, accumulator_class),
+                accumulator_concat_string, NULL,
+                NULL,
+                G_TYPE_STRING,
+                0);
+  g_signal_new ("accumulator-class-last-cleanup",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
+                G_STRUCT_OFFSET (TestClass, accumulator_class),
+                accumulator_concat_string, NULL,
+                NULL,
+                G_TYPE_STRING,
+                0);
   g_signal_new ("generic-marshaller-1",
                 G_TYPE_FROM_CLASS (klass),
                 G_SIGNAL_RUN_LAST,
@@ -1227,6 +1279,76 @@ test_accumulator (void)
   g_object_unref (test);
 }
 
+static gboolean
+accumulator_concat_string (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, 
gpointer data)
+{
+  const gchar *acc = g_value_get_string (return_accu);
+  const gchar *ret = g_value_get_string (handler_return);
+
+  g_assert_nonnull (ret);
+
+  if (acc == NULL)
+    g_value_set_string (return_accu, ret);
+  else
+    g_value_take_string (return_accu, g_strconcat (acc, ret, NULL));
+
+  return TRUE;
+}
+
+static gchar *
+accumulator_class_before_cb (gpointer instance, gpointer data)
+{
+  return g_strdup ("before");
+}
+
+static gchar *
+accumulator_class_after_cb (gpointer instance, gpointer data)
+{
+  return g_strdup ("after");
+}
+
+static gchar *
+accumulator_class (Test *test)
+{
+  return g_strdup ("class");
+}
+
+static void
+test_accumulator_class (void)
+{
+  const struct {
+    const gchar *signal_name;
+    const gchar *return_string;
+  } tests[] = {
+    {"accumulator-class-first", "classbeforeafter"},
+    {"accumulator-class-last", "beforeclassafter"},
+    {"accumulator-class-cleanup", "beforeafterclass"},
+    {"accumulator-class-first-last", "classbeforeclassafter"},
+    {"accumulator-class-first-last-cleanup", "classbeforeclassafterclass"},
+    {"accumulator-class-last-cleanup", "beforeclassafterclass"},
+  };
+  gsize i;
+
+  for (i = 0; i < G_N_ELEMENTS (tests); i++)
+    {
+      GObject *test;
+      gchar *ret = NULL;
+
+      g_test_message ("Signal: %s", tests[i].signal_name);
+
+      test = g_object_new (test_get_type (), NULL);
+
+      g_signal_connect (test, tests[i].signal_name, G_CALLBACK (accumulator_class_before_cb), NULL);
+      g_signal_connect_after (test, tests[i].signal_name, G_CALLBACK (accumulator_class_after_cb), NULL);
+      g_signal_emit_by_name (test, tests[i].signal_name, &ret);
+
+      g_assert_cmpstr (ret, ==, tests[i].return_string);
+      g_free (ret);
+
+      g_object_unref (test);
+    }
+}
+
 static gboolean
 in_set (const gchar *s,
         const gchar *set[])
@@ -1254,6 +1376,12 @@ test_introspection (void)
     "simple-detailed",
     "simple-2",
     "simple-accumulator",
+    "accumulator-class-first",
+    "accumulator-class-last",
+    "accumulator-class-cleanup",
+    "accumulator-class-first-last",
+    "accumulator-class-first-last-cleanup",
+    "accumulator-class-last-cleanup",
     "generic-marshaller-1",
     "generic-marshaller-2",
     "generic-marshaller-enum-return-signed",
@@ -1680,6 +1808,7 @@ main (int argc,
   g_test_add_func ("/gobject/signals/connect", test_connect);
   g_test_add_func ("/gobject/signals/emission-hook", test_emission_hook);
   g_test_add_func ("/gobject/signals/accumulator", test_accumulator);
+  g_test_add_func ("/gobject/signals/accumulator-class", test_accumulator_class);
   g_test_add_func ("/gobject/signals/introspection", test_introspection);
   g_test_add_func ("/gobject/signals/block-handler", test_block_handler);
   g_test_add_func ("/gobject/signals/stop-emission", test_stop_emission);


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