publically define GSignalInvocationHint structure that gets passed in to
authorTim Janik <timj@gtk.org>
Fri, 27 Oct 2000 16:48:11 +0000 (16:48 +0000)
committerTim Janik <timj@src.gnome.org>
Fri, 27 Oct 2000 16:48:11 +0000 (16:48 +0000)
Fri Oct 27 16:33:41 2000  Tim Janik  <timj@gtk.org>

        * gsignal.[hc]: publically define GSignalInvocationHint structure
        that gets passed in to closure invocations. added signal details.
        renamed GSignalType to GSignalFlags to comply with conventions.
        quite some cleanups and minor fixes. avoid uneccessary handler list
        walks upon invokation of after handlers. relookup handler list for
        restarted emissions. preliminary abort normal handler invokation if
        after handler is encountered.

        * glib-genmarshal.c:
        * gclosure.[hc]: moved invocation_hint to the end of the
        g_closure_invoke() arguments as sugegsted by kenelson.
        also made it a gpointer to be more generic. the invocation_hint
        is a caller specific thing that can be used to pass additional
        data in to closure invocations as documented with the caller
        invoking the closure.

docs/reference/glib/tmpl/macros_misc.sgml
docs/reference/glib/tmpl/misc_utils.sgml
gobject/ChangeLog
gobject/gclosure.c
gobject/gclosure.h
gobject/glib-genmarshal.c
gobject/gsignal.c
gobject/gsignal.h

index b27581833505264af24c91e9552c977e5ec395e1..06912edb867c686a77e0f29bdaea2b804564cfd5 100644 (file)
@@ -66,6 +66,7 @@ only one statement is expected by the compiler.
 Portable way to copy <type>va_list</type> variables.
 </para>
 
+<!-- # Unused Parameters # -->
 @ap1: the <type>va_list</type> variable to place a copy of @ap2 in.
 @ap2: a <type>va_list</type>.
 
index 9e7d29289dd5f7d2d98de84dcf6d54b8e887091c..8799e4166e1d33d078e2af50c08a8febbeca068f 100644 (file)
@@ -141,17 +141,6 @@ path it returns NULL.
 @Returns: a pointer into @file_name after the root component.
 
 
-<!-- ##### FUNCTION g_path_get_dirname ##### -->
-<para>
-Gets the directory components of a file name.  If the file name has no
-directory components "." is returned.  The returned string should be
-freed when no longer needed.
-</para>
-
-@file_name: the name of the file.
-@Returns: the directory components of the file.
-
-
 <!-- ##### FUNCTION g_path_get_basename ##### -->
 <para>
 Gets the name of the file without any leading directory components.
@@ -170,6 +159,17 @@ into the argument.
 @Returns: the name of the file without any leading directory components.
 
 
+<!-- ##### FUNCTION g_path_get_dirname ##### -->
+<para>
+Gets the directory components of a file name.  If the file name has no
+directory components "." is returned.  The returned string should be
+freed when no longer needed.
+</para>
+
+@file_name: the name of the file.
+@Returns: the directory components of the file.
+
+
 <!-- ##### FUNCTION g_filename_to_utf8 ##### -->
 <para>
 
index e1be144fa1a96f2fb3214dce5410ce6fa8bf606f..636d03a4c43082a59b853845d8b1ac1c332a32a0 100644 (file)
@@ -1,3 +1,21 @@
+Fri Oct 27 16:33:41 2000  Tim Janik  <timj@gtk.org>
+
+       * gsignal.[hc]: publically define GSignalInvocationHint structure
+       that gets passed in to closure invocations. added signal details.
+       renamed GSignalType to GSignalFlags to comply with conventions.
+       quite some cleanups and minor fixes. avoid uneccessary handler list
+       walks upon invokation of after handlers. relookup handler list for
+       restarted emissions. preliminary abort normal handler invokation if
+       after handler is encountered.
+
+       * glib-genmarshal.c:
+       * gclosure.[hc]: moved invocation_hint to the end of the
+       g_closure_invoke() arguments as sugegsted by kenelson.
+       also made it a gpointer to be more generic. the invocation_hint
+       is a caller specific thing that can be used to pass additional
+       data in to closure invocations as documented with the caller
+       invoking the closure.
+
 Fri Oct 27 05:35:14 2000  Tim Janik  <timj@gtk.org>
 
        * gobject.c (g_object_watch_closure): fixed realloc bug, reported
index 2dab1362a9bef0a0fb8621c2258974c5c686f0bf..8ecf091405f57f3fcf6e3f4b6a44614def98a1f4 100644 (file)
@@ -19,6 +19,7 @@
 #include       "gclosure.h"
 
 #include       "gvalue.h"
+#include       <string.h>
 
 
 /* FIXME: need caching allocators
@@ -387,10 +388,10 @@ g_closure_remove_fnotify (GClosure      *closure,
 
 void
 g_closure_invoke (GClosure       *closure,
-                 guint           invocation_hint,
                  GValue /*out*/ *return_value,
                  guint           n_param_values,
-                 const GValue   *param_values)
+                 const GValue   *param_values,
+                 gpointer        invocation_hint)
 {
   g_return_if_fail (closure != NULL);
   g_return_if_fail (closure->marshal || closure->meta_marshal);
@@ -415,9 +416,10 @@ g_closure_invoke (GClosure       *closure,
        }
       if (!in_marshal)
        closure_invoke_notifiers (closure, PRE_NOTIFY);
-      marshal (closure, invocation_hint,
+      marshal (closure,
               return_value,
               n_param_values, param_values,
+              invocation_hint,
               marshal_data);
       if (!in_marshal)
        closure_invoke_notifiers (closure, POST_NOTIFY);
@@ -477,10 +479,10 @@ g_cclosure_new_swap (GCallback      callback_func,
 
 static void
 g_type_class_meta_marshal (GClosure       *closure,
-                          guint           invocation_hint,
                           GValue /*out*/ *return_value,
                           guint           n_param_values,
                           const GValue   *param_values,
+                          gpointer        invocation_hint,
                           gpointer        marshal_data)
 {
   GTypeClass *class;
@@ -491,16 +493,19 @@ g_type_class_meta_marshal (GClosure       *closure,
   class = G_TYPE_INSTANCE_GET_CLASS (g_value_get_as_pointer (param_values + 0), itype, GTypeClass);
   callback = G_STRUCT_MEMBER (gpointer, class, offset);
   if (callback)
-    closure->marshal (closure, invocation_hint, return_value,
-                     n_param_values, param_values, callback);
+    closure->marshal (closure,
+                     return_value,
+                     n_param_values, param_values,
+                     invocation_hint,
+                     callback);
 }
 
 static void
 g_type_iface_meta_marshal (GClosure       *closure,
-                          guint           invocation_hint,
                           GValue /*out*/ *return_value,
                           guint           n_param_values,
                           const GValue   *param_values,
+                          gpointer        invocation_hint,
                           gpointer        marshal_data)
 {
   GTypeClass *class;
@@ -511,8 +516,11 @@ g_type_iface_meta_marshal (GClosure       *closure,
   class = G_TYPE_INSTANCE_GET_INTERFACE (g_value_get_as_pointer (param_values + 0), itype, GTypeClass);
   callback = G_STRUCT_MEMBER (gpointer, class, offset);
   if (callback)
-    closure->marshal (closure, invocation_hint, return_value,
-                     n_param_values, param_values, callback);
+    closure->marshal (closure,
+                     return_value,
+                     n_param_values, param_values,
+                     invocation_hint,
+                     callback);
 }
 
 GClosure*
index 423ccebb433ce274987c1c52ecdb2cc19be74c63..2ca0f3fa33a637b4c43bd5f86e5ec89931761df3 100644 (file)
@@ -41,10 +41,10 @@ typedef     gpointer GCallback;
 typedef void  (*GClosureNotify)                (gpointer        data,
                                         GClosure       *closure);
 typedef void  (*GClosureMarshal)       (GClosure       *closure,
-                                        guint           invocation_hint,
                                         GValue         *return_value,
                                         guint           n_param_values,
                                         const GValue   *param_values,
+                                        gpointer        invocation_hint,
                                         gpointer        marshal_data);
 typedef struct _GCClosure               GCClosure;
 
@@ -69,10 +69,10 @@ struct _GClosure
   /*< public >*/       guint    is_invalid : 1;
 
   /*< private >*/      void   (*marshal)  (GClosure       *closure,
-                                           guint           invocation_hint,
                                            GValue /*out*/ *return_value,
                                            guint           n_param_values,
                                            const GValue   *param_values,
+                                           gpointer        invocation_hint,
                                            gpointer        marshal_data);
   /*< protected >*/    gpointer data;
 
@@ -139,10 +139,10 @@ void              g_closure_set_meta_marshal      (GClosure       *closure,
                                                 GClosureMarshal meta_marshal);
 void           g_closure_invalidate            (GClosure       *closure);
 void           g_closure_invoke                (GClosure       *closure,
-                                                guint           invocation_hint,
                                                 GValue /*out*/ *return_value,
                                                 guint           n_param_values,
-                                                const GValue   *param_values);
+                                                const GValue   *param_values,
+                                                gpointer        invocation_hint);
 
 
 /*
index 34081f70fc445dcf5963c49743dff3adb96c3438..b13d7693632ac002fd677e63362945987633ea3c 100644 (file)
@@ -248,10 +248,10 @@ generate_marshal (const gchar *signame,
       ind = fprintf (fout, "extern void ");
       ind += fprintf (fout, "%s_%s (", marshaller_prefix, signame);
       fprintf (fout,   "GClosure     *closure,\n");
-      fprintf (fout, "%sguint         invocation_hint,\n", indent (ind));
       fprintf (fout, "%sGValue       *return_value,\n", indent (ind));
       fprintf (fout, "%sguint         n_param_values,\n", indent (ind));
       fprintf (fout, "%sconst GValue *param_values,\n", indent (ind));
+      fprintf (fout, "%sgpointer      invocation_hint,\n", indent (ind));
       fprintf (fout, "%sgpointer      marshal_data);\n", indent (ind));
     }
   if (gen_cbody)
@@ -260,10 +260,10 @@ generate_marshal (const gchar *signame,
       fprintf (fout, "void\n");
       ind = fprintf (fout, "%s_%s (", marshaller_prefix, signame);
       fprintf (fout,   "GClosure     *closure,\n");
-      fprintf (fout, "%sguint         invocation_hint,\n", indent (ind));
       fprintf (fout, "%sGValue       *return_value,\n", indent (ind));
       fprintf (fout, "%sguint         n_param_values,\n", indent (ind));
       fprintf (fout, "%sconst GValue *param_values,\n", indent (ind));
+      fprintf (fout, "%sgpointer      invocation_hint,\n", indent (ind));
       fprintf (fout, "%sgpointer      marshal_data)\n", indent (ind));
       fprintf (fout, "{\n");
 
index 5beb947b6facb0083ea6d3d00795dd160baee9c3..0c4f11759df7787f55006efa0006510181d58033 100644 (file)
@@ -103,6 +103,7 @@ static        Handler*          handler_lookup        (gpointer         instance
 static        Handler*          handler_find          (gpointer         instance,
                                                       GSignalMatchType mask,
                                                       guint            signal_id,
+                                                      GQuark           detail,
                                                       GClosure        *closure,
                                                       gpointer         func,
                                                       gpointer         data);
@@ -112,13 +113,17 @@ static inline void              handler_unref_R       (guint            signal_i
                                                       Handler         *handler);
 static inline void              emission_push         (Emission       **emission_list_p,
                                                       guint            signal_id,
+                                                      GQuark           detail,
                                                       gpointer         instance,
                                                       EmissionState   *state_p);
-static inline void              emission_pop          (Emission       **emission_list_p);
+static inline void              emission_pop          (Emission       **emission_list_p,
+                                                      EmissionState   *state_p);
 static inline Emission*         emission_find         (Emission        *emission_list,
                                                       guint            signal_id,
+                                                      GQuark           detail,
                                                       gpointer         instance);
 static       void              signal_emit_R         (SignalNode      *node,
+                                                      GQuark           detail,
                                                       gpointer         instance,
                                                       GValue          *return_value,
                                                       const GValue    *instance_and_params);
@@ -155,6 +160,7 @@ struct _Emission
 {
   Emission      *next;
   guint          signal_id;
+  GQuark        detail;
   gpointer       instance;
   EmissionState *state_p;
 };
@@ -170,6 +176,7 @@ struct _Handler
   guint         id;
   Handler      *next;
   Handler      *prev;
+  GQuark       detail;
   guint         ref_count : 16;
 #define HANDLER_MAX_REF_COUNT   (1 << 16)
   guint         block_count : 12;
@@ -308,6 +315,7 @@ static Handler*
 handler_find (gpointer         instance,
              GSignalMatchType mask,
              guint            signal_id,
+             GQuark           detail,
              GClosure        *closure,
              gpointer         func,
              gpointer         data)
@@ -327,9 +335,10 @@ handler_find (gpointer         instance,
          
       mask = ~mask;
       for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
-        if (((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
-           ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
+        if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
+           ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
             ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
+           ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
            ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
                                              handler->closure->meta_marshal == 0 &&
                                              ((GCClosure*) handler->closure)->callback == func)))
@@ -358,9 +367,10 @@ handler_find (gpointer         instance,
                }
 
               for (handler = hlist->handlers; handler; handler = handler->next)
-                if (((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
-                   ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
+               if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
+                    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
                     ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
+                   ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
                    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
                                                      handler->closure->meta_marshal == 0 &&
                                                      ((GCClosure*) handler->closure)->callback == func)))
@@ -387,6 +397,7 @@ handler_new (gboolean after)
   handler->id = handler_id++;
   handler->prev = NULL;
   handler->next = NULL;
+  handler->detail = 0;
   handler->ref_count = 1;
   handler->block_count = 0;
   handler->after = after != FALSE;
@@ -474,6 +485,7 @@ handler_insert (guint    signal_id,
 static inline void
 emission_push (Emission     **emission_list_p,
               guint          signal_id,
+              GQuark         detail,
               gpointer       instance,
               EmissionState *state_p)
 {
@@ -482,29 +494,39 @@ emission_push (Emission     **emission_list_p,
                                              EMISSION_PRE_ALLOC);
   emission->next = *emission_list_p;
   emission->signal_id = signal_id;
+  emission->detail = detail;
   emission->instance = instance;
   emission->state_p = state_p;
   *emission_list_p = emission;
 }
 
 static inline void
-emission_pop (Emission **emission_list_p)
+emission_pop (Emission     **emission_list_p,
+             EmissionState *state_p)
 {
-  Emission *emission = *emission_list_p;
-  
-  *emission_list_p = emission->next;
+  Emission **loc = emission_list_p, *emission = *loc;
+
+  while (emission->state_p != state_p)
+    {
+      loc = &emission->next;
+      emission = *loc;
+    }
+  *loc = emission->next;
   g_generic_node_free (&g_emission_ts, emission);
 }
 
 static inline Emission*
 emission_find (Emission *emission_list,
               guint     signal_id,
+              GQuark    detail,
               gpointer  instance)
 {
   Emission *emission;
   
   for (emission = emission_list; emission; emission = emission->next)
-    if (emission->instance == instance && emission->signal_id == signal_id)
+    if (emission->instance == instance &&
+       emission->signal_id == signal_id &&
+       emission->detail == detail)
       return emission;
   return NULL;
 }
@@ -575,7 +597,8 @@ g_signals_destroy (GType itype)
 
 void
 g_signal_stop_emission (gpointer instance,
-                        guint    signal_id)
+                        guint    signal_id,
+                       GQuark   detail)
 {
   SignalNode *node;
   
@@ -584,10 +607,16 @@ g_signal_stop_emission (gpointer instance,
   
   G_LOCK (g_signal_mutex);
   node = LOOKUP_SIGNAL_NODE (signal_id);
+  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
+    {
+      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
+      G_UNLOCK (g_signal_mutex);
+      return;
+    }
   if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
     {
       Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
-      Emission *emission = emission_find (emission_list, signal_id, instance);
+      Emission *emission = emission_find (emission_list, signal_id, detail, instance);
       
       if (emission)
         {
@@ -664,7 +693,7 @@ g_signal_query (guint         signal_id,
 guint
 g_signal_newv (const gchar       *signal_name,
                GType              itype,
-               GSignalType        signal_flags,
+               GSignalFlags       signal_flags,
                GClosure          *class_closure,
                GSignalAccumulator accumulator,
                GSignalCMarshaller c_marshaller,
@@ -752,12 +781,7 @@ g_signal_newv (const gchar       *signal_name,
   node->destroyed = FALSE;
   
   /* setup reinitializable portion */
-  node->flags = signal_flags & (G_SIGNAL_RUN_FIRST |
-                                G_SIGNAL_RUN_LAST |
-                               G_SIGNAL_RUN_CLEANUP |
-                                G_SIGNAL_NO_RECURSE |
-                                G_SIGNAL_ACTION |
-                                G_SIGNAL_NO_HOOKS);
+  node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
   node->n_params = n_params;
   node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
   node->return_type = return_type;
@@ -817,6 +841,7 @@ signal_destroy_R (SignalNode *signal_node)
 guint
 g_signal_connect_closure (gpointer  instance,
                          guint     signal_id,
+                         GQuark    detail,
                          GClosure *closure,
                          gboolean  after)
 {
@@ -829,11 +854,18 @@ g_signal_connect_closure (gpointer  instance,
   
   G_LOCK (g_signal_mutex);
   node = LOOKUP_SIGNAL_NODE (signal_id);
+  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
+    {
+      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
+      G_UNLOCK (g_signal_mutex);
+      return 0;
+    }
   if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
     {
       Handler *handler = handler_new (after);
       
       handler_id = handler->id;
+      handler->detail = detail;
       handler->closure = g_closure_ref (closure);
       handler_insert (signal_id, instance, handler);
       if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
@@ -964,6 +996,7 @@ guint
 g_signal_handler_find (gpointer         instance,
                        GSignalMatchType mask,
                        guint            signal_id,
+                      GQuark           detail,
                        GClosure        *closure,
                        gpointer         func,
                        gpointer         data)
@@ -972,9 +1005,10 @@ g_signal_handler_find (gpointer         instance,
   guint handler_id;
   
   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
+  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
   
   G_LOCK (g_signal_mutex);
-  handler = handler_find (instance, mask, signal_id, closure, func, data);
+  handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
   handler_id = handler ? handler->id : 0;
   G_UNLOCK (g_signal_mutex);
   
@@ -984,6 +1018,7 @@ g_signal_handler_find (gpointer         instance,
 gboolean
 g_signal_handler_pending (gpointer instance,
                           guint    signal_id,
+                         GQuark   detail,
                           gboolean may_be_blocked)
 {
   Handler *handler = NULL;
@@ -992,11 +1027,21 @@ g_signal_handler_pending (gpointer instance,
   g_return_val_if_fail (signal_id > 0, FALSE);
   
   G_LOCK (g_signal_mutex);
-  handler = handler_find (instance, G_SIGNAL_MATCH_ID, signal_id, NULL, NULL, NULL);
-  if (!may_be_blocked)
-    for (; handler; handler = handler->next)
-      if (!handler->block_count)
-        break;
+  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);
+         G_UNLOCK (g_signal_mutex);
+         return FALSE;
+       }
+    }
+  handler = handler_find (instance,
+                         (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL |
+                          (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
+                         signal_id, detail, NULL, NULL, NULL);
   G_UNLOCK (g_signal_mutex);
   
   return handler != NULL;
@@ -1005,6 +1050,7 @@ g_signal_handler_pending (gpointer instance,
 void
 g_signal_emitv (const GValue *instance_and_params,
                guint         signal_id,
+               GQuark        detail,
                GValue       *return_value)
 {
   SignalNode *node;
@@ -1024,6 +1070,12 @@ g_signal_emitv (const GValue *instance_and_params,
 #ifndef G_DISABLE_CHECKS
   if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
+  if (detail && !(node->flags & G_SIGNAL_DETAILED))
+    {
+      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
+      G_UNLOCK (g_signal_mutex);
+      return;
+    }
   for (i = 0; i < node->n_params; i++)
     if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
       {
@@ -1059,29 +1111,31 @@ g_signal_emitv (const GValue *instance_and_params,
     return_value = NULL;
 #endif /* !G_DISABLE_CHECKS */
   
-  signal_emit_R (node, instance, return_value, instance_and_params);
+  signal_emit_R (node, detail, instance, return_value, instance_and_params);
   
   G_UNLOCK (g_signal_mutex);
 }
 
 static void
 signal_emit_R (SignalNode   *node,
+              GQuark        detail,
               gpointer      instance,
               GValue       *return_value,
               const GValue *instance_and_params)
 {
   EmissionState emission_state = 0;
   GSignalAccumulator accumulator;
+  GSignalInvocationHint ihint;
   GClosure *class_closure;
   HandlerList *hlist;
-  Handler *handlers;
+  Handler *handler_list = NULL;
   GValue accu;
   gboolean accu_used = FALSE;
   guint signal_id = node->signal_id;
   
   if (node->flags & G_SIGNAL_NO_RECURSE)
     {
-      Emission *emission = emission_find (g_restart_emissions, signal_id, instance);
+      Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
       
       if (emission)
        {
@@ -1089,6 +1143,8 @@ signal_emit_R (SignalNode   *node,
          return;
        }
     }
+  ihint.signal_id = node->signal_id;
+  ihint.detail = detail;
   accumulator = node->accumulator;
   if (accumulator)
     {
@@ -1097,15 +1153,20 @@ signal_emit_R (SignalNode   *node,
       G_LOCK (g_signal_mutex);
     }
   emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
-                signal_id, instance, &emission_state);
+                signal_id, detail, instance, &emission_state);
   class_closure = node->class_closure;
-  hlist = handler_list_lookup (signal_id, instance);
-  handlers = hlist ? hlist->handlers : NULL;
-  if (handlers)
-    handler_ref (handlers);
   
  EMIT_RESTART:
   
+  if (handler_list)
+    handler_unref_R (signal_id, instance, handler_list);
+  hlist = handler_list_lookup (signal_id, instance);
+  handler_list = hlist ? hlist->handlers : NULL;
+  if (handler_list)
+    handler_ref (handler_list);
+  
+  ihint.run_type = G_SIGNAL_RUN_FIRST;
+  
   if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
     {
       emission_state = EMISSION_RUN;
@@ -1116,21 +1177,21 @@ signal_emit_R (SignalNode   *node,
          if (accu_used)
            g_value_reset (&accu);
          g_closure_invoke (class_closure,
-                           (signal_id << 8) | G_SIGNAL_RUN_FIRST,
                            &accu,
                            node->n_params + 1,
-                           instance_and_params);
-         if (!accumulator (signal_id, return_value, &accu) &&
+                           instance_and_params,
+                           &ihint);
+         if (!accumulator (&ihint, return_value, &accu) &&
              emission_state == EMISSION_RUN)
            emission_state = EMISSION_STOP;
          accu_used = TRUE;
        }
       else
        g_closure_invoke (class_closure,
-                         (signal_id << 8) | G_SIGNAL_RUN_FIRST,
                          return_value,
                          node->n_params + 1,
-                         instance_and_params);
+                         instance_and_params,
+                         &ihint);
       G_LOCK (g_signal_mutex);
       
       if (emission_state == EMISSION_STOP)
@@ -1151,18 +1212,23 @@ signal_emit_R (SignalNode   *node,
        goto EMIT_RESTART;
     }
   
-  if (handlers)
+  if (handler_list)
     {
-      Handler *handler = handlers;
+      Handler *handler = handler_list;
       
       emission_state = EMISSION_RUN;
-      
       handler_ref (handler);
       do
        {
          Handler *tmp;
          
-         if (!handler->after && !handler->block_count)
+         if (handler->after)
+           {
+             handler_unref_R (signal_id, instance, handler_list);
+             handler_list = handler;
+             break;
+           }
+         else if (!handler->block_count && (!handler->detail || handler->detail == detail))
            {
              G_UNLOCK (g_signal_mutex);
              if (accumulator)
@@ -1170,21 +1236,21 @@ signal_emit_R (SignalNode   *node,
                  if (accu_used)
                    g_value_reset (&accu);
                  g_closure_invoke (handler->closure,
-                                   (signal_id << 8) | G_SIGNAL_RUN_FIRST,
                                    &accu,
                                    node->n_params + 1,
-                                   instance_and_params);
-                 if (!accumulator (signal_id, return_value, &accu) &&
+                                   instance_and_params,
+                                   &ihint);
+                 if (!accumulator (&ihint, return_value, &accu) &&
                      emission_state == EMISSION_RUN)
                    emission_state = EMISSION_STOP;
                  accu_used = TRUE;
                }
              else
                g_closure_invoke (handler->closure,
-                                 (signal_id << 8) | G_SIGNAL_RUN_FIRST,
                                  return_value,
                                  node->n_params + 1,
-                                 instance_and_params);
+                                 instance_and_params,
+                                 &ihint);
              G_LOCK (g_signal_mutex);
              
              tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
@@ -1194,7 +1260,8 @@ signal_emit_R (SignalNode   *node,
          
          if (tmp)
            handler_ref (tmp);
-         handler_unref_R (signal_id, instance, handler);
+         handler_unref_R (signal_id, instance, handler_list);
+         handler_list = handler;
          handler = tmp;
        }
       while (handler);
@@ -1205,6 +1272,8 @@ signal_emit_R (SignalNode   *node,
        goto EMIT_RESTART;
     }
   
+  ihint.run_type = G_SIGNAL_RUN_LAST;
+  
   if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
     {
       emission_state = EMISSION_RUN;
@@ -1215,21 +1284,21 @@ signal_emit_R (SignalNode   *node,
          if (accu_used)
            g_value_reset (&accu);
          g_closure_invoke (class_closure,
-                           (signal_id << 8) | G_SIGNAL_RUN_LAST,
                            &accu,
                            node->n_params + 1,
-                           instance_and_params);
-          if (!accumulator (signal_id, return_value, &accu) &&
+                           instance_and_params,
+                           &ihint);
+          if (!accumulator (&ihint, return_value, &accu) &&
              emission_state == EMISSION_RUN)
            emission_state = EMISSION_STOP;
          accu_used = TRUE;
        }
       else
        g_closure_invoke (class_closure,
-                         (signal_id << 8) | G_SIGNAL_RUN_LAST,
                          return_value,
                          node->n_params + 1,
-                         instance_and_params);
+                         instance_and_params,
+                         &ihint);
       G_LOCK (g_signal_mutex);
       
       if (emission_state == EMISSION_STOP)
@@ -1238,18 +1307,17 @@ signal_emit_R (SignalNode   *node,
        goto EMIT_RESTART;
     }
   
-  if (handlers)
+  if (handler_list)
     {
-      Handler *handler = handlers;
+      Handler *handler = handler_list;
       
       emission_state = EMISSION_RUN;
-      
       handler_ref (handler);
       do
        {
          Handler *tmp;
          
-         if (handler->after && !handler->block_count)
+         if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
            {
              G_UNLOCK (g_signal_mutex);
               if (accumulator)
@@ -1257,21 +1325,21 @@ signal_emit_R (SignalNode   *node,
                  if (accu_used)
                    g_value_reset (&accu);
                  g_closure_invoke (handler->closure,
-                                   (signal_id << 8) | G_SIGNAL_RUN_LAST,
                                    &accu,
                                    node->n_params + 1,
-                                   instance_and_params);
-                 if (!accumulator (signal_id, return_value, &accu) &&
+                                   instance_and_params,
+                                   &ihint);
+                 if (!accumulator (&ihint, return_value, &accu) &&
                      emission_state == EMISSION_RUN)
                    emission_state = EMISSION_STOP;
                  accu_used = TRUE;
                }
              else
                g_closure_invoke (handler->closure,
-                                 (signal_id << 8) | G_SIGNAL_RUN_LAST,
                                  return_value,
                                  node->n_params + 1,
-                                 instance_and_params);
+                                 instance_and_params,
+                                 &ihint);
              G_LOCK (g_signal_mutex);
              
              tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
@@ -1294,36 +1362,42 @@ signal_emit_R (SignalNode   *node,
   
  EMIT_CLEANUP:
   
+  ihint.run_type = G_SIGNAL_RUN_CLEANUP;
+  
   if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
     {
+      gboolean need_unset = FALSE;
+      
       emission_state = EMISSION_STOP;
       
       G_UNLOCK (g_signal_mutex);
       if (node->return_type != G_TYPE_NONE)
        {
          if (!accumulator)
-           g_value_init (&accu, node->return_type);
+           {
+             g_value_init (&accu, node->return_type);
+             need_unset = TRUE;
+           }
          else if (accu_used)
            g_value_reset (&accu);
-         accu_used = TRUE;
        }
       g_closure_invoke (class_closure,
-                       (signal_id << 8) | G_SIGNAL_RUN_CLEANUP,
                        node->return_type != G_TYPE_NONE ? &accu : NULL,
                        node->n_params + 1,
-                       instance_and_params);
-      if (node->return_type != G_TYPE_NONE && !accumulator)
+                       instance_and_params,
+                       &ihint);
+      if (need_unset)
        g_value_unset (&accu);
       G_LOCK (g_signal_mutex);
-
+      
       if (emission_state == EMISSION_RESTART)
        goto EMIT_RESTART;
     }
   
-  if (handlers)
-    handler_unref_R (signal_id, instance, handlers);
+  if (handler_list)
+    handler_unref_R (signal_id, instance, handler_list);
   
-  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions);
+  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
   if (accumulator)
     {
       G_UNLOCK (g_signal_mutex);
index f2be46f63d8dcb266579ce751f7a635a19575c53..bc2f75c8066603bffdf08ad18ca8b3ac95eb9a35 100644 (file)
@@ -30,9 +30,16 @@ extern "C" {
 #endif /* __cplusplus */
 
 
-/* --- macros --- */
-#define        G_SIGNAL_HINT_ID(hint)          ((hint) >> 8) 
-#define        G_SIGNAL_HINT_RUN_TYPE(hint)    ((hint) & 0xff)
+/* --- typedefs --- */
+typedef struct _GSignalQuery            GSignalQuery;
+typedef struct _GSignalInvocationHint   GSignalInvocationHint;
+typedef        GClosureMarshal                  GSignalCMarshaller;
+typedef gboolean (*GSignalEmissionHook) (GSignalInvocationHint *ihint,
+                                        guint                  n_param_values,
+                                        const GValue          *param_values);
+typedef gboolean (*GSignalAccumulator) (GSignalInvocationHint *ihint,
+                                        GValue                *return_accu,
+                                        const GValue          *return_value);
 
 
 /* --- run & match types --- */
@@ -42,48 +49,46 @@ typedef enum
   G_SIGNAL_RUN_LAST    = 1 << 1,
   G_SIGNAL_RUN_CLEANUP = 1 << 2,
   G_SIGNAL_NO_RECURSE  = 1 << 3,
-  G_SIGNAL_ACTION      = 1 << 4,
-  G_SIGNAL_NO_HOOKS    = 1 << 5
-} GSignalType;
+  G_SIGNAL_DETAILED    = 1 << 4,
+  G_SIGNAL_ACTION      = 1 << 5,
+  G_SIGNAL_NO_HOOKS    = 1 << 6
+#define        G_SIGNAL_FLAGS_MASK  0x7f
+} GSignalFlags;
 typedef enum
 {
   G_SIGNAL_MATCH_ID       = 1 << 0,
-  G_SIGNAL_MATCH_CLOSURE   = 1 << 1,
-  G_SIGNAL_MATCH_FUNC     = 1 << 2,
-  G_SIGNAL_MATCH_DATA     = 1 << 3,
-  G_SIGNAL_MATCH_UNBLOCKED = 1 << 4,
-  G_SIGNAL_MATCH_MASK     = 0x1f
+  G_SIGNAL_MATCH_DETAIL           = 1 << 1,
+  G_SIGNAL_MATCH_CLOSURE   = 1 << 2,
+  G_SIGNAL_MATCH_FUNC     = 1 << 3,
+  G_SIGNAL_MATCH_DATA     = 1 << 4,
+  G_SIGNAL_MATCH_UNBLOCKED = 1 << 5
+#define        G_SIGNAL_MATCH_MASK  0x3f
 } GSignalMatchType;
 
 
-/* --- signal queries --- */
-typedef struct _GSignalQuery GSignalQuery;
-struct _GSignalQuery
+/* --- signal information --- */
+struct _GSignalInvocationHint
+{
+  guint                signal_id;
+  GQuark       detail;
+  GSignalFlags run_type;
+};
+struct _GSignalQuery
 {
   guint                signal_id;
   const gchar  *signal_name;
   GType                itype;
-  GSignalType  signal_flags;
+  GSignalFlags signal_flags;
   GType                return_type;
   guint                n_params;
   const GType  *param_types;
 };
 
 
-/* --- function types --- */
-typedef gboolean  (*GSignalEmissionHook)       (guint          signal_id,
-                                                guint          n_values,
-                                                const GValue  *values);
-typedef gboolean  (*GSignalAccumulator)                (guint          signal_id,
-                                                GValue        *return_accu,
-                                                const GValue  *return_value);
-typedef        GClosureMarshal                 GSignalCMarshaller;
-
-
 /* --- signals --- */
 guint  g_signal_newv                   (const gchar            *signal_name,
                                         GType                   itype,
-                                        GSignalType             signal_flags,
+                                        GSignalFlags            signal_flags,
                                         GClosure               *class_closure,
                                         GSignalAccumulator      accumulator,
                                         GSignalCMarshaller      c_marshaller,
@@ -92,6 +97,7 @@ guint g_signal_newv                   (const gchar            *signal_name,
                                         GType                  *param_types);
 void   g_signal_emitv                  (const GValue           *instance_and_params,
                                         guint                   signal_id,
+                                        GQuark                  detail,
                                         GValue                 *return_value);
 guint  g_signal_lookup                 (const gchar            *name,
                                         GType                   itype);
@@ -103,6 +109,7 @@ void        g_signal_query                  (guint                   signal_id,
 /* --- signal handlers --- */
 guint   g_signal_connect_closure       (gpointer                instance,
                                         guint                   signal_id,
+                                        GQuark                  detail,
                                         GClosure               *closure,
                                         gboolean                after);
 void    g_signal_handler_disconnect    (gpointer                instance,
@@ -114,17 +121,20 @@ void       g_signal_handler_unblock       (gpointer                instance,
 guint   g_signal_handler_find          (gpointer                instance,
                                         GSignalMatchType        mask,
                                         guint                   signal_id,
+                                        GQuark                  detail,
                                         GClosure               *closure,
                                         gpointer                func,
                                         gpointer                data);
 gboolean g_signal_has_handler_pending  (gpointer                instance,
                                         guint                   signal_id,
+                                        GQuark                  detail,
                                         gboolean                may_be_blocked);
 
 
 /* --- signal emissions --- */
 void   g_signal_stop_emission          (gpointer                instance,
-                                        guint                   signal_id);
+                                        guint                   signal_id,
+                                        GQuark                  detail);
 guint  g_signal_add_emission_hook_full (guint                   signal_id,
                                         GClosure               *closure);
 void   g_signal_remove_emission_hook   (guint                   signal_id,