[glib] signal: return TRUE from g_signal_has_handler_pending for custom class closure



commit 69002f726d597c613223ad0ea8e6262b73842f1b
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Sep 14 13:15:51 2015 +0200

    signal: return TRUE from g_signal_has_handler_pending for custom class closure
    
    This is almost always what you want, because if you're using this you
    want to know if any "custom code" (i.e. not the default class closure)
    is going to be run if you emit this signal.
    
    I looked at all the existing uses of this and they were all broken in the
    presence of g_signal_override_class_closure().
    
    https://bugzilla.gnome.org/show_bug.cgi?id=754986

 gobject/gsignal.c |   33 ++++++++++++++++++++++-----------
 1 files changed, 22 insertions(+), 11 deletions(-)
---
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index 96f0757..91d748a 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -1526,7 +1526,14 @@ signal_find_class_closure (SignalNode *node,
       ClassClosure key;
 
       /* cc->instance_type is 0 for default closure */
-      
+
+      if (g_bsearch_array_get_n_nodes (bsa) == 1)
+        {
+          cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
+          if (cc && cc->instance_type == 0) /* check for default closure */
+            return cc;
+        }
+
       key.instance_type = itype;
       cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
       while (!cc && key.instance_type)
@@ -1546,12 +1553,6 @@ signal_lookup_closure (SignalNode    *node,
 {
   ClassClosure *cc;
 
-  if (node->class_closure_bsa && g_bsearch_array_get_n_nodes (node->class_closure_bsa) == 1)
-    {
-      cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
-      if (cc && cc->instance_type == 0) /* check for default closure */
-        return cc->closure;
-    }
   cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
   return cc ? cc->closure : NULL;
 }
@@ -2951,6 +2952,9 @@ g_signal_handlers_disconnect_matched (gpointer         instance,
  * consistent with how a signal emitted with @detail would be delivered
  * to those handlers.
  *
+ * Since 2.46 this also checks for a non-default class closure being
+ * installed, as this is basically always what you want.
+ *
  * One example of when you might use this is when the arguments to the
  * signal are difficult to compute. A class implementor may opt to not
  * emit the signal if no one is attached anyway, thus saving the cost
@@ -2967,15 +2971,16 @@ g_signal_has_handler_pending (gpointer instance,
 {
   HandlerMatch *mlist;
   gboolean has_pending;
+  SignalNode *node;
   
   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
   g_return_val_if_fail (signal_id > 0, FALSE);
   
   SIGNAL_LOCK ();
+
+  node = LOOKUP_SIGNAL_NODE (signal_id);
   if (detail)
     {
-      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
-      
       if (!(node->flags & G_SIGNAL_DETAILED))
        {
          g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
@@ -2992,9 +2997,15 @@ g_signal_has_handler_pending (gpointer instance,
       handler_match_free1_R (mlist, instance);
     }
   else
-    has_pending = FALSE;
+    {
+      ClassClosure *class_closure = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
+      if (class_closure != NULL && class_closure->instance_type != 0)
+        has_pending = TRUE;
+      else
+        has_pending = FALSE;
+    }
   SIGNAL_UNLOCK ();
-  
+
   return has_pending;
 }
 


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