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

« back to all changes in this revision

Viewing changes to src/indicator-appmenu.c

* Upstream Merge
  * GMenuModel menu support

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
#include "gen-application-menu-registrar.xml.h"
39
39
#include "gen-application-menu-renderer.xml.h"
40
40
#include "indicator-appmenu-marshal.h"
41
 
#include "window-menus.h"
 
41
#include "window-menu.h"
 
42
#include "window-menu-dbusmenu.h"
 
43
#include "window-menu-model.h"
42
44
#include "dbus-shared.h"
43
45
#include "gdk-get-func.h"
44
46
 
81
83
 
82
84
        gulong retry_registration;
83
85
 
84
 
        WindowMenus * default_app;
 
86
        WindowMenu * default_app;
85
87
        GHashTable * apps;
86
88
 
87
89
        BamfMatcher * matcher;
99
101
        GArray * window_menus;
100
102
 
101
103
        GHashTable * desktop_windows;
102
 
        WindowMenus * desktop_menu;
 
104
        WindowMenu * desktop_menu;
103
105
 
104
106
        GDBusConnection * bus;
105
107
        guint owner_id;
151
153
                                                                      guint windowid,
152
154
                                                                      guint timestamp);
153
155
static void switch_default_app                                       (IndicatorAppmenu * iapp,
154
 
                                                                      WindowMenus * newdef,
 
156
                                                                      WindowMenu * newdef,
155
157
                                                                      BamfWindow * active_window);
156
158
static void find_desktop_windows                                     (IndicatorAppmenu * iapp);
157
159
static void new_window                                               (BamfMatcher * matcher,
160
162
static void old_window                                               (BamfMatcher * matcher,
161
163
                                                                      BamfView * view,
162
164
                                                                      gpointer user_data);
163
 
static void window_entry_added                                       (WindowMenus * mw,
164
 
                                                                      IndicatorObjectEntry * entry,
165
 
                                                                      gpointer user_data);
166
 
static void window_entry_removed                                     (WindowMenus * mw,
167
 
                                                                      IndicatorObjectEntry * entry,
168
 
                                                                      gpointer user_data);
169
 
static void window_status_changed                                    (WindowMenus * mw,
 
165
static void window_entry_added                                       (WindowMenu * mw,
 
166
                                                                      IndicatorObjectEntry * entry,
 
167
                                                                      gpointer user_data);
 
168
static void window_entry_removed                                     (WindowMenu * mw,
 
169
                                                                      IndicatorObjectEntry * entry,
 
170
                                                                      gpointer user_data);
 
171
static void window_status_changed                                    (WindowMenu * mw,
170
172
                                                                      DbusmenuStatus status,
171
173
                                                                      IndicatorAppmenu * iapp);
172
 
static void window_show_menu                                         (WindowMenus * mw,
 
174
static void window_show_menu                                         (WindowMenu * mw,
173
175
                                                                      IndicatorObjectEntry * entry,
174
176
                                                                      guint timestamp,
175
177
                                                                      gpointer user_data);
176
 
static void window_a11y_update                                       (WindowMenus * mw,
 
178
static void window_a11y_update                                       (WindowMenu * mw,
177
179
                                                                      IndicatorObjectEntry * entry,
178
180
                                                                      gpointer user_data);
179
181
static void active_window_changed                                    (BamfMatcher * matcher,
589
591
                gpointer pwm = g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(xid));
590
592
                if (pwm != NULL) {
591
593
                        g_debug("Setting Desktop Menus to: %X", xid);
592
 
                        iapp->desktop_menu = WINDOW_MENUS(pwm);
 
594
                        iapp->desktop_menu = WINDOW_MENU(pwm);
593
595
                }
594
596
        }
595
597
 
642
644
 
643
645
        gpointer pwm = g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(xid));
644
646
        if (pwm != NULL) {
645
 
                WindowMenus * wm = WINDOW_MENUS(pwm);
 
647
                WindowMenu * wm = WINDOW_MENU(pwm);
646
648
                iapp->desktop_menu = wm;
647
649
                g_debug("Setting Desktop Menus to: %X", xid);
648
650
                if (iapp->active_window == NULL && iapp->default_app == NULL) {
756
758
 
757
759
        /* If we have a focused app with menus, use it's windows */
758
760
        if (iapp->default_app != NULL) {
759
 
                return window_menus_get_entries(iapp->default_app);
 
761
                return window_menu_get_entries(iapp->default_app);
760
762
        }
761
763
 
762
764
        /* Else, let's go with desktop windows if there isn't a focused window */
764
766
                if (iapp->desktop_menu == NULL) {
765
767
                        return NULL;
766
768
                } else {
767
 
                        return window_menus_get_entries(iapp->desktop_menu);
 
769
                        return window_menu_get_entries(iapp->desktop_menu);
768
770
                }
769
771
        }
770
772
 
814
816
        IndicatorAppmenu * iapp = INDICATOR_APPMENU(io);
815
817
        if (iapp->default_app != NULL) {
816
818
                /* Find the location in the app */
817
 
                count = window_menus_get_location(iapp->default_app, entry);
 
819
                count = window_menu_get_location(iapp->default_app, entry);
818
820
        } else if (iapp->active_window != NULL) {
819
821
                /* Find the location in the window menus */
820
822
                for (count = 0; count < iapp->window_menus->len; count++) {
829
831
        } else {
830
832
                /* Find the location in the desktop menu */
831
833
                if (iapp->desktop_menu != NULL) {
832
 
                        count = window_menus_get_location(iapp->desktop_menu, entry);
 
834
                        count = window_menu_get_location(iapp->desktop_menu, entry);
833
835
                }
834
836
        }
835
837
        return count;
842
844
        return entry_activate_window(io, entry, 0, timestamp);
843
845
}
844
846
 
 
847
/* Find the BAMF Window that is associated with that XID.  Unfortunately
 
848
   this requires a bit of searching, don't do it too often */
 
849
static BamfWindow *
 
850
xid_to_bamf_window (IndicatorAppmenu * iapp, guint xid)
 
851
{
 
852
        GList * windows = bamf_matcher_get_windows(iapp->matcher);
 
853
        GList * window;
 
854
        BamfWindow * newwindow = NULL;
 
855
 
 
856
        for (window = windows; window != NULL; window = g_list_next(window)) {
 
857
                if (!BAMF_IS_WINDOW(window->data)) {
 
858
                        continue;
 
859
                }
 
860
 
 
861
                BamfWindow * testwindow = BAMF_WINDOW(window->data);
 
862
 
 
863
                if (xid == bamf_window_get_xid(testwindow)) {
 
864
                        newwindow = testwindow;
 
865
                        break;
 
866
                }
 
867
        }
 
868
        g_list_free(windows);
 
869
 
 
870
        return newwindow;
 
871
}
 
872
 
845
873
/* Responds to a menuitem being activated on the panel. */
846
874
static void
847
875
entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp)
851
879
        /* We need to force a focus change in this case as we probably
852
880
           just haven't gotten the signal from BAMF yet */
853
881
        if (windowid != 0) {
854
 
                GList * windows = bamf_matcher_get_windows(iapp->matcher);
855
 
                GList * window;
856
 
                BamfView * newwindow = NULL;
857
 
 
858
 
                for (window = windows; window != NULL; window = g_list_next(window)) {
859
 
                        if (!BAMF_IS_WINDOW(window->data)) {
860
 
                                continue;
861
 
                        }
862
 
 
863
 
                        BamfWindow * testwindow = BAMF_WINDOW(window->data);
864
 
 
865
 
                        if (windowid == bamf_window_get_xid(testwindow)) {
866
 
                                newwindow = BAMF_VIEW(testwindow);
867
 
                                break;
868
 
                        }
869
 
                }
870
 
                g_list_free(windows);
 
882
                BamfView * newwindow = BAMF_VIEW(xid_to_bamf_window(iapp, windowid));
871
883
 
872
884
                if (newwindow != NULL) {
873
885
                        active_window_changed(iapp->matcher, BAMF_VIEW(iapp->active_window), newwindow, iapp);
875
887
        }
876
888
 
877
889
        if (iapp->default_app != NULL) {
878
 
                window_menus_entry_activate(iapp->default_app, entry, timestamp);
 
890
                window_menu_entry_activate(iapp->default_app, entry, timestamp);
879
891
                return;
880
892
        }
881
893
 
882
894
        if (iapp->active_window == NULL) {
883
895
                if (iapp->desktop_menu != NULL) {
884
 
                        window_menus_entry_activate(iapp->desktop_menu, entry, timestamp);
 
896
                        window_menu_entry_activate(iapp->desktop_menu, entry, timestamp);
885
897
                }
886
898
                return;
887
899
        }
969
981
/* Switch applications, remove all the entires for the previous
970
982
   one and add them for the new application */
971
983
static void
972
 
switch_default_app (IndicatorAppmenu * iapp, WindowMenus * newdef, BamfWindow * active_window)
 
984
switch_default_app (IndicatorAppmenu * iapp, WindowMenu * newdef, BamfWindow * active_window)
973
985
{
974
986
        if (iapp->default_app == newdef && iapp->default_app != NULL) {
975
987
                /* We've got an app with menus and it hasn't changed. */
1024
1036
 
1025
1037
                /* Connect signals */
1026
1038
                iapp->sig_entry_added =   g_signal_connect(G_OBJECT(iapp->default_app),
1027
 
                                                           WINDOW_MENUS_SIGNAL_ENTRY_ADDED,
 
1039
                                                           WINDOW_MENU_SIGNAL_ENTRY_ADDED,
1028
1040
                                                           G_CALLBACK(window_entry_added),
1029
1041
                                                           iapp);
1030
1042
                iapp->sig_entry_removed = g_signal_connect(G_OBJECT(iapp->default_app),
1031
 
                                                           WINDOW_MENUS_SIGNAL_ENTRY_REMOVED,
 
1043
                                                           WINDOW_MENU_SIGNAL_ENTRY_REMOVED,
1032
1044
                                                           G_CALLBACK(window_entry_removed),
1033
1045
                                                           iapp);
1034
1046
                iapp->sig_status_changed = g_signal_connect(G_OBJECT(iapp->default_app),
1035
 
                                                           WINDOW_MENUS_SIGNAL_STATUS_CHANGED,
 
1047
                                                           WINDOW_MENU_SIGNAL_STATUS_CHANGED,
1036
1048
                                                           G_CALLBACK(window_status_changed),
1037
1049
                                                           iapp);
1038
1050
                iapp->sig_show_menu     = g_signal_connect(G_OBJECT(iapp->default_app),
1039
 
                                                           WINDOW_MENUS_SIGNAL_SHOW_MENU,
 
1051
                                                           WINDOW_MENU_SIGNAL_SHOW_MENU,
1040
1052
                                                           G_CALLBACK(window_show_menu),
1041
1053
                                                           iapp);
1042
1054
                iapp->sig_a11y_update   = g_signal_connect(G_OBJECT(iapp->default_app),
1043
 
                                                           WINDOW_MENUS_SIGNAL_A11Y_UPDATE,
 
1055
                                                           WINDOW_MENU_SIGNAL_A11Y_UPDATE,
1044
1056
                                                           G_CALLBACK(window_a11y_update),
1045
1057
                                                           iapp);
1046
1058
        }
1048
1060
        /* show the entries that we're swapping in */
1049
1061
        indicator_object_set_visible (INDICATOR_OBJECT(iapp), TRUE);
1050
1062
 
1051
 
                /* Set up initial state for new entries if needed */
 
1063
        /* Set up initial state for new entries if needed */
1052
1064
        if (iapp->default_app != NULL &&
1053
 
            window_menus_get_status (iapp->default_app) != DBUSMENU_STATUS_NORMAL) {
 
1065
            window_menu_get_status (iapp->default_app) != WINDOW_MENU_STATUS_NORMAL) {
1054
1066
                window_status_changed (iapp->default_app,
1055
 
                                       window_menus_get_status (iapp->default_app),
 
1067
                                       window_menu_get_status (iapp->default_app),
1056
1068
                                       iapp);
1057
1069
        }
1058
1070
 
1083
1095
                return;
1084
1096
        }
1085
1097
 
1086
 
        WindowMenus * menus = NULL;
 
1098
        WindowMenu * menus = NULL;
1087
1099
        guint32 xid = 0;
1088
1100
 
1089
1101
        while (window != NULL && menus == NULL) {
1091
1103
        
1092
1104
                menus = g_hash_table_lookup(appmenu->apps, GUINT_TO_POINTER(xid));
1093
1105
 
 
1106
                /* First look to see if we can get these from the
 
1107
                   GMenuModel access */
 
1108
                if (menus == NULL) {
 
1109
                        gchar * uniquename = bamf_window_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
 
1110
 
 
1111
                        if (uniquename != NULL) {
 
1112
                                menus = WINDOW_MENU(window_menu_model_new(/* TODO */ NULL, window));
 
1113
 
 
1114
                                g_hash_table_insert(appmenu->apps, GUINT_TO_POINTER(xid), menus);
 
1115
                        }
 
1116
 
 
1117
                        g_free(uniquename);
 
1118
                }
 
1119
 
1094
1120
                if (menus == NULL) {
1095
1121
                        g_debug("Looking for parent window on XID %d", xid);
1096
1122
                        window = bamf_window_get_transient(window);
1116
1142
menus_destroyed (GObject * menus, gpointer user_data)
1117
1143
{
1118
1144
        gboolean reload_menus = FALSE;
1119
 
        WindowMenus * wm = WINDOW_MENUS(menus);
 
1145
        WindowMenu * wm = WINDOW_MENU(menus);
1120
1146
        IndicatorAppmenu * iapp = INDICATOR_APPMENU(user_data);
1121
1147
 
1122
 
        guint32 xid = window_menus_get_xid(wm);
 
1148
        guint32 xid = window_menu_get_xid(wm);
1123
1149
        g_return_if_fail(xid != 0);
1124
1150
 
1125
1151
        g_hash_table_steal(iapp->apps, GUINT_TO_POINTER(xid));
1158
1184
        g_hash_table_remove(iapp->destruction_timers, GUINT_TO_POINTER(windowid));
1159
1185
 
1160
1186
        if (g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid)) == NULL && windowid != 0) {
1161
 
                WindowMenus * wm = window_menus_new(windowid, sender, objectpath);
 
1187
                WindowMenu * wm = WINDOW_MENU(window_menu_dbusmenu_new(windowid, sender, objectpath));
1162
1188
                g_return_val_if_fail(wm != NULL, FALSE);
1163
1189
 
1164
1190
                g_hash_table_insert(iapp->apps, GUINT_TO_POINTER(windowid), wm);
1233
1259
static GVariant *
1234
1260
get_menu_for_window (IndicatorAppmenu * iapp, guint windowid, GError ** error)
1235
1261
{
1236
 
        WindowMenus * wm = NULL;
 
1262
        WindowMenu * wm = NULL;
1237
1263
 
1238
1264
        if (windowid == 0) {
1239
1265
                wm = iapp->default_app;
1240
1266
        } else {
1241
 
                wm = WINDOW_MENUS(g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid)));
 
1267
                wm = WINDOW_MENU(g_hash_table_lookup(iapp->apps, GUINT_TO_POINTER(windowid)));
1242
1268
        }
1243
1269
 
1244
1270
        if (wm == NULL) {
1246
1272
                return NULL;
1247
1273
        }
1248
1274
 
1249
 
        return g_variant_new("(so)", window_menus_get_address(wm),
1250
 
                             window_menus_get_path(wm));
 
1275
        GVariantBuilder builder;
 
1276
        g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
 
1277
 
 
1278
        if (IS_WINDOW_MENU_DBUSMENU(wm)) {
 
1279
                g_variant_builder_add_value(&builder, g_variant_new_string(window_menu_dbusmenu_get_address(WINDOW_MENU_DBUSMENU(wm))));
 
1280
                g_variant_builder_add_value(&builder, g_variant_new_object_path(window_menu_dbusmenu_get_path(WINDOW_MENU_DBUSMENU(wm))));
 
1281
        } else {
 
1282
                g_variant_builder_add_value(&builder, g_variant_new_string(""));
 
1283
                g_variant_builder_add_value(&builder, g_variant_new_object_path("/"));
 
1284
        }
 
1285
 
 
1286
        return g_variant_builder_end(&builder);
1251
1287
}
1252
1288
 
1253
1289
/* Get all the menus we have */
1269
1305
 
1270
1306
                GVariantBuilder tuple;
1271
1307
                g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE);
1272
 
                g_variant_builder_add_value(&tuple, g_variant_new_uint32(window_menus_get_xid(WINDOW_MENUS(hash_val))));
1273
 
                g_variant_builder_add_value(&tuple, g_variant_new_string(window_menus_get_address(WINDOW_MENUS(hash_val))));
1274
 
                g_variant_builder_add_value(&tuple, g_variant_new_object_path(window_menus_get_path(WINDOW_MENUS(hash_val))));
 
1308
                g_variant_builder_add_value(&tuple, g_variant_new_uint32(window_menu_get_xid(WINDOW_MENU(hash_val))));
 
1309
 
 
1310
                if (IS_WINDOW_MENU_DBUSMENU(hash_val)) {
 
1311
                        g_variant_builder_add_value(&tuple, g_variant_new_string(window_menu_dbusmenu_get_address(WINDOW_MENU_DBUSMENU(hash_val))));
 
1312
                        g_variant_builder_add_value(&tuple, g_variant_new_object_path(window_menu_dbusmenu_get_path(WINDOW_MENU_DBUSMENU(hash_val))));
 
1313
                } else {
 
1314
                        g_variant_builder_add_value(&tuple, g_variant_new_string(""));
 
1315
                        g_variant_builder_add_value(&tuple, g_variant_new_object_path("/"));
 
1316
                }
1275
1317
 
1276
1318
                g_variant_builder_add_value(&array, g_variant_builder_end(&tuple));
1277
1319
        }
1324
1366
 
1325
1367
/* Pass up the entry added event */
1326
1368
static void
1327
 
window_entry_added (WindowMenus * mw, IndicatorObjectEntry * entry, gpointer user_data)
 
1369
window_entry_added (WindowMenu * mw, IndicatorObjectEntry * entry, gpointer user_data)
1328
1370
{
1329
1371
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, entry);
1330
1372
        return;
1332
1374
 
1333
1375
/* Pass up the entry removed event */
1334
1376
static void
1335
 
window_entry_removed (WindowMenus * mw, IndicatorObjectEntry * entry, gpointer user_data)
 
1377
window_entry_removed (WindowMenu * mw, IndicatorObjectEntry * entry, gpointer user_data)
1336
1378
{
1337
1379
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, entry);
1338
1380
        return;
1340
1382
 
1341
1383
/* Pass up the status changed event */
1342
1384
static void
1343
 
window_status_changed (WindowMenus * mw, DbusmenuStatus status, IndicatorAppmenu * iapp)
 
1385
window_status_changed (WindowMenu * mw, DbusmenuStatus status, IndicatorAppmenu * iapp)
1344
1386
{
1345
1387
        gboolean show_now = (status == DBUSMENU_STATUS_NOTICE);
1346
1388
        GList * entry_head, * entries;
1357
1399
 
1358
1400
/* Pass up the show menu event */
1359
1401
static void
1360
 
window_show_menu (WindowMenus * mw, IndicatorObjectEntry * entry, guint timestamp, gpointer user_data)
 
1402
window_show_menu (WindowMenu * mw, IndicatorObjectEntry * entry, guint timestamp, gpointer user_data)
1361
1403
{
1362
1404
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_MENU_SHOW, entry, timestamp);
1363
1405
        return;
1365
1407
 
1366
1408
/* Pass up the accessible string update */
1367
1409
static void
1368
 
window_a11y_update (WindowMenus * mw, IndicatorObjectEntry * entry, gpointer user_data)
 
1410
window_a11y_update (WindowMenu * mw, IndicatorObjectEntry * entry, gpointer user_data)
1369
1411
{
1370
1412
        g_signal_emit_by_name(G_OBJECT(user_data), INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, entry);
1371
1413
        return;