[vala/tintou/gdbus-properties: 227/228] gdbus: Bind properties with the GDBusProxy directly
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/tintou/gdbus-properties: 227/228] gdbus: Bind properties with the GDBusProxy directly
- Date: Sat, 7 Aug 2021 14:43:39 +0000 (UTC)
commit 68e75e6fec05dd8b56462642c4915f0d6b7801c1
Author: Corentin Noël <corentin elementary io>
Date: Tue Apr 7 23:50:55 2020 +0200
gdbus: Bind properties with the GDBusProxy directly
codegen/valagdbusclientmodule.vala | 259 ++++++++++++++++++++++++++++++++++++-
codegen/valagdbusservermodule.vala | 101 +++++++++++++++
tests/Makefile.am | 1 +
tests/dbus/properties.test | 110 ++++++++++++++++
vala/valasemanticanalyzer.vala | 5 -
5 files changed, 470 insertions(+), 6 deletions(-)
---
diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala
index 697b08758..dd39b299d 100644
--- a/codegen/valagdbusclientmodule.vala
+++ b/codegen/valagdbusclientmodule.vala
@@ -210,17 +210,51 @@ public class Vala.GDBusClientModule : GDBusModule {
cfile.add_type_member_definition (define_type);
+ generate_properties_enums (iface);
+
var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
proxy_class_init.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
proxy_class_init.modifiers = CCodeModifiers.STATIC;
push_function (proxy_class_init);
var proxy_class = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY_CLASS"));
proxy_class.add_argument (new CCodeIdentifier ("klass"));
- ccode.add_assignment (new CCodeMemberAccess.pointer (proxy_class, "g_signal"), new
CCodeIdentifier (lower_cname + "_g_signal"));
+ ccode.add_declaration ("GDBusProxyClass *", new CCodeVariableDeclarator.zero ("proxy_class",
proxy_class));
+ var proxy_class_identifier = new CCodeIdentifier ("proxy_class");
+
+ var object_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
+ object_class.add_argument (new CCodeIdentifier ("klass"));
+ ccode.add_declaration ("GObjectClass *", new CCodeVariableDeclarator.zero ("object_class",
object_class));
+ var object_class_identifier = new CCodeIdentifier ("object_class");
+
+ ccode.add_assignment (new CCodeMemberAccess.pointer (proxy_class_identifier, "g_signal"), new
CCodeIdentifier (lower_cname + "_g_signal"));
+ ccode.add_assignment (new CCodeMemberAccess.pointer (proxy_class_identifier,
"g_properties_changed"), new CCodeIdentifier (lower_cname + "_g_properties_changed"));
+
+ ccode.add_assignment (new CCodeMemberAccess.pointer (object_class_identifier,
"get_property"), new CCodeIdentifier (lower_cname + "_get_property"));
+ ccode.add_assignment (new CCodeMemberAccess.pointer (object_class_identifier,
"set_property"), new CCodeIdentifier (lower_cname + "_set_property"));
+
+ var sym_name = get_ccode_upper_case_name (iface) + "_PROXY";
+ var pspecs = new CCodeIdentifier ("%s_proxy_properties".printf (get_ccode_lower_case_name
(iface)));
+ foreach (Property prop in iface.get_properties ()) {
+ var upper_identifier = new CCodeIdentifier ("%s_%s_PROPERTY".printf (sym_name,
Symbol.camel_case_to_lower_case (prop.name).ascii_up ()));
+ var override_func = new CCodeFunctionCall (new CCodeIdentifier
("g_object_class_override_property"));
+ override_func.add_argument (object_class_identifier);
+ override_func.add_argument (upper_identifier);
+ override_func.add_argument (get_property_canonical_cconstant (prop));
+ ccode.add_expression (override_func);
+ var find_prop = new CCodeFunctionCall (new CCodeIdentifier
("g_object_class_find_property"));
+ find_prop.add_argument (object_class_identifier);
+ find_prop.add_argument (get_property_canonical_cconstant (prop));
+ ccode.add_assignment (new CCodeElementAccess (pspecs, upper_identifier), find_prop);
+ }
+
pop_function ();
cfile.add_function (proxy_class_init);
+ generate_pspec_from_dbus_property (iface);
+ generate_get_property_function (iface);
+ generate_set_property_function (iface);
generate_signal_handler_function (iface);
+ generate_properties_changed_handler_function (iface);
if (in_plugin) {
var proxy_class_finalize = new CCodeFunction (lower_cname + "_class_finalize",
"void");
@@ -506,6 +540,117 @@ public class Vala.GDBusClientModule : GDBusModule {
return wrapper_name;
}
+ void generate_properties_enums (ObjectTypeSymbol sym) {
+ var prop_enum = new CCodeEnum ();
+ var sym_name = get_ccode_upper_case_name (sym) + "_PROXY";
+ prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (sym_name)));
+ var properties = sym.get_properties ();
+ foreach (Property prop in properties) {
+ prop_enum.add_value (new CCodeEnumValue ("%s_%s_PROPERTY".printf (sym_name,
Symbol.camel_case_to_lower_case (prop.name).ascii_up ())));
+ }
+
+ var last_prop = "%s_NUM_PROPERTIES".printf (sym_name);
+ prop_enum.add_value (new CCodeEnumValue (last_prop));
+ cfile.add_type_declaration (prop_enum);
+
+ var prop_array_decl = new CCodeDeclaration ("GParamSpec*");
+ prop_array_decl.modifiers |= CCodeModifiers.STATIC;
+ prop_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_proxy_properties".printf
(get_ccode_lower_case_name (sym)), null, new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier
(last_prop))));
+ cfile.add_type_declaration (prop_array_decl);
+ }
+
+ void generate_get_property_function (ObjectTypeSymbol sym) {
+ var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "proxy_get_property",
"void");
+ cfunc.add_parameter (new CCodeParameter ("object", "GObject*"));
+ cfunc.add_parameter (new CCodeParameter ("property_id", "guint"));
+ cfunc.add_parameter (new CCodeParameter ("value", "GValue*"));
+ cfunc.add_parameter (new CCodeParameter ("pspec", "GParamSpec*"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ cfile.add_function_declaration (cfunc);
+
+ push_function (cfunc);
+
+ ccode.add_declaration ("%s *".printf (get_ccode_name (sym)), new CCodeVariableDeclarator
("self"));
+ ccode.add_declaration ("GVariant *", new CCodeVariableDeclarator ("variant", null));
+ ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator.zero
("dbus_property_name", new CCodeConstant ("NULL")));
+
+ var cast_call = generate_instance_cast (new CCodeIdentifier ("object"), sym);
+ ccode.add_assignment (new CCodeIdentifier ("self"), cast_call);
+
+ ccode.open_switch (new CCodeIdentifier ("property_id"));
+
+ var sym_name = get_ccode_upper_case_name (sym) + "_PROXY";
+ var dbus_proxy_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY"));
+ dbus_proxy_cast.add_argument (new CCodeIdentifier ("object"));
+ foreach (Property prop in sym.get_properties ()) {
+ if (prop.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+
+ var upper_identifier = new CCodeIdentifier ("%s_%s_PROPERTY".printf (sym_name,
Symbol.camel_case_to_lower_case (prop.name).ascii_up ()));
+ ccode.add_case (upper_identifier);
+
+ string proxy_name = "%sdbus_proxy_get_%s".printf (get_ccode_lower_case_prefix (sym),
prop.name);
+ property_to_value (prop, new CCodeIdentifier (proxy_name), new CCodeIdentifier
("self"));
+
+ ccode.add_break ();
+ }
+
+ ccode.add_default ();
+ ccode.add_statement (new CCodeReturnStatement (null));
+ ccode.close ();
+
+ pop_function ();
+
+ cfile.add_function (cfunc);
+ }
+
+ void generate_set_property_function (ObjectTypeSymbol sym) {
+ // Create the function
+ var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "proxy_set_property",
"void");
+ cfunc.add_parameter (new CCodeParameter ("object", "GObject*"));
+ cfunc.add_parameter (new CCodeParameter ("property_id", "guint"));
+ cfunc.add_parameter (new CCodeParameter ("value", "const GValue*"));
+ cfunc.add_parameter (new CCodeParameter ("pspec", "GParamSpec*"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ cfile.add_function_declaration (cfunc);
+
+ push_function (cfunc);
+
+ var cast_call = generate_instance_cast (new CCodeIdentifier ("object"), sym);
+ ccode.add_declaration ("%s *".printf (get_ccode_name (sym)), new CCodeVariableDeclarator
("self"));
+ ccode.add_assignment (new CCodeIdentifier ("self"), cast_call);
+
+ ccode.open_switch (new CCodeIdentifier ("property_id"));
+
+ var sym_name = get_ccode_upper_case_name (sym) + "_PROXY";
+ foreach (Property prop in sym.get_properties ()) {
+ if (prop.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+
+ var upper_identifier = new CCodeIdentifier ("%s_%s_PROPERTY".printf (sym_name,
Symbol.camel_case_to_lower_case (prop.name).ascii_up ()));
+ ccode.add_case (upper_identifier);
+
+ string proxy_name = "%sdbus_proxy_set_%s".printf (get_ccode_lower_case_prefix (sym),
prop.name);
+ property_from_value (prop, new CCodeIdentifier (proxy_name), new CCodeIdentifier
("self"));
+
+ ccode.add_break ();
+ }
+
+ ccode.add_default ();
+ ccode.add_statement (new CCodeReturnStatement (null));
+ ccode.close ();
+
+ pop_function ();
+
+ cfile.add_function (cfunc);
+ }
+
void generate_signal_handler_function (ObjectTypeSymbol sym) {
var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "proxy_g_signal", "void");
cfunc.add_parameter (new CCodeParameter ("proxy", "GDBusProxy*"));
@@ -555,6 +700,118 @@ public class Vala.GDBusClientModule : GDBusModule {
cfile.add_function (cfunc);
}
+ void generate_pspec_from_dbus_property (ObjectTypeSymbol sym) {
+ var cfunc = new CCodeFunction ("_vala_%sfind_property_from_dbus_name".printf
(get_ccode_lower_case_prefix (sym)), "GParamSpec *");
+ cfunc.add_parameter (new CCodeParameter ("dbus_property_name", "const gchar *"));
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ cfile.add_function_declaration (cfunc);
+
+ push_function (cfunc);
+
+ bool firstif = true;
+
+ var pspecs = new CCodeIdentifier ("%s_proxy_properties".printf (get_ccode_lower_case_name
(sym)));
+ var sym_name = get_ccode_upper_case_name (sym) + "_PROXY";
+ foreach (Property prop in sym.get_properties ()) {
+ if (prop.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+
+ var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("g_strcmp0"));
+ ccheck.add_argument (new CCodeIdentifier ("dbus_property_name"));
+ ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member
(prop))));
+
+ var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new
CCodeConstant ("0"));
+ if (firstif) {
+ ccode.open_if (cond);
+ firstif = false;
+ } else {
+ ccode.else_if (cond);
+ }
+
+ var upper_identifier = new CCodeIdentifier ("%s_%s_PROPERTY".printf (sym_name,
Symbol.camel_case_to_lower_case (prop.name).ascii_up ()));
+ ccode.add_statement (new CCodeReturnStatement (new CCodeElementAccess (pspecs,
upper_identifier)));
+ }
+
+ if (!firstif) {
+ ccode.close ();
+ }
+
+ ccode.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
+
+ pop_function ();
+ cfile.add_function (cfunc);
+ }
+
+ void generate_properties_changed_handler_function (ObjectTypeSymbol sym) {
+ var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) +
"proxy_g_properties_changed", "void");
+ cfunc.add_parameter (new CCodeParameter ("proxy", "GDBusProxy*"));
+ cfunc.add_parameter (new CCodeParameter ("changed_properties", "GVariant*"));
+ cfunc.add_parameter (new CCodeParameter ("invalidated_properties", "const gchar* const*"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ cfile.add_function_declaration (cfunc);
+
+ push_function (cfunc);
+
+ ccode.add_declaration ("GVariantIter *", new CCodeVariableDeclarator ("iter", null));
+ ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("key", null));
+ ccode.add_declaration ("GParamSpec *", new CCodeVariableDeclarator ("pspec", null));
+ ccode.add_declaration ("guint", new CCodeVariableDeclarator ("n", null));
+ var pspec_identifier = new CCodeIdentifier ("pspec");
+ var n_identifier = new CCodeIdentifier ("n");
+ var variant_get = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get"));
+ variant_get.add_argument (new CCodeIdentifier ("changed_properties"));
+ variant_get.add_argument (new CCodeConstant.string ("\"a{sv}\""));
+ variant_get.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("iter")));
+ ccode.add_expression (variant_get);
+
+ var variant_iter_next = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next"));
+ variant_iter_next.add_argument (new CCodeIdentifier ("iter"));
+ variant_iter_next.add_argument (new CCodeConstant.string ("\"{&sv}\""));
+ variant_iter_next.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("key")));
+ variant_iter_next.add_argument (new CCodeConstant ("NULL"));
+
+ ccode.open_while (variant_iter_next);
+ var find_property_from_dbus_name = new CCodeFunctionCall (new CCodeIdentifier
("_vala_%sfind_property_from_dbus_name".printf (get_ccode_lower_case_prefix (sym))));
+ find_property_from_dbus_name.add_argument (new CCodeIdentifier ("key"));
+ ccode.add_assignment (pspec_identifier, find_property_from_dbus_name);
+
+ ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, pspec_identifier,
new CCodeConstant ("NULL")));
+
+ var notify_by_pspec = new CCodeFunctionCall (new CCodeIdentifier
("g_object_notify_by_pspec"));
+ notify_by_pspec.add_argument (new CCodeCastExpression (new CCodeIdentifier ("proxy"),
"GObject *"));
+ notify_by_pspec.add_argument (pspec_identifier);
+ ccode.add_expression (notify_by_pspec);
+
+ ccode.close ();
+ ccode.close ();
+
+ var variant_iter_free = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_free"));
+ variant_iter_free.add_argument (new CCodeIdentifier ("iter"));
+ ccode.add_expression (variant_iter_free);
+
+ var for_init = new CCodeAssignment (n_identifier, new CCodeConstant ("0"));
+ var for_increment = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT,
n_identifier);
+ var for_condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new
CCodeElementAccess (new CCodeIdentifier ("invalidated_properties"), n_identifier), new CCodeConstant
("NULL"));
+ ccode.open_for (for_init, for_condition, for_increment);
+ var find_invalidated_property_from_dbus_name = new CCodeFunctionCall (new CCodeIdentifier
("_vala_%sfind_property_from_dbus_name".printf (get_ccode_lower_case_prefix (sym))));
+ find_invalidated_property_from_dbus_name.add_argument (new CCodeElementAccess (new
CCodeIdentifier ("invalidated_properties"), n_identifier));
+ ccode.add_assignment (pspec_identifier, find_invalidated_property_from_dbus_name);
+
+ ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, pspec_identifier,
new CCodeConstant ("NULL")));
+ ccode.add_expression (notify_by_pspec);
+ ccode.close ();
+ ccode.close ();
+
+ pop_function ();
+
+ cfile.add_function (cfunc);
+ }
+
+
void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name, int
method_timeout) {
var gdbusproxy = new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *");
diff --git a/codegen/valagdbusservermodule.vala b/codegen/valagdbusservermodule.vala
index e6f379c9f..99f1812e5 100644
--- a/codegen/valagdbusservermodule.vala
+++ b/codegen/valagdbusservermodule.vala
@@ -712,6 +712,105 @@ public class Vala.GDBusServerModule : GDBusClientModule {
}
}
+ void generate_property_notify (ObjectTypeSymbol sym, Property prop) {
+ var cfunc = new CCodeFunction ("_%snotify_%s".printf (get_ccode_lower_case_prefix (sym),
prop.name), "void");
+ cfunc.add_parameter (new CCodeParameter ("gobject", "GObject *"));
+ cfunc.add_parameter (new CCodeParameter ("pspec", "GParamSpec *"));
+ cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer"));
+
+ cfunc.modifiers |= CCodeModifiers.STATIC;
+
+ push_function (cfunc);
+
+ ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator.zero ("data", new
CCodeIdentifier ("user_data")));
+ ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new
CCodeConstant ("NULL")));
+ ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator.zero ("parameters", new
CCodeConstant ("NULL")));
+ ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator.zero ("variant", new
CCodeConstant ("NULL")));
+ ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("changed_builder",
null));
+ ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("invalidated_builder",
null));
+
+ var variant_builder_init = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_builder_init"));
+ variant_builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF,
new CCodeIdentifier ("changed_builder")));
+ variant_builder_init.add_argument (new CCodeConstant ("G_VARIANT_TYPE_VARDICT"));
+ ccode.add_expression (variant_builder_init);
+
+ var variant_builder_init2 = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_builder_init"));
+ variant_builder_init2.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF,
new CCodeIdentifier ("invalidated_builder")));
+ variant_builder_init2.add_argument (new CCodeConstant ("G_VARIANT_TYPE_STRING_ARRAY"));
+ ccode.add_expression (variant_builder_init2);
+
+ var cast_call = generate_instance_cast (new CCodeIdentifier ("gobject"), sym);
+ ccode.add_declaration ("%s *".printf (get_ccode_name (sym)), new CCodeVariableDeclarator
("self"));
+ ccode.add_assignment (new CCodeIdentifier ("self"), cast_call);
+
+ var dbus_get_property = new CCodeFunctionCall (new CCodeIdentifier ("_dbus_%s".printf
(get_ccode_name (prop.get_accessor))));
+ dbus_get_property.add_argument (new CCodeIdentifier ("self"));
+ ccode.add_assignment (new CCodeIdentifier ("variant"), dbus_get_property);
+
+ var variant_builder_add = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_builder_add"));
+ variant_builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF,
new CCodeIdentifier ("changed_builder")));
+ variant_builder_add.add_argument (new CCodeConstant.string ("\"{sv}\""));
+ variant_builder_add.add_argument (new CCodeConstant.string ("\"%s\"".printf
(get_dbus_name_for_member (prop))));
+ variant_builder_add.add_argument (new CCodeIdentifier ("variant"));
+ ccode.add_expression (variant_builder_add);
+
+ var variant_new = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new"));
+ variant_new.add_argument (new CCodeConstant.string ("\"(sa{sv}as)\""));
+ variant_new.add_argument (new CCodeConstant.string ("\"%s\"".printf (get_dbus_name (sym))));
+ variant_new.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("changed_builder")));
+ variant_new.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("invalidated_builder")));
+ ccode.add_assignment (new CCodeIdentifier ("parameters"), variant_new);
+
+ var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_connection_emit_signal"));
+ disconnect_call.add_argument (new CCodeCastExpression (new CCodeElementAccess (new
CCodeIdentifier ("data"), new CCodeConstant ("1")), "GDBusConnection *"));
+ disconnect_call.add_argument (new CCodeConstant ("NULL"));
+ disconnect_call.add_argument (new CCodeCastExpression (new CCodeElementAccess (new
CCodeIdentifier ("data"), new CCodeConstant ("2")), "const gchar *"));
+ disconnect_call.add_argument (new CCodeConstant.string
("\"org.freedesktop.DBus.Properties\""));
+ disconnect_call.add_argument (new CCodeConstant.string ("\"PropertiesChanged\""));
+ disconnect_call.add_argument (new CCodeIdentifier ("parameters"));
+ disconnect_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("error")));
+ ccode.add_expression (disconnect_call);
+
+ pop_function ();
+
+ cfile.add_function_declaration (cfunc);
+ cfile.add_function (cfunc);
+ }
+
+ void handle_properties (ObjectTypeSymbol sym, bool connect) {
+ string dbus_iface_name = get_dbus_name (sym);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ foreach (Property prop in sym.get_properties ()) {
+ if (prop.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+ if (!is_dbus_visible (prop)) {
+ continue;
+ }
+
+ var notify_name = "_%snotify_%s".printf (get_ccode_lower_case_prefix (sym),
prop.name);
+ if (connect) {
+ generate_property_notify (sym, prop);
+ var connect_call = new CCodeFunctionCall (new CCodeIdentifier
("g_signal_connect"));
+ connect_call.add_argument (new CCodeIdentifier ("object"));
+ connect_call.add_argument (new CCodeConstant.string ("\"notify::%s\"".printf
(get_ccode_name (prop))));
+ connect_call.add_argument (new CCodeCastExpression (new CCodeIdentifier
(notify_name), "GCallback"));
+ connect_call.add_argument (new CCodeIdentifier ("data"));
+ ccode.add_expression (connect_call);
+ } else {
+ // disconnect the signals
+ var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier
("g_signal_handlers_disconnect_by_func"));
+ disconnect_call.add_argument (new CCodeElementAccess (new CCodeIdentifier
("data"), new CCodeConstant ("0")));
+ disconnect_call.add_argument (new CCodeIdentifier (notify_name));
+ disconnect_call.add_argument (new CCodeIdentifier ("data"));
+ ccode.add_expression (disconnect_call);
+ }
+ }
+ }
+
void generate_interface_method_call_function (ObjectTypeSymbol sym) {
var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) +
"dbus_interface_method_call", "void");
cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*"));
@@ -1165,6 +1264,7 @@ public class Vala.GDBusServerModule : GDBusClientModule {
ccode.close ();
handle_signals (sym, true);
+ handle_properties (sym, true);
ccode.add_return (new CCodeIdentifier ("result"));
@@ -1181,6 +1281,7 @@ public class Vala.GDBusServerModule : GDBusClientModule {
ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier
("user_data")));
handle_signals (sym, false);
+ handle_properties (sym, false);
var unref_object = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function
(sym)));
unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new
CCodeConstant ("0")));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f0ec0e9c4..2ead6682e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -730,6 +730,7 @@ TESTS = \
dbus/enum-string-marshalling.vala \
dbus/generics.test \
dbus/no-reply.test \
+ dbus/properties.test \
dbus/signals.test \
dbus/filedescriptor.test \
dbus/filedescriptor-async.test \
diff --git a/tests/dbus/properties.test b/tests/dbus/properties.test
new file mode 100644
index 000000000..46358a34b
--- /dev/null
+++ b/tests/dbus/properties.test
@@ -0,0 +1,110 @@
+Packages: gio-2.0
+D-Bus
+
+Program: client
+
+[DBus (name = "org.example.Test")]
+interface Test : Object {
+ public abstract string test_property { owned get; set; }
+ public abstract int test_int_property { get; set; }
+ public abstract void change_everything () throws GLib.Error;
+ public abstract void check_everything () throws GLib.Error;
+}
+
+class Test2 : Object {
+ public string test_property { get; set; }
+ public int test_int_property { get; set; }
+}
+
+void main () {
+ // client
+ Test test = Bus.get_proxy_sync (BusType.SESSION, "org.example.Test", "/org/example/test",
DBusProxyFlags.NONE);
+ assert (test.test_property == "foo");
+ assert (test.test_int_property == 17);
+
+ Test2 test2 = new Test2 ();
+ test.bind_property ("test-property", test2, "test-property", BindingFlags.SYNC_CREATE |
BindingFlags.BIDIRECTIONAL);
+ test.bind_property ("test-int-property", test2, "test-int-property", BindingFlags.SYNC_CREATE |
BindingFlags.BIDIRECTIONAL);
+
+ {
+ MainLoop main_loop = new MainLoop ();
+
+ assert (test2.test_property == "foo");
+ assert (test2.test_int_property == 17);
+
+ test2.notify["test-int-property"].connect ((p) => {
+ assert (((ParamSpecInt) p).name == "test-int-property");
+ main_loop.quit ();
+ });
+
+ test.change_everything ();
+ main_loop.run ();
+
+ assert (test.test_property == "bar");
+ assert (test.test_int_property == 53);
+ }
+ {
+ MainLoop main_loop2 = new MainLoop ();
+
+ assert (test2.test_property == "bar");
+ assert (test2.test_int_property == 53);
+
+ test.notify["test-property"].connect ((p) => {
+ assert (((ParamSpecString) p).name == "test-property");
+ main_loop2.quit ();
+ });
+
+ test2.test_property = "baz";
+ test2.test_int_property = 765;
+ main_loop2.run ();
+
+ assert (test2.test_property == "baz");
+ assert (test2.test_int_property == 765);
+
+ test.check_everything ();
+ }
+}
+
+Program: server
+
+[DBus (name = "org.example.Test")]
+class Test : Object {
+ public string test_property { owned get; set; default = "foo";}
+ public int test_int_property { get; set; default = 17; }
+
+ public void change_everything () throws GLib.Error {
+ test_property = "bar";
+ test_int_property = 53;
+ }
+
+ public void check_everything () throws GLib.Error {
+ assert (test_property == "baz");
+ assert (test_int_property == 765);
+ }
+}
+
+MainLoop main_loop;
+
+void client_exit (Pid pid, int status) {
+ // client finished, terminate server
+ assert (status == 0);
+ main_loop.quit ();
+}
+
+void main () {
+ var conn = Bus.get_sync (BusType.SESSION);
+ conn.register_object ("/org/example/test", new Test ());
+
+ // try to register service in session bus
+ var request_result = conn.call_sync ("org.freedesktop.DBus", "/org/freedesktop/DBus",
"org.freedesktop.DBus", "RequestName",
+ new Variant ("(su)", "org.example.Test", 0x4), null, 0, -1);
+ assert ((uint) request_result.get_child_value (0) == 1);
+
+ // server ready, spawn client
+ Pid client_pid;
+ Process.spawn_async (null, { "dbus_properties_client" }, null, SpawnFlags.DO_NOT_REAP_CHILD, null,
out client_pid);
+ ChildWatch.add (client_pid, client_exit);
+
+ main_loop = new MainLoop ();
+ main_loop.run ();
+}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 553695568..c18304457 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -473,11 +473,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return false;
}
- if (type_sym is Interface && type_sym.get_attribute ("DBus") != null) {
- // GObject properties not currently supported in D-Bus interfaces
- return false;
- }
-
return true;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]