[glib/halfline/debug-metrics: 7/22] gdbus-codegen: honor "Property.EmitsChangedSignal" annotations




commit 3c8c42d4fbfd498e0c1737f6d3f02f6dbe564d15
Author: Thomas Jost <schnouki schnouki net>
Date:   Thu Dec 13 03:06:02 2018 -0800

    gdbus-codegen: honor "Property.EmitsChangedSignal" annotations
    
    Co-Authored-by: Andy Holmes <andrew g r holmes gmail com>

 gio/gdbus-2.0/codegen/codegen.py   | 18 +++++++++++++-----
 gio/gdbus-2.0/codegen/dbustypes.py |  7 +++++++
 gio/tests/gdbus-test-codegen.c     | 36 ++++++++++++++++++++++++++++++------
 gio/tests/test-codegen.xml         |  6 ++++++
 4 files changed, 56 insertions(+), 11 deletions(-)
---
diff --git a/gio/gdbus-2.0/codegen/codegen.py b/gio/gdbus-2.0/codegen/codegen.py
index f6892af95..442bd3f5d 100644
--- a/gio/gdbus-2.0/codegen/codegen.py
+++ b/gio/gdbus-2.0/codegen/codegen.py
@@ -665,7 +665,8 @@ class CodeGenerator:
                            '{\n'
                            '  GDBusPropertyInfo parent_struct;\n'
                            '  const gchar *hyphen_name;\n'
-                           '  gboolean use_gvariant;\n'
+                           '  guint use_gvariant : 1;\n'
+                           '  guint emits_changed_signal : 1;\n'
                            '} _ExtendedGDBusPropertyInfo;\n'
                            '\n')
 
@@ -960,9 +961,13 @@ class CodeGenerator:
                                        '  "%s",\n'
                                        %(p.name_hyphen))
                     if not utils.lookup_annotation(p.annotations, 'org.gtk.GDBus.C.ForceGVariant'):
-                        self.outfile.write('  FALSE\n')
+                        self.outfile.write('  FALSE,\n')
                     else:
+                        self.outfile.write('  TRUE,\n')
+                    if p.emits_changed_signal:
                         self.outfile.write('  TRUE\n')
+                    else:
+                        self.outfile.write('  FALSE\n')
                     self.outfile.write('};\n'
                                        '\n')
 
@@ -2595,14 +2600,17 @@ class CodeGenerator:
                                '  const GValue *value,\n'
                                '  GParamSpec   *pspec)\n'
                                '{\n'%(i.name_lower))
-            self.outfile.write('  %sSkeleton *skeleton = %s%s_SKELETON (object);\n'
+            self.outfile.write('  const _ExtendedGDBusPropertyInfo *info;\n'
+                               '  %sSkeleton *skeleton = %s%s_SKELETON (object);\n'
                                '  g_assert (prop_id != 0 && prop_id - 1 < %d);\n'
+                               '  info = (const _ExtendedGDBusPropertyInfo *) 
_%s_property_info_pointers[prop_id - 1];\n'
                                '  g_mutex_lock (&skeleton->priv->lock);\n'
                                '  g_object_freeze_notify (object);\n'
                                '  if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))\n'
                                '    {\n'
-                               '      if (g_dbus_interface_skeleton_get_connection 
(G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL)\n'
-                               '        _%s_schedule_emit_changed (skeleton, (const 
_ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1], prop_id, 
&skeleton->priv->properties[prop_id - 1]);\n'
+                               '      if (g_dbus_interface_skeleton_get_connection 
(G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL &&\n'
+                               '          info->emits_changed_signal)\n'
+                               '        _%s_schedule_emit_changed (skeleton, info, prop_id, 
&skeleton->priv->properties[prop_id - 1]);\n'
                                '      g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);\n'
                                '      g_object_notify_by_pspec (object, pspec);\n'
                                '    }\n'
diff --git a/gio/gdbus-2.0/codegen/dbustypes.py b/gio/gdbus-2.0/codegen/dbustypes.py
index bfc69f596..359880ff7 100644
--- a/gio/gdbus-2.0/codegen/dbustypes.py
+++ b/gio/gdbus-2.0/codegen/dbustypes.py
@@ -327,6 +327,7 @@ class Property:
         self.doc_string = ''
         self.since = ''
         self.deprecated = False
+        self.emits_changed_signal = True
 
     def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface):
         if len(self.doc_string) == 0:
@@ -356,6 +357,12 @@ class Property:
         if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true':
             self.deprecated = True
 
+        # FIXME: for now we only support 'false' and 'const' on the signal itself, see #674913 and
+        # http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
+        # for details
+        if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Property.EmitsChangedSignal') in 
('false', 'const'):
+            self.emits_changed_signal = False
+
 class Interface:
     def __init__(self, name):
         self.name = name
diff --git a/gio/tests/gdbus-test-codegen.c b/gio/tests/gdbus-test-codegen.c
index 1c4e83c4c..c906d05ae 100644
--- a/gio/tests/gdbus-test-codegen.c
+++ b/gio/tests/gdbus-test-codegen.c
@@ -1767,9 +1767,9 @@ on_object_proxy_removed (GDBusObjectManagerClient  *manager,
 }
 
 static void
-property_d_changed (GObject    *object,
-                   GParamSpec *pspec,
-                   gpointer    user_data)
+property_changed (GObject    *object,
+                 GParamSpec *pspec,
+                 gpointer    user_data)
 {
   gboolean *changed = user_data;
 
@@ -1782,6 +1782,8 @@ om_check_property_and_signal_emission (GMainLoop  *loop,
                                        FooiGenBar *proxy)
 {
   gboolean d_changed = FALSE;
+  gboolean quiet_changed = FALSE;
+  gboolean quiet_too_changed = FALSE;
   guint handler;
 
   /* First PropertiesChanged */
@@ -1803,13 +1805,35 @@ om_check_property_and_signal_emission (GMainLoop  *loop,
    * notifications are serialized.
    */
   handler = g_signal_connect (proxy, "notify::d",
-                             G_CALLBACK (property_d_changed), &d_changed);
+                             G_CALLBACK (property_changed), &d_changed);
   foo_igen_bar_set_d (skeleton, 1.0);
   foo_igen_bar_set_i (skeleton, 2);
   _g_assert_property_notify (proxy, "i");
   g_assert (d_changed == FALSE);
   g_signal_handler_disconnect (proxy, handler);
 
+  /* Verify that re-setting a property with the "EmitsChangedSignal"
+   * set to false doesn't emit a signal. */
+  handler = g_signal_connect (proxy, "notify::quiet",
+                             G_CALLBACK (property_changed), &quiet_changed);
+  foo_igen_bar_set_quiet (skeleton, "hush!");
+  foo_igen_bar_set_i (skeleton, 3);
+  _g_assert_property_notify (proxy, "i");
+  g_assert (quiet_changed == FALSE);
+  g_assert_cmpstr (foo_igen_bar_get_quiet (skeleton), ==, "hush!");
+  g_signal_handler_disconnect (proxy, handler);
+
+  /* Also verify that re-setting a property with the "EmitsChangedSignal"
+   * set to 'const' doesn't emit a signal. */
+  handler = g_signal_connect (proxy, "notify::quiet-too",
+                             G_CALLBACK (property_changed), &quiet_changed);
+  foo_igen_bar_set_quiet_too (skeleton, "hush too!");
+  foo_igen_bar_set_i (skeleton, 4);
+  _g_assert_property_notify (proxy, "i");
+  g_assert (quiet_too_changed == FALSE);
+  g_assert_cmpstr (foo_igen_bar_get_quiet_too (skeleton), ==, "hush too!");
+  g_signal_handler_disconnect (proxy, handler);
+
   /* Then just a regular signal */
   foo_igen_bar_emit_another_signal (skeleton, "word");
   _g_assert_signal_received (proxy, "another-signal");
@@ -2151,7 +2175,7 @@ check_object_manager (void)
    * that ObjectManager.GetManagedObjects() works
    */
   om_check_get_all (c, loop,
-                    "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': 
{'org.project.Bar': {'y': <byte 0x00>, 'b': <false>, 'n': <int16 0>, 'q': <uint16 0>, 'i': <0>, 'u': <uint32 
0>, 'x': <int64 0>, 't': <uint64 0>, 'd': <0.0>, 's': <''>, 'o': <objectpath '/'>, 'g': <signature ''>, 'ay': 
<b''>, 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 
'ReadonlyProperty': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': <objectpath '/'>, 
'unset_g': <signature ''>, 'unset_ay': <b''>, 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag 
[]>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 
'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)");
+                    "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': 
{'org.project.Bar': {'y': <byte 0x00>, 'b': <false>, 'n': <int16 0>, 'q': <uint16 0>, 'i': <0>, 'u': <uint32 
0>, 'x': <int64 0>, 't': <uint64 0>, 'd': <0.0>, 's': <''>, 'o': <objectpath '/'>, 'g': <signature ''>, 'ay': 
<b''>, 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 
'ReadonlyProperty': <''>, 'quiet': <''>, 'quiet_too': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': 
<''>, 'unset_o': <objectpath '/'>, 'unset_g': <signature ''>, 'unset_ay': <b''>, 'unset_as': <@as []>, 
'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay 
[], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 
'force_struct': <(0,)>}}},)");
 
   /* Set connection to NULL, causing everything to be unexported.. verify this.. and
    * then set the connection back.. and then check things still work
@@ -2163,7 +2187,7 @@ check_object_manager (void)
 
   g_dbus_object_manager_server_set_connection (manager, c);
   om_check_get_all (c, loop,
-                    "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': 
{'org.project.Bar': {'y': <byte 0x00>, 'b': <false>, 'n': <int16 0>, 'q': <uint16 0>, 'i': <0>, 'u': <uint32 
0>, 'x': <int64 0>, 't': <uint64 0>, 'd': <0.0>, 's': <''>, 'o': <objectpath '/'>, 'g': <signature ''>, 'ay': 
<b''>, 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 
'ReadonlyProperty': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': <''>, 'unset_o': <objectpath '/'>, 
'unset_g': <signature ''>, 'unset_ay': <b''>, 'unset_as': <@as []>, 'unset_ao': <@ao []>, 'unset_ag': <@ag 
[]>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay [], @as [], @ao [], @ag [])>}, 
'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 'force_struct': <(0,)>}}},)");
+                    "({objectpath '/managed/first': {'com.acme.Coyote': {'Mood': <''>}}, '/managed/second': 
{'org.project.Bar': {'y': <byte 0x00>, 'b': <false>, 'n': <int16 0>, 'q': <uint16 0>, 'i': <0>, 'u': <uint32 
0>, 'x': <int64 0>, 't': <uint64 0>, 'd': <0.0>, 's': <''>, 'o': <objectpath '/'>, 'g': <signature ''>, 'ay': 
<b''>, 'as': <@as []>, 'aay': <@aay []>, 'ao': <@ao []>, 'ag': <@ag []>, 'FinallyNormalName': <''>, 
'ReadonlyProperty': <''>, 'quiet': <''>, 'quiet_too': <''>, 'unset_i': <0>, 'unset_d': <0.0>, 'unset_s': 
<''>, 'unset_o': <objectpath '/'>, 'unset_g': <signature ''>, 'unset_ay': <b''>, 'unset_as': <@as []>, 
'unset_ao': <@ao []>, 'unset_ag': <@ag []>, 'unset_struct': <(0, 0.0, '', objectpath '/', signature '', @ay 
[], @as [], @ao [], @ag [])>}, 'org.project.Bat': {'force_i': <0>, 'force_s': <''>, 'force_ay': <@ay []>, 
'force_struct': <(0,)>}}},)");
 
   /* Also check that the ObjectManagerClient returns these objects - and
    * that they are of the right GType cf. what was requested via
diff --git a/gio/tests/test-codegen.xml b/gio/tests/test-codegen.xml
index 885a21f77..39d8769c7 100644
--- a/gio/tests/test-codegen.xml
+++ b/gio/tests/test-codegen.xml
@@ -106,6 +106,12 @@
     <property name="FinallyNormalName" type="s" access="readwrite"/>
     <property name="ReadonlyProperty" type="s" access="read"/>
     <property name="WriteonlyProperty" type="s" access="write"/>
+    <property name="quiet" type="s" access="readwrite">
+      <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
+    </property>
+    <property name="quiet_too" type="s" access="readwrite">
+      <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
+    </property>
 
     <!-- unset properties -->
     <property name="unset_i" type="i" access="readwrite"/>


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