From d06d284ac8d73024e5d46fedad07c512447d2484 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Sat, 16 Jan 2010 19:05:33 +0100 Subject: [PATCH] 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 2fee6b9b0..ebbc29863 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 388ef5903..6290a68bd 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 390cece7e..593f0ceaa 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 851011ce5..11a110933 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 (); } -- 2.47.3