Merge lp:~ted/libdbusmenu/group-prop-change-signals into lp:libdbusmenu/0.5

Proposed by Ted Gould
Status: Merged
Merged at revision: 212
Proposed branch: lp:~ted/libdbusmenu/group-prop-change-signals
Merge into: lp:libdbusmenu/0.5
Diff against target: 1207 lines (+539/-231)
9 files modified
configure.ac (+3/-7)
libdbusmenu-glib/client.c (+108/-80)
libdbusmenu-glib/dbus-menu.xml (+46/-63)
libdbusmenu-glib/menuitem-private.h (+3/-2)
libdbusmenu-glib/menuitem.c (+49/-15)
libdbusmenu-glib/menuitem.h (+6/-5)
libdbusmenu-glib/server.c (+319/-58)
tests/json-loader.c (+0/-1)
tests/test-glib-layout-client.c (+5/-0)
To merge this branch: bzr merge lp:~ted/libdbusmenu/group-prop-change-signals
Reviewer Review Type Date Requested Status
DBus Menu Team Pending
Review via email: mp+49849@code.launchpad.net

This proposal supersedes a proposal from 2011-02-15.

Description of the change

Makes it so that the property update signals are all aggregated into a single larger message so that we don't send as much dbus traffic.

This also includes the no-xml. They got merged together and I don't know how to get LP to take them back appart. Here's the message from that one:

Removes the XML from the GetLayout function and instead replaces it with a recursive DBus data type. Can get large.

Some notes:
* This is the basic feature, things like the properties aren't currently used
* There is no default handling so there is only a stub there for now, that's a future branch

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2011-02-10 20:15:31 +0000
3+++ configure.ac 2011-02-15 18:02:06 +0000
4@@ -42,11 +42,9 @@
5 ###########################
6
7 GLIB_REQUIRED_VERSION=2.26
8-XML_REQUIRED_VERSION=2.6
9
10 PKG_CHECK_MODULES(DBUSMENUGLIB, glib-2.0 >= $GLIB_REQUIRED_VERSION
11- gio-2.0 >= $GLIB_REQUIRED_VERSION
12- libxml-2.0 >= $XML_REQUIRED_VERSION)
13+ gio-2.0 >= $GLIB_REQUIRED_VERSION)
14
15 AC_SUBST(DBUSMENUGLIB_CFLAGS)
16 AC_SUBST(DBUSMENUGLIB_LIBS)
17@@ -65,16 +63,14 @@
18 [with_gtk=2])
19 AS_IF([test "x$with_gtk" = x3],
20 [PKG_CHECK_MODULES(DBUSMENUGTK, gtk+-3.0 >= $GTK3_REQUIRED_VERSION
21- glib-2.0 >= $GLIB_REQUIRED_VERSION
22- libxml-2.0 >= $XML_REQUIRED_VERSION)
23+ glib-2.0 >= $GLIB_REQUIRED_VERSION)
24 AC_SUBST(DBUSMENUGTK_CFLAGS)
25 AC_SUBST(DBUSMENUGTK_LIBS)
26 AC_DEFINE(HAVE_GTK3, 1, [whether gtk3 is available])
27 ],
28 [test "x$with_gtk" = x2],
29 [PKG_CHECK_MODULES(DBUSMENUGTK, gtk+-2.0 >= $GTK_REQUIRED_VERSION
30- glib-2.0 >= $GLIB_REQUIRED_VERSION
31- libxml-2.0 >= $XML_REQUIRED_VERSION)
32+ glib-2.0 >= $GLIB_REQUIRED_VERSION)
33 AC_SUBST(DBUSMENUGTK_CFLAGS)
34 AC_SUBST(DBUSMENUGTK_LIBS)
35 ],
36
37=== modified file 'libdbusmenu-glib/client.c'
38--- libdbusmenu-glib/client.c 2011-01-31 16:48:21 +0000
39+++ libdbusmenu-glib/client.c 2011-02-15 18:02:06 +0000
40@@ -32,9 +32,6 @@
41
42 #include <gio/gio.h>
43
44-#include <libxml/parser.h>
45-#include <libxml/tree.h>
46-
47 #include "client.h"
48 #include "menuitem.h"
49 #include "menuitem-private.h"
50@@ -151,9 +148,8 @@
51 static void id_prop_update (GDBusProxy * proxy, gint id, gchar * property, GVariant * value, DbusmenuClient * client);
52 static void id_update (GDBusProxy * proxy, gint id, DbusmenuClient * client);
53 static void build_proxies (DbusmenuClient * client);
54-static gint parse_node_get_id (xmlNodePtr node);
55-static DbusmenuMenuitem * parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy);
56-static gint parse_layout (DbusmenuClient * client, const gchar * layout);
57+static DbusmenuMenuitem * parse_layout_xml(DbusmenuClient * client, GVariant * layout, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy);
58+static gint parse_layout (DbusmenuClient * client, GVariant * layout);
59 static void update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data);
60 static void update_layout (DbusmenuClient * client);
61 static void menuitem_get_properties_cb (GVariant * properties, GError * error, gpointer data);
62@@ -1030,11 +1026,60 @@
63 {
64 g_return_if_fail(DBUSMENU_IS_CLIENT(user_data));
65 DbusmenuClient * client = DBUSMENU_CLIENT(user_data);
66+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
67
68 if (g_strcmp0(signal, "LayoutUpdated") == 0) {
69 guint revision; gint parent;
70 g_variant_get(params, "(ui)", &revision, &parent);
71 layout_update(proxy, revision, parent, client);
72+ } else if (priv->root == NULL) {
73+ /* Drop out here, all the rest of these really need to have a root
74+ node so we can just ignore them if there isn't one. */
75+ } else if (g_strcmp0(signal, "ItemPropertiesUpdated") == 0) {
76+ /* Remove before adding just incase there is a duplicate, against the
77+ rules, but we can handle it so let's do it. */
78+ GVariantIter ritems;
79+ g_variant_iter_init(&ritems, g_variant_get_child_value(params, 1));
80+
81+ GVariant * ritem;
82+ while ((ritem = g_variant_iter_next_value(&ritems)) != NULL) {
83+ gint id = g_variant_get_int32(g_variant_get_child_value(ritem, 0));
84+ DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
85+
86+ if (menuitem == NULL) {
87+ continue;
88+ }
89+
90+ GVariantIter properties;
91+ g_variant_iter_init(&properties, g_variant_get_child_value(ritem, 1));
92+ gchar * property;
93+
94+ while (g_variant_iter_next(&properties, "s", &property)) {
95+ g_debug("Removing property '%s' on %d", property, id);
96+ dbusmenu_menuitem_property_remove(menuitem, property);
97+ }
98+ }
99+
100+ GVariantIter items;
101+ g_variant_iter_init(&items, g_variant_get_child_value(params, 0));
102+
103+ GVariant * item;
104+ while ((item = g_variant_iter_next_value(&items)) != NULL) {
105+ gint id = g_variant_get_int32(g_variant_get_child_value(item, 0));
106+ GVariantIter properties;
107+ g_variant_iter_init(&properties, g_variant_get_child_value(item, 1));
108+ gchar * property;
109+ GVariant * value;
110+
111+ while (g_variant_iter_next(&properties, "{sv}", &property, &value)) {
112+ GVariant * internalvalue = value;
113+ if (G_LIKELY(g_variant_is_of_type(value, G_VARIANT_TYPE_VARIANT))) {
114+ /* Unboxing if needed */
115+ internalvalue = g_variant_get_variant(value);
116+ }
117+ id_prop_update(proxy, id, property, internalvalue, client);
118+ }
119+ }
120 } else if (g_strcmp0(signal, "ItemPropertyUpdated") == 0) {
121 gint id; gchar * property; GVariant * value;
122 g_variant_get(params, "(isv)", &id, &property, &value);
123@@ -1054,40 +1099,6 @@
124 return;
125 }
126
127-/* Get the ID attribute of the node, parse it and
128- return it. Also we're checking to ensure the node
129- is a 'menu' here. */
130-static gint
131-parse_node_get_id (xmlNodePtr node)
132-{
133- if (node == NULL) {
134- return -1;
135- }
136- if (node->type != XML_ELEMENT_NODE) {
137- return -1;
138- }
139- if (g_strcmp0((gchar *)node->name, "menu") != 0) {
140- /* This kills some nodes early */
141- g_warning("XML Node is not 'menu' it is '%s'", node->name);
142- return -1;
143- }
144-
145- xmlAttrPtr attrib;
146- for (attrib = node->properties; attrib != NULL; attrib = attrib->next) {
147- if (g_strcmp0((gchar *)attrib->name, "id") == 0) {
148- if (attrib->children != NULL) {
149- gint id = (guint)g_ascii_strtoll((gchar *)attrib->children->content, NULL, 10);
150- /* g_debug ("Found ID: %d", id); */
151- return id;
152- }
153- break;
154- }
155- }
156-
157- g_warning("Unable to find an ID on the node");
158- return -1;
159-}
160-
161 /* This is the callback for the properties on a menu item. There
162 should be all of them in the Hash, and they we use foreach to
163 copy them into the menuitem.
164@@ -1265,7 +1276,7 @@
165 edata->event = g_strdup(name);
166 edata->timestamp = timestamp;
167 edata->variant = variant;
168- g_variant_ref(variant);
169+ g_variant_ref_sink(variant);
170
171 g_dbus_proxy_call(priv->menuproxy,
172 "Event",
173@@ -1390,10 +1401,14 @@
174 /* Parse recursively through the XML and make it into
175 objects as need be */
176 static DbusmenuMenuitem *
177-parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy)
178+parse_layout_xml(DbusmenuClient * client, GVariant * layout, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy)
179 {
180+ if (layout == NULL) {
181+ return NULL;
182+ }
183+
184 /* First verify and figure out what we've got */
185- gint id = parse_node_get_id(node);
186+ gint id = g_variant_get_int32(g_variant_get_child_value(layout, 0));
187 if (id < 0) {
188 return NULL;
189 }
190@@ -1405,20 +1420,26 @@
191 g_return_val_if_fail(id == dbusmenu_menuitem_get_id(item), NULL);
192
193 /* Some variables */
194- xmlNodePtr children;
195- guint position;
196+ GVariantIter children;
197+ g_variant_iter_init(&children, g_variant_get_child_value(layout, 2));
198+ GVariant * child;
199+
200+ guint position = 0;
201 GList * oldchildren = g_list_copy(dbusmenu_menuitem_get_children(item));
202 /* g_debug("Starting old children: %d", g_list_length(oldchildren)); */
203
204 /* Go through all the XML Nodes and make sure that we have menuitems
205 to cover those XML nodes. */
206- for (children = node->children, position = 0; children != NULL; children = children->next, position++) {
207+ while ((child = g_variant_iter_next_value(&children)) != NULL) {
208 /* g_debug("Looking at child: %d", position); */
209- gint childid = parse_node_get_id(children);
210+ if (g_variant_is_of_type(child, G_VARIANT_TYPE_VARIANT)) {
211+ child = g_variant_get_variant(child);
212+ }
213+
214+ gint childid = g_variant_get_int32(g_variant_get_child_value(child, 0));
215 if (childid < 0) {
216 /* Don't increment the position when there isn't a valid
217 node in the XML tree. It's probably a comment. */
218- position--;
219 continue;
220 }
221 DbusmenuMenuitem * childmi = NULL;
222@@ -1451,6 +1472,8 @@
223 dbusmenu_menuitem_child_reorder(item, childmi, position);
224 parse_layout_update(childmi, client);
225 }
226+
227+ position++;
228 }
229
230 /* Remove any children that are no longer used by this version of
231@@ -1473,14 +1496,20 @@
232 }
233
234 /* now it's time to recurse down the tree. */
235- children = node->children;
236+ g_variant_iter_init(&children, g_variant_get_child_value(layout, 2));
237+
238+ child = g_variant_iter_next_value(&children);
239 GList * childmis = dbusmenu_menuitem_get_children(item);
240- while (children != NULL && childmis != NULL) {
241- gint xmlid = parse_node_get_id(children);
242+ while (child != NULL && childmis != NULL) {
243+ if (g_variant_is_of_type(child, G_VARIANT_TYPE_VARIANT)) {
244+ child = g_variant_get_variant(child);
245+ }
246+
247+ gint xmlid = g_variant_get_int32(g_variant_get_child_value(child, 0));
248 /* If this isn't a valid menu item we need to move on
249 until we have one. This avoids things like comments. */
250 if (xmlid < 0) {
251- children = children->next;
252+ child = g_variant_iter_next_value(&children);
253 continue;
254 }
255
256@@ -1489,13 +1518,14 @@
257 g_debug("Recursing parse_layout_xml. XML ID: %d MI ID: %d", xmlid, miid);
258 #endif
259
260- parse_layout_xml(client, children, DBUSMENU_MENUITEM(childmis->data), item, proxy);
261+ parse_layout_xml(client, child, DBUSMENU_MENUITEM(childmis->data), item, proxy);
262
263- children = children->next;
264+ child = g_variant_iter_next_value(&children);
265 childmis = g_list_next(childmis);
266 }
267- if (children != NULL) {
268- g_warning("Sync failed, now we've got extra XML nodes.");
269+
270+ if (child != NULL) {
271+ g_warning("Sync failed, now we've got extra layout nodes.");
272 }
273 if (childmis != NULL) {
274 g_warning("Sync failed, now we've got extra menu items.");
275@@ -1507,7 +1537,7 @@
276 /* Take the layout passed to us over DBus and turn it into
277 a set of beautiful objects */
278 static gint
279-parse_layout (DbusmenuClient * client, const gchar * layout)
280+parse_layout (DbusmenuClient * client, GVariant * layout)
281 {
282 #ifdef MASSIVEDEBUGGING
283 g_debug("Client Parsing a new layout");
284@@ -1515,17 +1545,6 @@
285
286 DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
287
288- xmlDocPtr xmldoc;
289-
290- /* No one should need more characters than this! */
291- xmldoc = xmlReadMemory(layout, g_utf8_strlen(layout, 1024*1024), "dbusmenu.xml", NULL, 0);
292-
293- xmlNodePtr root = xmlDocGetRootElement(xmldoc);
294-
295- if (root == NULL) {
296- g_warning("Unable to get root node of menu XML");
297- }
298-
299 DbusmenuMenuitem * oldroot = priv->root;
300
301 if (priv->root == NULL) {
302@@ -1534,11 +1553,10 @@
303 parse_layout_update(priv->root, client);
304 }
305
306- priv->root = parse_layout_xml(client, root, priv->root, NULL, priv->menuproxy);
307- xmlFreeDoc(xmldoc);
308+ priv->root = parse_layout_xml(client, layout, priv->root, NULL, priv->menuproxy);
309
310 if (priv->root == NULL) {
311- g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, layout);
312+ g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, g_variant_print(layout, TRUE));
313 }
314
315 if (priv->root != oldroot) {
316@@ -1579,14 +1597,10 @@
317 goto out;
318 }
319
320- guint rev;
321- gchar * xml;
322-
323- g_variant_get(params, "(us)", &rev, &xml);
324- g_variant_unref(params);
325-
326- guint parseable = parse_layout(client, xml);
327- g_free(xml);
328+ guint rev = g_variant_get_uint32(g_variant_get_child_value(params, 0));
329+ GVariant * layout = g_variant_get_child_value(params, 1);
330+
331+ guint parseable = parse_layout(client, layout);
332
333 if (parseable == 0) {
334 g_warning("Unable to parse layout!");
335@@ -1612,6 +1626,10 @@
336 priv->layoutcall = NULL;
337 }
338
339+ if (params != NULL) {
340+ g_variant_unref(params);
341+ }
342+
343 g_object_unref(G_OBJECT(client));
344 return;
345 }
346@@ -1639,10 +1657,20 @@
347
348 priv->layoutcall = g_cancellable_new();
349
350+ GVariantBuilder tupleb;
351+ g_variant_builder_init(&tupleb, G_VARIANT_TYPE_TUPLE);
352+
353+ g_variant_builder_add_value(&tupleb, g_variant_new_int32(0)); // root
354+ g_variant_builder_add_value(&tupleb, g_variant_new_int32(-1)); // recurse
355+ g_variant_builder_add_value(&tupleb, g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0)); // props
356+
357+ GVariant * args = g_variant_builder_end(&tupleb);
358+ // g_debug("Args (type: %s): %s", g_variant_get_type_string(args), g_variant_print(args, TRUE));
359+
360 g_object_ref(G_OBJECT(client));
361 g_dbus_proxy_call(priv->menuproxy,
362 "GetLayout",
363- g_variant_new("(i)", 0), /* root */
364+ args,
365 G_DBUS_CALL_FLAGS_NONE,
366 -1, /* timeout */
367 priv->layoutcall, /* cancellable */
368
369=== modified file 'libdbusmenu-glib/dbus-menu.xml'
370--- libdbusmenu-glib/dbus-menu.xml 2011-01-13 15:53:15 +0000
371+++ libdbusmenu-glib/dbus-menu.xml 2011-02-15 18:02:06 +0000
372@@ -174,34 +174,38 @@
373 <!-- Functions -->
374
375 <method name="GetLayout">
376- <dox:d><![CDATA[
377- Provides an XML representation of the menu hierarchy
378-
379- XML syntax:
380-
381- @verbatim
382-<menu id="0"> # Root container
383- <menu id="1"> # First level menu, for example "File"
384- <menu id="2"/> ~ Second level menu, for example "Open"
385- <menu id="3"/>
386- ...
387- </menu>
388- <menu id="4"> # Another first level menu, say "Edit"
389- ...
390- </menu>
391- ...
392-</menu>
393- @endverbatim
394- ]]></dox:d>
395+ <dox:d>
396+ Provides the layout and propertiers that are attached to the entries
397+ that are in the layout. It only gives the items that are children
398+ of the item that is specified in @parentId. It will return all of the
399+ properties or specific ones depending of the value in @propertyNames.
400+
401+ The format is recursive, where the second 'v' is in the same format
402+ as the original 'a(ia(sv)a(v))'. If the @recursive flag is set to
403+ less than one then the second array will have zero entries.
404+ </dox:d>
405 <arg type="i" name="parentId" direction="in">
406 <dox:d>The ID of the parent node for the layout. For
407 grabbing the layout from the root node use zero.</dox:d>
408 </arg>
409+ <arg type="i" name="recurse" direction="in">
410+ <dox:d>
411+ The amount of levels of recursion to use. -1, as value would
412+ deliver all the items under the @parentId.
413+ </dox:d>
414+ </arg>
415+ <arg type="as" name="propertyNames" direction="in" >
416+ <dox:d>
417+ The list of item properties we are
418+ interested in. If there are no entries in the list all of
419+ the properties will be sent.
420+ </dox:d>
421+ </arg>
422 <arg type="u" name="revision" direction="out">
423 <dox:d>The revision number of the layout. For matching
424 with layoutUpdated signals.</dox:d>
425 </arg>
426- <arg type="s" name="layout" direction="out">
427+ <arg type="(ia{sv}av)" name="layout" direction="out">
428 <dox:d>The layout as an XML string of IDs.</dox:d>
429 </arg>
430 </method>
431@@ -236,33 +240,21 @@
432 </arg>
433 </method>
434
435- <method name="GetChildren">
436- <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="DBusMenuItemList"/>
437- <arg type="i" name="id" direction="in" />
438- <arg type="as" name="propertyNames" direction="in" />
439- <arg type="a(ia{sv})" name="properties" direction="out" />
440- </method>
441-
442 <method name="GetProperty">
443- <arg type="i" name="id" direction="in" />
444- <arg type="s" name="name" direction="in" />
445- <arg type="v" name="value" direction="out" />
446- </method>
447-
448- <method name="GetProperties">
449 <dox:d>
450- Returns multiple properties in one call. This is more efficient than
451- GetProperty.
452-
453+ Get a signal property on a single item. This is not useful if you're
454+ going to implement this interface, it should only be used if you're
455+ debugging via a commandline tool.
456 </dox:d>
457- <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
458- <arg type="i" name="id" direction="in" >
459- <dox:d>The item whose properties we want to retrieve.</dox:d>
460- </arg>
461- <arg type="as" name="propertyNames" direction="in" >
462- <dox:d>List of string name of the properties we want. If the list contains no entries, all properties are sent.</dox:d>
463- </arg>
464- <arg type="a{sv}" name="properties" direction="out" />
465+ <arg type="i" name="id" direction="in">
466+ <dox:d>the id of the item which received the event</dox:d>
467+ </arg>
468+ <arg type="s" name="name" direction="in">
469+ <dox:d>the name of the property to get</dox:d>
470+ </arg>
471+ <arg type="v" name="value" direction="out">
472+ <dox:d>the value of the property</dox:d>
473+ </arg>
474 </method>
475
476 <method name="Event">
477@@ -309,25 +301,16 @@
478 </method>
479
480 <!-- Signals -->
481- <signal name="ItemPropertyUpdated">
482- <dox:d>
483- Triggered by the application to notify the applet that the property @a property
484- from item @a id has changed to @a value.
485- </dox:d>
486- <arg type="i" name="id" direction="out" />
487- <arg type="s" name="prop" direction="out" />
488- <arg type="v" name="value" direction="out" />
489- </signal>
490-
491- <signal name="ItemUpdated">
492- <dox:d>
493- Triggered by the application to notify the applet that all properties of item
494- </dox:d>
495- <arg type="i" name="id" direction="out" >
496- <dox:d>id which should be considered outdated</dox:d>
497- </arg>
498- </signal>
499-
500+ <signal name="ItemsPropertiesUpdated">
501+ <dox:d>
502+ Triggered when there are lots of property updates across many items
503+ so they all get grouped into a single dbus message. The format is
504+ the ID of the item with a hashtable of names and values for those
505+ properties.
506+ </dox:d>
507+ <arg type="a(ia(sv))" name="props" direction="out" />
508+ <arg type="a(ia(s))" name="props_removed" direction="out" />
509+ </signal>
510 <signal name="LayoutUpdated">
511 <dox:d>
512 Triggered by the application to notify display of a layout update, up to
513
514=== modified file 'libdbusmenu-glib/menuitem-private.h'
515--- libdbusmenu-glib/menuitem-private.h 2010-10-14 21:00:38 +0000
516+++ libdbusmenu-glib/menuitem-private.h 2011-02-15 18:02:06 +0000
517@@ -33,10 +33,11 @@
518
519 G_BEGIN_DECLS
520
521-void dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array);
522+GVariant * dbusmenu_menuitem_build_variant (DbusmenuMenuitem * mi, const gchar ** properties, gint recurse);
523 gboolean dbusmenu_menuitem_realized (DbusmenuMenuitem * mi);
524 void dbusmenu_menuitem_set_realized (DbusmenuMenuitem * mi);
525-GVariant * dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi);
526+GVariant * dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi, const gchar ** properties);
527+gboolean dbusmenu_menuitem_property_is_default (DbusmenuMenuitem * mi, const gchar * property);
528
529 G_END_DECLS
530
531
532=== modified file 'libdbusmenu-glib/menuitem.c'
533--- libdbusmenu-glib/menuitem.c 2011-02-04 17:00:07 +0000
534+++ libdbusmenu-glib/menuitem.c 2011-02-15 18:02:06 +0000
535@@ -1009,7 +1009,7 @@
536
537 if (value != NULL) {
538 gchar * lprop = g_strdup(property);
539- g_variant_ref(value);
540+ g_variant_ref_sink(value);
541
542 if (currentval == NULL || !g_variant_equal((GVariant*)currentval, value)) {
543 g_hash_table_replace(priv->properties, lprop, value);
544@@ -1213,7 +1213,7 @@
545 GHashTable * table = (GHashTable *)in_data;
546 gchar * key = (gchar *)in_key;
547 GVariant * value = (GVariant *)in_value;
548- g_variant_ref(value);
549+ g_variant_ref_sink(value);
550 g_hash_table_insert(table, g_strdup(key), value);
551 return;
552 }
553@@ -1250,7 +1250,9 @@
554 static void
555 variant_helper (gpointer in_key, gpointer in_value, gpointer user_data)
556 {
557- g_variant_builder_add((GVariantBuilder *)user_data, "{sv}", in_key, in_value);
558+ GVariant * value = g_variant_new_dict_entry(g_variant_new_string((gchar *)in_key),
559+ g_variant_new_variant((GVariant *)in_value));
560+ g_variant_builder_add_value((GVariantBuilder *)user_data, value);
561 return;
562 }
563
564@@ -1264,7 +1266,7 @@
565 Return Value: A GVariant of type "a{sv}" or NULL on error.
566 */
567 GVariant *
568-dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi)
569+dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi, const gchar ** properties)
570 {
571 g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
572
573@@ -1274,7 +1276,7 @@
574
575 if (g_hash_table_size(priv->properties) > 0) {
576 GVariantBuilder builder;
577- g_variant_builder_init(&builder, g_variant_type_new("a{sv}"));
578+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
579
580 g_hash_table_foreach(priv->properties, variant_helper, &builder);
581
582@@ -1322,7 +1324,7 @@
583
584
585 /**
586- dbusmenu_menuitem_buildxml:
587+ dbusmenu_menuitem_buildvariant:
588 @mi: #DbusmenuMenuitem to represent in XML
589 @array: (element-type utf8): A list of string that will be turned into an XML file
590
591@@ -1332,28 +1334,50 @@
592 start tag and one that is a closing tag. It will allow it's
593 children to place their own tags in the array in between those two.
594 */
595-void
596-dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array)
597+GVariant *
598+dbusmenu_menuitem_build_variant (DbusmenuMenuitem * mi, const gchar ** properties, gint recurse)
599 {
600- g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
601+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
602
603 gint id = 0;
604 if (!dbusmenu_menuitem_get_root(mi)) {
605 id = dbusmenu_menuitem_get_id(mi);
606 }
607
608+ /* This is the tuple that'll build up being a representation of
609+ this entry */
610+ GVariantBuilder tupleb;
611+ g_variant_builder_init(&tupleb, G_VARIANT_TYPE_TUPLE);
612+
613+ /* Add our ID */
614+ g_variant_builder_add_value(&tupleb, g_variant_new_int32(id));
615+
616+ /* Figure out the properties */
617+ GVariant * props = dbusmenu_menuitem_properties_variant(mi, properties);
618+ if (props != NULL) {
619+ g_variant_builder_add_value(&tupleb, props);
620+ } else {
621+ g_variant_builder_add_value(&tupleb, g_variant_parse(G_VARIANT_TYPE("a{sv}"), "[ ]", NULL, NULL, NULL));
622+ }
623+
624+ /* Pillage the children */
625 GList * children = dbusmenu_menuitem_get_children(mi);
626- if (children == NULL) {
627- g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\"/>", id));
628+ if (children == NULL && recurse != 0) {
629+ g_variant_builder_add_value(&tupleb, g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0));
630 } else {
631- g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\">", id));
632+ GVariantBuilder childrenbuilder;
633+ g_variant_builder_init(&childrenbuilder, G_VARIANT_TYPE_ARRAY);
634+
635 for ( ; children != NULL; children = children->next) {
636- dbusmenu_menuitem_buildxml(DBUSMENU_MENUITEM(children->data), array);
637+ GVariant * child = dbusmenu_menuitem_build_variant(DBUSMENU_MENUITEM(children->data), properties, recurse - 1);
638+
639+ g_variant_builder_add_value(&childrenbuilder, g_variant_new_variant(child));
640 }
641- g_ptr_array_add(array, g_strdup("</menu>"));
642+
643+ g_variant_builder_add_value(&tupleb, g_variant_builder_end(&childrenbuilder));
644 }
645
646- return;
647+ return g_variant_builder_end(&tupleb);
648 }
649
650 typedef struct {
651@@ -1473,3 +1497,13 @@
652
653 return;
654 }
655+
656+/* Checks to see if the value of this property is unique or just the
657+ default value. */
658+/* TODO: Implement this */
659+gboolean
660+dbusmenu_menuitem_property_is_default (DbusmenuMenuitem * mi, const gchar * property)
661+{
662+ /* No defaults system yet */
663+ return FALSE;
664+}
665
666=== modified file 'libdbusmenu-glib/menuitem.h'
667--- libdbusmenu-glib/menuitem.h 2011-01-07 05:25:02 +0000
668+++ libdbusmenu-glib/menuitem.h 2011-02-15 18:02:06 +0000
669@@ -111,14 +111,15 @@
670 typedef void (*dbusmenu_menuitem_about_to_show_cb) (DbusmenuMenuitem * mi, gpointer user_data);
671
672 /**
673- * dbusmenu_menuitem_buildxml_slot_t:
674+ * dbusmenu_menuitem_buildvariant_slot_t:
675 * @mi: (in): Menu item that should be built from
676- * @stringarray: (inout) (transfer none) (array) (element-type utf8): An array of strings that can be combined into an XML file.
677 *
678 * This is the function that is called to represent this menu item
679- * as an XML fragment. Should call it's own children.
680+ * as a variant. Should call it's own children.
681+ *
682+ * Return value: (transfer full) A variant representing this item and it's children
683 */
684-typedef void (*dbusmenu_menuitem_buildxml_slot_t) (DbusmenuMenuitem * mi, GPtrArray* stringarray);
685+typedef GVariant * (*dbusmenu_menuitem_buildvariant_slot_t) (DbusmenuMenuitem * mi, gchar ** properties);
686
687 /**
688 * DbusmenuMenuitemClass:
689@@ -155,7 +156,7 @@
690 void (*realized) (void);
691
692 /* Virtual functions */
693- dbusmenu_menuitem_buildxml_slot_t buildxml;
694+ dbusmenu_menuitem_buildvariant_slot_t buildvariant;
695 void (*handle_event) (DbusmenuMenuitem * mi, const gchar * name, GVariant * value, guint timestamp);
696 void (*send_about_to_show) (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gpointer user_data), gpointer cb_data);
697
698
699=== modified file 'libdbusmenu-glib/server.c'
700--- libdbusmenu-glib/server.c 2011-01-31 14:10:49 +0000
701+++ libdbusmenu-glib/server.c 2011-02-15 18:02:06 +0000
702@@ -54,6 +54,9 @@
703 GDBusConnection * bus;
704 GCancellable * bus_lookup;
705 guint dbus_registration;
706+
707+ GArray * prop_array;
708+ guint property_idle;
709 };
710
711 #define DBUSMENU_SERVER_GET_PRIVATE(o) (DBUSMENU_SERVER(o)->priv)
712@@ -156,6 +159,7 @@
713 static void menuitem_signals_remove (DbusmenuMenuitem * mi,
714 gpointer data);
715 static GQuark error_quark (void);
716+static void prop_array_teardown (GArray * prop_array);
717 static void bus_get_layout (DbusmenuServer * server,
718 GVariant * params,
719 GDBusMethodInvocation * invocation);
720@@ -354,6 +358,17 @@
721
722 if (priv->layout_idle != 0) {
723 g_source_remove(priv->layout_idle);
724+ priv->layout_idle = 0;
725+ }
726+
727+ if (priv->property_idle != 0) {
728+ g_source_remove(priv->property_idle);
729+ priv->property_idle = 0;
730+ }
731+
732+ if (priv->prop_array != NULL) {
733+ prop_array_teardown(priv->prop_array);
734+ priv->prop_array = NULL;
735 }
736
737 if (priv->root != NULL) {
738@@ -418,6 +433,15 @@
739 if (priv->root != NULL) {
740 dbusmenu_menuitem_foreach(priv->root, menuitem_signals_remove, obj);
741 dbusmenu_menuitem_set_root(priv->root, FALSE);
742+
743+ GList * properties = dbusmenu_menuitem_properties_list(priv->root);
744+ GList * iter;
745+ for (iter = properties; iter != NULL; iter = g_list_next(iter)) {
746+ gchar * property = (gchar *)iter->data;
747+ menuitem_property_changed(priv->root, property, NULL, DBUSMENU_SERVER(obj));
748+ }
749+ g_list_free(properties);
750+
751 g_object_unref(G_OBJECT(priv->root));
752 priv->root = NULL;
753 }
754@@ -426,6 +450,14 @@
755 g_object_ref(G_OBJECT(priv->root));
756 dbusmenu_menuitem_set_root(priv->root, TRUE);
757 dbusmenu_menuitem_foreach(priv->root, menuitem_signals_create, obj);
758+
759+ GList * properties = dbusmenu_menuitem_properties_list(priv->root);
760+ GList * iter;
761+ for (iter = properties; iter != NULL; iter = g_list_next(iter)) {
762+ gchar * property = (gchar *)iter->data;
763+ menuitem_property_changed(priv->root, property, dbusmenu_menuitem_property_get_variant(priv->root, property), DBUSMENU_SERVER(obj));
764+ }
765+ g_list_free(properties);
766 } else {
767 g_debug("Setting root node to NULL");
768 }
769@@ -440,17 +472,6 @@
770 }
771
772 static void
773-xmlarray_foreach_free (gpointer arrayentry, gpointer userdata)
774-{
775- if (arrayentry != NULL) {
776- /* g_debug("Freeing pointer: %s", (gchar *)arrayentry); */
777- g_free(arrayentry);
778- }
779-
780- return;
781-}
782-
783-static void
784 get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
785 {
786 DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(obj);
787@@ -633,22 +654,264 @@
788 return;
789 }
790
791+typedef struct _prop_idle_item_t prop_idle_item_t;
792+struct _prop_idle_item_t {
793+ gint id;
794+ GArray * array;
795+};
796+
797+typedef struct _prop_idle_prop_t prop_idle_prop_t;
798+struct _prop_idle_prop_t {
799+ gchar * property;
800+ GVariant * variant;
801+};
802+
803+/* Takes appart our data structure so we don't leak any
804+ memory or references. */
805+static void
806+prop_array_teardown (GArray * prop_array)
807+{
808+ int i, j;
809+
810+ for (i = 0; i < prop_array->len; i++) {
811+ prop_idle_item_t * iitem = &g_array_index(prop_array, prop_idle_item_t, i);
812+
813+ for (j = 0; j < iitem->array->len; j++) {
814+ prop_idle_prop_t * iprop = &g_array_index(iitem->array, prop_idle_prop_t, j);
815+
816+ g_free(iprop->property);
817+
818+ if (iprop->variant != NULL) {
819+ g_variant_unref(iprop->variant);
820+ }
821+ }
822+
823+ g_array_free(iitem->array, TRUE);
824+ }
825+
826+ g_array_free(prop_array, TRUE);
827+
828+ return;
829+}
830+
831+/* Works in the idle to send a set of property updates so that they'll
832+ all update in a single dbus message. */
833+static gboolean
834+menuitem_property_idle (gpointer user_data)
835+{
836+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(user_data);
837+
838+ /* Source will get removed as we return */
839+ priv->property_idle = 0;
840+
841+ /* If there are no items, let's just not signal */
842+ if (priv->prop_array == NULL) {
843+ return FALSE;
844+ }
845+
846+ int i, j;
847+ GVariantBuilder itembuilder;
848+ gboolean item_init = FALSE;
849+
850+ GVariantBuilder removeitembuilder;
851+ gboolean removeitem_init = FALSE;
852+
853+ for (i = 0; i < priv->prop_array->len; i++) {
854+ prop_idle_item_t * iitem = &g_array_index(priv->prop_array, prop_idle_item_t, i);
855+
856+ GVariantBuilder dictbuilder;
857+ gboolean dictinit = FALSE;
858+
859+ GVariantBuilder removedictbuilder;
860+ gboolean removedictinit = FALSE;
861+
862+ /* Go throught each item and see if it should go in the removal list
863+ or the additive list. */
864+ for (j = 0; j < iitem->array->len; j++) {
865+ prop_idle_prop_t * iprop = &g_array_index(iitem->array, prop_idle_prop_t, j);
866+
867+ if (iprop->variant != NULL) {
868+ if (!dictinit) {
869+ g_variant_builder_init(&dictbuilder, G_VARIANT_TYPE_DICTIONARY);
870+ dictinit = TRUE;
871+ }
872+
873+ GVariant * entry = g_variant_new_dict_entry(g_variant_new_string(iprop->property),
874+ g_variant_new_variant(iprop->variant));
875+
876+ g_variant_builder_add_value(&dictbuilder, entry);
877+ } else {
878+ if (!removedictinit) {
879+ g_variant_builder_init(&removedictbuilder, G_VARIANT_TYPE_ARRAY);
880+ removedictinit = TRUE;
881+ }
882+
883+ g_variant_builder_add_value(&removedictbuilder, g_variant_new_string(iprop->property));
884+ }
885+ }
886+
887+ /* If we've got new values that are real values we need to add that
888+ to the list of items to send the value of */
889+ if (dictinit) {
890+ GVariantBuilder tuplebuilder;
891+ g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
892+
893+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(iitem->id));
894+ g_variant_builder_add_value(&tuplebuilder, g_variant_builder_end(&dictbuilder));
895+
896+ if (!item_init) {
897+ g_variant_builder_init(&itembuilder, G_VARIANT_TYPE_ARRAY);
898+ item_init = TRUE;
899+ }
900+
901+ g_variant_builder_add_value(&itembuilder, g_variant_builder_end(&tuplebuilder));
902+ }
903+
904+ /* If we've got properties that have been removed then we need to add
905+ them to the list of removed items */
906+ if (removedictinit) {
907+ GVariantBuilder tuplebuilder;
908+ g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
909+
910+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(iitem->id));
911+ g_variant_builder_add_value(&tuplebuilder, g_variant_builder_end(&removedictbuilder));
912+
913+ if (!removeitem_init) {
914+ g_variant_builder_init(&removeitembuilder, G_VARIANT_TYPE_ARRAY);
915+ removeitem_init = TRUE;
916+ }
917+
918+ g_variant_builder_add_value(&removeitembuilder, g_variant_builder_end(&tuplebuilder));
919+ }
920+ }
921+
922+ GVariant * megadata[2];
923+
924+ if (item_init) {
925+ megadata[0] = g_variant_builder_end(&itembuilder);
926+ } else {
927+ GError * error = NULL;
928+ megadata[0] = g_variant_parse(G_VARIANT_TYPE("a(ia{sv})"), "[ ]", NULL, NULL, &error);
929+
930+ if (error != NULL) {
931+ g_warning("Unable to parse '[ ]' as a 'a(ia{sv})': %s", error->message);
932+ g_error_free(error);
933+ }
934+ }
935+
936+ if (removeitem_init) {
937+ megadata[1] = g_variant_builder_end(&removeitembuilder);
938+ } else {
939+ GError * error = NULL;
940+ megadata[1] = g_variant_parse(G_VARIANT_TYPE("a(ia(s))"), "[ ]", NULL, NULL, &error);
941+
942+ if (error != NULL) {
943+ g_warning("Unable to parse '[ ]' as a 'a(ia(s))': %s", error->message);
944+ g_error_free(error);
945+ }
946+ }
947+
948+ if (priv->dbusobject != NULL && priv->bus != NULL) {
949+ g_dbus_connection_emit_signal(priv->bus,
950+ NULL,
951+ priv->dbusobject,
952+ DBUSMENU_INTERFACE,
953+ "ItemPropertiesUpdated",
954+ g_variant_new_tuple(megadata, 2),
955+ NULL);
956+ } else {
957+ g_variant_unref(megadata[0]);
958+ g_variant_unref(megadata[1]);
959+ }
960+
961+ /* Clean everything up */
962+ prop_array_teardown(priv->prop_array);
963+ priv->prop_array = NULL;
964+
965+ return FALSE;
966+}
967+
968 static void
969 menuitem_property_changed (DbusmenuMenuitem * mi, gchar * property, GVariant * variant, DbusmenuServer * server)
970 {
971+ int i;
972+ gint item_id;
973+
974 DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
975
976- g_signal_emit(G_OBJECT(server), signals[ID_PROP_UPDATE], 0, dbusmenu_menuitem_get_id(mi), property, variant, TRUE);
977-
978- if (priv->dbusobject != NULL && priv->bus != NULL) {
979- g_dbus_connection_emit_signal(priv->bus,
980- NULL,
981- priv->dbusobject,
982- DBUSMENU_INTERFACE,
983- "ItemPropertyUpdated",
984- g_variant_new("(isv)", dbusmenu_menuitem_get_id(mi), property, variant),
985- NULL);
986- }
987+ item_id = dbusmenu_menuitem_get_id(mi);
988+
989+ g_signal_emit(G_OBJECT(server), signals[ID_PROP_UPDATE], 0, item_id, property, variant, TRUE);
990+
991+ /* See if we have a property array, if not, we need to
992+ build one of these suckers */
993+ if (priv->prop_array == NULL) {
994+ priv->prop_array = g_array_new(FALSE, FALSE, sizeof(prop_idle_item_t));
995+ }
996+
997+ /* Look to see if we already have this item in the list
998+ and use it if so */
999+ prop_idle_item_t * item = NULL;
1000+ for (i = 0; i < priv->prop_array->len; i++) {
1001+ prop_idle_item_t * iitem = &g_array_index(priv->prop_array, prop_idle_item_t, i);
1002+ if (iitem->id == item_id) {
1003+ item = iitem;
1004+ break;
1005+ }
1006+ }
1007+
1008+ GArray * properties = NULL;
1009+ /* If not, we'll need to build ourselves one */
1010+ if (item == NULL) {
1011+ prop_idle_item_t myitem;
1012+ myitem.id = item_id;
1013+ myitem.array = g_array_new(FALSE, FALSE, sizeof(prop_idle_prop_t));
1014+
1015+ g_array_append_val(priv->prop_array, myitem);
1016+ properties = myitem.array;
1017+ } else {
1018+ properties = item->array;
1019+ }
1020+
1021+ /* Check to see if this property is in the list */
1022+ prop_idle_prop_t * prop = NULL;
1023+ for (i = 0; i < properties->len; i++) {
1024+ prop_idle_prop_t * iprop = &g_array_index(properties, prop_idle_prop_t, i);
1025+ if (g_strcmp0(iprop->property, property) == 0) {
1026+ prop = iprop;
1027+ break;
1028+ }
1029+ }
1030+
1031+ /* If it's the default value we want to treat it like a clearing
1032+ of the value so that it doesn't get sent over dbus and waste
1033+ bandwidth */
1034+ if (dbusmenu_menuitem_property_is_default(mi, property)) {
1035+ variant = NULL;
1036+ }
1037+
1038+ /* If so, we need to swap the value */
1039+ if (prop != NULL) {
1040+ g_variant_unref(prop->variant);
1041+ prop->variant = variant;
1042+ } else {
1043+ /* else we need to add it */
1044+ prop_idle_prop_t myprop;
1045+ myprop.property = g_strdup(property);
1046+ myprop.variant = variant;
1047+
1048+ g_array_append_val(properties, myprop);
1049+ }
1050+ if (variant != NULL) {
1051+ g_variant_ref_sink(variant);
1052+ }
1053+
1054+ /* Check to see if the idle is already queued, and queue it
1055+ if not. */
1056+ if (priv->property_idle == 0) {
1057+ priv->property_idle = g_idle_add(menuitem_property_idle, server);
1058+ }
1059+
1060 return;
1061 }
1062
1063@@ -757,26 +1020,28 @@
1064 {
1065 DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
1066
1067- gint parent = 0;
1068- g_variant_get(params, "(i)", &parent);
1069+ /* Input */
1070+ gint parent = g_variant_get_int32(g_variant_get_child_value(params, 0));
1071+ gint recurse = g_variant_get_int32(g_variant_get_child_value(params, 1));
1072+ const gchar ** props = g_variant_get_strv(g_variant_get_child_value(params, 2), NULL);
1073
1074+ /* Output */
1075 guint revision = priv->layout_revision;
1076- GPtrArray * xmlarray = g_ptr_array_new();
1077-
1078- if (parent == 0) {
1079- if (priv->root == NULL) {
1080- /* g_debug("Getting layout without root node!"); */
1081- g_ptr_array_add(xmlarray, g_strdup("<menu id=\"0\"/>"));
1082+ GVariant * items = NULL;
1083+
1084+ if (priv->root != NULL) {
1085+ items = dbusmenu_menuitem_build_variant(priv->root, props, recurse);
1086+ }
1087+
1088+ /* What happens if we don't have anything? */
1089+ if (items == NULL) {
1090+ if (parent == 0) {
1091+ /* We should always have a root, so we'll make up one for
1092+ right now. */
1093+ items = g_variant_parse(G_VARIANT_TYPE("(ia{sv}av)"), "(0, [], [])", NULL, NULL, NULL);
1094 } else {
1095- dbusmenu_menuitem_buildxml(priv->root, xmlarray);
1096- }
1097- } else {
1098- DbusmenuMenuitem * item = NULL;
1099- if (priv->root != NULL) {
1100- item = dbusmenu_menuitem_find_id(priv->root, parent);
1101- }
1102-
1103- if (item == NULL) {
1104+ /* If we were looking for a specific ID that's an error that
1105+ we should send back, so let's do that. */
1106 g_dbus_method_invocation_return_error(invocation,
1107 error_quark(),
1108 INVALID_MENUITEM_ID,
1109@@ -784,23 +1049,19 @@
1110 parent);
1111 return;
1112 }
1113- dbusmenu_menuitem_buildxml(item, xmlarray);
1114 }
1115- g_ptr_array_add(xmlarray, NULL);
1116-
1117- /* build string */
1118- gchar * layout = g_strjoinv("", (gchar **)xmlarray->pdata);
1119-
1120- g_ptr_array_foreach(xmlarray, xmlarray_foreach_free, NULL);
1121- g_ptr_array_free(xmlarray, TRUE);
1122-
1123+
1124+ /* Build the final variant tuple */
1125+ GVariantBuilder tuplebuilder;
1126+ g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
1127+
1128+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_uint32(revision));
1129+ g_variant_builder_add_value(&tuplebuilder, items);
1130+
1131+ GVariant * retval = g_variant_builder_end(&tuplebuilder);
1132+ // g_debug("Sending layout type: %s", g_variant_get_type_string(retval));
1133 g_dbus_method_invocation_return_value(invocation,
1134- g_variant_new("(us)",
1135- revision,
1136- layout));
1137-
1138- g_free(layout);
1139-
1140+ retval);
1141 return;
1142 }
1143
1144@@ -874,7 +1135,7 @@
1145 return;
1146 }
1147
1148- GVariant * dict = dbusmenu_menuitem_properties_variant(mi);
1149+ GVariant * dict = dbusmenu_menuitem_properties_variant(mi, NULL);
1150
1151 g_dbus_method_invocation_return_value(invocation, g_variant_new("(a{sv})", dict));
1152
1153@@ -922,7 +1183,7 @@
1154 GVariantBuilder wbuilder;
1155 g_variant_builder_init(&wbuilder, G_VARIANT_TYPE_TUPLE);
1156 g_variant_builder_add(&wbuilder, "i", id);
1157- GVariant * props = dbusmenu_menuitem_properties_variant(mi);
1158+ GVariant * props = dbusmenu_menuitem_properties_variant(mi, NULL);
1159
1160 if (props == NULL) {
1161 GError * error = NULL;
1162@@ -982,7 +1243,7 @@
1163 gint id = dbusmenu_menuitem_get_id(mi);
1164 g_variant_builder_add_value(&tuple, g_variant_new_int32(id));
1165
1166- GVariant * props = dbusmenu_menuitem_properties_variant(mi);
1167+ GVariant * props = dbusmenu_menuitem_properties_variant(mi, NULL);
1168 g_variant_builder_add_value(&tuple, props);
1169
1170 g_variant_builder_add_value(builder, g_variant_builder_end(&tuple));
1171@@ -1105,7 +1366,7 @@
1172 event_data->variant = g_variant_get_variant(event_data->variant);
1173 }
1174
1175- g_variant_ref(event_data->variant);
1176+ g_variant_ref_sink(event_data->variant);
1177
1178 g_timeout_add(0, event_local_handler, event_data);
1179
1180
1181=== modified file 'tests/json-loader.c'
1182--- tests/json-loader.c 2010-12-02 03:35:46 +0000
1183+++ tests/json-loader.c 2011-02-15 18:02:06 +0000
1184@@ -109,7 +109,6 @@
1185
1186 if (variant != NULL) {
1187 dbusmenu_menuitem_property_set_variant(mi, member, variant);
1188- g_variant_unref(variant);
1189 }
1190 }
1191
1192
1193=== modified file 'tests/test-glib-layout-client.c'
1194--- tests/test-glib-layout-client.c 2010-02-05 17:54:42 +0000
1195+++ tests/test-glib-layout-client.c 2011-02-15 18:02:06 +0000
1196@@ -81,6 +81,11 @@
1197 g_debug("Layout Updated");
1198
1199 DbusmenuMenuitem * menuroot = dbusmenu_client_get_root(client);
1200+ if (menuroot == NULL) {
1201+ g_debug("Root NULL, waiting");
1202+ return;
1203+ }
1204+
1205 layout_t * layout = &layouts[layouton];
1206
1207 if (!verify_root_to_layout(menuroot, layout)) {

Subscribers

People subscribed via source and target branches