[Gtk-sharp-list] bug: Removing event handlers

Gonzalo Paniagua Javier gonzalo@ximian.com
05 Feb 2003 15:16:20 +0100


--=-nR+iQKdSLyZ7TZD0Retu
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit

El mié, 05-02-2003 a las 15:40, Lee Mallabone escribió:
> Greetings,
> 
> I've found what I think is a bug with removing event handlers in
> Gtk#/mono.
> 
> When I use:
> 
> button.Clicked -= new EventHandler(handler1);
> 
> the handler is not actually removed, and still receives events from the
> button.
> 
> I've attached a small test case that demonstrates this behaviour - after
> switching event handlers on a button, both the old and the new handlers
> are fired rather than just the new handler.
> 
> Could anyone please comment on whether they can reproduce this? I'm
> using RedHat 8.0 with mono 0.19 and Gtk# 0.7.
> 
> I've opened a bug on bugzilla.ximian.com to track this, (bug #37635),
> but thought I'd post here in case there's some magic quick fix I'm just
> not seeing. :)

Here's the magic quick fix ;-).

The patch attached adds a couple of methods in SignalCallback.cs to
add/remove a delegate from the _handle.

Also modifies Signal.cs in the generator to make use of the above
methods when adding/removing a handler for a signal.

Ok to commit?

-Gonzalo

P.S.: the generated code for signals now looks like:
[GLib.Signal("clicked")]
public event EventHandler Clicked {
	add {
		if (EventList["clicked"] == null)
			Signals["clicked"] = new GtkSharp.voidObjectSignal(this, Handle,
"clicked", value, System.Type.GetType("System.EventArgs"));
		else
			((GtkSharp.SignalCallback) Signals ["clicked"]).AddDelegate (value);
		EventList.AddHandler("clicked", value);
	}
	remove {
		EventList.RemoveHandler("clicked", value);
		if (EventList["clicked"] == null)
			Signals.Remove("clicked");
		else
			((GtkSharp.SignalCallback) Signals ["clicked"]).RemoveDelegate
(value);
			}
		}



P.S.2: ah! I also changed MulticastDelegate to be just Delegate to avoid
casting :-) (all delegates are MulticastDelegates)


--=-nR+iQKdSLyZ7TZD0Retu
Content-Disposition: attachment; filename=signals.patch
Content-Type: text/x-patch; name=signals.patch; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: generator/Signal.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/generator/Signal.cs,v
retrieving revision 1.11
diff -u -r1.11 Signal.cs
--- generator/Signal.cs	9 Dec 2002 23:36:18 -0000	1.11
+++ generator/Signal.cs	5 Feb 2003 13:58:47 -0000
@@ -163,13 +163,16 @@
 			sw.Write("(this, Handle, " + cname + ", value, System.Type.GetType(\"" + argsname);
 			if (argsname != "System.EventArgs")
 				sw.Write("," + container_type.NS.ToLower() + "-sharp");
-			sw.WriteLine("\"));");
+			sw.WriteLine("\"));\n\t\t\t\telse");
+			sw.WriteLine("\t\t\t\t\t((GtkSharp.SignalCallback) Signals [{0}]).AddDelegate (value);", cname);
 			sw.WriteLine("\t\t\t\tEventList.AddHandler(" + cname + ", value);");
 			sw.WriteLine("\t\t\t}");
 			sw.WriteLine("\t\t\tremove {");
 			sw.WriteLine("\t\t\t\tEventList.RemoveHandler(" + cname + ", value);");
 			sw.WriteLine("\t\t\t\tif (EventList[" + cname + "] == null)");
 			sw.WriteLine("\t\t\t\t\tSignals.Remove(" + cname + ");");
+			sw.WriteLine("\t\t\t\telse");
+			sw.WriteLine("\t\t\t\t\t((GtkSharp.SignalCallback) Signals [{0}]).RemoveDelegate (value);", cname);
 			sw.WriteLine("\t\t\t}");
 			sw.WriteLine("\t\t}");
 			sw.WriteLine();
Index: generator/SignalHandler.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/generator/SignalHandler.cs,v
retrieving revision 1.18
diff -u -r1.18 SignalHandler.cs
--- generator/SignalHandler.cs	10 Nov 2002 10:03:50 -0000	1.18
+++ generator/SignalHandler.cs	5 Feb 2003 13:58:47 -0000
@@ -168,7 +168,7 @@
 			sw.WriteLine(" int flags);");
 			sw.WriteLine();
 			sw.Write("\t\tpublic " + sname + "(GLib.Object obj, IntPtr raw, ");
-			sw.WriteLine("String name, MulticastDelegate eh, Type argstype) : base(obj, eh, argstype)");
+			sw.WriteLine("String name, Delegate eh, Type argstype) : base(obj, eh, argstype)");
 			sw.WriteLine("\t\t{");
 			sw.WriteLine("\t\t\tif (_Delegate == null) {");
 			sw.WriteLine("\t\t\t\t_Delegate = new " + dname + "(" + cbname + ");");
Index: glib/SignalCallback.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/glib/SignalCallback.cs,v
retrieving revision 1.3
diff -u -r1.3 SignalCallback.cs
--- glib/SignalCallback.cs	16 Jul 2002 23:14:35 -0000	1.3
+++ glib/SignalCallback.cs	5 Feb 2003 13:58:47 -0000
@@ -28,7 +28,7 @@
 
 		// protected instance members
 		protected GLib.Object _obj;
-		protected MulticastDelegate _handler;
+		protected Delegate _handler;
 		protected int _key;
 		protected Type _argstype;
 
@@ -40,7 +40,7 @@
 		///	Initializes instance data.
 		/// </remarks>
 
-		public SignalCallback (GLib.Object obj, MulticastDelegate eh, Type argstype)
+		public SignalCallback (GLib.Object obj, Delegate eh, Type argstype)
 		{
 			_key = _NextKey++;
 			_obj = obj;
@@ -49,5 +49,14 @@
 			_Instances [_key] = this;
 		}
 
+		public void AddDelegate (Delegate d)
+		{
+			_handler = Delegate.Combine (_handler, d);
+		}
+
+		public void RemoveDelegate (Delegate d)
+		{
+			_handler = Delegate.Remove (_handler, d);
+		}
 	}
 }

--=-nR+iQKdSLyZ7TZD0Retu--