[vala] Support connect_after for signals



commit d06d284ac8d73024e5d46fedad07c512447d2484
Author: Luca Bruno <lethalman88 gmail com>
Date:   Sat Jan 16 19:05:33 2010 +0100

    Support connect_after for signals
    
    Fixes bug 560773.

 codegen/valaccodemodule.vala   |    4 ++++
 codegen/valagobjectmodule.vala |   38 ++++++++++++++++++++++++++++++++++----
 codegen/valagsignalmodule.vala |   29 ++++++++++++++++++++---------
 vala/valasignaltype.vala       |   15 +++++++++++++++
 4 files changed, 73 insertions(+), 13 deletions(-)
---
diff --git a/codegen/valaccodemodule.vala b/codegen/valaccodemodule.vala
index 2fee6b9..ebbc298 100644
--- a/codegen/valaccodemodule.vala
+++ b/codegen/valaccodemodule.vala
@@ -375,6 +375,10 @@ public abstract class Vala.CCodeModule {
 		return next.get_dynamic_signal_connect_wrapper_name (node);
 	}
 
+	public virtual string get_dynamic_signal_connect_after_wrapper_name (DynamicSignal node) {
+		return next.get_dynamic_signal_connect_after_wrapper_name (node);
+	}
+
 	public virtual string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal node) {
 		return next.get_dynamic_signal_disconnect_wrapper_name (node);
 	}
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index 388ef59..6290a68 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -626,7 +626,7 @@ internal class Vala.GObjectModule : GTypeModule {
 		func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
 		func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
 		var block = new CCodeBlock ();
-		generate_gobject_connect_wrapper (sig, block);
+		generate_gobject_connect_wrapper (sig, block, false);
 
 		// append to C source file
 		source_declarations.add_type_member_declaration (func.copy ());
@@ -637,14 +637,41 @@ internal class Vala.GObjectModule : GTypeModule {
 		return connect_wrapper_name;
 	}
 
-	void generate_gobject_connect_wrapper (DynamicSignal sig, CCodeBlock block) {
+	public override string get_dynamic_signal_connect_after_wrapper_name (DynamicSignal sig) {
+		if (sig.dynamic_type.data_type == null
+		    || !sig.dynamic_type.data_type.is_subtype_of (gobject_type)) {
+			return base.get_dynamic_signal_connect_wrapper_name (sig);
+		}
+
+		string connect_wrapper_name = "_%sconnect_after".printf (get_dynamic_signal_cname (sig));
+		var func = new CCodeFunction (connect_wrapper_name, "void");
+		func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
+		func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
+		func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
+		func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
+		var block = new CCodeBlock ();
+		generate_gobject_connect_wrapper (sig, block, true);
+
+		// append to C source file
+		source_declarations.add_type_member_declaration (func.copy ());
+
+		func.block = block;
+		source_type_member_definition.append (func);
+
+		return connect_wrapper_name;
+	}
+
+	void generate_gobject_connect_wrapper (DynamicSignal sig, CCodeBlock block, bool after) {
 		var m = (Method) sig.handler.symbol_reference;
 
 		sig.accept (codegen);
 
 		string connect_func = "g_signal_connect_object";
 		if (m.binding != MemberBinding.INSTANCE) {
-			connect_func = "g_signal_connect";
+			if (!after)
+				connect_func = "g_signal_connect";
+			else
+				connect_func = "g_signal_connect_after";
 		}
 
 		var call = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
@@ -654,7 +681,10 @@ internal class Vala.GObjectModule : GTypeModule {
 		call.add_argument (new CCodeIdentifier ("data"));
 
 		if (m.binding == MemberBinding.INSTANCE) {
-			call.add_argument (new CCodeConstant ("0"));
+			if (!after)
+				call.add_argument (new CCodeConstant ("0"));
+			else
+				call.add_argument (new CCodeConstant ("G_CONNECT_AFTER"));
 		}
 
 		block.add_statement (new CCodeExpressionStatement (call));
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index 390cece..593f0ce 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -474,7 +474,7 @@ internal class Vala.GSignalModule : GObjectModule {
 			return null;
 		}
 
-		return connect_signal (sig, assignment.left, assignment.right, disconnect, assignment);
+		return connect_signal (sig, assignment.left, assignment.right, disconnect, false, assignment);
 	}
 
 	public override void visit_assignment (Assignment assignment) {
@@ -550,11 +550,12 @@ internal class Vala.GSignalModule : GObjectModule {
 		handler.accept (codegen);
 
 		bool disconnect = (method_type.method_symbol.name == "disconnect");
+		bool after = (method_type.method_symbol.name == "connect_after");
 
-		expr.ccodenode = connect_signal (sig, signal_access, handler, disconnect, expr);
+		expr.ccodenode = connect_signal (sig, signal_access, handler, disconnect, after, expr);
 	}
 
-	CCodeExpression? connect_signal (Signal sig, Expression signal_access, Expression handler, bool disconnect, CodeNode expr) {
+	CCodeExpression? connect_signal (Signal sig, Expression signal_access, Expression handler, bool disconnect, bool after, CodeNode expr) {
 		string connect_func;
 
 		var m = (Method) handler.symbol_reference;
@@ -562,15 +563,19 @@ internal class Vala.GSignalModule : GObjectModule {
 		if (!disconnect) {
 			// connect
 			if (sig is DynamicSignal) {
-				connect_func = head.get_dynamic_signal_connect_wrapper_name ((DynamicSignal) sig);
+				if (!after)
+					connect_func = head.get_dynamic_signal_connect_wrapper_name ((DynamicSignal) sig);
+				else
+					connect_func = head.get_dynamic_signal_connect_after_wrapper_name ((DynamicSignal) sig);
 			} else {
 				if (m.closure) {
 					connect_func = "g_signal_connect_data";
 				} else if (in_gobject_instance (m)) {
 					connect_func = "g_signal_connect_object";
-				} else {
+				} else if (!after) {
 					connect_func = "g_signal_connect";
-				}
+				} else
+					connect_func = "g_signal_connect_after";
 			}
 		} else {
 			// disconnect
@@ -669,7 +674,10 @@ internal class Vala.GSignalModule : GObjectModule {
 			ccall.add_argument (new CCodeCastExpression (handler_destroy_notify, "GClosureNotify"));
 
 			// sixth argument: connect_flags
-			ccall.add_argument (new CCodeConstant ("0"));
+			if (!after)
+				ccall.add_argument (new CCodeConstant ("0"));
+			else
+				ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER"));
 		} else if (m.binding == MemberBinding.INSTANCE) {
 			// g_signal_connect_object or g_signal_handlers_disconnect_matched
 			// or dynamic_signal_connect or dynamic_signal_disconnect
@@ -690,10 +698,13 @@ internal class Vala.GSignalModule : GObjectModule {
 				// g_signal_connect_object
 
 				// fifth argument: connect_flags
-				ccall.add_argument (new CCodeConstant ("0"));
+				if (!after)
+					ccall.add_argument (new CCodeConstant ("0"));
+				else
+					ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER"));
 			}
 		} else {
-			// g_signal_connect or g_signal_handlers_disconnect_matched
+			// g_signal_connect or g_signal_connect_after or g_signal_handlers_disconnect_matched
 			// or dynamic_signal_connect or dynamic_signal_disconnect
 
 			// fourth resp. seventh argument: user_data
diff --git a/vala/valasignaltype.vala b/vala/valasignaltype.vala
index 851011c..11a1109 100644
--- a/vala/valasignaltype.vala
+++ b/vala/valasignaltype.vala
@@ -29,6 +29,7 @@ public class Vala.SignalType : DataType {
 	public Signal signal_symbol { get; set; }
 
 	Method? connect_method;
+	Method? connect_after_method;
 	Method? disconnect_method;
 
 	public SignalType (Signal signal_symbol) {
@@ -78,6 +79,18 @@ public class Vala.SignalType : DataType {
 		return connect_method;
 	}
 
+	Method get_connect_after_method () {
+		if (connect_after_method == null) {
+			var ulong_type = new IntegerType ((Struct) CodeContext.get ().root.scope.lookup ("ulong"));
+			connect_after_method = new Method ("connect_after", ulong_type);
+			connect_after_method.access = SymbolAccessibility.PUBLIC;
+			connect_after_method.external = true;
+			connect_after_method.owner = signal_symbol.scope;
+			connect_after_method.add_parameter (new FormalParameter ("handler", get_handler_type ()));
+		}
+		return connect_after_method;
+	}
+
 	Method get_disconnect_method () {
 		if (disconnect_method == null) {
 			disconnect_method = new Method ("disconnect", new VoidType ());
@@ -92,6 +105,8 @@ public class Vala.SignalType : DataType {
 	public override Symbol? get_member (string member_name) {
 		if (member_name == "connect") {
 			return get_connect_method ();
+		} else if (member_name == "connect_after") {
+			return get_connect_after_method ();
 		} else if (member_name == "disconnect") {
 			return get_disconnect_method ();
 		}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]