2008-10-29 Mike Kestner <mkestner@novell.com>

* glib/Signal.cs : custom marshaling hooks
	* glib/SignalClosure.cs : support for custom marshalers.

svn path=/trunk/gtk-sharp/; revision=117424
This commit is contained in:
Mike Kestner 2008-10-29 21:41:57 +00:00
parent 3f81d52735
commit 4de7ad4914
3 changed files with 34 additions and 4 deletions

View file

@ -1,3 +1,8 @@
2008-10-29 Mike Kestner <mkestner@novell.com>
* glib/Signal.cs : custom marshaling hooks
* glib/SignalClosure.cs : support for custom marshalers.
2008-10-28 Stephane Delcroix <sdelcroix@novell.com>
* gtk/Gtk.Metadata: hide ConnectSignals.

View file

@ -127,12 +127,14 @@ namespace GLib {
Type args_type;
SignalClosure before_closure;
SignalClosure after_closure;
Delegate marshaler;
private Signal (GLib.Object obj, string signal_name, Delegate marshaler)
{
tref = obj.ToggleRef;
name = signal_name;
tref.Signals [name] = this;
this.marshaler = marshaler;
}
private Signal (GLib.Object obj, string signal_name, Type args_type)
@ -207,7 +209,6 @@ namespace GLib {
return Lookup (obj, name, typeof (EventArgs));
}
[Obsolete ("Replaced by Lookup (Object obj, string name, Type args_type)")]
public static Signal Lookup (GLib.Object obj, string name, Delegate marshaler)
{
Signal result = obj.ToggleRef.Signals [name] as Signal;
@ -243,7 +244,10 @@ namespace GLib {
if (d.Method.IsDefined (typeof (ConnectBeforeAttribute), false)) {
tref.Target.BeforeSignals [name] = Delegate.Combine (tref.Target.BeforeSignals [name] as Delegate, d);
if (before_closure == null) {
before_closure = new SignalClosure (tref.Handle, name, args_type);
if (marshaler == null)
before_closure = new SignalClosure (tref.Handle, name, args_type);
else
before_closure = new SignalClosure (tref.Handle, name, marshaler, this);
before_closure.Disposed += ClosureDisposedHandler;
before_closure.Invoked += ClosureInvokedHandler;
before_closure.Connect (false);
@ -251,7 +255,10 @@ namespace GLib {
} else {
tref.Target.AfterSignals [name] = Delegate.Combine (tref.Target.AfterSignals [name] as Delegate, d);
if (after_closure == null) {
after_closure = new SignalClosure (tref.Handle, name, args_type);
if (marshaler == null)
after_closure = new SignalClosure (tref.Handle, name, args_type);
else
after_closure = new SignalClosure (tref.Handle, name, marshaler, this);
after_closure.Disposed += ClosureDisposedHandler;
after_closure.Invoked += ClosureInvokedHandler;
after_closure.Connect (true);

View file

@ -25,7 +25,7 @@ namespace GLib {
using System.Collections;
using System.Runtime.InteropServices;
internal class ClosureInvokedArgs : EventArgs {
internal class ClosureInvokedArgs : EventArgs {
EventArgs args;
GLib.Object obj;
@ -59,6 +59,8 @@ namespace GLib {
string name;
uint id = UInt32.MaxValue;
System.Type args_type;
Delegate custom_marshaler;
GCHandle gch;
static Hashtable closures = new Hashtable ();
@ -71,6 +73,16 @@ namespace GLib {
this.args_type = args_type;
}
public SignalClosure (IntPtr obj, string signal_name, Delegate custom_marshaler, Signal signal)
{
gch = GCHandle.Alloc (signal);
raw_closure = g_cclosure_new (custom_marshaler, (IntPtr) gch, Notify);
closures [raw_closure] = this;
handle = obj;
name = signal_name;
this.custom_marshaler = custom_marshaler;
}
public event EventHandler Disposed;
public event ClosureInvokedHandler Invoked;
@ -91,6 +103,9 @@ namespace GLib {
{
Disconnect ();
closures.Remove (raw_closure);
if (custom_marshaler != null)
gch.Free ();
custom_marshaler = null;
if (Disposed != null)
Disposed (this, EventArgs.Empty);
GC.SuppressFinalize (this);
@ -181,6 +196,9 @@ namespace GLib {
[DllImport("glibsharpglue-2")]
static extern IntPtr glibsharp_closure_new (ClosureMarshal marshaler, ClosureNotify notify, IntPtr gch);
[DllImport("libgobject-2.0-0.dll")]
static extern IntPtr g_cclosure_new (Delegate cb, IntPtr user_data, ClosureNotify notify);
[DllImport("libgobject-2.0-0.dll")]
static extern uint g_signal_connect_closure (IntPtr obj, IntPtr name, IntPtr closure, bool is_after);