Merge lp:~ted/appmenu-gtk/dbusmenu-parser into lp:appmenu-gtk/0.4
- dbusmenu-parser
- Merge into trunk
Proposed by
Ted Gould
Status: | Merged |
---|---|
Merged at revision: | 108 |
Proposed branch: | lp:~ted/appmenu-gtk/dbusmenu-parser |
Merge into: | lp:appmenu-gtk/0.4 |
Prerequisite: | lp:~mterry/appmenu-gtk/misc-fixes |
Diff against target: |
732 lines (+44/-612) 1 file modified
src/bridge.c (+44/-612) |
To merge this branch: | bzr merge lp:~ted/appmenu-gtk/dbusmenu-parser |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mikkel Kamstrup Erlandsen (community) | Approve | ||
Review via email: mp+47623@code.launchpad.net |
Commit message
Description of the change
Switch to using the dbusmenu parser for parsing menu items.
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 'src/bridge.c' |
2 | --- src/bridge.c 2011-01-27 02:01:27 +0000 |
3 | +++ src/bridge.c 2011-01-27 02:01:27 +0000 |
4 | @@ -28,6 +28,7 @@ |
5 | #include <gio/gio.h> |
6 | |
7 | #include <libdbusmenu-gtk/menuitem.h> |
8 | +#include <libdbusmenu-gtk/parser.h> |
9 | #include <libdbusmenu-glib/menuitem.h> |
10 | #include <libdbusmenu-glib/server.h> |
11 | |
12 | @@ -65,7 +66,6 @@ |
13 | { |
14 | GtkWidget *window; |
15 | DbusmenuServer *server; |
16 | - DbusmenuMenuitem *root; |
17 | gchar *path; |
18 | gboolean registered; |
19 | AppMenuBridge *bridge; |
20 | @@ -171,12 +171,6 @@ |
21 | context->path = NULL; |
22 | } |
23 | |
24 | - if (context->root != NULL) |
25 | - { |
26 | - g_object_unref (context->root); |
27 | - context->root = NULL; |
28 | - } |
29 | - |
30 | if (context->server != NULL) |
31 | { |
32 | g_object_unref (context->server); |
33 | @@ -335,7 +329,7 @@ |
34 | } |
35 | } |
36 | |
37 | - if (!context->registered && context->server != NULL && context->root != NULL && GTK_IS_WINDOW (widget) && bridge->priv->appmenuproxy != NULL) |
38 | + if (!context->registered && context->server != NULL && GTK_IS_WINDOW (widget) && bridge->priv->appmenuproxy != NULL) |
39 | { |
40 | g_dbus_proxy_call(bridge->priv->appmenuproxy, |
41 | "RegisterWindow", |
42 | @@ -443,584 +437,6 @@ |
43 | return; |
44 | } |
45 | |
46 | - |
47 | -static GtkWidget * |
48 | -find_menu_label (GtkWidget *widget) |
49 | -{ |
50 | - GtkWidget *label = NULL; |
51 | - |
52 | - if (GTK_IS_LABEL (widget)) |
53 | - return widget; |
54 | - |
55 | - if (GTK_IS_CONTAINER (widget)) |
56 | - { |
57 | - GList *children; |
58 | - GList *l; |
59 | - |
60 | - children = gtk_container_get_children (GTK_CONTAINER (widget)); |
61 | - |
62 | - for (l = children; l; l = l->next) |
63 | - { |
64 | - label = find_menu_label (l->data); |
65 | - |
66 | - if (label) |
67 | - break; |
68 | - } |
69 | - |
70 | - g_list_free (children); |
71 | - } |
72 | - |
73 | - return label; |
74 | -} |
75 | - |
76 | -static void |
77 | -item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data) |
78 | -{ |
79 | - GtkWidget *child; |
80 | - |
81 | - if (user_data != NULL) |
82 | - { |
83 | - child = (GtkWidget *)user_data; |
84 | - |
85 | - if (GTK_IS_MENU_ITEM (child)) |
86 | - { |
87 | - gtk_menu_item_activate (GTK_MENU_ITEM (child)); |
88 | - } |
89 | - } |
90 | -} |
91 | - |
92 | -static gboolean |
93 | -item_about_to_show (DbusmenuMenuitem *item, gpointer user_data) |
94 | -{ |
95 | - GtkWidget *child; |
96 | - |
97 | - if (user_data != NULL) |
98 | - { |
99 | - child = (GtkWidget *)user_data; |
100 | - |
101 | - if (GTK_IS_MENU_ITEM (child)) |
102 | - { |
103 | - // Only called for items with submens. So we activate it here in |
104 | - // case the program dynamically creates menus (like empathy does) |
105 | - gtk_menu_item_activate (GTK_MENU_ITEM (child)); |
106 | - } |
107 | - } |
108 | - |
109 | - return TRUE; |
110 | -} |
111 | - |
112 | -static gboolean |
113 | -should_show_image (GtkImage *image) |
114 | -{ |
115 | - GtkWidget *item; |
116 | - |
117 | - item = gtk_widget_get_ancestor (GTK_WIDGET (image), |
118 | - GTK_TYPE_IMAGE_MENU_ITEM); |
119 | - |
120 | - if (item) |
121 | - { |
122 | - GtkSettings *settings; |
123 | - gboolean gtk_menu_images; |
124 | - |
125 | - settings = gtk_widget_get_settings (item); |
126 | - |
127 | - g_object_get (settings, "gtk-menu-images", >k_menu_images, NULL); |
128 | - |
129 | - if (gtk_menu_images) |
130 | - return TRUE; |
131 | - |
132 | - return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item)); |
133 | - } |
134 | - |
135 | - return FALSE; |
136 | -} |
137 | - |
138 | -static gboolean |
139 | -update_stock_item (DbusmenuMenuitem *menuitem, |
140 | - GtkWidget *widget) |
141 | -{ |
142 | - GtkStockItem stock; |
143 | - GtkImage *image; |
144 | - |
145 | - g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE); |
146 | - |
147 | - image = GTK_IMAGE (widget); |
148 | - |
149 | - if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK) |
150 | - return FALSE; |
151 | - |
152 | - gtk_stock_lookup (image->data.stock.stock_id, &stock); |
153 | - |
154 | - if (should_show_image (image)) |
155 | - dbusmenu_menuitem_property_set (menuitem, |
156 | - DBUSMENU_MENUITEM_PROP_ICON_NAME, |
157 | - image->data.stock.stock_id); |
158 | - else |
159 | - dbusmenu_menuitem_property_remove (menuitem, |
160 | - DBUSMENU_MENUITEM_PROP_ICON_NAME); |
161 | - |
162 | - const gchar *label = dbusmenu_menuitem_property_get (menuitem, |
163 | - DBUSMENU_MENUITEM_PROP_LABEL); |
164 | - |
165 | - if (stock.label != NULL && label != NULL) |
166 | - { |
167 | - dbusmenu_menuitem_property_set (menuitem, |
168 | - DBUSMENU_MENUITEM_PROP_LABEL, |
169 | - stock.label); |
170 | - |
171 | - return TRUE; |
172 | - } |
173 | - |
174 | - return FALSE; |
175 | -} |
176 | - |
177 | -static void |
178 | -update_icon_name (DbusmenuMenuitem *menuitem, |
179 | - GtkWidget *widget) |
180 | -{ |
181 | - GtkImage *image; |
182 | - |
183 | - g_return_if_fail (GTK_IS_IMAGE (widget)); |
184 | - |
185 | - image = GTK_IMAGE (widget); |
186 | - |
187 | - if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME) |
188 | - return; |
189 | - |
190 | - if (should_show_image (image)) |
191 | - dbusmenu_menuitem_property_set (menuitem, |
192 | - DBUSMENU_MENUITEM_PROP_ICON_NAME, |
193 | - image->data.name.icon_name); |
194 | - else |
195 | - dbusmenu_menuitem_property_remove (menuitem, |
196 | - DBUSMENU_MENUITEM_PROP_ICON_NAME); |
197 | -} |
198 | - |
199 | -static void |
200 | -widget_notify_cb (GtkWidget *widget, |
201 | - GParamSpec *pspec, |
202 | - gpointer data) |
203 | -{ |
204 | - DbusmenuMenuitem *child = (DbusmenuMenuitem *)data; |
205 | - |
206 | - if (pspec->name == g_intern_static_string ("sensitive")) |
207 | - { |
208 | - dbusmenu_menuitem_property_set_bool (child, |
209 | - DBUSMENU_MENUITEM_PROP_ENABLED, |
210 | - gtk_widget_get_sensitive (widget)); |
211 | - } |
212 | - else if (pspec->name == g_intern_static_string ("label")) |
213 | - { |
214 | - dbusmenu_menuitem_property_set (child, |
215 | - DBUSMENU_MENUITEM_PROP_LABEL, |
216 | - gtk_menu_item_get_label (GTK_MENU_ITEM (widget))); |
217 | - } |
218 | - else if (pspec->name == g_intern_static_string ("visible")) |
219 | - { |
220 | - dbusmenu_menuitem_property_set_bool (child, |
221 | - DBUSMENU_MENUITEM_PROP_VISIBLE, |
222 | - gtk_widget_get_visible (widget)); |
223 | - } |
224 | - else if (pspec->name == g_intern_static_string ("stock")) |
225 | - { |
226 | - update_stock_item (child, widget); |
227 | - } |
228 | - else if (pspec->name == g_intern_static_string ("icon-name")) |
229 | - { |
230 | - update_icon_name (child, widget); |
231 | - } |
232 | - else if (pspec->name == g_intern_static_string ("parent")) |
233 | - { |
234 | - /* |
235 | - * We probably should have added a 'remove' method to the |
236 | - * UbuntuMenuProxy early on, but it's late in the cycle now. |
237 | - */ |
238 | - if (gtk_widget_get_parent (widget) == NULL) |
239 | - { |
240 | - g_signal_handlers_disconnect_by_func (widget, |
241 | - G_CALLBACK (widget_notify_cb), |
242 | - child); |
243 | - |
244 | - DbusmenuMenuitem *parent = g_object_get_data (G_OBJECT (child), "dbusmenu-parent"); |
245 | - |
246 | - if (DBUSMENU_IS_MENUITEM (parent) && DBUSMENU_IS_MENUITEM (child)) |
247 | - { |
248 | - dbusmenu_menuitem_child_delete (parent, child); |
249 | - } |
250 | - } |
251 | - } |
252 | -} |
253 | - |
254 | -static void |
255 | -label_notify_cb (GtkWidget *widget, |
256 | - GParamSpec *pspec, |
257 | - gpointer data) |
258 | -{ |
259 | - DbusmenuMenuitem *child = (DbusmenuMenuitem *)data; |
260 | - |
261 | - if (pspec->name == g_intern_static_string ("label")) |
262 | - { |
263 | - dbusmenu_menuitem_property_set (child, |
264 | - DBUSMENU_MENUITEM_PROP_LABEL, |
265 | - gtk_label_get_text (GTK_LABEL (widget))); |
266 | - } |
267 | -} |
268 | - |
269 | -static void |
270 | -menuitem_notify_cb (GtkWidget *widget, |
271 | - GParamSpec *pspec, |
272 | - gpointer data) |
273 | -{ |
274 | - if (pspec->name == g_intern_static_string ("visible")) |
275 | - { |
276 | - AppWindowContext *context = (AppWindowContext *)data; |
277 | - GtkWidget *toplevel = gtk_widget_get_toplevel (widget); |
278 | - GtkWidget *window = NULL; |
279 | - |
280 | - if (context != NULL) |
281 | - window = context->window; |
282 | - |
283 | - if (toplevel == window) |
284 | - { |
285 | - rebuild (context->bridge, window); |
286 | - } |
287 | - |
288 | - /* We only care about this once, so let's disconnect now. */ |
289 | - g_signal_handlers_disconnect_by_func (widget, |
290 | - G_CALLBACK (menuitem_notify_cb), |
291 | - data); |
292 | - } |
293 | -} |
294 | - |
295 | -static void |
296 | -checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi) |
297 | -{ |
298 | - dbusmenu_menuitem_property_set_int (mi, |
299 | - DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, |
300 | - gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); |
301 | -} |
302 | - |
303 | -static void |
304 | -accel_changed (GtkWidget *widget, |
305 | - gpointer data) |
306 | -{ |
307 | - DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data; |
308 | - dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget)); |
309 | -} |
310 | - |
311 | -static void |
312 | -action_notify_cb (GtkAction *action, |
313 | - GParamSpec *pspec, |
314 | - gpointer data) |
315 | -{ |
316 | - DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data; |
317 | - |
318 | - if (pspec->name == g_intern_static_string ("sensitive")) |
319 | - { |
320 | - dbusmenu_menuitem_property_set_bool (mi, |
321 | - DBUSMENU_MENUITEM_PROP_ENABLED, |
322 | - gtk_action_is_sensitive (action)); |
323 | - } |
324 | - else if (pspec->name == g_intern_static_string ("visible")) |
325 | - { |
326 | - dbusmenu_menuitem_property_set_bool (mi, |
327 | - DBUSMENU_MENUITEM_PROP_VISIBLE, |
328 | - gtk_action_is_visible (action)); |
329 | - } |
330 | - else if (pspec->name == g_intern_static_string ("active")) |
331 | - { |
332 | - dbusmenu_menuitem_property_set_bool (mi, |
333 | - DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, |
334 | - gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); |
335 | - } |
336 | - else if (pspec->name == g_intern_static_string ("label")) |
337 | - { |
338 | - dbusmenu_menuitem_property_set (mi, |
339 | - DBUSMENU_MENUITEM_PROP_LABEL, |
340 | - gtk_action_get_label (action)); |
341 | - } |
342 | -} |
343 | - |
344 | -static DbusmenuMenuitem * |
345 | -construct_dbusmenu_for_widget (GtkWidget *widget) |
346 | -{ |
347 | - DbusmenuMenuitem *mi = dbusmenu_menuitem_new (); |
348 | - |
349 | - if (GTK_IS_MENU_ITEM (widget)) |
350 | - { |
351 | - gboolean visible = FALSE; |
352 | - gboolean sensitive = FALSE; |
353 | - if (GTK_IS_SEPARATOR_MENU_ITEM (widget)) |
354 | - { |
355 | - dbusmenu_menuitem_property_set (mi, |
356 | - "type", |
357 | - "separator"); |
358 | - |
359 | - visible = gtk_widget_get_visible (widget); |
360 | - sensitive = gtk_widget_get_sensitive (widget); |
361 | - } |
362 | - else |
363 | - { |
364 | - gboolean label_set = FALSE; |
365 | - |
366 | - g_signal_connect (widget, |
367 | - "accel-closures-changed", |
368 | - G_CALLBACK (accel_changed), |
369 | - mi); |
370 | - |
371 | - if (GTK_IS_CHECK_MENU_ITEM (widget)) |
372 | - { |
373 | - dbusmenu_menuitem_property_set (mi, |
374 | - DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, |
375 | - gtk_check_menu_item_get_draw_as_radio (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK); |
376 | - |
377 | - dbusmenu_menuitem_property_set_int (mi, |
378 | - DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, |
379 | - gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); |
380 | - |
381 | - g_signal_connect (widget, |
382 | - "activate", |
383 | - G_CALLBACK (checkbox_toggled), |
384 | - mi); |
385 | - } |
386 | - |
387 | - if (GTK_IS_IMAGE_MENU_ITEM (widget)) |
388 | - { |
389 | - GtkWidget *image; |
390 | - GtkImageType image_type; |
391 | - |
392 | - image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget)); |
393 | - |
394 | - if (GTK_IS_IMAGE (image)) |
395 | - { |
396 | - image_type = gtk_image_get_storage_type (GTK_IMAGE (image)); |
397 | - |
398 | - if (image_type == GTK_IMAGE_STOCK) |
399 | - { |
400 | - label_set = update_stock_item (mi, image); |
401 | - } |
402 | - else if (image_type == GTK_IMAGE_ICON_NAME) |
403 | - { |
404 | - update_icon_name (mi, image); |
405 | - } |
406 | - else if (image_type == GTK_IMAGE_PIXBUF) |
407 | - { |
408 | - dbusmenu_menuitem_property_set_image (mi, |
409 | - DBUSMENU_MENUITEM_PROP_ICON_DATA, |
410 | - gtk_image_get_pixbuf (GTK_IMAGE (image))); |
411 | - } |
412 | - } |
413 | - } |
414 | - |
415 | - GtkWidget *label = find_menu_label (widget); |
416 | - |
417 | - dbusmenu_menuitem_property_set (mi, |
418 | - "label", |
419 | - label ? gtk_label_get_text (GTK_LABEL (label)) : NULL); |
420 | - |
421 | - if (label) |
422 | - { |
423 | - // Sometimes, an app will directly find and modify the label |
424 | - // (like empathy), so watch the label especially for that. |
425 | - g_signal_connect (G_OBJECT (label), |
426 | - "notify", |
427 | - G_CALLBACK (label_notify_cb), |
428 | - mi); |
429 | - } |
430 | - |
431 | - if (GTK_IS_ACTIVATABLE (widget)) |
432 | - { |
433 | - GtkActivatable *activatable = GTK_ACTIVATABLE (widget); |
434 | - |
435 | - if (gtk_activatable_get_use_action_appearance (activatable)) |
436 | - { |
437 | - GtkAction *action = gtk_activatable_get_related_action (activatable); |
438 | - |
439 | - if (action) |
440 | - { |
441 | - visible = gtk_action_is_visible (action); |
442 | - sensitive = gtk_action_is_sensitive (action); |
443 | - |
444 | - g_signal_connect_object (action, "notify", |
445 | - G_CALLBACK (action_notify_cb), |
446 | - mi, |
447 | - G_CONNECT_AFTER); |
448 | - } |
449 | - } |
450 | - } |
451 | - |
452 | - if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget)) |
453 | - { |
454 | - visible = gtk_widget_get_visible (widget); |
455 | - sensitive = gtk_widget_get_sensitive (widget); |
456 | - } |
457 | - |
458 | - dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget)); |
459 | - |
460 | - g_signal_connect (G_OBJECT (mi), |
461 | - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, |
462 | - G_CALLBACK (item_activated), |
463 | - widget); |
464 | - |
465 | - g_signal_connect (G_OBJECT (mi), |
466 | - DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, |
467 | - G_CALLBACK (item_about_to_show), |
468 | - widget); |
469 | - } |
470 | - |
471 | - dbusmenu_menuitem_property_set_bool (mi, |
472 | - DBUSMENU_MENUITEM_PROP_VISIBLE, |
473 | - visible); |
474 | - |
475 | - dbusmenu_menuitem_property_set_bool (mi, |
476 | - DBUSMENU_MENUITEM_PROP_ENABLED, |
477 | - sensitive); |
478 | - |
479 | - g_signal_connect (widget, |
480 | - "notify", |
481 | - G_CALLBACK (widget_notify_cb), |
482 | - mi); |
483 | - } |
484 | - |
485 | - return mi; |
486 | -} |
487 | - |
488 | -static void |
489 | -rebuild_item (GtkWidget *widget, |
490 | - RecurseContext *recurse) |
491 | -{ |
492 | - if (GTK_IS_CONTAINER (widget)) |
493 | - { |
494 | - gboolean increment = GTK_IS_MENU_BAR (widget) || GTK_IS_MENU_ITEM (widget); |
495 | - |
496 | - if (increment) |
497 | - recurse->count++; |
498 | - |
499 | - /* Okay, this is a little janky and all.. but some applications update some |
500 | - * menuitem properties such as sensitivity on the activate callback. This |
501 | - * seems a little weird, but it's not our place to judge when all this code |
502 | - * is so crazy. So we're going to get ever crazier and activate all the |
503 | - * menus that are directly below the menubar and force the applications to |
504 | - * update their sensitivity. The menus won't actually popup in the app |
505 | - * window due to our gtk+ patches. |
506 | - * |
507 | - * Note that this will not force menuitems in submenus to be updated as well. |
508 | - */ |
509 | - if (recurse->count == 0 && GTK_IS_MENU_BAR (widget)) |
510 | - { |
511 | - GList *children = gtk_container_get_children (GTK_CONTAINER (widget)); |
512 | - |
513 | - for (; children != NULL; children = children->next) |
514 | - { |
515 | - gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget), |
516 | - children->data, |
517 | - TRUE); |
518 | - } |
519 | - |
520 | - g_list_free (children); |
521 | - } |
522 | - |
523 | - if (recurse->count > -1 && increment) |
524 | - { |
525 | - DbusmenuMenuitem *dmi = g_hash_table_lookup (recurse->context->lookup, widget); |
526 | - if (dmi != NULL) |
527 | - { |
528 | - if (increment) |
529 | - recurse->count--; |
530 | - |
531 | - return; |
532 | - } |
533 | - else |
534 | - { |
535 | - recurse->stack[recurse->count] = construct_dbusmenu_for_widget (widget); |
536 | - g_hash_table_insert (recurse->context->lookup, widget, recurse->stack[recurse->count]); |
537 | - } |
538 | - |
539 | - if (!gtk_widget_get_visible (widget)) |
540 | - { |
541 | - g_signal_connect (G_OBJECT (widget), |
542 | - "notify", |
543 | - G_CALLBACK (menuitem_notify_cb), |
544 | - recurse->context); |
545 | - } |
546 | - |
547 | - if (GTK_IS_TEAROFF_MENU_ITEM (widget)) |
548 | - { |
549 | - dbusmenu_menuitem_property_set_bool (recurse->stack[recurse->count], |
550 | - DBUSMENU_MENUITEM_PROP_VISIBLE, |
551 | - FALSE); |
552 | - } |
553 | - |
554 | - if (recurse->count > 0) |
555 | - { |
556 | - GList *children = NULL; |
557 | - GList *peek = NULL; |
558 | - |
559 | - if (recurse->stack[recurse->count - 1]) |
560 | - { |
561 | - children = dbusmenu_menuitem_get_children (recurse->stack[recurse->count - 1]); |
562 | - |
563 | - if (children) |
564 | - { |
565 | - peek = g_list_find (children, recurse->stack[recurse->count]); |
566 | - } |
567 | - |
568 | - if (!peek) |
569 | - { |
570 | - /* Should we set a weak ref on the parent? */ |
571 | - g_object_set_data (G_OBJECT (recurse->stack[recurse->count]), |
572 | - "dbusmenu-parent", |
573 | - recurse->stack[recurse->count - 1]); |
574 | - dbusmenu_menuitem_child_append (recurse->stack[recurse->count - 1], |
575 | - recurse->stack[recurse->count]); |
576 | - } |
577 | - } |
578 | - else |
579 | - { |
580 | - DbusmenuMenuitem *item = g_hash_table_lookup (recurse->context->lookup, |
581 | - gtk_widget_get_parent (widget)); |
582 | - |
583 | - if (item) |
584 | - { |
585 | - children = dbusmenu_menuitem_get_children (item); |
586 | - |
587 | - if (children) |
588 | - { |
589 | - peek = g_list_find (children, recurse->stack[recurse->count]); |
590 | - } |
591 | - |
592 | - if (!peek) |
593 | - { |
594 | - g_object_set_data (G_OBJECT (recurse->stack[recurse->count]), |
595 | - "dbusmenu-parent", |
596 | - recurse->stack[recurse->count - 1]); |
597 | - |
598 | - dbusmenu_menuitem_child_append (item, recurse->stack[recurse->count]); |
599 | - } |
600 | - } |
601 | - } |
602 | - } |
603 | - } |
604 | - |
605 | - gtk_container_foreach (GTK_CONTAINER (widget), |
606 | - (GtkCallback)rebuild_item, |
607 | - recurse); |
608 | - |
609 | - if (GTK_IS_MENU_ITEM (widget)) |
610 | - { |
611 | - GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)); |
612 | - |
613 | - if (menu != NULL) |
614 | - { |
615 | - rebuild_item (menu, recurse); |
616 | - } |
617 | - } |
618 | - |
619 | - if (increment) |
620 | - recurse->count--; |
621 | - } |
622 | -} |
623 | - |
624 | typedef struct _RebuildData { |
625 | AppMenuBridge *bridge; |
626 | GtkWidget *widget; |
627 | @@ -1076,15 +492,48 @@ |
628 | g_hash_table_insert (rebuild_ids, toplevel, GUINT_TO_POINTER (id)); |
629 | } |
630 | |
631 | +static DbusmenuMenuitem * find_menu_bar (GtkWidget * widget); |
632 | + |
633 | +static void |
634 | +find_menu_bar_helper (GtkWidget * widget, gpointer data) |
635 | +{ |
636 | + DbusmenuMenuitem ** mi = (DbusmenuMenuitem **)data; |
637 | + |
638 | + /* We've already found a menu, let's get through the |
639 | + foreach as quickly as possible */ |
640 | + if (*mi != NULL) { |
641 | + return; |
642 | + } |
643 | + |
644 | + *mi = find_menu_bar(widget); |
645 | + return; |
646 | +} |
647 | + |
648 | +static DbusmenuMenuitem * |
649 | +find_menu_bar (GtkWidget * widget) |
650 | +{ |
651 | + if (GTK_IS_MENU_BAR(widget) || GTK_IS_MENU_ITEM(widget)) { |
652 | + return dbusmenu_gtk_parse_menu_structure(widget); |
653 | + } |
654 | + |
655 | + if (GTK_IS_CONTAINER(widget)) { |
656 | + DbusmenuMenuitem * mi = NULL; |
657 | + |
658 | + gtk_container_foreach(GTK_CONTAINER(widget), find_menu_bar_helper, &mi); |
659 | + |
660 | + return mi; |
661 | + } |
662 | + |
663 | + return NULL; |
664 | +} |
665 | + |
666 | + |
667 | static void |
668 | rebuild_window_items (AppMenuBridge *bridge, |
669 | GtkWidget *toplevel) |
670 | { |
671 | XID xid; |
672 | AppWindowContext *context = NULL; |
673 | - RecurseContext recurse; |
674 | - |
675 | - memset (&recurse, 0, sizeof (RecurseContext)); |
676 | |
677 | if (!GTK_IS_WINDOW (toplevel)) |
678 | { |
679 | @@ -1147,14 +596,6 @@ |
680 | context->bridge = bridge; |
681 | context->lookup = g_hash_table_new (g_direct_hash, g_direct_equal); |
682 | bridge->priv->windows = g_list_prepend (bridge->priv->windows, context); |
683 | - |
684 | - recurse.previous = FALSE; |
685 | - recurse.count = -1; |
686 | - } |
687 | - else |
688 | - { |
689 | - recurse.previous = TRUE; |
690 | - recurse.count = 0; |
691 | } |
692 | |
693 | if (context->window) |
694 | @@ -1183,24 +624,15 @@ |
695 | if (!context->server) |
696 | context->server = dbusmenu_server_new (context->path); |
697 | |
698 | - recurse.bridge = bridge; |
699 | - recurse.context = context; |
700 | - |
701 | - gtk_container_foreach (GTK_CONTAINER (toplevel), |
702 | - (GtkCallback)rebuild_item, |
703 | - &recurse); |
704 | - |
705 | - if (recurse.stack[0] != NULL && DBUSMENU_IS_MENUITEM (recurse.stack[0])) |
706 | - { |
707 | - context->root = recurse.stack[0]; |
708 | - |
709 | - dbusmenu_server_set_root (context->server, context->root); |
710 | - } |
711 | + DbusmenuMenuitem * mi = find_menu_bar(toplevel); |
712 | + dbusmenu_server_set_root(context->server, mi); |
713 | + if (mi != NULL) { |
714 | + g_object_unref(G_OBJECT(mi)); |
715 | + } |
716 | |
717 | register_application_windows (bridge); |
718 | } |
719 | |
720 | - |
721 | static void |
722 | toplevel_realized (GtkWidget *widget, |
723 | gpointer user_data) |
724 | @@ -1316,7 +748,7 @@ |
725 | |
726 | if (mi != NULL) |
727 | { |
728 | - DbusmenuMenuitem *child_dmi = construct_dbusmenu_for_widget (child); |
729 | + DbusmenuMenuitem *child_dmi = dbusmenu_gtk_parse_menu_structure (child); |
730 | |
731 | g_object_set_data (G_OBJECT (child_dmi), "dbusmenu-parent", mi); |
732 | dbusmenu_menuitem_child_add_position (mi, |
review approve
This looks good at least, but I must confess that I didn't test it and
could give some serious breakage if not working properly. So please
triple check the functionality before merging :-)