~ubuntu-branches/ubuntu/oneiric/gnome-panel/oneiric

« back to all changes in this revision

Viewing changes to .pc/09_default_icons.patch/gnome-panel/menu.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Bicha
  • Date: 2011-08-17 21:57:14 UTC
  • mfrom: (1.13.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110817215714-mr18pl4hqedmprd7
Tags: 1:3.1.5-0ubuntu1
* New upstream release.
* debian/control: Bump gnome-menus dependencies
* debian/libpanel-applet-4-dev.install: No longer any *.a files to install
* debian/patches/09_default_icons.patch: Disabled until it can be ported
* debian/patches/90_build_fixes.patch: Dropped, applied upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 1997 - 2000 The Free Software Foundation
3
 
 * Copyright (C) 2000 Helix Code, Inc.
4
 
 * Copyright (C) 2000 Eazel, Inc.
5
 
 * Copyright (C) 2004 Red Hat Inc.
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU General Public License as
9
 
 * published by the Free Software Foundation; either version 2 of the
10
 
 * License, or (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful, but
13
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20
 
 * 02111-1307, USA.
21
 
 */
22
 
 
23
 
#include <config.h>
24
 
 
25
 
#include "menu.h"
26
 
 
27
 
#include <string.h>
28
 
 
29
 
#include <glib/gi18n.h>
30
 
#include <gio/gio.h>
31
 
#include <gdk/gdkkeysyms.h>
32
 
 
33
 
#include <libpanel-util/panel-keyfile.h>
34
 
#include <libpanel-util/panel-xdg.h>
35
 
 
36
 
#include "launcher.h"
37
 
#include "panel-util.h"
38
 
#include "panel.h"
39
 
#include "panel-stock-icons.h"
40
 
#include "panel-action-button.h"
41
 
#include "panel-menu-button.h"
42
 
#include "panel-menu-items.h"
43
 
#include "panel-globals.h"
44
 
#include "panel-run-dialog.h"
45
 
#include "panel-lockdown.h"
46
 
#include "panel-icon-names.h"
47
 
 
48
 
typedef struct {
49
 
        GtkWidget    *pixmap;
50
 
        const char   *stock_id;
51
 
        GIcon        *gicon;
52
 
        char         *image;
53
 
        char         *fallback_image;
54
 
        GtkIconTheme *icon_theme;
55
 
        GtkIconSize   icon_size;
56
 
} IconToLoad;
57
 
 
58
 
typedef struct {
59
 
        GtkWidget   *image;
60
 
        const char  *stock_id;
61
 
        GIcon       *gicon;
62
 
        GdkPixbuf   *pixbuf;
63
 
        GtkIconSize  icon_size;
64
 
} IconToAdd;
65
 
 
66
 
static guint load_icons_id = 0;
67
 
static GHashTable *loaded_icons = NULL;
68
 
static GList *icons_to_load = NULL;
69
 
static GList *icons_to_add = NULL;
70
 
 
71
 
static GSList *image_menu_items = NULL;
72
 
 
73
 
static GtkWidget *populate_menu_from_directory (GtkWidget          *menu,
74
 
                                                GMenuTreeDirectory *directory);
75
 
 
76
 
static void panel_load_menu_image_deferred (GtkWidget   *image_menu_item,
77
 
                                            GtkIconSize  icon_size,
78
 
                                            const char  *stock_id,
79
 
                                            GIcon       *gicon,
80
 
                                            const char  *image_filename,
81
 
                                            const char  *fallback_image_filename);
82
 
 
83
 
GtkWidget *
84
 
add_menu_separator (GtkWidget *menu)
85
 
{
86
 
        GtkWidget *menuitem;
87
 
        
88
 
        menuitem = gtk_separator_menu_item_new ();
89
 
        gtk_widget_set_sensitive (menuitem, FALSE);
90
 
        gtk_widget_show (menuitem);
91
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
92
 
 
93
 
        return menuitem;
94
 
}
95
 
 
96
 
static void
97
 
activate_app_def (GtkWidget      *menuitem,
98
 
                  GMenuTreeEntry *entry)
99
 
{
100
 
        const char       *path;
101
 
 
102
 
        path = gmenu_tree_entry_get_desktop_file_path (entry);
103
 
        panel_menu_item_activate_desktop_file (menuitem, path);
104
 
}
105
 
 
106
 
PanelWidget *
107
 
menu_get_panel (GtkWidget *menu)
108
 
{
109
 
        PanelWidget *retval = NULL;
110
 
 
111
 
        g_return_val_if_fail (menu != NULL, NULL);
112
 
 
113
 
        if (GTK_IS_MENU_ITEM (menu))
114
 
                menu = gtk_widget_get_parent (menu);
115
 
 
116
 
        g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
117
 
 
118
 
        while (menu) {
119
 
                retval = g_object_get_data (G_OBJECT (menu), "menu_panel");
120
 
                if (retval)
121
 
                        break;
122
 
 
123
 
                menu = gtk_widget_get_parent (gtk_menu_get_attach_widget (GTK_MENU (menu)));
124
 
                if (!GTK_IS_MENU (menu))
125
 
                        break;
126
 
        }
127
 
 
128
 
        if (retval && !PANEL_IS_WIDGET (retval)) {
129
 
                g_warning ("Invalid PanelWidget associated with menu");
130
 
                retval = NULL;
131
 
        }
132
 
 
133
 
        if (!retval) {
134
 
                g_warning ("Cannot find the PanelWidget associated with menu");
135
 
                retval = panels->data;
136
 
        }
137
 
 
138
 
        return retval;
139
 
}
140
 
 
141
 
static void
142
 
setup_menu_panel (GtkWidget *menu)
143
 
{
144
 
        PanelWidget *panel;
145
 
 
146
 
        panel = g_object_get_data (G_OBJECT (menu), "menu_panel");
147
 
        if (panel)
148
 
                return;
149
 
 
150
 
        panel = menu_get_panel (menu);
151
 
        g_object_set_data (G_OBJECT (menu), "menu_panel", panel);
152
 
 
153
 
        if (panel)
154
 
                gtk_menu_set_screen (GTK_MENU (menu),
155
 
                                     gtk_widget_get_screen (GTK_WIDGET (panel)));
156
 
}
157
 
 
158
 
GdkScreen *
159
 
menuitem_to_screen (GtkWidget *menuitem)
160
 
{
161
 
        PanelWidget *panel_widget;
162
 
 
163
 
        panel_widget = menu_get_panel (menuitem);
164
 
 
165
 
        return gtk_window_get_screen (GTK_WINDOW (panel_widget->toplevel));
166
 
}
167
 
 
168
 
static void
169
 
reload_image_menu_items (void)
170
 
{
171
 
        GSList *l;
172
 
 
173
 
        for (l = image_menu_items; l; l = l->next) {
174
 
                GtkWidget *image = l->data;
175
 
                gboolean   is_mapped;
176
 
      
177
 
                is_mapped = gtk_widget_get_mapped (image);
178
 
 
179
 
                if (is_mapped)
180
 
                        gtk_widget_unmap (image);
181
 
 
182
 
                gtk_image_set_from_pixbuf (GTK_IMAGE (image), NULL);
183
 
    
184
 
                if (is_mapped)
185
 
                        gtk_widget_map (image);
186
 
 
187
 
        }
188
 
}
189
 
 
190
 
static void
191
 
icon_theme_changed (GtkIconTheme *icon_theme,
192
 
                    gpointer      data)
193
 
{
194
 
        reload_image_menu_items ();
195
 
}
196
 
 
197
 
GtkWidget *
198
 
panel_create_menu (void)
199
 
{
200
 
        GtkWidget       *retval;
201
 
        GtkStyleContext *context;
202
 
        static gboolean  registered_icon_theme_changer = FALSE;
203
 
 
204
 
        if (!registered_icon_theme_changer) {
205
 
                registered_icon_theme_changer = TRUE;
206
 
 
207
 
                g_signal_connect (gtk_icon_theme_get_default (), "changed",
208
 
                                  G_CALLBACK (icon_theme_changed), NULL);
209
 
        }
210
 
        
211
 
        retval = gtk_menu_new ();
212
 
        gtk_widget_set_name (retval, "gnome-panel-main-menu");
213
 
 
214
 
        context = gtk_widget_get_style_context (retval);
215
 
        gtk_style_context_add_class (context, "gnome-panel-main-menu");
216
 
 
217
 
        return retval;
218
 
}
219
 
 
220
 
GtkWidget *
221
 
create_empty_menu (void)
222
 
{
223
 
        GtkWidget *retval;
224
 
 
225
 
        retval = panel_create_menu ();
226
 
 
227
 
        g_signal_connect (retval, "show", G_CALLBACK (setup_menu_panel), NULL);
228
 
 
229
 
        /* intercept all right button clicks makes sure they don't
230
 
           go to the object itself */
231
 
        g_signal_connect (retval, "button_press_event",
232
 
                          G_CALLBACK (menu_dummy_button_press_event), NULL);
233
 
 
234
 
        return retval;
235
 
}
236
 
 
237
 
static void
238
 
icon_to_load_free (IconToLoad *icon)
239
 
{
240
 
        if (!icon)
241
 
                return;
242
 
 
243
 
        if (icon->pixmap)
244
 
                g_object_unref (icon->pixmap);
245
 
        icon->pixmap = NULL;
246
 
 
247
 
        if (icon->gicon)
248
 
                g_object_unref (icon->gicon);
249
 
        icon->gicon = NULL;
250
 
 
251
 
        g_free (icon->image);          icon->image = NULL;
252
 
        g_free (icon->fallback_image); icon->fallback_image = NULL;
253
 
        g_free (icon);
254
 
}
255
 
 
256
 
static IconToLoad *
257
 
icon_to_load_copy (IconToLoad *icon)
258
 
{
259
 
        IconToLoad *retval;
260
 
 
261
 
        if (!icon)
262
 
                return NULL;
263
 
 
264
 
        retval = g_new0 (IconToLoad, 1);
265
 
 
266
 
        retval->pixmap         = g_object_ref (icon->pixmap);
267
 
        if (icon->gicon)
268
 
                retval->gicon  = g_object_ref (icon->gicon);
269
 
        else
270
 
                retval->gicon  = NULL;
271
 
        retval->image          = g_strdup (icon->image);
272
 
        retval->fallback_image = g_strdup (icon->fallback_image);
273
 
        retval->stock_id       = icon->stock_id;
274
 
        retval->icon_size      = icon->icon_size;
275
 
 
276
 
        return retval;
277
 
}
278
 
 
279
 
static void
280
 
remove_pixmap_from_loaded (gpointer data, GObject *where_the_object_was)
281
 
{
282
 
        char *key = data;
283
 
 
284
 
        if (loaded_icons != NULL)
285
 
                g_hash_table_remove (loaded_icons, key);
286
 
 
287
 
        g_free (key);
288
 
}
289
 
 
290
 
GdkPixbuf *
291
 
panel_make_menu_icon (GtkIconTheme *icon_theme,
292
 
                      const char   *icon,
293
 
                      const char   *fallback,
294
 
                      int           size,
295
 
                      gboolean     *long_operation)
296
 
{
297
 
        GdkPixbuf *pb;
298
 
        char *file, *key;
299
 
        gboolean loaded;
300
 
 
301
 
        g_return_val_if_fail (size > 0, NULL);
302
 
 
303
 
        file = NULL;
304
 
        if (icon != NULL)
305
 
                file = panel_find_icon (icon_theme, icon, size);
306
 
        if (file == NULL && fallback != NULL)
307
 
                file = panel_find_icon (icon_theme, fallback, size);
308
 
 
309
 
        if (file == NULL)
310
 
                return NULL;
311
 
 
312
 
        if (long_operation != NULL)
313
 
                *long_operation = TRUE;
314
 
 
315
 
        pb = NULL;
316
 
 
317
 
        loaded = FALSE;
318
 
 
319
 
        key = g_strdup_printf ("%d:%s", size, file);
320
 
 
321
 
        if (loaded_icons != NULL &&
322
 
            (pb = g_hash_table_lookup (loaded_icons, key)) != NULL) {
323
 
                if (pb != NULL)
324
 
                        g_object_ref (G_OBJECT (pb));
325
 
        }
326
 
 
327
 
        if (pb == NULL) {
328
 
                pb = gdk_pixbuf_new_from_file (file, NULL);
329
 
                if (pb) {
330
 
                        gint width, height;
331
 
 
332
 
                        width = gdk_pixbuf_get_width (pb);
333
 
                        height = gdk_pixbuf_get_height (pb);
334
 
                        
335
 
                        /* if we want 24 and we get 22, do nothing;
336
 
                         * else scale */
337
 
                        if (!(size - 2 <= width && width <= size &&
338
 
                              size - 2 <= height && height <= size)) {
339
 
                                GdkPixbuf *tmp;
340
 
 
341
 
                                tmp = gdk_pixbuf_scale_simple (pb, size, size,
342
 
                                                               GDK_INTERP_BILINEAR);
343
 
 
344
 
                                g_object_unref (pb);
345
 
                                pb = tmp;
346
 
                        }
347
 
                }
348
 
                                
349
 
                /* add icon to the hash table so we don't load it again */
350
 
                loaded = TRUE;
351
 
        }
352
 
 
353
 
        if (pb == NULL) {
354
 
                g_free (file);
355
 
                g_free (key);
356
 
                return NULL;
357
 
        }
358
 
 
359
 
        if (loaded &&
360
 
            (gdk_pixbuf_get_width (pb) != size &&
361
 
             gdk_pixbuf_get_height (pb) != size)) {
362
 
                GdkPixbuf *pb2;
363
 
                int        dest_width;
364
 
                int        dest_height;
365
 
                int        width;
366
 
                int        height;
367
 
 
368
 
                width  = gdk_pixbuf_get_width (pb);
369
 
                height = gdk_pixbuf_get_height (pb);
370
 
 
371
 
                if (height > width) {
372
 
                        dest_width  = (size * width) / height;
373
 
                        dest_height = size;
374
 
                } else {
375
 
                        dest_width  = size;
376
 
                        dest_height = (size * height) / width;
377
 
                }
378
 
 
379
 
                pb2 = gdk_pixbuf_scale_simple (pb, dest_width, dest_height,
380
 
                                               GDK_INTERP_BILINEAR);
381
 
                g_object_unref (G_OBJECT (pb));
382
 
                pb = pb2;
383
 
        }
384
 
 
385
 
        if (loaded) {
386
 
                if (loaded_icons == NULL)
387
 
                        loaded_icons = g_hash_table_new_full
388
 
                                (g_str_hash, g_str_equal,
389
 
                                 (GDestroyNotify) g_free,
390
 
                                 (GDestroyNotify) g_object_unref);
391
 
                g_hash_table_replace (loaded_icons,
392
 
                                      g_strdup (key),
393
 
                                      g_object_ref (G_OBJECT (pb)));
394
 
                g_object_weak_ref (G_OBJECT (pb),
395
 
                                   (GWeakNotify) remove_pixmap_from_loaded,
396
 
                                   g_strdup (key));
397
 
        } else {
398
 
                /* we didn't load from disk */
399
 
                if (long_operation != NULL)
400
 
                        *long_operation = FALSE;
401
 
        }
402
 
 
403
 
        g_free (file);
404
 
        g_free (key);
405
 
 
406
 
        return pb;
407
 
}
408
 
 
409
 
static void
410
 
menu_item_style_updated (GtkImage *image,
411
 
                         gpointer  data)
412
 
{
413
 
        GtkWidget   *widget;
414
 
        GdkPixbuf   *pixbuf;
415
 
        GtkIconSize  icon_size = (GtkIconSize) GPOINTER_TO_INT (data);
416
 
        int          icon_height;
417
 
        gboolean     is_mapped;
418
 
 
419
 
        if (!gtk_icon_size_lookup (icon_size, NULL, &icon_height))
420
 
                return;
421
 
 
422
 
        pixbuf = gtk_image_get_pixbuf (image);
423
 
        if (!pixbuf)
424
 
                return;
425
 
 
426
 
        if (gdk_pixbuf_get_height (pixbuf) == icon_height)
427
 
                return;
428
 
 
429
 
        widget = GTK_WIDGET (image);
430
 
 
431
 
        is_mapped = gtk_widget_get_mapped (widget);
432
 
        if (is_mapped)
433
 
                gtk_widget_unmap (widget);
434
 
 
435
 
        gtk_image_set_from_pixbuf (image, NULL);
436
 
    
437
 
        if (is_mapped)
438
 
                gtk_widget_map (widget);
439
 
}
440
 
 
441
 
static void
442
 
do_icons_to_add (void)
443
 
{
444
 
        while (icons_to_add) {
445
 
                IconToAdd *icon_to_add = icons_to_add->data;
446
 
 
447
 
                icons_to_add = g_list_delete_link (icons_to_add, icons_to_add);
448
 
 
449
 
                if (icon_to_add->stock_id) {
450
 
                        gtk_image_set_from_stock (
451
 
                                GTK_IMAGE (icon_to_add->image),
452
 
                                icon_to_add->stock_id,
453
 
                                icon_to_add->icon_size);
454
 
                } else if (icon_to_add->gicon) {
455
 
                        gtk_image_set_from_gicon (
456
 
                                GTK_IMAGE (icon_to_add->image),
457
 
                                icon_to_add->gicon,
458
 
                                icon_to_add->icon_size);
459
 
                } else {
460
 
                        g_assert (icon_to_add->pixbuf);
461
 
 
462
 
                        gtk_image_set_from_pixbuf (
463
 
                                GTK_IMAGE (icon_to_add->image),
464
 
                                icon_to_add->pixbuf);
465
 
 
466
 
                        g_signal_connect (icon_to_add->image, "style-updated",
467
 
                                          G_CALLBACK (menu_item_style_updated),
468
 
                                          GINT_TO_POINTER (icon_to_add->icon_size));
469
 
 
470
 
                        g_object_unref (icon_to_add->pixbuf);
471
 
                }
472
 
 
473
 
                if (icon_to_add->gicon)
474
 
                        g_object_unref (icon_to_add->gicon);
475
 
                g_object_unref (icon_to_add->image);
476
 
                g_free (icon_to_add);
477
 
        }
478
 
}
479
 
 
480
 
static gboolean
481
 
load_icons_handler (gpointer data)
482
 
{
483
 
        IconToLoad *icon;
484
 
        gboolean    long_operation = FALSE;
485
 
 
486
 
load_icons_handler_again:
487
 
 
488
 
        if (!icons_to_load) {
489
 
                load_icons_id = 0;
490
 
                do_icons_to_add ();
491
 
 
492
 
                return FALSE;
493
 
        }
494
 
 
495
 
        icon = icons_to_load->data;
496
 
        icons_to_load->data = NULL;
497
 
        /* pop */
498
 
        icons_to_load = g_list_delete_link (icons_to_load, icons_to_load);
499
 
 
500
 
        /* if not visible anymore, just ignore */
501
 
        if ( ! gtk_widget_get_visible (icon->pixmap)) {
502
 
                icon_to_load_free (icon);
503
 
                /* we didn't do anything long/hard, so just do this again,
504
 
                 * this is fun, don't go back to main loop */
505
 
                goto load_icons_handler_again;
506
 
        }
507
 
 
508
 
        if (icon->stock_id || icon->gicon) {
509
 
                IconToAdd *icon_to_add;
510
 
 
511
 
                icon_to_add            = g_new (IconToAdd, 1);
512
 
                icon_to_add->image     = g_object_ref (icon->pixmap);
513
 
                icon_to_add->stock_id  = icon->stock_id;
514
 
                icon_to_add->pixbuf    = NULL;
515
 
                icon_to_add->icon_size = icon->icon_size;
516
 
                if (icon->gicon)
517
 
                        icon_to_add->gicon = g_object_ref (icon->gicon);
518
 
                else
519
 
                        icon_to_add->gicon = NULL;
520
 
 
521
 
                icons_to_add = g_list_prepend (icons_to_add, icon_to_add);
522
 
        } else {
523
 
                IconToAdd *icon_to_add;
524
 
                GdkPixbuf *pb;
525
 
                int        icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
526
 
 
527
 
                gtk_icon_size_lookup (icon->icon_size, NULL, &icon_height);
528
 
 
529
 
                pb = panel_make_menu_icon (icon->icon_theme,
530
 
                                           icon->image,
531
 
                                           icon->fallback_image,
532
 
                                           icon_height,
533
 
                                           &long_operation);
534
 
                if (!pb) {
535
 
                        icon_to_load_free (icon);
536
 
                        if (long_operation)
537
 
                                /* this may have been a long operation so jump back to
538
 
                                 * the main loop for a while */
539
 
                                return TRUE;
540
 
                        else
541
 
                                /* we didn't do anything long/hard, so just do this again,
542
 
                                 * this is fun, don't go back to main loop */
543
 
                                goto load_icons_handler_again;
544
 
                }
545
 
 
546
 
                icon_to_add            = g_new (IconToAdd, 1);
547
 
                icon_to_add->image     = g_object_ref (icon->pixmap);
548
 
                icon_to_add->stock_id  = NULL;
549
 
                icon_to_add->gicon     = NULL;
550
 
                icon_to_add->pixbuf    = pb;
551
 
                icon_to_add->icon_size = icon->icon_size;
552
 
 
553
 
                icons_to_add = g_list_prepend (icons_to_add, icon_to_add);
554
 
        }
555
 
 
556
 
        icon_to_load_free (icon);
557
 
 
558
 
        if (!long_operation)
559
 
                /* we didn't do anything long/hard, so just do this again,
560
 
                 * this is fun, don't go back to main loop */
561
 
                goto load_icons_handler_again;
562
 
 
563
 
        /* if still more we'll come back */
564
 
        return TRUE;
565
 
}
566
 
 
567
 
gboolean
568
 
menu_dummy_button_press_event (GtkWidget      *menuitem,
569
 
                               GdkEventButton *event)
570
 
{
571
 
        if (event->button == 3)
572
 
                return TRUE;
573
 
 
574
 
        return FALSE;
575
 
}
576
 
 
577
 
static void  
578
 
drag_begin_menu_cb (GtkWidget *widget, GdkDragContext     *context)
579
 
{
580
 
        /* FIXME: workaround for a possible gtk+ bug
581
 
         *    See bugs #92085(gtk+) and #91184(panel) for details.
582
 
         *    Maybe it's not needed with GtkTooltip?
583
 
         */
584
 
        g_object_set (widget, "has-tooltip", FALSE, NULL);
585
 
}
586
 
 
587
 
/* This is a _horrible_ hack to have this here. This needs to be added to the
588
 
 * GTK+ menuing code in some manner.
589
 
 */
590
 
static void  
591
 
drag_end_menu_cb (GtkWidget *widget, GdkDragContext     *context)
592
 
{
593
 
  GtkWidget *xgrab_shell;
594
 
  GtkWidget *parent;
595
 
 
596
 
  /* Find the last viewable ancestor, and make an X grab on it
597
 
   */
598
 
  parent = gtk_widget_get_parent (widget);
599
 
  xgrab_shell = NULL;
600
 
 
601
 
  /* FIXME: workaround for a possible gtk+ bug
602
 
   *    See bugs #92085(gtk+) and #91184(panel) for details.
603
 
   */
604
 
  g_object_set (widget, "has-tooltip", TRUE, NULL);
605
 
 
606
 
  while (parent)
607
 
    {
608
 
      gboolean viewable = TRUE;
609
 
      GtkWidget *tmp = parent;
610
 
      
611
 
      while (tmp)
612
 
        {
613
 
          if (!gtk_widget_get_mapped (tmp))
614
 
            {
615
 
              viewable = FALSE;
616
 
              break;
617
 
            }
618
 
          tmp = gtk_widget_get_parent (tmp);
619
 
        }
620
 
      
621
 
      if (viewable)
622
 
        xgrab_shell = parent;
623
 
      
624
 
      parent = gtk_menu_shell_get_parent_shell (GTK_MENU_SHELL (parent));
625
 
    }
626
 
  
627
 
  if (xgrab_shell && !gtk_menu_get_tearoff_state (GTK_MENU(xgrab_shell)))
628
 
    {
629
 
      gboolean      status;
630
 
      GdkDisplay    *display;
631
 
      GdkDevice     *pointer;
632
 
      GdkDevice     *keyboard;
633
 
      GdkDeviceManager *device_manager;
634
 
      GdkWindow *window = gtk_widget_get_window (xgrab_shell);
635
 
      GdkCursor *cursor = gdk_cursor_new (GDK_ARROW);
636
 
 
637
 
      display = gdk_window_get_display (window);
638
 
      device_manager = gdk_display_get_device_manager (display);
639
 
      pointer = gdk_device_manager_get_client_pointer (device_manager);
640
 
      keyboard = gdk_device_get_associated_device (pointer);
641
 
 
642
 
      /* FIXMEgpoo: Not sure if report to GDK_OWNERSHIP_WINDOW
643
 
                    or GDK_OWNERSHIP_APPLICATION. Idem for the
644
 
                    keyboard below */
645
 
      status = gdk_device_grab (pointer, window,
646
 
                                GDK_OWNERSHIP_WINDOW, TRUE,
647
 
                                GDK_BUTTON_PRESS_MASK
648
 
                                | GDK_BUTTON_RELEASE_MASK
649
 
                                | GDK_ENTER_NOTIFY_MASK
650
 
                                | GDK_LEAVE_NOTIFY_MASK
651
 
                                | GDK_POINTER_MOTION_MASK,
652
 
                                cursor, GDK_CURRENT_TIME);
653
 
 
654
 
      if (!status)
655
 
        {
656
 
          if (gdk_device_grab (keyboard, window,
657
 
                               GDK_OWNERSHIP_WINDOW, TRUE,
658
 
                               GDK_KEY_PRESS | GDK_KEY_RELEASE,
659
 
                               NULL, GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS)
660
 
            {
661
 
            /* FIXMEgpoo: We need either accessors or a workaround to grab
662
 
               the focus */
663
 
#if 0
664
 
             GTK_MENU_SHELL (xgrab_shell)->GSEAL(have_xgrab) = TRUE;
665
 
#endif
666
 
            }
667
 
          else
668
 
            {
669
 
              gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
670
 
            }
671
 
        }
672
 
 
673
 
      g_object_unref (cursor);
674
 
    }
675
 
}
676
 
 
677
 
static void  
678
 
drag_data_get_menu_cb (GtkWidget        *widget,
679
 
                       GdkDragContext   *context,
680
 
                       GtkSelectionData *selection_data,
681
 
                       guint             info,
682
 
                       guint             time,
683
 
                       GMenuTreeEntry   *entry)
684
 
{
685
 
        const char *path;
686
 
        char       *uri;
687
 
        char       *uri_list;
688
 
 
689
 
        path = gmenu_tree_entry_get_desktop_file_path (entry);
690
 
        uri = g_filename_to_uri (path, NULL, NULL);
691
 
        uri_list = g_strconcat (uri, "\r\n", NULL);
692
 
        g_free (uri);
693
 
 
694
 
        gtk_selection_data_set (selection_data,
695
 
                                gtk_selection_data_get_target (selection_data), 8, (guchar *)uri_list,
696
 
                                strlen (uri_list));
697
 
        g_free (uri_list);
698
 
}
699
 
 
700
 
static void
701
 
image_menuitem_set_size_request (GtkWidget  *menuitem,
702
 
                                 GtkIconSize icon_size)
703
 
{
704
 
        GtkStyleContext *context;
705
 
        GtkStateFlags state;
706
 
        GtkBorder padding, border;
707
 
        int border_width;
708
 
        int icon_height;
709
 
        int req_height;
710
 
 
711
 
        if (!gtk_icon_size_lookup (icon_size, NULL, &icon_height))
712
 
                return;
713
 
 
714
 
        /* If we don't have a pixmap for this menuitem
715
 
         * at least make sure its the same height as
716
 
         * the rest.
717
 
         * This is a bit ugly, since we should keep this in sync with what's in
718
 
         * gtk_menu_item_size_request()
719
 
         */
720
 
        context = gtk_widget_get_style_context (menuitem);
721
 
        state = gtk_widget_get_state_flags (menuitem);
722
 
        gtk_style_context_get_padding (context, state, &padding);
723
 
        gtk_style_context_get_border (context, state, &border);
724
 
 
725
 
        border_width = gtk_container_get_border_width (GTK_CONTAINER (menuitem));
726
 
        req_height = icon_height;
727
 
        req_height += (border_width * 2) + padding.top + padding.bottom + border.top + border.bottom;
728
 
        gtk_widget_set_size_request (menuitem, -1, req_height);
729
 
}
730
 
 
731
 
static char *
732
 
menu_escape_underscores_and_prepend (const char *text)
733
 
{
734
 
        GString    *escaped_text;
735
 
        const char *src;
736
 
        int         inserted;
737
 
        
738
 
        if (!text)
739
 
                return g_strdup (text);
740
 
 
741
 
        escaped_text = g_string_sized_new (strlen (text) + 1);
742
 
        g_string_printf (escaped_text, "_%s", text);
743
 
 
744
 
        src = text;
745
 
        inserted = 1;
746
 
 
747
 
        while (*src) {
748
 
                gunichar c;
749
 
 
750
 
                c = g_utf8_get_char (src);
751
 
 
752
 
                if (c == (gunichar)-1) {
753
 
                        g_warning ("Invalid input string for underscore escaping");
754
 
                        return g_strdup (text);
755
 
                } else if (c == '_') {
756
 
                        g_string_insert_c (escaped_text,
757
 
                                           src - text + inserted, '_');
758
 
                        inserted++;
759
 
                }
760
 
 
761
 
                src = g_utf8_next_char (src);
762
 
        }
763
 
 
764
 
        return g_string_free (escaped_text, FALSE);
765
 
}
766
 
 
767
 
void
768
 
setup_menuitem (GtkWidget   *menuitem,
769
 
                GtkIconSize  icon_size,
770
 
                GtkWidget   *image,
771
 
                const char  *title)
772
 
                               
773
 
{
774
 
        GtkWidget *label;
775
 
        char      *_title;
776
 
 
777
 
        /* this creates a label with an invisible mnemonic */
778
 
        label = g_object_new (GTK_TYPE_ACCEL_LABEL, NULL);
779
 
        _title = menu_escape_underscores_and_prepend (title);
780
 
        gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _title);
781
 
        g_free (_title);
782
 
 
783
 
        gtk_label_set_pattern (GTK_LABEL (label), "");
784
 
 
785
 
        gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), menuitem);
786
 
 
787
 
        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
788
 
        gtk_widget_show (label);
789
 
       
790
 
        gtk_container_add (GTK_CONTAINER (menuitem), label);
791
 
 
792
 
        if (image) {
793
 
                g_object_set_data_full (G_OBJECT (menuitem),
794
 
                                        "Panel:Image",
795
 
                                        g_object_ref (image),
796
 
                                        (GDestroyNotify) g_object_unref);
797
 
                gtk_widget_show (image);
798
 
                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
799
 
                                               image);
800
 
        } else if (icon_size != GTK_ICON_SIZE_INVALID)
801
 
                image_menuitem_set_size_request (menuitem, icon_size);
802
 
 
803
 
        gtk_widget_show (menuitem);
804
 
}
805
 
 
806
 
static void
807
 
drag_data_get_string_cb (GtkWidget *widget, GdkDragContext     *context,
808
 
                         GtkSelectionData   *selection_data, guint info,
809
 
                         guint time, const char *string)
810
 
{
811
 
        gtk_selection_data_set (selection_data,
812
 
                                gtk_selection_data_get_target (selection_data), 8, (guchar *)string,
813
 
                                strlen(string));
814
 
}
815
 
 
816
 
void
817
 
setup_uri_drag (GtkWidget  *menuitem,
818
 
                const char *uri,
819
 
                const char *icon)
820
 
{
821
 
        static GtkTargetEntry menu_item_targets[] = {
822
 
                { "text/uri-list", 0, 0 }
823
 
        };
824
 
 
825
 
        if (panel_lockdown_get_panels_locked_down_s ())
826
 
                return;
827
 
 
828
 
        gtk_drag_source_set (menuitem,
829
 
                             GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
830
 
                             menu_item_targets, 1,
831
 
                             GDK_ACTION_COPY);
832
 
 
833
 
        if (icon != NULL)
834
 
                gtk_drag_source_set_icon_name (menuitem, icon);
835
 
        
836
 
        g_signal_connect (G_OBJECT (menuitem), "drag_begin",
837
 
                          G_CALLBACK (drag_begin_menu_cb), NULL);
838
 
        g_signal_connect_data (G_OBJECT (menuitem), "drag_data_get",
839
 
                               G_CALLBACK (drag_data_get_string_cb),
840
 
                               g_strdup (uri),
841
 
                               (GClosureNotify)g_free,
842
 
                               0 /* connect_flags */);
843
 
        g_signal_connect (G_OBJECT (menuitem), "drag_end",
844
 
                          G_CALLBACK (drag_end_menu_cb), NULL);
845
 
}
846
 
 
847
 
void
848
 
setup_internal_applet_drag (GtkWidget             *menuitem,
849
 
                            PanelActionButtonType  type)
850
 
{
851
 
        static GtkTargetEntry menu_item_targets[] = {
852
 
                { "application/x-panel-applet-internal", 0, 0 }
853
 
        };
854
 
 
855
 
        if (panel_lockdown_get_panels_locked_down_s ())
856
 
                return;
857
 
 
858
 
        gtk_drag_source_set (menuitem,
859
 
                             GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
860
 
                             menu_item_targets, 1,
861
 
                             GDK_ACTION_COPY);
862
 
 
863
 
        if (panel_action_get_icon_name (type)  != NULL)
864
 
                gtk_drag_source_set_icon_name (menuitem,
865
 
                                               panel_action_get_icon_name (type));
866
 
        
867
 
        g_signal_connect (G_OBJECT (menuitem), "drag_begin",
868
 
                          G_CALLBACK (drag_begin_menu_cb), NULL);
869
 
        g_signal_connect_data (G_OBJECT (menuitem), "drag_data_get",
870
 
                               G_CALLBACK (drag_data_get_string_cb),
871
 
                               g_strdup (panel_action_get_drag_id (type)),
872
 
                               (GClosureNotify)g_free,
873
 
                               0 /* connect_flags */);
874
 
        g_signal_connect (G_OBJECT (menuitem), "drag_end",
875
 
                          G_CALLBACK (drag_end_menu_cb), NULL);
876
 
}
877
 
 
878
 
static void
879
 
submenu_to_display (GtkWidget *menu)
880
 
{
881
 
        GMenuTree           *tree;
882
 
        GMenuTreeDirectory  *directory;
883
 
        const char          *menu_path;
884
 
        void               (*append_callback) (GtkWidget *, gpointer);
885
 
        gpointer             append_data;
886
 
 
887
 
        if (!g_object_get_data (G_OBJECT (menu), "panel-menu-needs-loading"))
888
 
                return;
889
 
 
890
 
        g_object_set_data (G_OBJECT (menu), "panel-menu-needs-loading", NULL);
891
 
 
892
 
        directory = g_object_get_data (G_OBJECT (menu),
893
 
                                       "panel-menu-tree-directory");
894
 
        if (!directory) {
895
 
                menu_path = g_object_get_data (G_OBJECT (menu),
896
 
                                               "panel-menu-tree-path");
897
 
                if (!menu_path)
898
 
                        return;
899
 
 
900
 
                tree = g_object_get_data (G_OBJECT (menu), "panel-menu-tree");
901
 
                if (!tree)
902
 
                        return;
903
 
 
904
 
                directory = gmenu_tree_get_directory_from_path (tree,
905
 
                                                                menu_path);
906
 
 
907
 
                g_object_set_data_full (G_OBJECT (menu),
908
 
                                        "panel-menu-tree-directory",
909
 
                                        directory,
910
 
                                        (GDestroyNotify) gmenu_tree_item_unref);
911
 
        }
912
 
 
913
 
        if (directory)
914
 
                populate_menu_from_directory (menu, directory);
915
 
 
916
 
        append_callback = g_object_get_data (G_OBJECT (menu),
917
 
                                             "panel-menu-append-callback");
918
 
        append_data     = g_object_get_data (G_OBJECT (menu),
919
 
                                             "panel-menu-append-callback-data");
920
 
        if (append_callback)
921
 
                append_callback (menu, append_data);
922
 
}
923
 
 
924
 
static gboolean
925
 
submenu_to_display_in_idle (gpointer data)
926
 
{
927
 
        GtkWidget *menu = GTK_WIDGET (data);
928
 
 
929
 
        g_object_set_data (G_OBJECT (menu), "panel-menu-idle-id", NULL);
930
 
 
931
 
        submenu_to_display (menu);
932
 
 
933
 
        return FALSE;
934
 
}
935
 
 
936
 
static void
937
 
remove_submenu_to_display_idle (gpointer data)
938
 
{
939
 
        guint idle_id = GPOINTER_TO_UINT (data);
940
 
 
941
 
        g_source_remove (idle_id);
942
 
}
943
 
 
944
 
static GtkWidget *
945
 
create_fake_menu (GMenuTreeDirectory *directory)
946
 
{       
947
 
        GtkWidget *menu;
948
 
        guint      idle_id;
949
 
        
950
 
        menu = create_empty_menu ();
951
 
 
952
 
        g_object_set_data_full (G_OBJECT (menu),
953
 
                                "panel-menu-tree-directory",
954
 
                                gmenu_tree_item_ref (directory),
955
 
                                (GDestroyNotify) gmenu_tree_item_unref);
956
 
        
957
 
        g_object_set_data (G_OBJECT (menu),
958
 
                           "panel-menu-needs-loading",
959
 
                           GUINT_TO_POINTER (TRUE));
960
 
 
961
 
        g_signal_connect (menu, "show",
962
 
                          G_CALLBACK (submenu_to_display), NULL);
963
 
 
964
 
        idle_id = g_idle_add_full (G_PRIORITY_LOW,
965
 
                                   submenu_to_display_in_idle,
966
 
                                   menu,
967
 
                                   NULL);
968
 
        g_object_set_data_full (G_OBJECT (menu),
969
 
                                "panel-menu-idle-id",
970
 
                                GUINT_TO_POINTER (idle_id),
971
 
                                remove_submenu_to_display_idle);
972
 
 
973
 
        g_signal_connect (menu, "button_press_event",
974
 
                          G_CALLBACK (menu_dummy_button_press_event), NULL);
975
 
 
976
 
        return menu;
977
 
}
978
 
 
979
 
GtkWidget *
980
 
panel_image_menu_item_new (void)
981
 
{
982
 
        GtkWidget *menuitem;
983
 
        GtkStyleContext *context;
984
 
 
985
 
        menuitem = gtk_image_menu_item_new ();
986
 
        gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem),
987
 
                                                   TRUE);
988
 
        context = gtk_widget_get_style_context (menuitem);
989
 
        gtk_style_context_add_class (context, "gnome-panel-menu-item");
990
 
 
991
 
        return menuitem;
992
 
}
993
 
 
994
 
static GtkWidget *
995
 
create_submenu_entry (GtkWidget          *menu,
996
 
                      GMenuTreeDirectory *directory)
997
 
{
998
 
        GtkWidget *menuitem;
999
 
        gboolean   force_categories_icon;
1000
 
 
1001
 
        force_categories_icon = g_object_get_data (G_OBJECT (menu),
1002
 
                                                   "panel-menu-force-icon-for-categories") != NULL;
1003
 
 
1004
 
        if (force_categories_icon)
1005
 
                menuitem = panel_image_menu_item_new ();
1006
 
        else
1007
 
                menuitem = gtk_image_menu_item_new ();
1008
 
 
1009
 
        panel_load_menu_image_deferred (menuitem,
1010
 
                                        panel_menu_icon_get_size (),
1011
 
                                        NULL, NULL,
1012
 
                                        gmenu_tree_directory_get_icon (directory),
1013
 
                                        PANEL_ICON_FOLDER);
1014
 
 
1015
 
        setup_menuitem (menuitem,
1016
 
                        panel_menu_icon_get_size (),
1017
 
                        NULL,
1018
 
                        gmenu_tree_directory_get_name (directory));
1019
 
 
1020
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1021
 
 
1022
 
        gtk_widget_show (menuitem);
1023
 
 
1024
 
        return menuitem;
1025
 
}
1026
 
 
1027
 
static void
1028
 
create_submenu (GtkWidget          *menu,
1029
 
                GMenuTreeDirectory *directory,
1030
 
                GMenuTreeDirectory *alias_directory)
1031
 
{
1032
 
        GtkWidget *menuitem;
1033
 
        GtkWidget *submenu;
1034
 
        gboolean   force_categories_icon;
1035
 
 
1036
 
        if (alias_directory)
1037
 
                menuitem = create_submenu_entry (menu, alias_directory);
1038
 
        else
1039
 
                menuitem = create_submenu_entry (menu, directory);
1040
 
        
1041
 
        submenu = create_fake_menu (directory);
1042
 
 
1043
 
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
1044
 
 
1045
 
        /* Keep the infor that we force (or not) the icons to be visible */
1046
 
        force_categories_icon = g_object_get_data (G_OBJECT (menu),
1047
 
                                                   "panel-menu-force-icon-for-categories") != NULL;
1048
 
        g_object_set_data (G_OBJECT (submenu),
1049
 
                           "panel-menu-force-icon-for-categories",
1050
 
                           GINT_TO_POINTER (force_categories_icon));
1051
 
}
1052
 
 
1053
 
static void 
1054
 
create_header (GtkWidget       *menu,
1055
 
               GMenuTreeHeader *header)
1056
 
{
1057
 
        GMenuTreeDirectory *directory;
1058
 
        GtkWidget          *menuitem;
1059
 
 
1060
 
        directory = gmenu_tree_header_get_directory (header);
1061
 
        menuitem = create_submenu_entry (menu, directory);
1062
 
        gmenu_tree_item_unref (directory);
1063
 
 
1064
 
        g_signal_connect (menuitem, "activate",
1065
 
                          G_CALLBACK (gtk_false), NULL);
1066
 
}
1067
 
 
1068
 
static void
1069
 
create_menuitem (GtkWidget          *menu,
1070
 
                 GMenuTreeEntry     *entry,
1071
 
                 GMenuTreeDirectory *alias_directory)
1072
 
{
1073
 
        GtkWidget  *menuitem;
1074
 
        
1075
 
        menuitem = panel_image_menu_item_new ();
1076
 
 
1077
 
        panel_load_menu_image_deferred (menuitem,
1078
 
                                        panel_menu_icon_get_size (),
1079
 
                                        NULL, NULL,
1080
 
                                        alias_directory ? gmenu_tree_directory_get_icon (alias_directory) :
1081
 
                                                          gmenu_tree_entry_get_icon (entry),
1082
 
                                        NULL);
1083
 
 
1084
 
        setup_menuitem (menuitem,
1085
 
                        panel_menu_icon_get_size (),
1086
 
                        NULL,
1087
 
                        alias_directory ? gmenu_tree_directory_get_name (alias_directory) :
1088
 
                                          gmenu_tree_entry_get_display_name (entry));
1089
 
 
1090
 
        if (alias_directory &&
1091
 
            gmenu_tree_directory_get_comment (alias_directory))
1092
 
                panel_util_set_tooltip_text (menuitem,
1093
 
                                             gmenu_tree_directory_get_comment (alias_directory));
1094
 
        else if (!alias_directory &&
1095
 
                 gmenu_tree_entry_get_comment (entry))
1096
 
                panel_util_set_tooltip_text (menuitem,
1097
 
                                             gmenu_tree_entry_get_comment (entry));
1098
 
        else if (!alias_directory &&
1099
 
                 gmenu_tree_entry_get_generic_name (entry))
1100
 
                panel_util_set_tooltip_text (menuitem,
1101
 
                                             gmenu_tree_entry_get_generic_name (entry));
1102
 
 
1103
 
        g_signal_connect_after (menuitem, "button_press_event",
1104
 
                                G_CALLBACK (menu_dummy_button_press_event), NULL);
1105
 
 
1106
 
        if (!panel_lockdown_get_panels_locked_down_s ()) {
1107
 
                static GtkTargetEntry menu_item_targets[] = {
1108
 
                        { "text/uri-list", 0, 0 }
1109
 
                };
1110
 
 
1111
 
                gtk_drag_source_set (menuitem,
1112
 
                                     GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
1113
 
                                     menu_item_targets, 1,
1114
 
                                     GDK_ACTION_COPY);
1115
 
 
1116
 
                if (gmenu_tree_entry_get_icon (entry) != NULL) {
1117
 
                        const char *icon;
1118
 
                        char       *icon_no_ext;
1119
 
 
1120
 
                        icon = gmenu_tree_entry_get_icon (entry);
1121
 
                        if (!g_path_is_absolute (icon)) {
1122
 
                                icon_no_ext = panel_xdg_icon_remove_extension (icon);
1123
 
                                gtk_drag_source_set_icon_name (menuitem,
1124
 
                                                               icon_no_ext);
1125
 
                                g_free (icon_no_ext);
1126
 
                        }
1127
 
                }
1128
 
 
1129
 
                g_signal_connect (G_OBJECT (menuitem), "drag_begin",
1130
 
                                  G_CALLBACK (drag_begin_menu_cb), NULL);
1131
 
                g_signal_connect (menuitem, "drag_data_get",
1132
 
                                  G_CALLBACK (drag_data_get_menu_cb), entry);
1133
 
                g_signal_connect (menuitem, "drag_end",
1134
 
                                  G_CALLBACK (drag_end_menu_cb), NULL);
1135
 
        }
1136
 
 
1137
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1138
 
 
1139
 
        g_signal_connect (menuitem, "activate",
1140
 
                          G_CALLBACK (activate_app_def), entry);
1141
 
 
1142
 
        gtk_widget_show (menuitem);
1143
 
}
1144
 
 
1145
 
static void
1146
 
create_menuitem_from_alias (GtkWidget      *menu,
1147
 
                            GMenuTreeAlias *alias)
1148
 
{
1149
 
        GMenuTreeItem *aliased_item;
1150
 
 
1151
 
        aliased_item = gmenu_tree_alias_get_item (alias);
1152
 
 
1153
 
        switch (gmenu_tree_item_get_type (aliased_item)) {
1154
 
        case GMENU_TREE_ITEM_DIRECTORY:
1155
 
                create_submenu (menu,
1156
 
                                GMENU_TREE_DIRECTORY (aliased_item),
1157
 
                                gmenu_tree_alias_get_directory (alias));
1158
 
                break;
1159
 
 
1160
 
        case GMENU_TREE_ITEM_ENTRY:
1161
 
                create_menuitem (menu,
1162
 
                                 GMENU_TREE_ENTRY (aliased_item),
1163
 
                                 gmenu_tree_alias_get_directory (alias));
1164
 
                break;
1165
 
 
1166
 
        default:
1167
 
                break;
1168
 
        }
1169
 
 
1170
 
        gmenu_tree_item_unref (aliased_item);
1171
 
}
1172
 
 
1173
 
static void
1174
 
handle_gmenu_tree_changed (GMenuTree *tree,
1175
 
                           GtkWidget *menu)
1176
 
{
1177
 
        guint idle_id;
1178
 
        GList *list, *l;
1179
 
 
1180
 
        /* Remove existing items */
1181
 
        list = gtk_container_get_children (GTK_CONTAINER (menu));
1182
 
        for (l = list; l; l = l->next)
1183
 
                gtk_widget_destroy (l->data);
1184
 
        g_list_free (list);
1185
 
 
1186
 
        g_object_set_data_full (G_OBJECT (menu),
1187
 
                                "panel-menu-tree-directory",
1188
 
                                NULL, NULL);
1189
 
 
1190
 
        g_object_set_data (G_OBJECT (menu),
1191
 
                           "panel-menu-needs-loading",
1192
 
                           GUINT_TO_POINTER (TRUE));
1193
 
 
1194
 
        idle_id = g_idle_add_full (G_PRIORITY_LOW,
1195
 
                                   submenu_to_display_in_idle,
1196
 
                                   menu,
1197
 
                                   NULL);
1198
 
        g_object_set_data_full (G_OBJECT (menu),
1199
 
                                "panel-menu-idle-id",
1200
 
                                GUINT_TO_POINTER (idle_id),
1201
 
                                remove_submenu_to_display_idle);
1202
 
}
1203
 
 
1204
 
static void
1205
 
remove_gmenu_tree_monitor (GtkWidget *menu,
1206
 
                          GMenuTree  *tree)
1207
 
{
1208
 
        gmenu_tree_remove_monitor (tree,
1209
 
                                  (GMenuTreeChangedFunc) handle_gmenu_tree_changed,
1210
 
                                  menu);
1211
 
}
1212
 
 
1213
 
GtkWidget *
1214
 
create_applications_menu (const char *menu_file,
1215
 
                          const char *menu_path,
1216
 
                          gboolean    always_show_image)
1217
 
{
1218
 
        GMenuTree *tree;
1219
 
        GtkWidget *menu;
1220
 
        guint      idle_id;
1221
 
 
1222
 
        menu = create_empty_menu ();
1223
 
 
1224
 
        if (always_show_image)
1225
 
                g_object_set_data (G_OBJECT (menu),
1226
 
                                   "panel-menu-force-icon-for-categories",
1227
 
                                   GINT_TO_POINTER (TRUE));
1228
 
 
1229
 
        tree = gmenu_tree_lookup (menu_file, GMENU_TREE_FLAGS_NONE);
1230
 
        gmenu_tree_set_sort_key (tree, GMENU_TREE_SORT_DISPLAY_NAME);
1231
 
 
1232
 
        g_object_set_data_full (G_OBJECT (menu),
1233
 
                                "panel-menu-tree",
1234
 
                                gmenu_tree_ref (tree),
1235
 
                                (GDestroyNotify) gmenu_tree_unref);
1236
 
 
1237
 
        g_object_set_data_full (G_OBJECT (menu),
1238
 
                                "panel-menu-tree-path",
1239
 
                                g_strdup (menu_path ? menu_path : "/"),
1240
 
                                (GDestroyNotify) g_free);
1241
 
        
1242
 
        g_object_set_data (G_OBJECT (menu),
1243
 
                           "panel-menu-needs-loading",
1244
 
                           GUINT_TO_POINTER (TRUE));
1245
 
 
1246
 
        g_signal_connect (menu, "show",
1247
 
                          G_CALLBACK (submenu_to_display), NULL);
1248
 
 
1249
 
        idle_id = g_idle_add_full (G_PRIORITY_LOW,
1250
 
                                   submenu_to_display_in_idle,
1251
 
                                   menu,
1252
 
                                   NULL);
1253
 
        g_object_set_data_full (G_OBJECT (menu),
1254
 
                                "panel-menu-idle-id",
1255
 
                                GUINT_TO_POINTER (idle_id),
1256
 
                                remove_submenu_to_display_idle);
1257
 
 
1258
 
        g_signal_connect (menu, "button_press_event",
1259
 
                          G_CALLBACK (menu_dummy_button_press_event), NULL);
1260
 
 
1261
 
        gmenu_tree_add_monitor (tree,
1262
 
                               (GMenuTreeChangedFunc) handle_gmenu_tree_changed,
1263
 
                               menu);
1264
 
        g_signal_connect (menu, "destroy",
1265
 
                          G_CALLBACK (remove_gmenu_tree_monitor), tree);
1266
 
 
1267
 
        gmenu_tree_unref (tree);
1268
 
 
1269
 
        return menu;
1270
 
}
1271
 
 
1272
 
static GtkWidget *
1273
 
populate_menu_from_directory (GtkWidget          *menu,
1274
 
                              GMenuTreeDirectory *directory)
1275
 
{       
1276
 
        GList    *children;
1277
 
        GSList   *l;
1278
 
        GSList   *items;
1279
 
        gboolean  add_separator;
1280
 
 
1281
 
        children = gtk_container_get_children (GTK_CONTAINER (menu));
1282
 
        add_separator = (children != NULL);
1283
 
        g_list_free (children);
1284
 
 
1285
 
        items = gmenu_tree_directory_get_contents (directory);
1286
 
 
1287
 
        for (l = items; l; l = l->next) {
1288
 
                GMenuTreeItem *item = l->data;
1289
 
 
1290
 
                if (add_separator ||
1291
 
                    gmenu_tree_item_get_type (item) == GMENU_TREE_ITEM_SEPARATOR) {
1292
 
                        add_menu_separator (menu);
1293
 
                        add_separator = FALSE;
1294
 
                }
1295
 
 
1296
 
                switch (gmenu_tree_item_get_type (item)) {
1297
 
                case GMENU_TREE_ITEM_DIRECTORY:
1298
 
                        create_submenu (menu, GMENU_TREE_DIRECTORY (item), NULL);
1299
 
                        break;
1300
 
 
1301
 
                case GMENU_TREE_ITEM_ENTRY:
1302
 
                        create_menuitem (menu, GMENU_TREE_ENTRY (item), NULL);
1303
 
                        break;
1304
 
 
1305
 
                case GMENU_TREE_ITEM_SEPARATOR :
1306
 
                        /* already added */
1307
 
                        break;
1308
 
 
1309
 
                case GMENU_TREE_ITEM_ALIAS:
1310
 
                        create_menuitem_from_alias (menu, GMENU_TREE_ALIAS (item));
1311
 
                        break;
1312
 
 
1313
 
                case GMENU_TREE_ITEM_HEADER:
1314
 
                        create_header (menu, GMENU_TREE_HEADER (item));
1315
 
                        break;
1316
 
 
1317
 
                default:
1318
 
                        break;
1319
 
                }
1320
 
 
1321
 
                gmenu_tree_item_unref (item);
1322
 
        }
1323
 
 
1324
 
        g_slist_free (items);
1325
 
 
1326
 
        return menu;
1327
 
}
1328
 
 
1329
 
void
1330
 
setup_menu_item_with_icon (GtkWidget   *item,
1331
 
                           GtkIconSize  icon_size,
1332
 
                           const char  *icon_name,
1333
 
                           const char  *stock_id,
1334
 
                           GIcon       *gicon,
1335
 
                           const char  *title)
1336
 
{
1337
 
        if (icon_name || gicon || stock_id)
1338
 
                panel_load_menu_image_deferred (item, icon_size,
1339
 
                                                stock_id, gicon,
1340
 
                                                icon_name, NULL);
1341
 
 
1342
 
        setup_menuitem (item, icon_size, NULL, title);
1343
 
}
1344
 
 
1345
 
static void
1346
 
main_menu_append (GtkWidget *main_menu,
1347
 
                  gpointer   data)
1348
 
{
1349
 
        PanelWidget *panel;
1350
 
        GtkWidget   *item;
1351
 
        gboolean     add_separator;
1352
 
        GList       *children;
1353
 
        GList       *last;
1354
 
 
1355
 
        panel = PANEL_WIDGET (data);
1356
 
 
1357
 
        add_separator = FALSE;
1358
 
        children = gtk_container_get_children (GTK_CONTAINER (main_menu));
1359
 
        last = g_list_last (children);
1360
 
        if (last != NULL) {
1361
 
                add_separator = !GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
1362
 
        }
1363
 
        g_list_free (children);
1364
 
 
1365
 
        if (add_separator)
1366
 
                add_menu_separator (main_menu);
1367
 
 
1368
 
        item = panel_place_menu_item_new (TRUE);
1369
 
        panel_place_menu_item_set_panel (item, panel);
1370
 
        gtk_menu_shell_append (GTK_MENU_SHELL (main_menu), item);
1371
 
        gtk_widget_show (item);
1372
 
 
1373
 
        item = panel_desktop_menu_item_new (TRUE, FALSE);
1374
 
        panel_desktop_menu_item_set_panel (item, panel);
1375
 
        gtk_menu_shell_append (GTK_MENU_SHELL (main_menu), item);
1376
 
        gtk_widget_show (item);
1377
 
 
1378
 
        panel_menu_items_append_lock_logout (main_menu);
1379
 
}
1380
 
 
1381
 
GtkWidget *
1382
 
create_main_menu (PanelWidget *panel)
1383
 
{
1384
 
        GtkWidget *main_menu;
1385
 
 
1386
 
        main_menu = create_applications_menu ("applications.menu", NULL, TRUE);
1387
 
 
1388
 
        g_object_set_data (G_OBJECT (main_menu), "menu_panel", panel);
1389
 
        /* FIXME need to update the panel on parent_set */
1390
 
 
1391
 
        g_object_set_data (G_OBJECT (main_menu),
1392
 
                           "panel-menu-append-callback",
1393
 
                           main_menu_append);
1394
 
        g_object_set_data (G_OBJECT (main_menu),
1395
 
                           "panel-menu-append-callback-data",
1396
 
                           panel);
1397
 
 
1398
 
        return main_menu;
1399
 
}
1400
 
 
1401
 
static GList *
1402
 
find_in_load_list (GtkWidget *image)
1403
 
{
1404
 
        GList *li;
1405
 
        for (li = icons_to_load; li != NULL; li = li->next) {
1406
 
                IconToLoad *icon = li->data;
1407
 
                if (icon->pixmap == image)
1408
 
                        return li;
1409
 
        }
1410
 
        return NULL;
1411
 
}
1412
 
 
1413
 
static void
1414
 
image_menu_shown (GtkWidget *image, gpointer data)
1415
 
{
1416
 
        IconToLoad *new_icon;
1417
 
        IconToLoad *icon;
1418
 
        
1419
 
        icon = (IconToLoad *) data;
1420
 
 
1421
 
        /* if we've already handled this */
1422
 
        if (gtk_image_get_storage_type (GTK_IMAGE (image)) != GTK_IMAGE_EMPTY)
1423
 
                return;
1424
 
 
1425
 
        if (find_in_load_list (image) == NULL) {
1426
 
                new_icon = icon_to_load_copy (icon);
1427
 
                new_icon->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (image));
1428
 
                icons_to_load = g_list_append (icons_to_load, new_icon);
1429
 
        }
1430
 
        if (load_icons_id == 0)
1431
 
                load_icons_id = g_idle_add (load_icons_handler, NULL);
1432
 
}
1433
 
 
1434
 
static void
1435
 
image_menu_destroy (GtkWidget *image, gpointer data)
1436
 
{
1437
 
        image_menu_items = g_slist_remove (image_menu_items, image);
1438
 
}
1439
 
 
1440
 
static void
1441
 
panel_load_menu_image_deferred (GtkWidget   *image_menu_item,
1442
 
                                GtkIconSize  icon_size,
1443
 
                                const char  *stock_id,
1444
 
                                GIcon       *gicon,
1445
 
                                const char  *image_filename,
1446
 
                                const char  *fallback_image_filename)
1447
 
{
1448
 
        IconToLoad *icon;
1449
 
        GtkWidget *image;
1450
 
        int        icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
1451
 
 
1452
 
        icon = g_new (IconToLoad, 1);
1453
 
 
1454
 
        gtk_icon_size_lookup (icon_size, NULL, &icon_height);
1455
 
 
1456
 
        image = gtk_image_new ();
1457
 
        gtk_widget_set_size_request (image, icon_height, icon_height);
1458
 
 
1459
 
        /* this takes over the floating ref */
1460
 
        icon->pixmap = g_object_ref_sink (G_OBJECT (image));
1461
 
 
1462
 
        icon->stock_id       = stock_id;
1463
 
        if (gicon)
1464
 
                icon->gicon  = g_object_ref (gicon);
1465
 
        else
1466
 
                icon->gicon  = NULL;
1467
 
        icon->image          = g_strdup (image_filename);
1468
 
        icon->fallback_image = g_strdup (fallback_image_filename);
1469
 
        icon->icon_size      = icon_size;
1470
 
 
1471
 
        gtk_widget_show (image);
1472
 
 
1473
 
        g_object_set_data_full (G_OBJECT (image_menu_item),
1474
 
                                "Panel:Image",
1475
 
                                g_object_ref (image),
1476
 
                                (GDestroyNotify) g_object_unref);
1477
 
 
1478
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (image_menu_item),
1479
 
                                       image);
1480
 
 
1481
 
        g_signal_connect_data (image, "map",
1482
 
                               G_CALLBACK (image_menu_shown), icon,
1483
 
                               (GClosureNotify) icon_to_load_free, 0);
1484
 
 
1485
 
        g_signal_connect (image, "destroy",
1486
 
                          G_CALLBACK (image_menu_destroy), NULL);
1487
 
 
1488
 
        image_menu_items = g_slist_prepend (image_menu_items, image);
1489
 
}