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:
|
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 | 28 | #include <gio/gio.h> | 28 | #include <gio/gio.h> |
6 | 29 | 29 | ||
7 | 30 | #include <libdbusmenu-gtk/menuitem.h> | 30 | #include <libdbusmenu-gtk/menuitem.h> |
8 | 31 | #include <libdbusmenu-gtk/parser.h> | ||
9 | 31 | #include <libdbusmenu-glib/menuitem.h> | 32 | #include <libdbusmenu-glib/menuitem.h> |
10 | 32 | #include <libdbusmenu-glib/server.h> | 33 | #include <libdbusmenu-glib/server.h> |
11 | 33 | 34 | ||
12 | @@ -65,7 +66,6 @@ | |||
13 | 65 | { | 66 | { |
14 | 66 | GtkWidget *window; | 67 | GtkWidget *window; |
15 | 67 | DbusmenuServer *server; | 68 | DbusmenuServer *server; |
16 | 68 | DbusmenuMenuitem *root; | ||
17 | 69 | gchar *path; | 69 | gchar *path; |
18 | 70 | gboolean registered; | 70 | gboolean registered; |
19 | 71 | AppMenuBridge *bridge; | 71 | AppMenuBridge *bridge; |
20 | @@ -171,12 +171,6 @@ | |||
21 | 171 | context->path = NULL; | 171 | context->path = NULL; |
22 | 172 | } | 172 | } |
23 | 173 | 173 | ||
24 | 174 | if (context->root != NULL) | ||
25 | 175 | { | ||
26 | 176 | g_object_unref (context->root); | ||
27 | 177 | context->root = NULL; | ||
28 | 178 | } | ||
29 | 179 | |||
30 | 180 | if (context->server != NULL) | 174 | if (context->server != NULL) |
31 | 181 | { | 175 | { |
32 | 182 | g_object_unref (context->server); | 176 | g_object_unref (context->server); |
33 | @@ -335,7 +329,7 @@ | |||
34 | 335 | } | 329 | } |
35 | 336 | } | 330 | } |
36 | 337 | 331 | ||
38 | 338 | if (!context->registered && context->server != NULL && context->root != NULL && GTK_IS_WINDOW (widget) && bridge->priv->appmenuproxy != NULL) | 332 | if (!context->registered && context->server != NULL && GTK_IS_WINDOW (widget) && bridge->priv->appmenuproxy != NULL) |
39 | 339 | { | 333 | { |
40 | 340 | g_dbus_proxy_call(bridge->priv->appmenuproxy, | 334 | g_dbus_proxy_call(bridge->priv->appmenuproxy, |
41 | 341 | "RegisterWindow", | 335 | "RegisterWindow", |
42 | @@ -443,584 +437,6 @@ | |||
43 | 443 | return; | 437 | return; |
44 | 444 | } | 438 | } |
45 | 445 | 439 | ||
46 | 446 | |||
47 | 447 | static GtkWidget * | ||
48 | 448 | find_menu_label (GtkWidget *widget) | ||
49 | 449 | { | ||
50 | 450 | GtkWidget *label = NULL; | ||
51 | 451 | |||
52 | 452 | if (GTK_IS_LABEL (widget)) | ||
53 | 453 | return widget; | ||
54 | 454 | |||
55 | 455 | if (GTK_IS_CONTAINER (widget)) | ||
56 | 456 | { | ||
57 | 457 | GList *children; | ||
58 | 458 | GList *l; | ||
59 | 459 | |||
60 | 460 | children = gtk_container_get_children (GTK_CONTAINER (widget)); | ||
61 | 461 | |||
62 | 462 | for (l = children; l; l = l->next) | ||
63 | 463 | { | ||
64 | 464 | label = find_menu_label (l->data); | ||
65 | 465 | |||
66 | 466 | if (label) | ||
67 | 467 | break; | ||
68 | 468 | } | ||
69 | 469 | |||
70 | 470 | g_list_free (children); | ||
71 | 471 | } | ||
72 | 472 | |||
73 | 473 | return label; | ||
74 | 474 | } | ||
75 | 475 | |||
76 | 476 | static void | ||
77 | 477 | item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data) | ||
78 | 478 | { | ||
79 | 479 | GtkWidget *child; | ||
80 | 480 | |||
81 | 481 | if (user_data != NULL) | ||
82 | 482 | { | ||
83 | 483 | child = (GtkWidget *)user_data; | ||
84 | 484 | |||
85 | 485 | if (GTK_IS_MENU_ITEM (child)) | ||
86 | 486 | { | ||
87 | 487 | gtk_menu_item_activate (GTK_MENU_ITEM (child)); | ||
88 | 488 | } | ||
89 | 489 | } | ||
90 | 490 | } | ||
91 | 491 | |||
92 | 492 | static gboolean | ||
93 | 493 | item_about_to_show (DbusmenuMenuitem *item, gpointer user_data) | ||
94 | 494 | { | ||
95 | 495 | GtkWidget *child; | ||
96 | 496 | |||
97 | 497 | if (user_data != NULL) | ||
98 | 498 | { | ||
99 | 499 | child = (GtkWidget *)user_data; | ||
100 | 500 | |||
101 | 501 | if (GTK_IS_MENU_ITEM (child)) | ||
102 | 502 | { | ||
103 | 503 | // Only called for items with submens. So we activate it here in | ||
104 | 504 | // case the program dynamically creates menus (like empathy does) | ||
105 | 505 | gtk_menu_item_activate (GTK_MENU_ITEM (child)); | ||
106 | 506 | } | ||
107 | 507 | } | ||
108 | 508 | |||
109 | 509 | return TRUE; | ||
110 | 510 | } | ||
111 | 511 | |||
112 | 512 | static gboolean | ||
113 | 513 | should_show_image (GtkImage *image) | ||
114 | 514 | { | ||
115 | 515 | GtkWidget *item; | ||
116 | 516 | |||
117 | 517 | item = gtk_widget_get_ancestor (GTK_WIDGET (image), | ||
118 | 518 | GTK_TYPE_IMAGE_MENU_ITEM); | ||
119 | 519 | |||
120 | 520 | if (item) | ||
121 | 521 | { | ||
122 | 522 | GtkSettings *settings; | ||
123 | 523 | gboolean gtk_menu_images; | ||
124 | 524 | |||
125 | 525 | settings = gtk_widget_get_settings (item); | ||
126 | 526 | |||
127 | 527 | g_object_get (settings, "gtk-menu-images", >k_menu_images, NULL); | ||
128 | 528 | |||
129 | 529 | if (gtk_menu_images) | ||
130 | 530 | return TRUE; | ||
131 | 531 | |||
132 | 532 | return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item)); | ||
133 | 533 | } | ||
134 | 534 | |||
135 | 535 | return FALSE; | ||
136 | 536 | } | ||
137 | 537 | |||
138 | 538 | static gboolean | ||
139 | 539 | update_stock_item (DbusmenuMenuitem *menuitem, | ||
140 | 540 | GtkWidget *widget) | ||
141 | 541 | { | ||
142 | 542 | GtkStockItem stock; | ||
143 | 543 | GtkImage *image; | ||
144 | 544 | |||
145 | 545 | g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE); | ||
146 | 546 | |||
147 | 547 | image = GTK_IMAGE (widget); | ||
148 | 548 | |||
149 | 549 | if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK) | ||
150 | 550 | return FALSE; | ||
151 | 551 | |||
152 | 552 | gtk_stock_lookup (image->data.stock.stock_id, &stock); | ||
153 | 553 | |||
154 | 554 | if (should_show_image (image)) | ||
155 | 555 | dbusmenu_menuitem_property_set (menuitem, | ||
156 | 556 | DBUSMENU_MENUITEM_PROP_ICON_NAME, | ||
157 | 557 | image->data.stock.stock_id); | ||
158 | 558 | else | ||
159 | 559 | dbusmenu_menuitem_property_remove (menuitem, | ||
160 | 560 | DBUSMENU_MENUITEM_PROP_ICON_NAME); | ||
161 | 561 | |||
162 | 562 | const gchar *label = dbusmenu_menuitem_property_get (menuitem, | ||
163 | 563 | DBUSMENU_MENUITEM_PROP_LABEL); | ||
164 | 564 | |||
165 | 565 | if (stock.label != NULL && label != NULL) | ||
166 | 566 | { | ||
167 | 567 | dbusmenu_menuitem_property_set (menuitem, | ||
168 | 568 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
169 | 569 | stock.label); | ||
170 | 570 | |||
171 | 571 | return TRUE; | ||
172 | 572 | } | ||
173 | 573 | |||
174 | 574 | return FALSE; | ||
175 | 575 | } | ||
176 | 576 | |||
177 | 577 | static void | ||
178 | 578 | update_icon_name (DbusmenuMenuitem *menuitem, | ||
179 | 579 | GtkWidget *widget) | ||
180 | 580 | { | ||
181 | 581 | GtkImage *image; | ||
182 | 582 | |||
183 | 583 | g_return_if_fail (GTK_IS_IMAGE (widget)); | ||
184 | 584 | |||
185 | 585 | image = GTK_IMAGE (widget); | ||
186 | 586 | |||
187 | 587 | if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME) | ||
188 | 588 | return; | ||
189 | 589 | |||
190 | 590 | if (should_show_image (image)) | ||
191 | 591 | dbusmenu_menuitem_property_set (menuitem, | ||
192 | 592 | DBUSMENU_MENUITEM_PROP_ICON_NAME, | ||
193 | 593 | image->data.name.icon_name); | ||
194 | 594 | else | ||
195 | 595 | dbusmenu_menuitem_property_remove (menuitem, | ||
196 | 596 | DBUSMENU_MENUITEM_PROP_ICON_NAME); | ||
197 | 597 | } | ||
198 | 598 | |||
199 | 599 | static void | ||
200 | 600 | widget_notify_cb (GtkWidget *widget, | ||
201 | 601 | GParamSpec *pspec, | ||
202 | 602 | gpointer data) | ||
203 | 603 | { | ||
204 | 604 | DbusmenuMenuitem *child = (DbusmenuMenuitem *)data; | ||
205 | 605 | |||
206 | 606 | if (pspec->name == g_intern_static_string ("sensitive")) | ||
207 | 607 | { | ||
208 | 608 | dbusmenu_menuitem_property_set_bool (child, | ||
209 | 609 | DBUSMENU_MENUITEM_PROP_ENABLED, | ||
210 | 610 | gtk_widget_get_sensitive (widget)); | ||
211 | 611 | } | ||
212 | 612 | else if (pspec->name == g_intern_static_string ("label")) | ||
213 | 613 | { | ||
214 | 614 | dbusmenu_menuitem_property_set (child, | ||
215 | 615 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
216 | 616 | gtk_menu_item_get_label (GTK_MENU_ITEM (widget))); | ||
217 | 617 | } | ||
218 | 618 | else if (pspec->name == g_intern_static_string ("visible")) | ||
219 | 619 | { | ||
220 | 620 | dbusmenu_menuitem_property_set_bool (child, | ||
221 | 621 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
222 | 622 | gtk_widget_get_visible (widget)); | ||
223 | 623 | } | ||
224 | 624 | else if (pspec->name == g_intern_static_string ("stock")) | ||
225 | 625 | { | ||
226 | 626 | update_stock_item (child, widget); | ||
227 | 627 | } | ||
228 | 628 | else if (pspec->name == g_intern_static_string ("icon-name")) | ||
229 | 629 | { | ||
230 | 630 | update_icon_name (child, widget); | ||
231 | 631 | } | ||
232 | 632 | else if (pspec->name == g_intern_static_string ("parent")) | ||
233 | 633 | { | ||
234 | 634 | /* | ||
235 | 635 | * We probably should have added a 'remove' method to the | ||
236 | 636 | * UbuntuMenuProxy early on, but it's late in the cycle now. | ||
237 | 637 | */ | ||
238 | 638 | if (gtk_widget_get_parent (widget) == NULL) | ||
239 | 639 | { | ||
240 | 640 | g_signal_handlers_disconnect_by_func (widget, | ||
241 | 641 | G_CALLBACK (widget_notify_cb), | ||
242 | 642 | child); | ||
243 | 643 | |||
244 | 644 | DbusmenuMenuitem *parent = g_object_get_data (G_OBJECT (child), "dbusmenu-parent"); | ||
245 | 645 | |||
246 | 646 | if (DBUSMENU_IS_MENUITEM (parent) && DBUSMENU_IS_MENUITEM (child)) | ||
247 | 647 | { | ||
248 | 648 | dbusmenu_menuitem_child_delete (parent, child); | ||
249 | 649 | } | ||
250 | 650 | } | ||
251 | 651 | } | ||
252 | 652 | } | ||
253 | 653 | |||
254 | 654 | static void | ||
255 | 655 | label_notify_cb (GtkWidget *widget, | ||
256 | 656 | GParamSpec *pspec, | ||
257 | 657 | gpointer data) | ||
258 | 658 | { | ||
259 | 659 | DbusmenuMenuitem *child = (DbusmenuMenuitem *)data; | ||
260 | 660 | |||
261 | 661 | if (pspec->name == g_intern_static_string ("label")) | ||
262 | 662 | { | ||
263 | 663 | dbusmenu_menuitem_property_set (child, | ||
264 | 664 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
265 | 665 | gtk_label_get_text (GTK_LABEL (widget))); | ||
266 | 666 | } | ||
267 | 667 | } | ||
268 | 668 | |||
269 | 669 | static void | ||
270 | 670 | menuitem_notify_cb (GtkWidget *widget, | ||
271 | 671 | GParamSpec *pspec, | ||
272 | 672 | gpointer data) | ||
273 | 673 | { | ||
274 | 674 | if (pspec->name == g_intern_static_string ("visible")) | ||
275 | 675 | { | ||
276 | 676 | AppWindowContext *context = (AppWindowContext *)data; | ||
277 | 677 | GtkWidget *toplevel = gtk_widget_get_toplevel (widget); | ||
278 | 678 | GtkWidget *window = NULL; | ||
279 | 679 | |||
280 | 680 | if (context != NULL) | ||
281 | 681 | window = context->window; | ||
282 | 682 | |||
283 | 683 | if (toplevel == window) | ||
284 | 684 | { | ||
285 | 685 | rebuild (context->bridge, window); | ||
286 | 686 | } | ||
287 | 687 | |||
288 | 688 | /* We only care about this once, so let's disconnect now. */ | ||
289 | 689 | g_signal_handlers_disconnect_by_func (widget, | ||
290 | 690 | G_CALLBACK (menuitem_notify_cb), | ||
291 | 691 | data); | ||
292 | 692 | } | ||
293 | 693 | } | ||
294 | 694 | |||
295 | 695 | static void | ||
296 | 696 | checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi) | ||
297 | 697 | { | ||
298 | 698 | dbusmenu_menuitem_property_set_int (mi, | ||
299 | 699 | DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, | ||
300 | 700 | gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); | ||
301 | 701 | } | ||
302 | 702 | |||
303 | 703 | static void | ||
304 | 704 | accel_changed (GtkWidget *widget, | ||
305 | 705 | gpointer data) | ||
306 | 706 | { | ||
307 | 707 | DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data; | ||
308 | 708 | dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget)); | ||
309 | 709 | } | ||
310 | 710 | |||
311 | 711 | static void | ||
312 | 712 | action_notify_cb (GtkAction *action, | ||
313 | 713 | GParamSpec *pspec, | ||
314 | 714 | gpointer data) | ||
315 | 715 | { | ||
316 | 716 | DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data; | ||
317 | 717 | |||
318 | 718 | if (pspec->name == g_intern_static_string ("sensitive")) | ||
319 | 719 | { | ||
320 | 720 | dbusmenu_menuitem_property_set_bool (mi, | ||
321 | 721 | DBUSMENU_MENUITEM_PROP_ENABLED, | ||
322 | 722 | gtk_action_is_sensitive (action)); | ||
323 | 723 | } | ||
324 | 724 | else if (pspec->name == g_intern_static_string ("visible")) | ||
325 | 725 | { | ||
326 | 726 | dbusmenu_menuitem_property_set_bool (mi, | ||
327 | 727 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
328 | 728 | gtk_action_is_visible (action)); | ||
329 | 729 | } | ||
330 | 730 | else if (pspec->name == g_intern_static_string ("active")) | ||
331 | 731 | { | ||
332 | 732 | dbusmenu_menuitem_property_set_bool (mi, | ||
333 | 733 | DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, | ||
334 | 734 | gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); | ||
335 | 735 | } | ||
336 | 736 | else if (pspec->name == g_intern_static_string ("label")) | ||
337 | 737 | { | ||
338 | 738 | dbusmenu_menuitem_property_set (mi, | ||
339 | 739 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
340 | 740 | gtk_action_get_label (action)); | ||
341 | 741 | } | ||
342 | 742 | } | ||
343 | 743 | |||
344 | 744 | static DbusmenuMenuitem * | ||
345 | 745 | construct_dbusmenu_for_widget (GtkWidget *widget) | ||
346 | 746 | { | ||
347 | 747 | DbusmenuMenuitem *mi = dbusmenu_menuitem_new (); | ||
348 | 748 | |||
349 | 749 | if (GTK_IS_MENU_ITEM (widget)) | ||
350 | 750 | { | ||
351 | 751 | gboolean visible = FALSE; | ||
352 | 752 | gboolean sensitive = FALSE; | ||
353 | 753 | if (GTK_IS_SEPARATOR_MENU_ITEM (widget)) | ||
354 | 754 | { | ||
355 | 755 | dbusmenu_menuitem_property_set (mi, | ||
356 | 756 | "type", | ||
357 | 757 | "separator"); | ||
358 | 758 | |||
359 | 759 | visible = gtk_widget_get_visible (widget); | ||
360 | 760 | sensitive = gtk_widget_get_sensitive (widget); | ||
361 | 761 | } | ||
362 | 762 | else | ||
363 | 763 | { | ||
364 | 764 | gboolean label_set = FALSE; | ||
365 | 765 | |||
366 | 766 | g_signal_connect (widget, | ||
367 | 767 | "accel-closures-changed", | ||
368 | 768 | G_CALLBACK (accel_changed), | ||
369 | 769 | mi); | ||
370 | 770 | |||
371 | 771 | if (GTK_IS_CHECK_MENU_ITEM (widget)) | ||
372 | 772 | { | ||
373 | 773 | dbusmenu_menuitem_property_set (mi, | ||
374 | 774 | DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, | ||
375 | 775 | gtk_check_menu_item_get_draw_as_radio (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK); | ||
376 | 776 | |||
377 | 777 | dbusmenu_menuitem_property_set_int (mi, | ||
378 | 778 | DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, | ||
379 | 779 | gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); | ||
380 | 780 | |||
381 | 781 | g_signal_connect (widget, | ||
382 | 782 | "activate", | ||
383 | 783 | G_CALLBACK (checkbox_toggled), | ||
384 | 784 | mi); | ||
385 | 785 | } | ||
386 | 786 | |||
387 | 787 | if (GTK_IS_IMAGE_MENU_ITEM (widget)) | ||
388 | 788 | { | ||
389 | 789 | GtkWidget *image; | ||
390 | 790 | GtkImageType image_type; | ||
391 | 791 | |||
392 | 792 | image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget)); | ||
393 | 793 | |||
394 | 794 | if (GTK_IS_IMAGE (image)) | ||
395 | 795 | { | ||
396 | 796 | image_type = gtk_image_get_storage_type (GTK_IMAGE (image)); | ||
397 | 797 | |||
398 | 798 | if (image_type == GTK_IMAGE_STOCK) | ||
399 | 799 | { | ||
400 | 800 | label_set = update_stock_item (mi, image); | ||
401 | 801 | } | ||
402 | 802 | else if (image_type == GTK_IMAGE_ICON_NAME) | ||
403 | 803 | { | ||
404 | 804 | update_icon_name (mi, image); | ||
405 | 805 | } | ||
406 | 806 | else if (image_type == GTK_IMAGE_PIXBUF) | ||
407 | 807 | { | ||
408 | 808 | dbusmenu_menuitem_property_set_image (mi, | ||
409 | 809 | DBUSMENU_MENUITEM_PROP_ICON_DATA, | ||
410 | 810 | gtk_image_get_pixbuf (GTK_IMAGE (image))); | ||
411 | 811 | } | ||
412 | 812 | } | ||
413 | 813 | } | ||
414 | 814 | |||
415 | 815 | GtkWidget *label = find_menu_label (widget); | ||
416 | 816 | |||
417 | 817 | dbusmenu_menuitem_property_set (mi, | ||
418 | 818 | "label", | ||
419 | 819 | label ? gtk_label_get_text (GTK_LABEL (label)) : NULL); | ||
420 | 820 | |||
421 | 821 | if (label) | ||
422 | 822 | { | ||
423 | 823 | // Sometimes, an app will directly find and modify the label | ||
424 | 824 | // (like empathy), so watch the label especially for that. | ||
425 | 825 | g_signal_connect (G_OBJECT (label), | ||
426 | 826 | "notify", | ||
427 | 827 | G_CALLBACK (label_notify_cb), | ||
428 | 828 | mi); | ||
429 | 829 | } | ||
430 | 830 | |||
431 | 831 | if (GTK_IS_ACTIVATABLE (widget)) | ||
432 | 832 | { | ||
433 | 833 | GtkActivatable *activatable = GTK_ACTIVATABLE (widget); | ||
434 | 834 | |||
435 | 835 | if (gtk_activatable_get_use_action_appearance (activatable)) | ||
436 | 836 | { | ||
437 | 837 | GtkAction *action = gtk_activatable_get_related_action (activatable); | ||
438 | 838 | |||
439 | 839 | if (action) | ||
440 | 840 | { | ||
441 | 841 | visible = gtk_action_is_visible (action); | ||
442 | 842 | sensitive = gtk_action_is_sensitive (action); | ||
443 | 843 | |||
444 | 844 | g_signal_connect_object (action, "notify", | ||
445 | 845 | G_CALLBACK (action_notify_cb), | ||
446 | 846 | mi, | ||
447 | 847 | G_CONNECT_AFTER); | ||
448 | 848 | } | ||
449 | 849 | } | ||
450 | 850 | } | ||
451 | 851 | |||
452 | 852 | if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget)) | ||
453 | 853 | { | ||
454 | 854 | visible = gtk_widget_get_visible (widget); | ||
455 | 855 | sensitive = gtk_widget_get_sensitive (widget); | ||
456 | 856 | } | ||
457 | 857 | |||
458 | 858 | dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget)); | ||
459 | 859 | |||
460 | 860 | g_signal_connect (G_OBJECT (mi), | ||
461 | 861 | DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, | ||
462 | 862 | G_CALLBACK (item_activated), | ||
463 | 863 | widget); | ||
464 | 864 | |||
465 | 865 | g_signal_connect (G_OBJECT (mi), | ||
466 | 866 | DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, | ||
467 | 867 | G_CALLBACK (item_about_to_show), | ||
468 | 868 | widget); | ||
469 | 869 | } | ||
470 | 870 | |||
471 | 871 | dbusmenu_menuitem_property_set_bool (mi, | ||
472 | 872 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
473 | 873 | visible); | ||
474 | 874 | |||
475 | 875 | dbusmenu_menuitem_property_set_bool (mi, | ||
476 | 876 | DBUSMENU_MENUITEM_PROP_ENABLED, | ||
477 | 877 | sensitive); | ||
478 | 878 | |||
479 | 879 | g_signal_connect (widget, | ||
480 | 880 | "notify", | ||
481 | 881 | G_CALLBACK (widget_notify_cb), | ||
482 | 882 | mi); | ||
483 | 883 | } | ||
484 | 884 | |||
485 | 885 | return mi; | ||
486 | 886 | } | ||
487 | 887 | |||
488 | 888 | static void | ||
489 | 889 | rebuild_item (GtkWidget *widget, | ||
490 | 890 | RecurseContext *recurse) | ||
491 | 891 | { | ||
492 | 892 | if (GTK_IS_CONTAINER (widget)) | ||
493 | 893 | { | ||
494 | 894 | gboolean increment = GTK_IS_MENU_BAR (widget) || GTK_IS_MENU_ITEM (widget); | ||
495 | 895 | |||
496 | 896 | if (increment) | ||
497 | 897 | recurse->count++; | ||
498 | 898 | |||
499 | 899 | /* Okay, this is a little janky and all.. but some applications update some | ||
500 | 900 | * menuitem properties such as sensitivity on the activate callback. This | ||
501 | 901 | * seems a little weird, but it's not our place to judge when all this code | ||
502 | 902 | * is so crazy. So we're going to get ever crazier and activate all the | ||
503 | 903 | * menus that are directly below the menubar and force the applications to | ||
504 | 904 | * update their sensitivity. The menus won't actually popup in the app | ||
505 | 905 | * window due to our gtk+ patches. | ||
506 | 906 | * | ||
507 | 907 | * Note that this will not force menuitems in submenus to be updated as well. | ||
508 | 908 | */ | ||
509 | 909 | if (recurse->count == 0 && GTK_IS_MENU_BAR (widget)) | ||
510 | 910 | { | ||
511 | 911 | GList *children = gtk_container_get_children (GTK_CONTAINER (widget)); | ||
512 | 912 | |||
513 | 913 | for (; children != NULL; children = children->next) | ||
514 | 914 | { | ||
515 | 915 | gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget), | ||
516 | 916 | children->data, | ||
517 | 917 | TRUE); | ||
518 | 918 | } | ||
519 | 919 | |||
520 | 920 | g_list_free (children); | ||
521 | 921 | } | ||
522 | 922 | |||
523 | 923 | if (recurse->count > -1 && increment) | ||
524 | 924 | { | ||
525 | 925 | DbusmenuMenuitem *dmi = g_hash_table_lookup (recurse->context->lookup, widget); | ||
526 | 926 | if (dmi != NULL) | ||
527 | 927 | { | ||
528 | 928 | if (increment) | ||
529 | 929 | recurse->count--; | ||
530 | 930 | |||
531 | 931 | return; | ||
532 | 932 | } | ||
533 | 933 | else | ||
534 | 934 | { | ||
535 | 935 | recurse->stack[recurse->count] = construct_dbusmenu_for_widget (widget); | ||
536 | 936 | g_hash_table_insert (recurse->context->lookup, widget, recurse->stack[recurse->count]); | ||
537 | 937 | } | ||
538 | 938 | |||
539 | 939 | if (!gtk_widget_get_visible (widget)) | ||
540 | 940 | { | ||
541 | 941 | g_signal_connect (G_OBJECT (widget), | ||
542 | 942 | "notify", | ||
543 | 943 | G_CALLBACK (menuitem_notify_cb), | ||
544 | 944 | recurse->context); | ||
545 | 945 | } | ||
546 | 946 | |||
547 | 947 | if (GTK_IS_TEAROFF_MENU_ITEM (widget)) | ||
548 | 948 | { | ||
549 | 949 | dbusmenu_menuitem_property_set_bool (recurse->stack[recurse->count], | ||
550 | 950 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
551 | 951 | FALSE); | ||
552 | 952 | } | ||
553 | 953 | |||
554 | 954 | if (recurse->count > 0) | ||
555 | 955 | { | ||
556 | 956 | GList *children = NULL; | ||
557 | 957 | GList *peek = NULL; | ||
558 | 958 | |||
559 | 959 | if (recurse->stack[recurse->count - 1]) | ||
560 | 960 | { | ||
561 | 961 | children = dbusmenu_menuitem_get_children (recurse->stack[recurse->count - 1]); | ||
562 | 962 | |||
563 | 963 | if (children) | ||
564 | 964 | { | ||
565 | 965 | peek = g_list_find (children, recurse->stack[recurse->count]); | ||
566 | 966 | } | ||
567 | 967 | |||
568 | 968 | if (!peek) | ||
569 | 969 | { | ||
570 | 970 | /* Should we set a weak ref on the parent? */ | ||
571 | 971 | g_object_set_data (G_OBJECT (recurse->stack[recurse->count]), | ||
572 | 972 | "dbusmenu-parent", | ||
573 | 973 | recurse->stack[recurse->count - 1]); | ||
574 | 974 | dbusmenu_menuitem_child_append (recurse->stack[recurse->count - 1], | ||
575 | 975 | recurse->stack[recurse->count]); | ||
576 | 976 | } | ||
577 | 977 | } | ||
578 | 978 | else | ||
579 | 979 | { | ||
580 | 980 | DbusmenuMenuitem *item = g_hash_table_lookup (recurse->context->lookup, | ||
581 | 981 | gtk_widget_get_parent (widget)); | ||
582 | 982 | |||
583 | 983 | if (item) | ||
584 | 984 | { | ||
585 | 985 | children = dbusmenu_menuitem_get_children (item); | ||
586 | 986 | |||
587 | 987 | if (children) | ||
588 | 988 | { | ||
589 | 989 | peek = g_list_find (children, recurse->stack[recurse->count]); | ||
590 | 990 | } | ||
591 | 991 | |||
592 | 992 | if (!peek) | ||
593 | 993 | { | ||
594 | 994 | g_object_set_data (G_OBJECT (recurse->stack[recurse->count]), | ||
595 | 995 | "dbusmenu-parent", | ||
596 | 996 | recurse->stack[recurse->count - 1]); | ||
597 | 997 | |||
598 | 998 | dbusmenu_menuitem_child_append (item, recurse->stack[recurse->count]); | ||
599 | 999 | } | ||
600 | 1000 | } | ||
601 | 1001 | } | ||
602 | 1002 | } | ||
603 | 1003 | } | ||
604 | 1004 | |||
605 | 1005 | gtk_container_foreach (GTK_CONTAINER (widget), | ||
606 | 1006 | (GtkCallback)rebuild_item, | ||
607 | 1007 | recurse); | ||
608 | 1008 | |||
609 | 1009 | if (GTK_IS_MENU_ITEM (widget)) | ||
610 | 1010 | { | ||
611 | 1011 | GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)); | ||
612 | 1012 | |||
613 | 1013 | if (menu != NULL) | ||
614 | 1014 | { | ||
615 | 1015 | rebuild_item (menu, recurse); | ||
616 | 1016 | } | ||
617 | 1017 | } | ||
618 | 1018 | |||
619 | 1019 | if (increment) | ||
620 | 1020 | recurse->count--; | ||
621 | 1021 | } | ||
622 | 1022 | } | ||
623 | 1023 | |||
624 | 1024 | typedef struct _RebuildData { | 440 | typedef struct _RebuildData { |
625 | 1025 | AppMenuBridge *bridge; | 441 | AppMenuBridge *bridge; |
626 | 1026 | GtkWidget *widget; | 442 | GtkWidget *widget; |
627 | @@ -1076,15 +492,48 @@ | |||
628 | 1076 | g_hash_table_insert (rebuild_ids, toplevel, GUINT_TO_POINTER (id)); | 492 | g_hash_table_insert (rebuild_ids, toplevel, GUINT_TO_POINTER (id)); |
629 | 1077 | } | 493 | } |
630 | 1078 | 494 | ||
631 | 495 | static DbusmenuMenuitem * find_menu_bar (GtkWidget * widget); | ||
632 | 496 | |||
633 | 497 | static void | ||
634 | 498 | find_menu_bar_helper (GtkWidget * widget, gpointer data) | ||
635 | 499 | { | ||
636 | 500 | DbusmenuMenuitem ** mi = (DbusmenuMenuitem **)data; | ||
637 | 501 | |||
638 | 502 | /* We've already found a menu, let's get through the | ||
639 | 503 | foreach as quickly as possible */ | ||
640 | 504 | if (*mi != NULL) { | ||
641 | 505 | return; | ||
642 | 506 | } | ||
643 | 507 | |||
644 | 508 | *mi = find_menu_bar(widget); | ||
645 | 509 | return; | ||
646 | 510 | } | ||
647 | 511 | |||
648 | 512 | static DbusmenuMenuitem * | ||
649 | 513 | find_menu_bar (GtkWidget * widget) | ||
650 | 514 | { | ||
651 | 515 | if (GTK_IS_MENU_BAR(widget) || GTK_IS_MENU_ITEM(widget)) { | ||
652 | 516 | return dbusmenu_gtk_parse_menu_structure(widget); | ||
653 | 517 | } | ||
654 | 518 | |||
655 | 519 | if (GTK_IS_CONTAINER(widget)) { | ||
656 | 520 | DbusmenuMenuitem * mi = NULL; | ||
657 | 521 | |||
658 | 522 | gtk_container_foreach(GTK_CONTAINER(widget), find_menu_bar_helper, &mi); | ||
659 | 523 | |||
660 | 524 | return mi; | ||
661 | 525 | } | ||
662 | 526 | |||
663 | 527 | return NULL; | ||
664 | 528 | } | ||
665 | 529 | |||
666 | 530 | |||
667 | 1079 | static void | 531 | static void |
668 | 1080 | rebuild_window_items (AppMenuBridge *bridge, | 532 | rebuild_window_items (AppMenuBridge *bridge, |
669 | 1081 | GtkWidget *toplevel) | 533 | GtkWidget *toplevel) |
670 | 1082 | { | 534 | { |
671 | 1083 | XID xid; | 535 | XID xid; |
672 | 1084 | AppWindowContext *context = NULL; | 536 | AppWindowContext *context = NULL; |
673 | 1085 | RecurseContext recurse; | ||
674 | 1086 | |||
675 | 1087 | memset (&recurse, 0, sizeof (RecurseContext)); | ||
676 | 1088 | 537 | ||
677 | 1089 | if (!GTK_IS_WINDOW (toplevel)) | 538 | if (!GTK_IS_WINDOW (toplevel)) |
678 | 1090 | { | 539 | { |
679 | @@ -1147,14 +596,6 @@ | |||
680 | 1147 | context->bridge = bridge; | 596 | context->bridge = bridge; |
681 | 1148 | context->lookup = g_hash_table_new (g_direct_hash, g_direct_equal); | 597 | context->lookup = g_hash_table_new (g_direct_hash, g_direct_equal); |
682 | 1149 | bridge->priv->windows = g_list_prepend (bridge->priv->windows, context); | 598 | bridge->priv->windows = g_list_prepend (bridge->priv->windows, context); |
683 | 1150 | |||
684 | 1151 | recurse.previous = FALSE; | ||
685 | 1152 | recurse.count = -1; | ||
686 | 1153 | } | ||
687 | 1154 | else | ||
688 | 1155 | { | ||
689 | 1156 | recurse.previous = TRUE; | ||
690 | 1157 | recurse.count = 0; | ||
691 | 1158 | } | 599 | } |
692 | 1159 | 600 | ||
693 | 1160 | if (context->window) | 601 | if (context->window) |
694 | @@ -1183,24 +624,15 @@ | |||
695 | 1183 | if (!context->server) | 624 | if (!context->server) |
696 | 1184 | context->server = dbusmenu_server_new (context->path); | 625 | context->server = dbusmenu_server_new (context->path); |
697 | 1185 | 626 | ||
711 | 1186 | recurse.bridge = bridge; | 627 | DbusmenuMenuitem * mi = find_menu_bar(toplevel); |
712 | 1187 | recurse.context = context; | 628 | dbusmenu_server_set_root(context->server, mi); |
713 | 1188 | 629 | if (mi != NULL) { | |
714 | 1189 | gtk_container_foreach (GTK_CONTAINER (toplevel), | 630 | g_object_unref(G_OBJECT(mi)); |
715 | 1190 | (GtkCallback)rebuild_item, | 631 | } |
703 | 1191 | &recurse); | ||
704 | 1192 | |||
705 | 1193 | if (recurse.stack[0] != NULL && DBUSMENU_IS_MENUITEM (recurse.stack[0])) | ||
706 | 1194 | { | ||
707 | 1195 | context->root = recurse.stack[0]; | ||
708 | 1196 | |||
709 | 1197 | dbusmenu_server_set_root (context->server, context->root); | ||
710 | 1198 | } | ||
716 | 1199 | 632 | ||
717 | 1200 | register_application_windows (bridge); | 633 | register_application_windows (bridge); |
718 | 1201 | } | 634 | } |
719 | 1202 | 635 | ||
720 | 1203 | |||
721 | 1204 | static void | 636 | static void |
722 | 1205 | toplevel_realized (GtkWidget *widget, | 637 | toplevel_realized (GtkWidget *widget, |
723 | 1206 | gpointer user_data) | 638 | gpointer user_data) |
724 | @@ -1316,7 +748,7 @@ | |||
725 | 1316 | 748 | ||
726 | 1317 | if (mi != NULL) | 749 | if (mi != NULL) |
727 | 1318 | { | 750 | { |
729 | 1319 | DbusmenuMenuitem *child_dmi = construct_dbusmenu_for_widget (child); | 751 | DbusmenuMenuitem *child_dmi = dbusmenu_gtk_parse_menu_structure (child); |
730 | 1320 | 752 | ||
731 | 1321 | g_object_set_data (G_OBJECT (child_dmi), "dbusmenu-parent", mi); | 753 | g_object_set_data (G_OBJECT (child_dmi), "dbusmenu-parent", mi); |
732 | 1322 | dbusmenu_menuitem_child_add_position (mi, | 754 | 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 :-)