From 699238daaddfc4fc11dba7978c5a077fd30456a8 Mon Sep 17 00:00:00 2001 From: Bob Smith Date: Tue, 25 Sep 2001 15:56:50 +0000 Subject: [PATCH] Added refcounts to delegates to make sure they can be unpined when not needed. svn path=/trunk/gtk-sharp/; revision=962 --- ChangeLog | 4 ++++ gdk/Event.cs | 19 +++++++++++++++++++ gdk/Signals/SimpleEvent.cs | 12 ++++++++++++ glib/Signals/Simple.cs | 12 ++++++++++++ gtk/Button.cs | 8 ++++++++ gtk/Widget.cs | 29 +++++++++++++++++++++++++++-- 6 files changed, 82 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70156481b..69a2f7084 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2001-09-25 + * Added refcounts to delegates to make sure they can be unpined when + not needed. + 2001-09-21 * Signal system totally reworked. It should be stable now. diff --git a/gdk/Event.cs b/gdk/Event.cs index 98efb443e..782d5e32e 100644 --- a/gdk/Event.cs +++ b/gdk/Event.cs @@ -60,5 +60,24 @@ namespace Gdk { Marshal.WriteIntPtr(_event, new IntPtr((int)value)); } } + public EventAny Any + { + get + { + return (EventAll)this; + } + } + public static explicit EventAll (Event e) + { + return Marshal.PtrToStructure(e._event, EventAll); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct EventAny + { + public IntPtr type; + public IntPtr window; + public SByte send_event; } } diff --git a/gdk/Signals/SimpleEvent.cs b/gdk/Signals/SimpleEvent.cs index a500b8792..f3c8b3dfe 100644 --- a/gdk/Signals/SimpleEvent.cs +++ b/gdk/Signals/SimpleEvent.cs @@ -43,6 +43,7 @@ namespace Gdk.Signals { } return true; //FIXME: How do we manage the return value? } + private static int _simpleRefCount; private static SimpleEventDelegate _simpleDelegate; private static GCHandle _simpleEventGCHandle; public static SimpleEventDelegate Delegate @@ -54,8 +55,19 @@ namespace Gdk.Signals { SimpleEvent._simpleDelegate = new SimpleEventDelegate(SimpleCallback); SimpleEvent._simpleGCHandle = GCHandle.Alloc (SimpleEvent._simpleEventDelegate, GCHandleType.Pinned); } + SimpleEvent._simpleRefCount++; return SimpleEvent._simpleEventDelegate; } } + public static void Unref() + { + SimpleEvent._simpleRefCount--; + if (SimpleEvent._simpleRefCount < 1) + { + SimpleEvent._simpleRefCount = 0; + SimpleEvent._simpleEventGCHandle.free(); + SimpleEvent._simpleDelegate = null; + } + } } } diff --git a/glib/Signals/Simple.cs b/glib/Signals/Simple.cs index b3f9cc0bb..8b93acc7e 100644 --- a/glib/Signals/Simple.cs +++ b/glib/Signals/Simple.cs @@ -21,6 +21,7 @@ namespace Glib.Signals { eh(o, EventArgs.Empty); } } + private static int _simpleRefCount = 0; private static SimpleDelegate _simpleDelegate; private static GCHandle _simpleGCHandle; public static SimpleDelegate Delegate @@ -32,8 +33,19 @@ namespace Glib.Signals { Simple._simpleDelegate = new SimpleDelegate(SimpleCallback); Simple._simpleGCHandle = GCHandle.Alloc (Simple._simpleDelegate, GCHandleType.Pinned); } + Simple._simpleRefCount++; return Simple._simpleDelegate; } } + public static void Unref() + { + Simple._simpleRefCount--; + if (Simple._simpleRefCount < 1) + { + Simple._simpleRefCount = 0; + Simple._simpleGCHandle.free(); + Simple._simpleDelegate = null; + } + } } } diff --git a/gtk/Button.cs b/gtk/Button.cs index fae68e659..cd5ae4b01 100644 --- a/gtk/Button.cs +++ b/gtk/Button.cs @@ -37,6 +37,14 @@ namespace Gtk { RawObject = o; } + public ~Button () + { + foreach (EventHandler e in Events[ClickedEvent]) + { + Clicked -= e; + } + } + /// /// Button Constructor /// diff --git a/gtk/Widget.cs b/gtk/Widget.cs index 42fdc85a4..be3b0cc4d 100755 --- a/gtk/Widget.cs +++ b/gtk/Widget.cs @@ -11,8 +11,15 @@ namespace Gtk { using Glib; using Gdk; - public abstract class Widget : Object { - + public class Widget : Object { + public Widget() {} + public ~Widget() + { + foreach (EventHandler e in Events[DeleteEvent]) + { + DeleteEvent -= e; + } + } private static readonly string DeleteEvent = "delete-event"; public event EventHandler DeleteEvent { @@ -41,6 +48,10 @@ namespace Gtk { public void RemoveSimpleEvent(Object type, string name, EventHander value) { Events.RemoveHandler(type, value); + if (Events[type] == null) + { + DisconnectSimpleSignal(name, type); + } } public void RemoveSimpleEvent(String type, EventHandle value) @@ -61,6 +72,10 @@ namespace Gtk { public void RemoveGdkSimpleEvent(Object type, string name, EventHander value) { Events.RemoveHandler(type, value); + if (Events[type] == null) + { + DisconnectGdkSimpleEventSignal(name, type); + } } public void RemoveGdkSimpleEvent(String type, EventHandle value) @@ -81,6 +96,11 @@ namespace Gtk { new IntPtr (0), 0, 0); } + public void DisconnectSimpleSignal(string name, Object signal) + { + Glib.Signals.Simple.Unref(); + } + public void ConnectGdkSimpleSignal(string name, Object signal) { gtk_signal_connect_full(RawObject, name, Gdk.Signals.SimpleEvent.Delegate, @@ -88,6 +108,11 @@ namespace Gtk { new IntPtr (0), 0, 0); } + public void DisconnectGdkSimpleSignal(string name, Object signal) + { + Gdk.Signals.SimpleEvent.Unref(); + } + /// /// Show Method ///