Merge lp:~ted/libdbusmenu/reordering-all-over-again into lp:libdbusmenu/0.5

Proposed by Ted Gould
Status: Merged
Merged at revision: not available
Proposed branch: lp:~ted/libdbusmenu/reordering-all-over-again
Merge into: lp:libdbusmenu/0.5
Diff against target: 349 lines
6 files modified
libdbusmenu-glib/client.c (+58/-20)
libdbusmenu-glib/dbus-menu.xml (+1/-0)
libdbusmenu-glib/menuitem.c (+6/-4)
libdbusmenu-glib/menuitem.h (+1/-1)
libdbusmenu-glib/server.c (+27/-7)
libdbusmenu-glib/server.h (+1/-1)
To merge this branch: bzr merge lp:~ted/libdbusmenu/reordering-all-over-again
Reviewer Review Type Date Requested Status
Cody Russell (community) Approve
Review via email: mp+12367@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

Adds revision tracking of the layout to help fix some of the reordering bugs.

Revision history for this message
Cody Russell (bratsche) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libdbusmenu-glib/client.c'
2--- libdbusmenu-glib/client.c 2009-09-11 16:56:07 +0000
3+++ libdbusmenu-glib/client.c 2009-09-24 18:45:21 +0000
4@@ -67,6 +67,9 @@
5 DBusGProxy * propproxy;
6 DBusGProxyCall * layoutcall;
7
8+ gint current_revision;
9+ gint my_revision;
10+
11 DBusGProxy * dbusproxy;
12
13 GHashTable * type_handlers;
14@@ -91,13 +94,13 @@
15 static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec);
16 static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
17 /* Private Funcs */
18-static void layout_update (DBusGProxy * proxy, DbusmenuClient * client);
19+static void layout_update (DBusGProxy * proxy, gint revision, DbusmenuClient * client);
20 static void id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client);
21 static void id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client);
22 static void build_proxies (DbusmenuClient * client);
23 static guint parse_node_get_id (xmlNodePtr node);
24 static DbusmenuMenuitem * parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy);
25-static void parse_layout (DbusmenuClient * client, const gchar * layout);
26+static gint parse_layout (DbusmenuClient * client, const gchar * layout);
27 static void update_layout_cb (DBusGProxy * proxy, DBusGProxyCall * call, void * data);
28 static void update_layout (DbusmenuClient * client);
29 static void menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data);
30@@ -195,6 +198,9 @@
31 priv->propproxy = NULL;
32 priv->layoutcall = NULL;
33
34+ priv->current_revision = 0;
35+ priv->my_revision = 0;
36+
37 priv->dbusproxy = NULL;
38
39 priv->type_handlers = g_hash_table_new_full(g_str_hash, g_str_equal,
40@@ -301,9 +307,13 @@
41
42 /* Annoying little wrapper to make the right function update */
43 static void
44-layout_update (DBusGProxy * proxy, DbusmenuClient * client)
45+layout_update (DBusGProxy * proxy, gint revision, DbusmenuClient * client)
46 {
47- update_layout(client);
48+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
49+ priv->current_revision = revision;
50+ if (priv->current_revision > priv->my_revision) {
51+ update_layout(client);
52+ }
53 return;
54 }
55
56@@ -467,7 +477,7 @@
57 priv->dbusproxy = NULL;
58 }
59
60- dbus_g_proxy_add_signal(priv->menuproxy, "LayoutUpdate", G_TYPE_INVALID);
61+ dbus_g_proxy_add_signal(priv->menuproxy, "LayoutUpdate", G_TYPE_INT, G_TYPE_INVALID);
62 dbus_g_proxy_connect_signal(priv->menuproxy, "LayoutUpdate", G_CALLBACK(layout_update), client, NULL);
63
64 dbus_g_object_register_marshaller(_dbusmenu_server_marshal_VOID__UINT_STRING_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
65@@ -482,6 +492,34 @@
66 return;
67 }
68
69+/* Get the "revision" attribute of the node, parse it and
70+ return it. Also we're checking to ensure the node
71+ is a 'menu' here. */
72+static gint
73+parse_node_get_revision (xmlNodePtr node)
74+{
75+ if (g_strcmp0((gchar *)node->name, "menu") != 0) {
76+ /* This kills some nodes early */
77+ g_warning("XML Node is not 'menu' it is '%s'", node->name);
78+ return 0;
79+ }
80+
81+ xmlAttrPtr attrib;
82+ for (attrib = node->properties; attrib != NULL; attrib = attrib->next) {
83+ if (g_strcmp0((gchar *)attrib->name, "revision") == 0) {
84+ if (attrib->children != NULL) {
85+ guint revision = (guint)g_ascii_strtoull((gchar *)attrib->children->content, NULL, 10);
86+ /* g_debug ("Found ID: %d", id); */
87+ return revision;
88+ }
89+ break;
90+ }
91+ }
92+
93+ g_warning("Unable to find a revision on the node");
94+ return 0;
95+}
96+
97 /* Get the ID attribute of the node, parse it and
98 return it. Also we're checking to ensure the node
99 is a 'menu' here. */
100@@ -671,7 +709,7 @@
101
102 /* Take the layout passed to us over DBus and turn it into
103 a set of beautiful objects */
104-static void
105+static gint
106 parse_layout (DbusmenuClient * client, const gchar * layout)
107 {
108 DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
109@@ -681,6 +719,7 @@
110 xmldoc = xmlReadMemory(layout, g_utf8_strlen(layout, 16*1024), "dbusmenu.xml", NULL, 0);
111
112 xmlNodePtr root = xmlDocGetRootElement(xmldoc);
113+ gint revision = parse_node_get_revision(root);
114
115 DbusmenuMenuitem * oldroot = priv->root;
116 priv->root = parse_layout_xml(client, root, priv->root, NULL, priv->menuproxy);
117@@ -694,7 +733,7 @@
118 g_signal_emit(G_OBJECT(client), signals[ROOT_CHANGED], 0, priv->root, TRUE);
119 }
120
121- return;
122+ return revision;
123 }
124
125 /* When the layout property returns, here's where we take care of that. */
126@@ -716,11 +755,21 @@
127
128 const gchar * xml = g_value_get_string(&value);
129 /* g_debug("Got layout string: %s", xml); */
130- parse_layout(client, xml);
131-
132+ gint rev = parse_layout(client, xml);
133+
134+ if (rev == 0) {
135+ g_warning("Unable to parse layout!");
136+ return;
137+ }
138+
139+ priv->my_revision = rev;
140 /* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */
141 g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE);
142
143+ if (priv->my_revision < priv->current_revision) {
144+ update_layout(client);
145+ }
146+
147 return;
148 }
149
150@@ -803,17 +852,6 @@
151 return NULL;
152 }
153
154-#if 0
155-/* Seems to be a bug in dbus-glib that assert here, I think because
156- multiple people try and grab it. We're going to comment this out
157- for now as everyone should be listening to the root changed signal
158- anyway. */
159- if (priv->layoutcall != NULL) {
160- /* Will end the current call and block on it's completion */
161- update_layout_cb(priv->propproxy, priv->layoutcall, client);
162- }
163-#endif
164-
165 return priv->root;
166 }
167
168
169=== modified file 'libdbusmenu-glib/dbus-menu.xml'
170--- libdbusmenu-glib/dbus-menu.xml 2009-05-15 20:03:35 +0000
171+++ libdbusmenu-glib/dbus-menu.xml 2009-09-24 18:45:21 +0000
172@@ -57,6 +57,7 @@
173 <arg type="u" name="id" direction="out" />
174 </signal>
175 <signal name="LayoutUpdate">
176+ <arg type="i" name="revision" direction="out" />
177 </signal>
178
179 <!-- End of interesting stuff -->
180
181=== modified file 'libdbusmenu-glib/menuitem.c'
182--- libdbusmenu-glib/menuitem.c 2009-08-25 16:16:26 +0000
183+++ libdbusmenu-glib/menuitem.c 2009-09-24 18:45:21 +0000
184@@ -806,6 +806,7 @@
185 dbusmenu_menuitem_buildxml:
186 @mi: #DbusmenuMenuitem to represent in XML
187 @array: A list of string that will be turned into an XML file
188+ @revision: The revision of the layout to embed in the XML
189
190 This function will add strings to the array @array. It will put
191 at least one entry if this menu item has no children. If it has
192@@ -814,17 +815,18 @@
193 children to place their own tags in the array in between those two.
194 */
195 void
196-dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array)
197+dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array, gint revision)
198 {
199 g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
200
201 GList * children = dbusmenu_menuitem_get_children(mi);
202+ /* TODO: Only put revision info in the root node. Save some bandwidth. */
203 if (children == NULL) {
204- g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\" />", dbusmenu_menuitem_get_id(mi)));
205+ g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\" revision=\"%d\" />", dbusmenu_menuitem_get_id(mi), revision));
206 } else {
207- g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\">", dbusmenu_menuitem_get_id(mi)));
208+ g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\" revision=\"%d\">", dbusmenu_menuitem_get_id(mi), revision));
209 for ( ; children != NULL; children = children->next) {
210- dbusmenu_menuitem_buildxml(DBUSMENU_MENUITEM(children->data), array);
211+ dbusmenu_menuitem_buildxml(DBUSMENU_MENUITEM(children->data), array, revision);
212 }
213 g_ptr_array_add(array, g_strdup("</menu>"));
214 }
215
216=== modified file 'libdbusmenu-glib/menuitem.h'
217--- libdbusmenu-glib/menuitem.h 2009-09-02 14:48:52 +0000
218+++ libdbusmenu-glib/menuitem.h 2009-09-24 18:45:21 +0000
219@@ -136,7 +136,7 @@
220 void dbusmenu_menuitem_set_root (DbusmenuMenuitem * mi, gboolean root);
221 gboolean dbusmenu_menuitem_get_root (DbusmenuMenuitem * mi);
222
223-void dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array);
224+void dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array, gint revision);
225 void dbusmenu_menuitem_foreach (DbusmenuMenuitem * mi, void (*func) (DbusmenuMenuitem * mi, gpointer data), gpointer data);
226 void dbusmenu_menuitem_activate (DbusmenuMenuitem * mi);
227
228
229=== modified file 'libdbusmenu-glib/server.c'
230--- libdbusmenu-glib/server.c 2009-07-01 05:36:24 +0000
231+++ libdbusmenu-glib/server.c 2009-09-24 18:45:21 +0000
232@@ -47,6 +47,7 @@
233 {
234 DbusmenuMenuitem * root;
235 gchar * dbusobject;
236+ gint layout_revision;
237 };
238
239 #define DBUSMENU_SERVER_GET_PRIVATE(o) \
240@@ -142,6 +143,8 @@
241 /**
242 DbusmenuServer::layout-update:
243 @arg0: The #DbusmenuServer emitting the signal.
244+ @arg1: A revision number representing which revision the update
245+ represents itself as.
246
247 This signal is emitted any time the layout of the
248 menuitems under this server is changed.
249@@ -151,8 +154,8 @@
250 G_SIGNAL_RUN_LAST,
251 G_STRUCT_OFFSET(DbusmenuServerClass, layout_update),
252 NULL, NULL,
253- g_cclosure_marshal_VOID__VOID,
254- G_TYPE_NONE, 0);
255+ g_cclosure_marshal_VOID__INT,
256+ G_TYPE_NONE, 1, G_TYPE_INT);
257
258
259 g_object_class_install_property (object_class, PROP_DBUS_OBJECT,
260@@ -183,6 +186,7 @@
261
262 priv->root = NULL;
263 priv->dbusobject = NULL;
264+ priv->layout_revision = 1;
265
266 return;
267 }
268@@ -235,7 +239,8 @@
269 } else {
270 g_debug("Setting root node to NULL");
271 }
272- g_signal_emit(obj, signals[LAYOUT_UPDATE], 0, TRUE);
273+ priv->layout_revision++;
274+ g_signal_emit(obj, signals[LAYOUT_UPDATE], 0, priv->layout_revision, TRUE);
275 break;
276 case PROP_LAYOUT:
277 /* Can't set this, fall through to error */
278@@ -275,9 +280,9 @@
279 GPtrArray * xmlarray = g_ptr_array_new();
280 if (priv->root == NULL) {
281 /* g_debug("Getting layout without root node!"); */
282- g_ptr_array_add(xmlarray, g_strdup("<menu />"));
283+ g_ptr_array_add(xmlarray, g_strdup_printf("<menu revision=\"%d\" />", priv->layout_revision));
284 } else {
285- dbusmenu_menuitem_buildxml(priv->root, xmlarray);
286+ dbusmenu_menuitem_buildxml(priv->root, xmlarray, priv->layout_revision);
287 }
288 g_ptr_array_add(xmlarray, NULL);
289
290@@ -310,7 +315,9 @@
291 {
292 menuitem_signals_create(child, server);
293 /* TODO: We probably need to group the layout update signals to make the number more reasonble. */
294- g_signal_emit(G_OBJECT(server), signals[LAYOUT_UPDATE], 0, TRUE);
295+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
296+ priv->layout_revision++;
297+ g_signal_emit(G_OBJECT(server), signals[LAYOUT_UPDATE], 0, priv->layout_revision, TRUE);
298 return;
299 }
300
301@@ -319,7 +326,18 @@
302 {
303 menuitem_signals_remove(child, server);
304 /* TODO: We probably need to group the layout update signals to make the number more reasonble. */
305- g_signal_emit(G_OBJECT(server), signals[LAYOUT_UPDATE], 0, TRUE);
306+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
307+ priv->layout_revision++;
308+ g_signal_emit(G_OBJECT(server), signals[LAYOUT_UPDATE], 0, priv->layout_revision, TRUE);
309+ return;
310+}
311+
312+static void
313+menuitem_child_moved (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint newpos, guint oldpos, DbusmenuServer * server)
314+{
315+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
316+ priv->layout_revision++;
317+ g_signal_emit(G_OBJECT(server), signals[LAYOUT_UPDATE], 0, priv->layout_revision, TRUE);
318 return;
319 }
320
321@@ -330,6 +348,7 @@
322 {
323 g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(menuitem_child_added), data);
324 g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(menuitem_child_removed), data);
325+ g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(menuitem_child_moved), data);
326 g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menuitem_property_changed), data);
327 return;
328 }
329@@ -341,6 +360,7 @@
330 {
331 g_signal_handlers_disconnect_by_func(G_OBJECT(mi), G_CALLBACK(menuitem_child_added), data);
332 g_signal_handlers_disconnect_by_func(G_OBJECT(mi), G_CALLBACK(menuitem_child_removed), data);
333+ g_signal_handlers_disconnect_by_func(G_OBJECT(mi), G_CALLBACK(menuitem_child_moved), data);
334 g_signal_handlers_disconnect_by_func(G_OBJECT(mi), G_CALLBACK(menuitem_property_changed), data);
335 return;
336 }
337
338=== modified file 'libdbusmenu-glib/server.h'
339--- libdbusmenu-glib/server.h 2009-05-12 15:31:59 +0000
340+++ libdbusmenu-glib/server.h 2009-09-24 18:45:21 +0000
341@@ -71,7 +71,7 @@
342 /* Signals */
343 void (*id_prop_update)(guint id, gchar * property, gchar * value);
344 void (*id_update)(guint id);
345- void (*layout_update)(void);
346+ void (*layout_update)(gint revision);
347
348 /* Reserved */
349 void (*dbusmenu_server_reserved1)(void);

Subscribers

People subscribed via source and target branches