]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support connect_after for signals
authorLuca Bruno <lethalman88@gmail.com>
Sat, 16 Jan 2010 18:05:33 +0000 (19:05 +0100)
committerJürg Billeter <j@bitron.ch>
Sat, 13 Mar 2010 17:18:32 +0000 (18:18 +0100)
Fixes bug 560773.

codegen/valaccodemodule.vala
codegen/valagobjectmodule.vala
codegen/valagsignalmodule.vala
vala/valasignaltype.vala

index 2fee6b9b0f0bdd875af7acbd47d001b9949ad316..ebbc29863e6761de1457484ca84d4fff0319cbb0 100644 (file)
@@ -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);
        }
index 388ef590372dacb8f4c26367957910cbeb83d9a5..6290a68bdc06283df88dabb883be2a17bfe4b4cd 100644 (file)
@@ -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));
index 390cece7e22390b1392094b3c043f5e7b7cd3481..593f0ceaa5ec11290f9fe3dbf22f1bef8f57ca8b 100644 (file)
@@ -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
index 851011ce57a79101d320070454e4a05143399b46..11a110933bd282081dab23ab9419473130561f7e 100644 (file)
@@ -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 ();
                }