Signal connection order




Hello, all.

Why are all handlers always connected last? Ie. the calling order of
handlers is always the same as the order in which they're connected.
I'd like to do a little thingy in gimp that requires that a handler gets
called before another one that's connected earlier.

I made a minimalist patch that shows what I'm looking after, but before I
make a more complete one, I'd just like to know what the preferred syntax
would be for connecting a handler into the start of the list of handlers
for that signal and object. I think adding an extra argument in
gtk_signal_connect would be tedious for most people (as well as break all
gtk code)..

Also, is it really sensible that all the handlers for an object are in a
single list? Wouldn't either a list of lists (each sublist containing a
single type) or a hash be more sensible? And in the same go, would it be
sensible to have more options about the ordering, besides just this
"after" flag? How about using the full range of int in handlers so that
you could connect a handler at a certain priority and be guaranteed that
the handlers are called in their order of priority?

Just some thoughts...


Lauri Alanko
la@iki.fi


Here's the example to show what I'm aiming at.

--- gtksignal.h~	Tue Nov 25 00:37:46 1997
+++ gtksignal.h	Mon Dec 15 23:42:20 1997
@@ -95,6 +95,10 @@
 					   gpointer             data,
 					   GtkDestroyNotify     destroy_func,
 					   gint                 after);
+gint   gtk_signal_connect_start           (GtkObject           *object,
+					   const gchar         *name,
+					   GtkSignalFunc        func,
+					   gpointer             func_data);
 void   gtk_signal_disconnect              (GtkObject           *object,
 					   gint                 anid);
 void   gtk_signal_disconnect_by_data      (GtkObject           *object,
--- gtksignal.c~	Tue Nov 25 00:37:46 1997
+++ gtksignal.c	Mon Dec 15 23:52:46 1997
@@ -96,7 +96,8 @@
 static GtkHandler*  gtk_signal_handler_new     (void);
 static void         gtk_signal_handler_destroy (GtkHandler    *handler);
 static void         gtk_signal_handler_insert  (GtkObject     *object,
-						GtkHandler    *handler);
+						GtkHandler    *handler,
+						gint           first);
 static gint         gtk_signal_real_emit       (GtkObject     *object,
 						gint           signal_type,
 						va_list        args);
@@ -109,7 +110,8 @@
 						gpointer       func_data,
 						GtkSignalDestroy destroy_func,
 						gint           after,
-						gint           no_marshal);
+						gint           no_marshal,
+						gint           start);
 static GtkEmission* gtk_emission_new           (void);
 static void         gtk_emission_destroy       (GtkEmission    *emission);
 static void         gtk_emission_add           (GList         **emissions,
@@ -361,7 +363,7 @@
 
   return gtk_signal_connect_by_type (object, type, FALSE,
 				     func, func_data, NULL,
-				     FALSE, FALSE);
+				     FALSE, FALSE, FALSE);
 }
 
 gint
@@ -387,7 +389,7 @@
 
   return gtk_signal_connect_by_type (object, type, FALSE,
 				     func, func_data, NULL,
-				     TRUE, FALSE);
+				     TRUE, FALSE, FALSE);
 }
 
 gint
@@ -415,7 +417,7 @@
 
   return gtk_signal_connect_by_type (object, type, FALSE,
 				     (GtkSignalFunc) func, func_data,
-				     destroy_func, after, TRUE);
+				     destroy_func, after, TRUE, FALSE);
 }
 
 gint
@@ -441,7 +443,7 @@
 
   return gtk_signal_connect_by_type (object, type, TRUE,
 				     func, slot_object, NULL,
-				     FALSE, FALSE);
+				     FALSE, FALSE, FALSE);
 }
 
 gint
@@ -467,7 +469,33 @@
 
   return gtk_signal_connect_by_type (object, type, TRUE,
 				     func, slot_object, NULL,
-				     TRUE, FALSE);
+				     TRUE, FALSE, FALSE);
+}
+
+gint
+gtk_signal_connect_start (GtkObject     *object,
+			  const gchar   *name,
+			  GtkSignalFunc  func,
+			  gpointer       func_data)
+{
+  gint type;
+
+  g_return_val_if_fail (object != NULL, 0);
+
+  if (initialize)
+    gtk_signal_init ();
+
+  type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+  if (!type)
+    {
+      g_warning ("could not find signal type \"%s\" in the \"%s\" class ancestry",
+		 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+      return 0;
+    }
+
+  return gtk_signal_connect_by_type (object, type, FALSE,
+				     func, func_data, NULL,
+				     FALSE, FALSE, TRUE);
 }
 
 void
@@ -792,7 +820,8 @@
 
 static void
 gtk_signal_handler_insert (GtkObject  *object,
-			   GtkHandler *handler)
+			   GtkHandler *handler,
+			   gint        first)
 {
   GtkHandler *start;
   GtkHandler *tmp;
@@ -810,7 +839,8 @@
 
       while (tmp)
 	{
-	  if (tmp->signal_type < handler->signal_type)
+	  if (tmp->signal_type < handler->signal_type ||
+	      (first && tmp->signal_type == handler->signal_type))
 	    {
 	      if (prev)
 		prev->next = handler;
@@ -962,7 +992,8 @@
 			    gpointer         func_data,
 			    GtkSignalDestroy destroy_func,
 			    gint             after,
-			    gint             no_marshal)
+			    gint             no_marshal,
+			    gint             start)
 {
   GtkHandler *handler;
   gint *object_signals;
@@ -1007,7 +1038,7 @@
     handler->after = TRUE;
   handler->no_marshal = no_marshal;
 
-  gtk_signal_handler_insert (object, handler);
+  gtk_signal_handler_insert (object, handler, start);
   return handler->id;
 }
 




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