From 52e68fbeb6f7b91c63e651317d4626d3b913406e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9s=20G=2E=20Aragoneses?= <knocte@gmail.com>
Date: Wed, 14 May 2008 16:03:13 +0000
Subject: [PATCH] * atk/Object.custom: Track API changes in GLib.Signal. *
 glib/Signal.cs: AddEmissionHook binding (for closing #386950), and   change
 API of Emit to mimic the detailed_signal pattern. * glib/GType.cs:
 GType.FromName: new wrapper for native call. * glib/ObjectManager.cs: Use the
 new FromName managed method.

svn path=/trunk/gtk-sharp/; revision=103198
---
 ChangeLog             |  8 ++++++++
 atk/Object.custom     |  4 +++-
 glib/GType.cs         |  8 ++++++++
 glib/ObjectManager.cs |  5 +----
 glib/Signal.cs        | 47 +++++++++++++++++++++++++++++++++++++++----
 5 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6103bb1be..2eb8f3522 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-05-14  Andres G. Aragoneses <aaragoneses@novell.com> 
+
+	* atk/Object.custom: Track API changes in GLib.Signal.
+	* glib/Signal.cs: AddEmissionHook binding (for closing #386950), and
+	  change API of Emit to mimic the detailed_signal pattern.
+	* glib/GType.cs: GType.FromName: new wrapper for native call.
+	* glib/ObjectManager.cs: Use the new FromName managed method.
+
 2008-05-08  Mike Kestner  <mkestner@novell.com>
 
 	* atk/atk-api-2.12.raw: reparsed.
diff --git a/atk/Object.custom b/atk/Object.custom
index 10e4a17a3..3989c20c3 100644
--- a/atk/Object.custom
+++ b/atk/Object.custom
@@ -94,7 +94,9 @@
 
 		protected void EmitChildrenChanged (ChildrenChangedDetail detail, uint child_index, Atk.Object child)
 		{
-			GLib.Signal.Emit (this, "children-changed", detail.ToString().ToLower(), child_index, child);
+			GLib.Signal.Emit (this, 
+				"children-changed::" + detail.ToString ().ToLower (), 
+				child_index, child);
 		}
 		
 		protected enum ChildrenChangedDetail
diff --git a/glib/GType.cs b/glib/GType.cs
index 71d882143..4787f7e86 100755
--- a/glib/GType.cs
+++ b/glib/GType.cs
@@ -37,6 +37,11 @@ namespace GLib {
 			this.val = val;
 		}
 
+		public static GType FromName (string native_name)
+		{
+			return new GType (g_type_from_name (native_name));
+		}
+		
 		public static readonly GType Invalid = new GType ((IntPtr) TypeFundamentals.TypeInvalid);
 		public static readonly GType None = new GType ((IntPtr) TypeFundamentals.TypeNone);
 		public static readonly GType Interface = new GType ((IntPtr) TypeFundamentals.TypeInterface);
@@ -195,6 +200,9 @@ namespace GLib {
 
 		[DllImport("libgobject-2.0-0.dll")]
 		static extern IntPtr g_type_name (IntPtr raw);
+		
+		[DllImport("libgobject-2.0-0.dll")]
+		static extern IntPtr g_type_from_name (string name);
 
 		public override string ToString ()
 		{
diff --git a/glib/ObjectManager.cs b/glib/ObjectManager.cs
index 8cb91582f..b7592910e 100644
--- a/glib/ObjectManager.cs
+++ b/glib/ObjectManager.cs
@@ -58,7 +58,7 @@ namespace GLib {
 		[Obsolete ("Replaced by GType.Register (GType, Type)")]
 		public static void RegisterType (string native_name, string mangled)
 		{
-			RegisterType (new GType (g_type_from_name (native_name)), Type.GetType (mangled));
+			RegisterType (GType.FromName (native_name), Type.GetType (mangled));
 		}
 
 		[Obsolete ("Replaced by GType.Register (GType, Type)")]
@@ -86,8 +86,5 @@ namespace GLib {
 
 		[DllImport("libgobject-2.0-0.dll")]
 		static extern IntPtr g_type_parent (IntPtr typ);
-
-		[DllImport("libgobject-2.0-0.dll")]
-		static extern IntPtr g_type_from_name (string name);
 	}
 }
diff --git a/glib/Signal.cs b/glib/Signal.cs
index d1b3a3fa8..8f91e647a 100644
--- a/glib/Signal.cs
+++ b/glib/Signal.cs
@@ -1,8 +1,9 @@
 // GLib.Signal.cs - signal marshaling class
 //
 // Authors: Mike Kestner <mkestner@novell.com>
+//          Andrés G. Aragoneses <aaragoneses@novell.com>
 //
-// Copyright (c) 2005 Novell, Inc.
+// Copyright (c) 2005,2008 Novell, Inc.
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of version 2 of the Lesser GNU General 
@@ -278,10 +279,28 @@ namespace GLib {
 			}
 		}
 
-		public static object Emit (GLib.Object instance, string signal_name, string detail, params object[] args)
+		// format: children-changed::add
+		private static void ParseSignalDetail (string signal_detail, out string signal_name, out uint gquark)
 		{
-			uint signal_id = GetSignalId (signal_name, instance);
-			uint gquark = GetGQuarkFromString (detail);
+			//can't use String.Split because it doesn't accept a string arg (only char) in the 1.x profile
+			int link_pos = signal_detail.IndexOf ("::");
+			if (link_pos < 0) {
+				gquark = 0;
+				signal_name = signal_detail;
+			} else if (link_pos == 0) {
+				throw new FormatException ("Invalid detailed_signal: " + signal_detail);
+			} else {
+				signal_name = signal_detail.Substring (0, link_pos);
+				gquark = GetGQuarkFromString (signal_detail.Substring (link_pos + 2));
+			}
+		}
+		
+		public static object Emit (GLib.Object instance, string detailed_signal, params object[] args)
+		{
+			uint gquark, signal_id;
+			string signal_name;
+			ParseSignalDetail (detailed_signal, out signal_name, out gquark);
+			signal_id = GetSignalId (signal_name, instance);
 			GLib.Value[] vals = new GLib.Value [args.Length + 1];
 			GLib.ValueArray inst_and_params = new GLib.ValueArray ((uint) args.Length + 1);
 			
@@ -314,12 +333,28 @@ namespace GLib {
 		private static uint GetSignalId (string signal_name, GLib.Object obj)
 		{
 			IntPtr typeid = gtksharp_get_type_id (obj.Handle);
+			return GetSignalId (signal_name, typeid);
+		}
+		
+		private static uint GetSignalId (string signal_name, IntPtr typeid)
+		{
 			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (signal_name);
 			uint signal_id = g_signal_lookup (native_name, typeid);
 			GLib.Marshaller.Free (native_name);
 			return signal_id;
 		}
 		
+		public static ulong AddEmissionHook (string detailed_signal, GLib.GType type, EmissionHook handler_func)
+		{
+			uint gquark;
+			string signal_name;
+			ParseSignalDetail (detailed_signal, out signal_name, out gquark);
+			uint signal_id = GetSignalId (signal_name, type.Val);
+			if (signal_id == 0)
+				throw new Exception ("Invalid signal name: " + signal_name);
+			return g_signal_add_emission_hook (signal_id, gquark, new EmissionHookMarshaler (handler_func).Callback, IntPtr.Zero, IntPtr.Zero);
+		}
+		
 		[DllImport("libgobject-2.0-0.dll")]
 		static extern IntPtr g_signal_get_invocation_hint (IntPtr instance);
 
@@ -335,6 +370,10 @@ namespace GLib {
 		
 		[DllImport("glibsharpglue-2")]
 		static extern IntPtr gtksharp_get_type_id (IntPtr raw);
+		
+		[DllImport("libgobject-2.0-0.dll")]
+		static extern ulong g_signal_add_emission_hook (uint signal_id, uint gquark_detail, EmissionHookNative hook_func, IntPtr hook_data, IntPtr data_destroy);
+
 	}
 }