From bb326f46c93145219ae8ab0b5f4f9784a13919bf Mon Sep 17 00:00:00 2001 From: Mike Kestner Date: Thu, 4 Oct 2001 19:12:55 +0000 Subject: [PATCH] 2001-10-04 Mike Kestner * HACKING : Little bit of cleanup. * gdk/SimpleEvent.cs : Redesigned a bit. Docs. Replaced refcounting mechanism with an instance hash and added ctor/dtor. This class now completely encapsulates the signal attachment and forwarding mechanism for GdkEvent based signals. It attaches to the raw signal, maintains a ref to the associated event handler, and uses the static callback to activate the event handler on signal receipt. * sample/makefile : killed one last CSC explicit reference. svn path=/trunk/gtk-sharp/; revision=1076 --- ChangeLog | 11 +++++ HACKING | 24 ++++----- gdk/SimpleEvent.cs | 120 ++++++++++++++++++++++++++++++++++----------- sample/makefile | 2 - 4 files changed, 112 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7a413aa7d..0857a4ecc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2001-10-04 Mike Kestner + + * HACKING : Little bit of cleanup. + * gdk/SimpleEvent.cs : Redesigned a bit. Docs. Replaced refcounting + mechanism with an instance hash and added ctor/dtor. This class + now completely encapsulates the signal attachment and forwarding + mechanism for GdkEvent based signals. It attaches to the raw signal, + maintains a ref to the associated event handler, and uses the static + callback to activate the event handler on signal receipt. + * sample/makefile : killed one last CSC explicit reference. + 2001-10-02 Mike Kestner * glib/Value.cs : Tried adding CallingConvention.Cdecl to all the diff --git a/HACKING b/HACKING index df6c9d4eb..e3cc7e2c3 100755 --- a/HACKING +++ b/HACKING @@ -1,19 +1,15 @@ -Please please please hack on gtk-sharp. - -Okay, now for the details. +Before beginning work on something, please post your intentions to the +mailing list (gtk-sharp-list@ximian.com). Duplication of effort just gets +folks cranky in general. Prior to checking anything into CVS, please send a patch to the mailing list -(gtk-sharp-list@ximian.com) for approval. Any patches should be submitted in -diff -u format. Also, it is assumed that the submitter has verified that the -patch does not break the build, and hopefully that it doesn't break runtime. +for approval. Any patches should be submitted in diff -u format. Also, it is +assumed that the submitter has verified that the patch does not break the +build, and hopefully that it doesn't break runtime. -Second, patches without Documentation comments will be seriously frowned upon, +Patches without Documentation comments will be seriously frowned upon, if not outright rejected. All classes, methods, properties, events, etc... that are non-private should be documented with XML comment tags. At a minimum, -the summary and remarks tags, plus returns and params, if applicable. - -Third, Make a ChangeLog entry. Get credit for your hard work, and let me know -who I need to get cranky with at a glance, instead of having to do cvs history -reports. :-) - -Fourth, please please please hack on gtk-sharp. +the summary and remarks tags, plus returns and params, if applicable. Doing +this as we go is the only feasible way to make sure that our docs won't end +up sucking bigtime. diff --git a/gdk/SimpleEvent.cs b/gdk/SimpleEvent.cs index 945945d0e..e88e29505 100644 --- a/gdk/SimpleEvent.cs +++ b/gdk/SimpleEvent.cs @@ -6,6 +6,7 @@ namespace Gdk { using System; + using System.Collections; using System.Runtime.InteropServices; using GLib; using Gdk; @@ -29,42 +30,103 @@ namespace Gdk { } } - public delegate bool SimpleEventDelegate(IntPtr obj, IntPtr e, String name); + /// + /// SimpleEventDelegate Delegate + /// + /// + /// + /// Callback used to connect to GdkEvent based signals. + /// + + public delegate bool SimpleEventDelegate(IntPtr obj, IntPtr e, + int key); + + /// + /// SimpleEvent Class + /// + /// + /// + /// Connects to a specified signal on a raw object and relays + /// events to an EventHandle when they occur. + /// + public class SimpleEvent { - private static bool SimpleEventCallback (IntPtr obj, IntPtr e, String name) - { - GLib.Object o = GLib.Object.GetObject (obj); - EventHandler eh = (EventHandler) o.Events [name]; - if (eh != null) - { - EventArgs args = new SimpleEventArgs (new Gdk.Event(e)); - eh(o, args); - } - return true; //FIXME: How do we manage the return value? - } - private static int _RefCount; + // A Counter used to produce unique keys for instances. + private static int _NextKey = 0; + + // A hash table containing refs to all current instances. + private static Hashtable _Instances = new Hashtable (); + + // locals to create and pin the shared delegate. private static SimpleEventDelegate _Delegate; private static GCHandle _GCHandle; - public static SimpleEventDelegate Delegate + + // Shared delegate that relays events to registered handlers + private static bool SimpleEventCallback (IntPtr obj, IntPtr e, + int inst_key) { - get - { - if (_Delegate == null) - { - _Delegate = new SimpleEventDelegate(SimpleEventCallback); - _GCHandle = GCHandle.Alloc (_Delegate, GCHandleType.Pinned); - } - _RefCount++; - return _Delegate; - } + if (!_Instances.Contains (inst_key)) + throw new Exception ("Unexpected event key"); + + SimpleEvent se = (SimpleEvent) _Instances [inst_key]; + EventArgs args = new SimpleEventArgs ( + new Gdk.Event (e)); + se._handler (se._obj, args); + return true; //FIXME: How do we manage the return value? } - public static void Unref() + + // private instance members + private GLib.Object _obj; + private EventHandler _handler; + private int _key; + + /// + /// SimpleEvent Constructor + /// + /// + /// + /// Registers a new event handler for a specified signal. + /// A connection to the raw object signal is made which + /// causes any events which occur to be relayed to the + /// event handler. + /// + + [DllImport ("gobject-1.3.dll", CharSet=CharSet.Ansi, + CallingConvention=CallingConvention.Cdecl)] + static extern void g_signal_connect_data ( + IntPtr obj, IntPtr name, SimpleEventDelegate eh, + int key, IntPtr p, int flags); + + public SimpleEvent (GLib.Object obj, IntPtr raw, + String name, EventHandler eh) { - _RefCount--; - if (_RefCount < 1) - { - _RefCount = 0; + if (_Delegate == null) { + _Delegate = new SimpleEventDelegate ( + SimpleEventCallback); + _GCHandle = GCHandle.Alloc ( + _Delegate, GCHandleType.Pinned); + } + + _key = _NextKey++; + _Instances [_key] = this; + _obj = obj; + _handler = eh; + + g_signal_connect_data ( + raw, Marshal.StringToHGlobalAnsi (name), + _Delegate, _key, new IntPtr (0), 0); + } + + // Destructor is needed to release references from the instance + // table and unpin the delegate if no refs remain. + + ~SimpleEvent () + { + // FIXME: Disconnect the signal + _Instances.Remove (_key); + + if (_Instances.Count == 0) { _GCHandle.Free(); _Delegate = null; } diff --git a/sample/makefile b/sample/makefile index d56866e74..45beaef1c 100755 --- a/sample/makefile +++ b/sample/makefile @@ -1,5 +1,3 @@ -CSC=/cygdrive/c/winnt/microsoft.net/framework/v1.0.2914/csc.exe - all: @echo "You must use 'make windows' or 'make unix'." @echo "'make unix' is broken for now."