~indicator-applet-developers/indicator-appmenu/trunk.16.04

« back to all changes in this revision

Viewing changes to src/indicator-appmenu.c

  • Committer: CI Train Bot
  • Author(s): Marco Trevisan (Treviño)
  • Date: 2015-02-19 19:32:04 UTC
  • mfrom: (252.2.14 indicator-appmenu)
  • Revision ID: ci-train-bot@canonical.com-20150219193204-hv2cvizqtfv0nb5a

IndicatorAppmenu: add modes support and implement unity-all-menus mode

When this mode is enabled, we export all the menus to the indicator, it will be up
to unity to filter them out based on their parent xid. Fixes: #1309778
Approved by: PS Jenkins bot, Lars Uebernickel

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
Authors:
7
7
    Ted Gould <ted@canonical.com>
 
8
    Marco Trevisan <marco@canonical.com>
8
9
 
9
10
This program is free software: you can redistribute it and/or modify it 
10
11
under the terms of the GNU General Public License version 3, as published 
73
74
        STUBS_HIDE
74
75
};
75
76
 
 
77
typedef enum _AppmenuMode AppmenuMode;
 
78
enum _AppmenuMode {
 
79
        MODE_STANDARD,
 
80
        MODE_UNITY,
 
81
        MODE_UNITY_ALL_MENUS
 
82
};
 
83
 
76
84
struct _IndicatorAppmenuClass {
77
85
        IndicatorObjectClass parent_class;
78
 
 
79
 
        void (*window_registered) (IndicatorAppmenu * iapp, guint wid, gchar * address, gpointer path, gpointer user_data);
80
 
        void (*window_unregistered) (IndicatorAppmenu * iapp, guint wid, gpointer user_data);
81
86
};
82
87
 
83
88
struct _IndicatorAppmenu {
84
89
        IndicatorObject parent;
85
90
 
 
91
        AppmenuMode mode;
 
92
 
86
93
        WindowMenu * default_app;
87
94
        GHashTable * apps;
88
95
 
90
97
        BamfWindow * active_window;
91
98
        ActiveStubsState active_stubs;
92
99
 
93
 
        gulong sig_entry_added;
94
 
        gulong sig_entry_removed;
95
 
        gulong sig_status_changed;
96
 
        gulong sig_show_menu;
97
 
        gulong sig_a11y_update;
98
 
 
99
100
        GtkMenuItem * close_item;
100
 
 
101
101
        GArray * window_menus;
102
102
 
103
103
        GHashTable * desktop_windows;
137
137
/**********************
138
138
  Prototypes
139
139
 **********************/
 
140
static gboolean indicator_appmenu_delayed_init                       (IndicatorAppmenu * iapp);
140
141
static void indicator_appmenu_dispose                                (GObject *object);
141
142
static void indicator_appmenu_finalize                               (GObject *object);
142
143
static void build_window_menus                                       (IndicatorAppmenu * iapp);
153
154
static void switch_default_app                                       (IndicatorAppmenu * iapp,
154
155
                                                                      WindowMenu * newdef,
155
156
                                                                      BamfWindow * active_window);
156
 
static void find_desktop_windows                                     (IndicatorAppmenu * iapp);
 
157
static void find_relevant_windows                                    (IndicatorAppmenu * iapp);
157
158
static void new_window                                               (BamfMatcher * matcher,
158
159
                                                                      BamfView * view,
159
160
                                                                      gpointer user_data);
195
196
static void on_name_lost                                             (GDBusConnection * connection,
196
197
                                                                      const gchar * name,
197
198
                                                                      gpointer user_data);
 
199
static WindowMenu * ensure_menus                                     (IndicatorAppmenu * iapp,
 
200
                                                                          BamfWindow * window);
198
201
static GVariant * unregister_window                                  (IndicatorAppmenu * iapp,
199
202
                                                                      guint windowid);
 
203
static void connect_to_menu_signals                                  (IndicatorAppmenu * iapp,
 
204
                                                                          WindowMenu * menus);
200
205
 
201
206
/* Unique error codes for debug interface */
202
207
enum {
260
265
static void
261
266
indicator_appmenu_init (IndicatorAppmenu *self)
262
267
{
263
 
        self->default_app = NULL;
264
268
        self->apps = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
265
 
        self->matcher = NULL;
266
 
        self->active_window = NULL;
 
269
        self->mode = MODE_STANDARD;
267
270
        self->active_stubs = STUBS_UNKNOWN;
268
 
        self->close_item = NULL;
269
 
        self->bus = NULL;
270
 
        self->owner_id = 0;
271
 
        self->dbus_registration = 0;
272
 
 
273
 
        /* Setup the entries for the fallbacks */
274
 
        self->window_menus = g_array_sized_new(FALSE, FALSE, sizeof(IndicatorObjectEntry), 2);
275
271
 
276
272
        /* Setup the cache of windows with possible desktop entries */
277
273
        self->desktop_windows = g_hash_table_new(g_direct_hash, g_direct_equal);
278
 
        self->desktop_menu = NULL; /* Starts NULL until found */
279
 
 
280
 
        build_window_menus(self);
 
274
 
 
275
        g_idle_add((GSourceFunc) indicator_appmenu_delayed_init, self);
 
276
}
 
277
 
 
278
/* Delayed Init, this is done so it can happen after that the mode has been set */
 
279
static gboolean
 
280
indicator_appmenu_delayed_init (IndicatorAppmenu *self)
 
281
{
 
282
        if (indicator_object_check_environment(INDICATOR_OBJECT(self), "unity-all-menus")) {
 
283
                self->mode = MODE_UNITY_ALL_MENUS;
 
284
        } else if (indicator_object_check_environment(INDICATOR_OBJECT(self), "unity")) {
 
285
                self->mode = MODE_UNITY;
 
286
        }
 
287
 
 
288
        if (self->mode != MODE_STANDARD)
 
289
                self->active_stubs = STUBS_HIDE;
 
290
 
 
291
        if (self->active_stubs != STUBS_HIDE)
 
292
                build_window_menus(self);
281
293
 
282
294
        /* Get the default BAMF matcher */
283
295
        self->matcher = bamf_matcher_get_default();
293
305
                g_signal_connect(G_OBJECT(self->matcher), "view-closed", G_CALLBACK(old_window), self);
294
306
        }
295
307
 
296
 
        find_desktop_windows(self);
 
308
        find_relevant_windows(self);
297
309
 
298
310
        /* Request a name so others can find us */
299
311
        self->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
304
316
                                         on_name_lost,
305
317
                                         self,
306
318
                                         NULL);
 
319
 
 
320
        return G_SOURCE_REMOVE;
307
321
}
308
322
 
309
323
static void
365
379
                iapp->dbus_registration = 0;
366
380
        }
367
381
 
368
 
        if (iapp->bus != NULL) {
369
 
                g_object_unref(iapp->bus);
370
 
                iapp->bus = NULL;
371
 
        }
 
382
        g_clear_object(&iapp->bus);
372
383
 
373
384
        if (iapp->owner_id != 0) {
374
385
                g_bus_unown_name(iapp->owner_id);
377
388
 
378
389
        /* bring down the matcher before resetting to no menu so we don't
379
390
           get match signals */
380
 
        if (iapp->matcher != NULL) {
381
 
                g_object_unref(iapp->matcher);
382
 
                iapp->matcher = NULL;
383
 
        }
 
391
        g_clear_object(&iapp->matcher);
384
392
 
385
393
        /* No specific ref */
386
 
        switch_default_app (iapp, NULL, NULL);
387
 
 
388
 
        if (iapp->apps != NULL) {
389
 
                g_hash_table_destroy(iapp->apps);
390
 
                iapp->apps = NULL;
391
 
        }
392
 
 
393
 
        if (iapp->desktop_windows != NULL) {
394
 
                g_hash_table_destroy(iapp->desktop_windows);
395
 
                iapp->desktop_windows = NULL;
396
 
        }
 
394
        switch_default_app(iapp, NULL, NULL);
 
395
 
 
396
        g_clear_pointer(&iapp->apps, g_hash_table_destroy);
 
397
        g_clear_pointer(&iapp->desktop_windows, g_hash_table_destroy);
397
398
 
398
399
        if (iapp->desktop_menu != NULL) {
399
400
                /* Wait, nothing here?  Yup.  We're not referencing the
413
414
        IndicatorAppmenu * iapp = INDICATOR_APPMENU(object);
414
415
 
415
416
        if (iapp->window_menus != NULL) {
416
 
                if (iapp->window_menus->len != 0) {
417
 
                        g_warning("Window menus weren't free'd in dispose!");
 
417
                g_signal_handlers_disconnect_by_data(iapp->close_item, iapp);
 
418
 
 
419
                gint i;
 
420
                for (i = 0; i < iapp->window_menus->len; ++i) {
 
421
                        IndicatorObjectEntry *entry = &g_array_index(iapp->window_menus, IndicatorObjectEntry, i);
 
422
                        g_clear_object(&(entry->label));
 
423
                        g_clear_object(&(entry->menu));
418
424
                }
419
425
                g_array_free(iapp->window_menus, TRUE);
420
 
                iapp->window_menus = NULL;
421
426
        }
422
427
 
 
428
        g_signal_handlers_disconnect_by_data(iapp->matcher, iapp);
 
429
 
423
430
        G_OBJECT_CLASS (indicator_appmenu_parent_class)->finalize (object);
424
431
        return;
425
432
}
496
503
        GtkMenuItem * mi = NULL;
497
504
        GtkStockItem stockitem;
498
505
 
 
506
        /* Setup the entries for the fallbacks */
 
507
        iapp->window_menus = g_array_sized_new(FALSE, FALSE, sizeof(IndicatorObjectEntry), 2);
 
508
 
 
509
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
499
510
        /* File Menu */
500
511
        if (!gtk_stock_lookup(GTK_STOCK_FILE, &stockitem)) {
501
512
                g_warning("Unable to find the file menu stock item");
502
513
                stockitem.label = "_File";
503
514
        }
 
515
G_GNUC_END_IGNORE_DEPRECATIONS
 
516
 
504
517
        entries[0].label = GTK_LABEL(gtk_label_new_with_mnemonic(stockitem.label));
505
518
        g_object_ref(G_OBJECT(entries[0].label));
506
519
        gtk_widget_show(GTK_WIDGET(entries[0].label));
508
521
        entries[0].menu = GTK_MENU(gtk_menu_new());
509
522
        g_object_ref(G_OBJECT(entries[0].menu));
510
523
 
 
524
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
511
525
        mi = GTK_MENU_ITEM(gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, agroup));
 
526
G_GNUC_END_IGNORE_DEPRECATIONS
 
527
 
512
528
        gtk_widget_set_sensitive(GTK_WIDGET(mi), FALSE);
513
529
        g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(close_current), iapp);
514
530
        gtk_widget_show(GTK_WIDGET(mi));
519
535
 
520
536
        /* Copy the entries on the stack into the array */
521
537
        g_array_insert_vals(iapp->window_menus, 0, entries, 1);
522
 
 
523
 
        return;
524
538
}
525
539
 
526
540
/* Determine which windows should be used as the desktop
537
551
                if (pwm != NULL) {
538
552
                        g_debug("Setting Desktop Menus to: %X", xid);
539
553
                        iapp->desktop_menu = WINDOW_MENU(pwm);
 
554
                        break;
540
555
                }
541
556
        }
542
557
 
545
560
        return;
546
561
}
547
562
 
548
 
/* Puts all the desktop windows into the hash table so that we
 
563
/* Puts all the windows we care about into the hash table so that we
549
564
   can have a nice list of them. */
550
565
static void
551
 
find_desktop_windows (IndicatorAppmenu * iapp)
 
566
find_relevant_windows (IndicatorAppmenu * iapp)
552
567
{
553
568
        GList * windows = bamf_matcher_get_windows(iapp->matcher);
554
569
        GList * lwindow;
568
583
static void
569
584
new_window (BamfMatcher * matcher, BamfView * view, gpointer user_data)
570
585
{
571
 
        if (view == NULL || !BAMF_IS_WINDOW(view)) {
 
586
        if (!BAMF_IS_WINDOW(view)) {
572
587
                return;
573
588
        }
574
589
 
576
591
        IndicatorAppmenu * iapp = INDICATOR_APPMENU(user_data);
577
592
        guint32 xid = bamf_window_get_xid(window);
578
593
 
 
594
        if (iapp->mode == MODE_UNITY_ALL_MENUS) {
 
595
                ensure_menus(iapp, window);
 
596
                return;
 
597
        }
 
598
 
579
599
        if (bamf_window_get_window_type(window) != BAMF_WINDOW_DESKTOP) {
580
600
                return;
581
601
        }
593
613
                        switch_default_app(iapp, NULL, NULL);
594
614
                }
595
615
        }
596
 
 
597
 
        return;
598
616
}
599
617
 
600
618
/* When windows leave us, this function gets called */
601
619
static void
602
620
old_window (BamfMatcher * matcher, BamfView * view, gpointer user_data)
603
621
{
604
 
        if (view == NULL || !BAMF_IS_WINDOW(view)) {
 
622
        if (!BAMF_IS_WINDOW(view)) {
605
623
                return;
606
624
        }
607
625
 
617
635
/* List of desktop files that shouldn't have menu stubs. */
618
636
const static gchar * stubs_blacklist[] = {
619
637
        /* Firefox */
620
 
        "/usr/share/applications/firefox.desktop",
 
638
        "/firefox.desktop",
621
639
        /* Thunderbird */
622
 
        "/usr/share/applications/thunderbird.desktop",
 
640
        "/thunderbird.desktop",
623
641
        /* Open Office */
624
 
        "/usr/share/applications/openoffice.org-base.desktop",
625
 
        "/usr/share/applications/openoffice.org-impress.desktop",
626
 
        "/usr/share/applications/openoffice.org-calc.desktop",
627
 
        "/usr/share/applications/openoffice.org-math.desktop",
628
 
        "/usr/share/applications/openoffice.org-draw.desktop",
629
 
        "/usr/share/applications/openoffice.org-writer.desktop",
 
642
        "/openoffice.org-base.desktop",
 
643
        "/openoffice.org-impress.desktop",
 
644
        "/openoffice.org-calc.desktop",
 
645
        "/openoffice.org-math.desktop",
 
646
        "/openoffice.org-draw.desktop",
 
647
        "/openoffice.org-writer.desktop",
630
648
        /* Blender */
631
 
        "/usr/share/applications/blender-fullscreen.desktop",
632
 
        "/usr/share/applications/blender-windowed.desktop",
 
649
        "/blender-fullscreen.desktop",
 
650
        "/blender-windowed.desktop",
633
651
        /* Eclipse */
634
 
        "/usr/share/applications/eclipse.desktop",
 
652
        "/eclipse.desktop",
635
653
 
636
654
        NULL
637
655
};
652
670
 
653
671
        int i;
654
672
        for (i = 0; stubs_blacklist[i] != NULL; i++) {
655
 
                if (g_strcmp0(stubs_blacklist[i], desktop_file) == 0) {
 
673
                if (g_str_has_suffix(desktop_file, stubs_blacklist[i]) == 0) {
656
674
                        return FALSE;
657
675
                }
658
676
        }
666
684
{
667
685
        g_return_val_if_fail(IS_INDICATOR_APPMENU(io), NULL);
668
686
        IndicatorAppmenu * iapp = INDICATOR_APPMENU(io);
 
687
        GHashTableIter iter;
 
688
        gpointer value;
 
689
        GList* entries = NULL;
 
690
 
 
691
        if (iapp->mode == MODE_UNITY_ALL_MENUS) {
 
692
                g_hash_table_iter_init(&iter, iapp->apps);
 
693
                while (g_hash_table_iter_next(&iter, NULL, &value)) {
 
694
                        GList *app_entries = window_menu_get_entries(WINDOW_MENU (value));
 
695
                        entries = g_list_concat(app_entries, entries);
 
696
                }
 
697
 
 
698
                return entries;
 
699
        }
669
700
 
670
701
        /* If we have a focused app with menus, use it's windows */
671
702
        if (iapp->default_app != NULL) {
702
733
                return NULL;
703
734
        }
704
735
 
705
 
        if (indicator_object_check_environment(INDICATOR_OBJECT(iapp), "unity")) {
706
 
                return NULL;
707
 
        }
708
 
 
709
 
        GList * output = NULL;
710
 
        int i;
711
 
 
712
736
        /* There is only one item in window_menus now, but there
713
737
           was more, and there is likely to be more in the future
714
738
           so we're leaving this here to avoid a possible bug. */
 
739
        int i;
715
740
        for (i = 0; i < iapp->window_menus->len; i++) {
716
 
                output = g_list_append(output, &g_array_index(iapp->window_menus, IndicatorObjectEntry, i));
 
741
                entries = g_list_append(entries, &g_array_index(iapp->window_menus, IndicatorObjectEntry, i));
717
742
        }
718
743
 
719
 
        return output;
 
744
        return entries;
720
745
}
721
746
 
722
747
/* Grabs the location of the entry */
728
753
        if (iapp->default_app != NULL) {
729
754
                /* Find the location in the app */
730
755
                count = window_menu_get_location(iapp->default_app, entry);
731
 
        } else if (iapp->active_window != NULL) {
 
756
        } else if (iapp->active_window != NULL && iapp->window_menus) {
732
757
                /* Find the location in the window menus */
733
758
                for (count = 0; count < iapp->window_menus->len; count++) {
734
759
                        if (entry == &g_array_index(iapp->window_menus, IndicatorObjectEntry, count)) {
760
785
static BamfWindow *
761
786
xid_to_bamf_window (IndicatorAppmenu * iapp, guint xid)
762
787
{
763
 
        GList * windows = bamf_matcher_get_windows(iapp->matcher);
764
 
        GList * window;
 
788
        BamfApplication *application = bamf_matcher_get_application_for_xid(iapp->matcher, xid);
 
789
        GList * children = bamf_view_get_children (BAMF_VIEW (application));
 
790
        GList * l;
765
791
        BamfWindow * newwindow = NULL;
766
792
 
767
 
        for (window = windows; window != NULL; window = g_list_next(window)) {
768
 
                if (!BAMF_IS_WINDOW(window->data)) {
 
793
        for (l = children; l; l = l->next) {
 
794
                if (!BAMF_IS_WINDOW(l->data)) {
769
795
                        continue;
770
796
                }
771
797
 
772
 
                BamfWindow * testwindow = BAMF_WINDOW(window->data);
 
798
                BamfWindow * testwindow = BAMF_WINDOW(l->data);
773
799
 
774
800
                if (xid == bamf_window_get_xid(testwindow)) {
775
801
                        newwindow = testwindow;
776
802
                        break;
777
803
                }
778
804
        }
779
 
        g_list_free(windows);
 
805
        g_list_free(children);
780
806
 
781
807
        return newwindow;
782
808
}
842
868
static void
843
869
switch_active_window (IndicatorAppmenu * iapp, BamfWindow * active_window)
844
870
{
845
 
        if (iapp->active_window == active_window) {
 
871
        if (iapp->active_window == active_window || iapp->mode == MODE_UNITY_ALL_MENUS) {
846
872
                return;
847
873
        }
848
874
 
851
877
        }
852
878
 
853
879
        iapp->active_window = active_window;
854
 
        iapp->active_stubs = STUBS_UNKNOWN;
 
880
 
 
881
        if (iapp->mode == MODE_STANDARD)
 
882
                iapp->active_stubs = STUBS_UNKNOWN;
855
883
 
856
884
        /* Close any existing open menu by showing a null entry */
857
885
        window_show_menu(iapp->default_app, NULL, gtk_get_current_event_time(), iapp);
875
903
        if (xid == 0 || bamf_view_is_closed (BAMF_VIEW (iapp->active_window))) {
876
904
                return;
877
905
        }
878
 
 
 
906
 
879
907
        GdkWMFunction functions;
880
908
        if (!egg_xid_get_functions(xid, &functions)) {
881
909
                g_debug("Unable to get MWM functions for: %d", xid);
889
917
        return;
890
918
}
891
919
 
 
920
static void
 
921
connect_to_menu_signals (IndicatorAppmenu * iapp, WindowMenu * menus)
 
922
{
 
923
        g_return_if_fail(G_IS_OBJECT(menus));
 
924
 
 
925
        /* Connect signals */
 
926
        g_signal_connect(menus,
 
927
                         WINDOW_MENU_SIGNAL_ENTRY_ADDED,
 
928
                         G_CALLBACK(window_entry_added),
 
929
                         iapp);
 
930
        g_signal_connect(menus,
 
931
                         WINDOW_MENU_SIGNAL_ENTRY_REMOVED,
 
932
                         G_CALLBACK(window_entry_removed),
 
933
                         iapp);
 
934
        g_signal_connect(menus,
 
935
                         WINDOW_MENU_SIGNAL_STATUS_CHANGED,
 
936
                         G_CALLBACK(window_status_changed),
 
937
                         iapp);
 
938
        g_signal_connect(menus,
 
939
                         WINDOW_MENU_SIGNAL_SHOW_MENU,
 
940
                         G_CALLBACK(window_show_menu),
 
941
                         iapp);
 
942
        g_signal_connect(menus,
 
943
                         WINDOW_MENU_SIGNAL_A11Y_UPDATE,
 
944
                         G_CALLBACK(window_a11y_update),
 
945
                         iapp);
 
946
}
 
947
 
892
948
/* Switch applications, remove all the entires for the previous
893
949
   one and add them for the new application */
894
950
static void
895
951
switch_default_app (IndicatorAppmenu * iapp, WindowMenu * newdef, BamfWindow * active_window)
896
952
{
 
953
        if (iapp->mode == MODE_UNITY_ALL_MENUS) {
 
954
                return;
 
955
        }
 
956
 
897
957
        if (iapp->default_app == newdef && iapp->default_app != NULL) {
898
958
                /* We've got an app with menus and it hasn't changed. */
899
959
 
911
971
 
912
972
        /* hide the entries that we're swapping out */
913
973
        indicator_object_set_visible (INDICATOR_OBJECT(iapp), FALSE);
914
 
        
915
 
        /* Disconnect signals */
916
 
        if (iapp->sig_entry_added != 0) {
917
 
                g_signal_handler_disconnect(G_OBJECT(iapp->default_app), iapp->sig_entry_added);
918
 
                iapp->sig_entry_added = 0;
919
 
        }
920
 
        if (iapp->sig_entry_removed != 0) {
921
 
                g_signal_handler_disconnect(G_OBJECT(iapp->default_app), iapp->sig_entry_removed);
922
 
                iapp->sig_entry_removed = 0;
923
 
        }
924
 
        if (iapp->sig_status_changed != 0) {
925
 
                g_signal_handler_disconnect(G_OBJECT(iapp->default_app), iapp->sig_status_changed);
926
 
                iapp->sig_status_changed = 0;
927
 
        }
928
 
        if (iapp->sig_show_menu != 0) {
929
 
                g_signal_handler_disconnect(G_OBJECT(iapp->default_app), iapp->sig_show_menu);
930
 
                iapp->sig_show_menu = 0;
931
 
        }
932
 
        if (iapp->sig_a11y_update != 0) {
933
 
                g_signal_handler_disconnect(G_OBJECT(iapp->default_app), iapp->sig_a11y_update);
934
 
                iapp->sig_a11y_update = 0;
935
 
        }
936
 
 
937
 
        /* Default App is NULL, let's see if it needs replacement */
938
 
        iapp->default_app = NULL;
 
974
 
 
975
        if (iapp->default_app)
 
976
        {
 
977
                /* Disconnect signals */
 
978
                g_signal_handlers_disconnect_by_data(iapp->default_app, iapp);
 
979
 
 
980
                /* Default App is NULL, let's see if it needs replacement */
 
981
                iapp->default_app = NULL;
 
982
        }
939
983
 
940
984
        /* Update the active window pointer -- may be NULL */
941
985
        switch_active_window(iapp, active_window);
944
988
        if (newdef != NULL) {
945
989
                /* Switch */
946
990
                iapp->default_app = newdef;
947
 
 
948
 
                /* Connect signals */
949
 
                iapp->sig_entry_added =   g_signal_connect(G_OBJECT(iapp->default_app),
950
 
                                                           WINDOW_MENU_SIGNAL_ENTRY_ADDED,
951
 
                                                           G_CALLBACK(window_entry_added),
952
 
                                                           iapp);
953
 
                iapp->sig_entry_removed = g_signal_connect(G_OBJECT(iapp->default_app),
954
 
                                                           WINDOW_MENU_SIGNAL_ENTRY_REMOVED,
955
 
                                                           G_CALLBACK(window_entry_removed),
956
 
                                                           iapp);
957
 
                iapp->sig_status_changed = g_signal_connect(G_OBJECT(iapp->default_app),
958
 
                                                           WINDOW_MENU_SIGNAL_STATUS_CHANGED,
959
 
                                                           G_CALLBACK(window_status_changed),
960
 
                                                           iapp);
961
 
                iapp->sig_show_menu     = g_signal_connect(G_OBJECT(iapp->default_app),
962
 
                                                           WINDOW_MENU_SIGNAL_SHOW_MENU,
963
 
                                                           G_CALLBACK(window_show_menu),
964
 
                                                           iapp);
965
 
                iapp->sig_a11y_update   = g_signal_connect(G_OBJECT(iapp->default_app),
966
 
                                                           WINDOW_MENU_SIGNAL_A11Y_UPDATE,
967
 
                                                           G_CALLBACK(window_a11y_update),
968
 
                                                           iapp);
 
991
                connect_to_menu_signals(iapp, iapp->default_app);
969
992
        }
970
993
 
971
994
        /* show the entries that we're swapping in */
982
1005
        return;
983
1006
}
984
1007
 
 
1008
static void
 
1009
track_menus (IndicatorAppmenu * iapp, guint xid, WindowMenu * menus)
 
1010
{
 
1011
        g_return_if_fail(IS_WINDOW_MENU(menus));
 
1012
 
 
1013
        g_hash_table_insert(iapp->apps, GUINT_TO_POINTER(xid), menus);
 
1014
 
 
1015
        if (iapp->mode == MODE_UNITY_ALL_MENUS) {
 
1016
                connect_to_menu_signals(iapp, menus);
 
1017
        }
 
1018
}
 
1019
 
 
1020
static WindowMenu *
 
1021
ensure_menus (IndicatorAppmenu * iapp, BamfWindow * window)
 
1022
{
 
1023
        WindowMenu * menus = NULL;
 
1024
        guint32 xid = 0;
 
1025
 
 
1026
        while (window != NULL && menus == NULL) {
 
1027
                xid = bamf_window_get_xid(window);
 
1028
 
 
1029
                menus = g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(xid));
 
1030
 
 
1031
                /* First look to see if we can get these from the
 
1032
                   GMenuModel access */
 
1033
                if (menus == NULL) {
 
1034
                        gchar * uniquename = bamf_window_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
 
1035
 
 
1036
                        if (uniquename != NULL) {
 
1037
                                BamfApplication * app = bamf_matcher_get_application_for_window(iapp->matcher, window);
 
1038
 
 
1039
                                menus = WINDOW_MENU(window_menu_model_new(app, window));
 
1040
                                track_menus(iapp, xid, menus);
 
1041
                        }
 
1042
 
 
1043
                        g_free(uniquename);
 
1044
                }
 
1045
 
 
1046
                if (menus == NULL) {
 
1047
                        g_debug("Looking for parent window on XID %d", xid);
 
1048
                        window = bamf_window_get_transient(window);
 
1049
                }
 
1050
        }
 
1051
 
 
1052
        return menus;
 
1053
}
 
1054
 
985
1055
/* Recieve the signal that the window being shown
986
1056
   has now changed. */
987
1057
static void
1000
1070
 
1001
1071
        IndicatorAppmenu * appmenu = INDICATOR_APPMENU(user_data);
1002
1072
 
 
1073
        if (window != NULL && appmenu->mode == MODE_UNITY_ALL_MENUS) {
 
1074
                ensure_menus(appmenu, window);
 
1075
                return;
 
1076
        }
 
1077
 
1003
1078
        if (window != NULL && bamf_window_get_window_type(window) == BAMF_WINDOW_DESKTOP) {
1004
1079
                g_debug("Switching to menus from desktop");
1005
1080
                switch_default_app(appmenu, NULL, NULL);
1006
1081
                return;
1007
1082
        }
1008
1083
 
1009
 
        WindowMenu * menus = NULL;
1010
 
        guint32 xid = 0;
1011
 
 
1012
 
        while (window != NULL && menus == NULL) {
1013
 
                xid = bamf_window_get_xid(window);
1014
 
        
1015
 
                menus = g_hash_table_lookup(appmenu->apps, GUINT_TO_POINTER(xid));
1016
 
 
1017
 
                /* First look to see if we can get these from the
1018
 
                   GMenuModel access */
1019
 
                if (menus == NULL) {
1020
 
                        gchar * uniquename = bamf_window_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
1021
 
 
1022
 
                        if (uniquename != NULL) {
1023
 
                                BamfApplication * app = bamf_matcher_get_application_for_window(matcher, window);
1024
 
 
1025
 
                                menus = WINDOW_MENU(window_menu_model_new(app, window));
1026
 
 
1027
 
                                g_hash_table_insert(appmenu->apps, GUINT_TO_POINTER(xid), menus);
1028
 
                        }
1029
 
 
1030
 
                        g_free(uniquename);
1031
 
                }
1032
 
 
1033
 
                if (menus == NULL) {
1034
 
                        g_debug("Looking for parent window on XID %d", xid);
1035
 
                        window = bamf_window_get_transient(window);
1036
 
                }
1037
 
        }
 
1084
        WindowMenu * menus = ensure_menus (appmenu, window);
1038
1085
 
1039
1086
        /* Note: We're not using window here, but re-casting the
1040
1087
           newwindow variable.  Which means we stay where we were
1041
1088
           but get the menus from parents. */
1042
 
        g_debug("Switching to menus from XID %d", xid);
 
1089
        g_debug("Switching to menus from XID %d", newview ? bamf_window_get_xid(BAMF_WINDOW(newview)) : 0);
1043
1090
        if (newview != NULL) {
1044
1091
                switch_default_app(appmenu, menus, BAMF_WINDOW(newview));
1045
1092
        } else {
1046
1093
                switch_default_app(appmenu, menus, NULL);
1047
1094
        }
1048
 
 
1049
 
        return;
1050
1095
}
1051
1096
 
1052
1097
/* Respond to the menus being destroyed.  We need to deregister
1056
1101
{
1057
1102
        gboolean reload_menus = FALSE;
1058
1103
        WindowMenu * wm = g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid));
1059
 
        g_return_if_fail (wm != NULL);
 
1104
        g_return_if_fail (IS_WINDOW_MENU(wm));
1060
1105
 
1061
1106
        g_hash_table_steal(iapp->apps, GUINT_TO_POINTER(windowid));
 
1107
        g_signal_handlers_disconnect_by_data(wm, iapp);
1062
1108
 
1063
1109
        g_debug("Removing menus for %d", windowid);
1064
1110
 
1094
1140
                WindowMenu * wm = WINDOW_MENU(window_menu_dbusmenu_new(windowid, sender, objectpath));
1095
1141
                g_return_val_if_fail(wm != NULL, FALSE);
1096
1142
 
1097
 
                g_hash_table_insert(iapp->apps, GUINT_TO_POINTER(windowid), wm);
 
1143
                track_menus(iapp, windowid, wm);
1098
1144
 
1099
1145
                emit_signal(iapp, "WindowRegistered",
1100
1146
                            g_variant_new("(uso)", windowid, sender, objectpath));
1271
1317
{
1272
1318
        entry->parent_object = user_data;
1273
1319
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, entry);
1274
 
        return;
1275
1320
}
1276
1321
 
1277
1322
/* Pass up the entry removed event */
1280
1325
{
1281
1326
        entry->parent_object = user_data;
1282
1327
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, entry);
1283
 
        return;
1284
1328
}
1285
1329
 
1286
1330
/* Pass up the status changed event */
1296
1340
                IndicatorObjectEntry * entry = (IndicatorObjectEntry *)entries->data;
1297
1341
                g_signal_emit(G_OBJECT(iapp), INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED_ID, 0, entry, show_now);
1298
1342
        }
1299
 
 
1300
 
        return;
1301
1343
}
1302
1344
 
1303
1345
/* Pass up the show menu event */
1305
1347
window_show_menu (WindowMenu * mw, IndicatorObjectEntry * entry, guint timestamp, gpointer user_data)
1306
1348
{
1307
1349
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_MENU_SHOW, entry, timestamp);
1308
 
        return;
1309
1350
}
1310
1351
 
1311
1352
/* Pass up the accessible string update */
1313
1354
window_a11y_update (WindowMenu * mw, IndicatorObjectEntry * entry, gpointer user_data)
1314
1355
{
1315
1356
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, entry);
1316
 
        return;
1317
1357
}
1318
1358
 
1319
1359
/**********************