Merge lp:~ted/libdbusmenu/reordering-all-over-again into lp:libdbusmenu/0.5
- reordering-all-over-again
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cody Russell (community) | Approve | ||
Review via email: mp+12367@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote : | # |
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); |
Adds revision tracking of the layout to help fix some of the reordering bugs.