~unity-api-team/hud/lp-1288025

« back to all changes in this revision

Viewing changes to src/window-menu-model.c

Tags: upstream-13.04.0
Import upstream version 13.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2012 Canonical Limited
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the licence, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16
 
 *
17
 
 * Author: Ted Gould <ted.gould@canonical.com>
18
 
 */
19
 
 
20
 
#ifdef HAVE_CONFIG_H
21
 
#include "config.h"
22
 
#endif
23
 
 
24
 
#include <libbamf/libbamf.h>
25
 
#include <gio/gio.h>
26
 
#include <gtk/gtk.h>
27
 
#include <glib/gi18n.h>
28
 
#include <gio/gdesktopappinfo.h>
29
 
 
30
 
#include "window-menu-model.h"
31
 
 
32
 
struct _WindowMenuModelPrivate {
33
 
        guint xid;
34
 
 
35
 
        GtkAccelGroup * accel_group;
36
 
        GActionGroup * app_actions;
37
 
        GActionGroup * win_actions;
38
 
 
39
 
        /* Application Menu */
40
 
        GDBusMenuModel * app_menu_model;
41
 
        IndicatorObjectEntry application_menu;
42
 
        gboolean has_application_menu;
43
 
 
44
 
        /* Window Menus */
45
 
        GDBusMenuModel * win_menu_model;
46
 
        GtkMenu * win_menu;
47
 
        gulong win_menu_insert;
48
 
        gulong win_menu_remove;
49
 
};
50
 
 
51
 
#define WINDOW_MENU_MODEL_GET_PRIVATE(o) \
52
 
(G_TYPE_INSTANCE_GET_PRIVATE ((o), WINDOW_MENU_MODEL_TYPE, WindowMenuModelPrivate))
53
 
 
54
 
/* Base class stuff */
55
 
static void                window_menu_model_class_init (WindowMenuModelClass *klass);
56
 
static void                window_menu_model_init       (WindowMenuModel *self);
57
 
static void                window_menu_model_dispose    (GObject *object);
58
 
static void                window_menu_model_finalize   (GObject *object);
59
 
 
60
 
/* Window Menu subclassin' */
61
 
static GList *             get_entries                  (WindowMenu * wm);
62
 
static guint               get_location                 (WindowMenu * wm,
63
 
                                                         IndicatorObjectEntry * entry);
64
 
static WindowMenuStatus    get_status                   (WindowMenu * wm);
65
 
static gboolean            get_error_state              (WindowMenu * wm);
66
 
static guint               get_xid                      (WindowMenu * wm);
67
 
 
68
 
/* GLib boilerplate */
69
 
G_DEFINE_TYPE (WindowMenuModel, window_menu_model, WINDOW_MENU_TYPE);
70
 
 
71
 
/* Prefixes to the action muxer */
72
 
#define ACTION_MUX_PREFIX_WIN  "win"
73
 
#define ACTION_MUX_PREFIX_APP  "app"
74
 
 
75
 
/* Entry data on the menuitem */
76
 
#define ENTRY_DATA  "window-menu-model-menuitem-entry"
77
 
 
78
 
static void
79
 
window_menu_model_class_init (WindowMenuModelClass *klass)
80
 
{
81
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
82
 
 
83
 
        g_type_class_add_private (klass, sizeof (WindowMenuModelPrivate));
84
 
 
85
 
        object_class->dispose = window_menu_model_dispose;
86
 
        object_class->finalize = window_menu_model_finalize;
87
 
 
88
 
        WindowMenuClass * wm_class = WINDOW_MENU_CLASS(klass);
89
 
 
90
 
        wm_class->get_entries = get_entries;
91
 
        wm_class->get_location = get_location;
92
 
        wm_class->get_status = get_status;
93
 
        wm_class->get_error_state = get_error_state;
94
 
        wm_class->get_xid = get_xid;
95
 
 
96
 
        return;
97
 
}
98
 
 
99
 
static void
100
 
window_menu_model_init (WindowMenuModel *self)
101
 
{
102
 
        self->priv = WINDOW_MENU_MODEL_GET_PRIVATE(self);
103
 
 
104
 
        self->priv->accel_group = gtk_accel_group_new();
105
 
 
106
 
        return;
107
 
}
108
 
 
109
 
static void
110
 
window_menu_model_dispose (GObject *object)
111
 
{
112
 
        WindowMenuModel * menu = WINDOW_MENU_MODEL(object);
113
 
 
114
 
        g_clear_object(&menu->priv->accel_group);
115
 
 
116
 
        /* Application Menu */
117
 
        g_clear_object(&menu->priv->app_menu_model);
118
 
        g_clear_object(&menu->priv->application_menu.label);
119
 
        g_clear_object(&menu->priv->application_menu.menu);
120
 
 
121
 
        /* Window Menus */
122
 
        if (menu->priv->win_menu_insert != 0) {
123
 
                g_signal_handler_disconnect(menu->priv->win_menu, menu->priv->win_menu_insert);
124
 
                menu->priv->win_menu_insert = 0;
125
 
        }
126
 
 
127
 
        if (menu->priv->win_menu_remove != 0) {
128
 
                g_signal_handler_disconnect(menu->priv->win_menu, menu->priv->win_menu_remove);
129
 
                menu->priv->win_menu_remove = 0;
130
 
        }
131
 
 
132
 
        g_clear_object(&menu->priv->win_menu_model);
133
 
        g_clear_object(&menu->priv->win_menu);
134
 
 
135
 
        g_clear_object(&menu->priv->win_actions);
136
 
        g_clear_object(&menu->priv->app_actions);
137
 
 
138
 
        G_OBJECT_CLASS (window_menu_model_parent_class)->dispose (object);
139
 
        return;
140
 
}
141
 
 
142
 
static void
143
 
window_menu_model_finalize (GObject *object)
144
 
{
145
 
 
146
 
        G_OBJECT_CLASS (window_menu_model_parent_class)->finalize (object);
147
 
        return;
148
 
}
149
 
 
150
 
/* Adds the application menu and turns the whole thing into an object
151
 
   entry that can be used elsewhere */
152
 
static void
153
 
add_application_menu (WindowMenuModel * menu, const gchar * appname, GMenuModel * model)
154
 
{
155
 
        g_return_if_fail(G_IS_MENU_MODEL(model));
156
 
 
157
 
        menu->priv->app_menu_model = g_object_ref(model);
158
 
 
159
 
        if (appname != NULL) {
160
 
                menu->priv->application_menu.label = GTK_LABEL(gtk_label_new(appname));
161
 
        } else {
162
 
                menu->priv->application_menu.label = GTK_LABEL(gtk_label_new(_("Unknown Application Name")));
163
 
        }
164
 
        g_object_ref_sink(menu->priv->application_menu.label);
165
 
        gtk_widget_show(GTK_WIDGET(menu->priv->application_menu.label));
166
 
 
167
 
        menu->priv->application_menu.menu = GTK_MENU(gtk_menu_new_from_model(model));
168
 
        if (menu->priv->app_actions) {
169
 
                gtk_widget_insert_action_group(GTK_WIDGET(menu->priv->application_menu.menu), ACTION_MUX_PREFIX_APP, menu->priv->app_actions);
170
 
        }
171
 
        if (menu->priv->win_actions) {
172
 
                gtk_widget_insert_action_group(GTK_WIDGET(menu->priv->application_menu.menu), ACTION_MUX_PREFIX_WIN, menu->priv->win_actions);
173
 
        }
174
 
 
175
 
        gtk_widget_show(GTK_WIDGET(menu->priv->application_menu.menu));
176
 
        g_object_ref_sink(menu->priv->application_menu.menu);
177
 
 
178
 
        menu->priv->has_application_menu = TRUE;
179
 
 
180
 
        return;
181
 
}
182
 
 
183
 
/* Find the label in a GTK MenuItem */
184
 
GtkLabel *
185
 
mi_find_label (GtkWidget * mi)
186
 
{
187
 
        if (GTK_IS_LABEL(mi)) {
188
 
                return GTK_LABEL(mi);
189
 
        }
190
 
 
191
 
        GtkLabel * retval = NULL;
192
 
 
193
 
        if (GTK_IS_CONTAINER(mi)) {
194
 
                GList * children = gtk_container_get_children(GTK_CONTAINER(mi));
195
 
                GList * child = children;
196
 
 
197
 
                while (child != NULL && retval == NULL) {
198
 
                        if (GTK_IS_WIDGET(child->data)) {
199
 
                                retval = mi_find_label(GTK_WIDGET(child->data));
200
 
                        }
201
 
                        child = g_list_next(child);
202
 
                }
203
 
 
204
 
                g_list_free(children);
205
 
        }
206
 
 
207
 
        return retval;
208
 
}
209
 
 
210
 
/* Find the icon in a GTK MenuItem */
211
 
GtkImage *
212
 
mi_find_icon (GtkWidget * mi)
213
 
{
214
 
        if (GTK_IS_IMAGE(mi)) {
215
 
                return GTK_IMAGE(mi);
216
 
        }
217
 
 
218
 
        GtkImage * retval = NULL;
219
 
 
220
 
        if (GTK_IS_CONTAINER(mi)) {
221
 
                GList * children = gtk_container_get_children(GTK_CONTAINER(mi));
222
 
                GList * child = children;
223
 
 
224
 
                while (child != NULL && retval == NULL) {
225
 
                        if (GTK_IS_WIDGET(child->data)) {
226
 
                                retval = mi_find_icon(GTK_WIDGET(child->data));
227
 
                        }
228
 
                        child = g_list_next(child);
229
 
                }
230
 
 
231
 
                g_list_free(children);
232
 
        }
233
 
 
234
 
        return retval;
235
 
}
236
 
 
237
 
/* Check the menu and make sure we return it if it's a menu
238
 
   all proper like that */
239
 
GtkMenu *
240
 
mi_find_menu (GtkMenuItem * mi)
241
 
{
242
 
        GtkWidget * retval = gtk_menu_item_get_submenu(mi);
243
 
        if (GTK_IS_MENU(retval)) {
244
 
                return GTK_MENU(retval);
245
 
        } else {
246
 
                return NULL;
247
 
        }
248
 
}
249
 
 
250
 
typedef struct _WindowMenuEntry WindowMenuEntry;
251
 
struct _WindowMenuEntry {
252
 
        IndicatorObjectEntry entry;
253
 
 
254
 
        GtkMenuItem * gmi;
255
 
 
256
 
        gulong label_sig;
257
 
        gulong sensitive_sig;
258
 
        gulong visible_sig;
259
 
};
260
 
 
261
 
/* Destroy and unref the items of the object entry */
262
 
static void
263
 
entry_object_free (gpointer inentry)
264
 
{
265
 
        WindowMenuEntry * entry = (WindowMenuEntry *)inentry;
266
 
 
267
 
        if (entry->label_sig != 0) {
268
 
                g_signal_handler_disconnect(entry->gmi, entry->label_sig);
269
 
        }
270
 
 
271
 
        if (entry->sensitive_sig != 0) {
272
 
                g_signal_handler_disconnect(entry->gmi, entry->sensitive_sig);
273
 
        }
274
 
 
275
 
        if (entry->visible_sig != 0) {
276
 
                g_signal_handler_disconnect(entry->gmi, entry->visible_sig);
277
 
        }
278
 
 
279
 
        g_clear_object(&entry->entry.label);
280
 
        g_clear_object(&entry->entry.image);
281
 
        g_clear_object(&entry->entry.menu);
282
 
 
283
 
        g_free(entry);
284
 
        return;
285
 
}
286
 
 
287
 
/* Sync the menu label changing to the label object */
288
 
static void
289
 
entry_label_notify (GObject * obj, GParamSpec * pspec, gpointer user_data)
290
 
{
291
 
        g_return_if_fail(GTK_IS_MENU_ITEM(obj));
292
 
 
293
 
        GtkMenuItem * gmi = GTK_MENU_ITEM(obj);
294
 
        WindowMenuEntry * entry = (WindowMenuEntry *)user_data;
295
 
 
296
 
        if (entry->entry.label != NULL) {
297
 
                const gchar * label = gtk_menu_item_get_label(gmi);
298
 
                gtk_label_set_label(entry->entry.label, label);
299
 
        }
300
 
 
301
 
        return;
302
 
}
303
 
 
304
 
/* Watch for visible changes and ensure they can be picked up by the
305
 
   indicator object host */
306
 
static void
307
 
entry_visible_notify (GObject * obj, GParamSpec * pspec, gpointer user_data)
308
 
{
309
 
        g_return_if_fail(GTK_IS_WIDGET(obj));
310
 
        GtkWidget * widget = GTK_WIDGET(obj);
311
 
        WindowMenuEntry * entry = (WindowMenuEntry *)user_data;
312
 
        gboolean visible = gtk_widget_get_visible(widget);
313
 
 
314
 
        if (entry->entry.label != NULL) {
315
 
                gtk_widget_set_visible(GTK_WIDGET(entry->entry.label), visible);
316
 
        }
317
 
 
318
 
        if (entry->entry.image != NULL) {
319
 
                gtk_widget_set_visible(GTK_WIDGET(entry->entry.image), visible);
320
 
        }
321
 
 
322
 
        return;
323
 
}
324
 
 
325
 
/* Watch for sensitive changes and ensure they can be picked up by the
326
 
   indicator object host */
327
 
static void
328
 
entry_sensitive_notify (GObject * obj, GParamSpec * pspec, gpointer user_data)
329
 
{
330
 
        g_return_if_fail(GTK_IS_WIDGET(obj));
331
 
        GtkWidget * widget = GTK_WIDGET(obj);
332
 
        WindowMenuEntry * entry = (WindowMenuEntry *)user_data;
333
 
        gboolean sensitive = gtk_widget_get_sensitive(widget);
334
 
 
335
 
        if (entry->entry.label != NULL) {
336
 
                gtk_widget_set_sensitive(GTK_WIDGET(entry->entry.label), sensitive);
337
 
        }
338
 
 
339
 
        if (entry->entry.image != NULL) {
340
 
                gtk_widget_set_sensitive(GTK_WIDGET(entry->entry.image), sensitive);
341
 
        }
342
 
 
343
 
        return;
344
 
}
345
 
 
346
 
/* Put an entry on a menu item */
347
 
static void
348
 
entry_on_menuitem (WindowMenuModel * menu, GtkMenuItem * gmi)
349
 
{
350
 
        WindowMenuEntry * entry = g_new0(WindowMenuEntry, 1);
351
 
 
352
 
        if (menu->priv->app_actions) {
353
 
                gtk_widget_insert_action_group(GTK_WIDGET(gmi), ACTION_MUX_PREFIX_APP, menu->priv->app_actions);
354
 
        }
355
 
        if (menu->priv->win_actions) {
356
 
                gtk_widget_insert_action_group(GTK_WIDGET(gmi), ACTION_MUX_PREFIX_WIN, menu->priv->win_actions);
357
 
        }
358
 
 
359
 
 
360
 
        entry->gmi = gmi;
361
 
 
362
 
        entry->entry.label = mi_find_label(GTK_WIDGET(gmi));
363
 
        entry->entry.image = mi_find_icon(GTK_WIDGET(gmi));
364
 
        entry->entry.menu = mi_find_menu(gmi);
365
 
 
366
 
        if (entry->entry.label == NULL && entry->entry.image == NULL) {
367
 
                const gchar * label = gtk_menu_item_get_label(gmi);
368
 
                if (label == NULL) {
369
 
                        g_warning("Item doesn't have a label or an image, aborting");
370
 
                        return;
371
 
                }
372
 
 
373
 
                entry->entry.label = GTK_LABEL(gtk_label_new(label));
374
 
                gtk_widget_show(GTK_WIDGET(entry->entry.label));
375
 
                entry->label_sig = g_signal_connect(G_OBJECT(gmi), "notify::label", G_CALLBACK(entry_label_notify), entry->entry.label);
376
 
        }
377
 
 
378
 
        if (entry->entry.label != NULL) {
379
 
                g_object_ref_sink(entry->entry.label);
380
 
        }
381
 
 
382
 
        if (entry->entry.image != NULL) {
383
 
                g_object_ref_sink(entry->entry.image);
384
 
        }
385
 
 
386
 
        if (entry->entry.menu != NULL) {
387
 
                g_object_ref_sink(entry->entry.menu);
388
 
        }
389
 
 
390
 
        entry->sensitive_sig = g_signal_connect(G_OBJECT(gmi), "notify::sensitive", G_CALLBACK(entry_sensitive_notify), entry);
391
 
        entry->visible_sig = g_signal_connect(G_OBJECT(gmi), "notify::visible", G_CALLBACK(entry_visible_notify), entry);
392
 
 
393
 
        g_object_set_data_full(G_OBJECT(gmi), ENTRY_DATA, entry, entry_object_free);
394
 
 
395
 
        return;
396
 
}
397
 
 
398
 
/* A child item was added to a menu we're watching.  Let's try to integrate it. */
399
 
static void
400
 
item_inserted_cb (GtkContainer *menu,
401
 
                  GtkWidget    *widget,
402
 
                  gint          position,
403
 
                  gpointer      data)
404
 
{
405
 
        if (g_object_get_data(G_OBJECT(widget), ENTRY_DATA) == NULL) {
406
 
                entry_on_menuitem(WINDOW_MENU_MODEL(data), GTK_MENU_ITEM(widget));
407
 
        }
408
 
 
409
 
        if (g_object_get_data(G_OBJECT(widget), ENTRY_DATA) != NULL) {
410
 
                g_signal_emit_by_name(data, WINDOW_MENU_SIGNAL_ENTRY_ADDED, g_object_get_data(G_OBJECT(widget), ENTRY_DATA));
411
 
        }
412
 
 
413
 
        return;
414
 
}
415
 
 
416
 
/* A child item was removed from a menu we're watching. */
417
 
static void
418
 
item_removed_cb (GtkContainer *menu, GtkWidget *widget, gpointer data)
419
 
{
420
 
        g_signal_emit_by_name(data, WINDOW_MENU_SIGNAL_ENTRY_REMOVED, g_object_get_data(G_OBJECT(widget), ENTRY_DATA));
421
 
        return;
422
 
}
423
 
 
424
 
/* Adds the window menu and turns it into a set of IndicatorObjectEntries
425
 
   that can be used elsewhere */
426
 
static void
427
 
add_window_menu (WindowMenuModel * menu, GMenuModel * model)
428
 
{
429
 
        menu->priv->win_menu_model = g_object_ref(model);
430
 
 
431
 
        menu->priv->win_menu = GTK_MENU(gtk_menu_new_from_model(model));
432
 
        g_assert(menu->priv->win_menu != NULL);
433
 
        g_object_ref_sink(menu->priv->win_menu);
434
 
 
435
 
        menu->priv->win_menu_insert = g_signal_connect(G_OBJECT (menu->priv->win_menu),
436
 
                "insert",
437
 
                G_CALLBACK (item_inserted_cb),
438
 
                menu);
439
 
        menu->priv->win_menu_remove = g_signal_connect (G_OBJECT (menu->priv->win_menu),
440
 
                "remove",
441
 
                G_CALLBACK (item_removed_cb),
442
 
                menu);
443
 
 
444
 
        GList * children = gtk_container_get_children(GTK_CONTAINER(menu->priv->win_menu));
445
 
        GList * child;
446
 
        for (child = children; child != NULL; child = g_list_next(child)) {
447
 
                GtkMenuItem * gmi = GTK_MENU_ITEM(child->data);
448
 
 
449
 
                if (gmi == NULL) {
450
 
                        continue;
451
 
                }
452
 
 
453
 
                entry_on_menuitem(menu, gmi);
454
 
        }
455
 
        g_list_free(children);
456
 
 
457
 
        return;
458
 
}
459
 
 
460
 
/* Builds the menu model from the window for the application */
461
 
WindowMenuModel *
462
 
window_menu_model_new (BamfApplication * app, BamfWindow * window)
463
 
{
464
 
        g_return_val_if_fail(BAMF_IS_APPLICATION(app), NULL);
465
 
        g_return_val_if_fail(BAMF_IS_WINDOW(window), NULL);
466
 
 
467
 
        WindowMenuModel * menu = g_object_new(WINDOW_MENU_MODEL_TYPE, NULL);
468
 
 
469
 
        menu->priv->xid = bamf_window_get_xid(window);
470
 
 
471
 
        gchar *unique_bus_name;
472
 
        gchar *app_menu_object_path;
473
 
        gchar *menubar_object_path;
474
 
        gchar *application_object_path;
475
 
        gchar *window_object_path;
476
 
        GDBusConnection *session;
477
 
 
478
 
        unique_bus_name = bamf_window_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
479
 
 
480
 
        if (unique_bus_name == NULL) {
481
 
                /* If this isn't set, we won't get very far... */
482
 
                return NULL;
483
 
        }
484
 
 
485
 
        app_menu_object_path = bamf_window_get_utf8_prop (window, "_GTK_APP_MENU_OBJECT_PATH");
486
 
        menubar_object_path = bamf_window_get_utf8_prop (window, "_GTK_MENUBAR_OBJECT_PATH");
487
 
        application_object_path = bamf_window_get_utf8_prop (window, "_GTK_APPLICATION_OBJECT_PATH");
488
 
        window_object_path = bamf_window_get_utf8_prop (window, "_GTK_WINDOW_OBJECT_PATH");
489
 
 
490
 
        session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
491
 
 
492
 
        /* Setup actions */
493
 
        if (application_object_path != NULL) {
494
 
                menu->priv->app_actions = G_ACTION_GROUP(g_dbus_action_group_get (session, unique_bus_name, application_object_path));
495
 
        }
496
 
 
497
 
        if (window_object_path != NULL) {
498
 
                menu->priv->win_actions = G_ACTION_GROUP(g_dbus_action_group_get (session, unique_bus_name, window_object_path));
499
 
        }
500
 
 
501
 
        /* Build us some menus */
502
 
        if (app_menu_object_path != NULL) {
503
 
                const gchar * desktop_path = bamf_application_get_desktop_file(app);
504
 
                gchar * app_name = NULL;
505
 
 
506
 
                if (desktop_path != NULL) {
507
 
                        GDesktopAppInfo * desktop = g_desktop_app_info_new_from_filename(desktop_path);
508
 
 
509
 
                        if (desktop != NULL) {
510
 
                                app_name = g_strdup(g_app_info_get_name(G_APP_INFO(desktop)));
511
 
 
512
 
                                g_object_unref(desktop);
513
 
                        }
514
 
                }
515
 
 
516
 
                GMenuModel * model = G_MENU_MODEL(g_dbus_menu_model_get (session, unique_bus_name, app_menu_object_path));
517
 
 
518
 
                add_application_menu(menu, app_name, model);
519
 
 
520
 
                g_object_unref(model);
521
 
                g_free(app_name);
522
 
        }
523
 
 
524
 
        if (menubar_object_path != NULL) {
525
 
                GMenuModel * model = G_MENU_MODEL(g_dbus_menu_model_get (session, unique_bus_name, menubar_object_path));
526
 
 
527
 
                add_window_menu(menu, model);
528
 
 
529
 
                g_object_unref(model);
530
 
        }
531
 
 
532
 
        /* when the action groups change, we could end up having items
533
 
         * enabled/disabled.  how to deal with that?
534
 
         */
535
 
 
536
 
        g_free (unique_bus_name);
537
 
        g_free (app_menu_object_path);
538
 
        g_free (menubar_object_path);
539
 
        g_free (application_object_path);
540
 
        g_free (window_object_path);
541
 
 
542
 
        g_object_unref (session);
543
 
 
544
 
        return menu;
545
 
}
546
 
 
547
 
/* Get the list of entries */
548
 
static GList *
549
 
get_entries (WindowMenu * wm)
550
 
{
551
 
        g_return_val_if_fail(IS_WINDOW_MENU_MODEL(wm), NULL);
552
 
        WindowMenuModel * menu = WINDOW_MENU_MODEL(wm);
553
 
 
554
 
        GList * ret = NULL;
555
 
 
556
 
        if (menu->priv->has_application_menu) {
557
 
                ret = g_list_append(ret, &menu->priv->application_menu);
558
 
        }
559
 
 
560
 
        if (menu->priv->win_menu != NULL) {
561
 
                GList * children = gtk_container_get_children(GTK_CONTAINER(menu->priv->win_menu));
562
 
                GList * child;
563
 
                for (child = children; child != NULL; child = g_list_next(child)) {
564
 
                        gpointer entry = g_object_get_data(child->data, ENTRY_DATA);
565
 
 
566
 
                        if (entry == NULL) {
567
 
                                /* Try to build the entry, it is possible (but unlikely) that
568
 
                                   we could beat the signal that this isn't created.  So we'll
569
 
                                   just handle that race here */
570
 
                                entry_on_menuitem(menu, GTK_MENU_ITEM(child->data));
571
 
                                entry = g_object_get_data(child->data, ENTRY_DATA);
572
 
                        }
573
 
 
574
 
                        if (entry != NULL) {
575
 
                                ret = g_list_append(ret, entry);
576
 
                        }
577
 
                }
578
 
 
579
 
                g_list_free(children);
580
 
        }
581
 
 
582
 
        return ret;
583
 
}
584
 
 
585
 
/* Find the location of an entry */
586
 
static guint
587
 
get_location (WindowMenu * wm, IndicatorObjectEntry * entry)
588
 
{
589
 
        g_return_val_if_fail(IS_WINDOW_MENU_MODEL(wm), 0);
590
 
        WindowMenuModel * menu = WINDOW_MENU_MODEL(wm);
591
 
 
592
 
        gboolean found = FALSE;
593
 
        guint pos = 0;
594
 
 
595
 
        if (menu->priv->has_application_menu) {
596
 
                if (entry == &menu->priv->application_menu) {
597
 
                        pos = 0;
598
 
                        found = TRUE;
599
 
                } else {
600
 
                        /* We need to put a shift in if there is an application
601
 
                           menu and we're not looking for that one */
602
 
                        pos = 1;
603
 
                }
604
 
        }
605
 
 
606
 
        if (menu->priv->win_menu != NULL) {
607
 
                GList * children = gtk_container_get_children(GTK_CONTAINER(menu->priv->win_menu));
608
 
                GList * child;
609
 
                for (child = children; child != NULL; child = g_list_next(child), pos++) {
610
 
                        gpointer lentry = g_object_get_data(child->data, ENTRY_DATA);
611
 
 
612
 
                        if (entry == lentry) {
613
 
                                found = TRUE;
614
 
                                break;
615
 
                        }
616
 
                }
617
 
 
618
 
                g_list_free(children);
619
 
        }
620
 
 
621
 
        if (!found) {
622
 
                /* NOTE: Not printing any of the values here because there's
623
 
                   a pretty good chance that they're not valid.  Let's not crash
624
 
                   things here. */
625
 
                g_warning("Unable to find entry: %p", entry);
626
 
        }
627
 
 
628
 
        return pos;
629
 
}
630
 
 
631
 
/* Get's the status of the application to whether underlines should be
632
 
   shown to the application.  GMenuModel doesn't give us this info. */
633
 
static WindowMenuStatus
634
 
get_status (WindowMenu * wm)
635
 
{
636
 
        return WINDOW_MENU_STATUS_NORMAL;
637
 
}
638
 
 
639
 
/* Says whether the application is in error, GMenuModel doesn't give us this
640
 
   information on the app */
641
 
static gboolean
642
 
get_error_state (WindowMenu * wm)
643
 
{
644
 
        return FALSE;
645
 
}
646
 
 
647
 
/* Get the XID of this guy */
648
 
static guint
649
 
get_xid (WindowMenu * wm)
650
 
{
651
 
        g_return_val_if_fail(IS_WINDOW_MENU_MODEL(wm), 0);
652
 
        return WINDOW_MENU_MODEL(wm)->priv->xid;
653
 
}