source: trunk/third/gnome-core/panel/menu.c @ 17167

Revision 17167, 164.8 KB checked in by ghudson, 23 years ago (diff)
Merge with gnome-core 1.4.0.6.
Line 
1/*
2 * GNOME panel menu module.
3 * (C) 1997, 1998, 1999, 2000 The Free Software Foundation
4 * Copyright 2000 Helix Code, Inc.
5 * Copyright 2000 Eazel, Inc.
6 *
7 * Authors: Miguel de Icaza
8 *          Federico Mena
9 */
10
11#include <config.h>
12#include <ctype.h>
13#include <stdio.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <sys/wait.h>
17#include <fcntl.h>
18#include <dirent.h>
19#include <unistd.h>
20#include <string.h>
21#include <limits.h>
22#include <errno.h>
23#include <math.h>
24#include <gnome.h>
25
26#include "panel-include.h"
27#include "panel-widget.h"
28#include "tearoffitem.h"
29#include "gnome-run.h"
30#include "title-item.h"
31#include "scroll-menu.h"
32#include "icon-entry-hack.h"
33#include "multiscreen-stuff.h"
34#include "conditional.h"
35
36/*#define PANEL_DEBUG 1*/
37
38typedef enum {
39        SMALL_ICON_SIZE  = 20,
40        MEDIUM_ICON_SIZE = 32,
41        BIG_ICON_SIZE    = 48
42} IconSize;
43
44static char *gnome_folder = NULL;
45
46extern GSList *applets;
47extern GSList *applets_last;
48extern int applet_count;
49
50/*list of all toplevel panel widgets (basep) created*/
51extern GSList *panel_list;
52/*list of all PanelWidgets created*/
53extern GSList *panels;
54
55extern gboolean commie_mode;
56extern gboolean no_run_box;
57extern GlobalConfig global_config;
58
59extern int config_sync_timeout;
60extern int panels_to_sync;
61extern int applets_to_sync;
62extern int need_complete_save;
63
64extern int base_panels;
65
66extern char *kde_menudir;
67extern char *kde_icondir;
68extern char *kde_mini_icondir;
69
70extern GtkTooltips *panel_tooltips;
71
72static GtkStyle *title_style;
73
74enum {
75        HELP_BUTTON = 0,
76        REVERT_BUTTON,
77        CLOSE_BUTTON
78};
79
80typedef struct _TearoffMenu TearoffMenu;
81struct _TearoffMenu {
82        GtkWidget *menu;
83        GSList *mfl;
84        char *special;
85        char *title;
86        char *wmclass;
87};
88
89/* list of TearoffMenu s */
90static GSList *tearoffs = NULL;
91
92typedef struct _ShowItemMenu ShowItemMenu;
93struct _ShowItemMenu {
94        int type;
95        const char *item_loc;
96        MenuFinfo *mf;
97        GtkWidget *menu;
98        GtkWidget *menuitem;
99        int applet;
100};
101
102typedef struct _FakeIcon FakeIcon;
103struct _FakeIcon {
104        GtkWidget *fake;
105        char *file;
106        int size;
107};
108
109static guint load_icons_id = 0;
110static GSList *icons_to_load = NULL;
111
112static GtkWidget * create_menu_at_fr (GtkWidget *menu,
113                                      FileRec *fr,
114                                      gboolean applets,
115                                      gboolean launcher_add,
116                                      gboolean favourites_add,
117                                      const char *dir_name,
118                                      const char *pixmap_name,
119                                      gboolean fake_submenus,
120                                      gboolean force,
121                                      gboolean title);
122static GtkWidget * create_panel_submenu (GtkWidget *m,
123                                         gboolean fake_sub,
124                                         gboolean tearoff,
125                                         gboolean is_base);
126static GtkWidget * create_desktop_menu (GtkWidget *m,
127                                        gboolean fake_sub,
128                                        gboolean tearoff);
129
130static GtkWidget * fake_pixmap_from_fake (FakeIcon *fake);
131
132static void add_kde_submenu (GtkWidget *root_menu,
133                             gboolean fake_submenus,
134                             gboolean launcher_add,
135                             gboolean favourites_add);
136static void add_distribution_submenu (GtkWidget *root_menu,
137                                      gboolean fake_submenus,
138                                      gboolean launcher_add,
139                                      gboolean favourites_add);
140
141static GtkWidget * create_add_launcher_menu (GtkWidget *menu,
142                                             gboolean fake_submenus);
143static GtkWidget * create_add_favourites_menu (GtkWidget *menu,
144                                               gboolean fake_submenus);
145
146static void setup_menuitem_try_pixmap (GtkWidget *menuitem,
147                                       const char *try_file,
148                                       const char *title,
149                                       IconSize icon_size);
150
151/*to be called on startup to load in some of the directories,
152  this makes the startup a little bit slower, and take up slightly
153  more ram, but it also speeds up later operation*/
154void
155init_menus (void)
156{
157        const DistributionInfo *distribution_info = get_distribution_info ();
158        char *menu;
159        GdkFont *font;
160
161        /*just load the menus from disk, don't make the widgets
162          this just reads the .desktops of the top most directory
163          and a level down*/
164        menu = g_strdup ("/var/athena/menus");
165        if (menu != NULL)
166                fr_read_dir (NULL, menu, NULL, NULL, 2);
167        g_free (menu);
168
169        menu = gnome_datadir_file ("applets");
170        if (menu != NULL)
171                fr_read_dir (NULL, menu, NULL, NULL, 2);
172        g_free (menu);
173
174        menu = gnome_util_home_file ("apps");
175        if (menu != NULL)
176                fr_read_dir (NULL, menu, NULL, NULL, 2);
177        g_free (menu);
178
179        if (distribution_info != NULL &&
180            distribution_info->menu_init_func != NULL)
181                distribution_info->menu_init_func ();
182
183        title_style = gtk_style_copy (gtk_widget_get_default_style ());
184        font = gdk_font_load ("-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-1");
185        if (font)
186          {
187            gdk_font_unref (title_style->font);
188            title_style->font = font;
189          }
190}
191
192static gboolean
193check_for_screen (GtkWidget *w, GdkEvent *ev, gpointer data)
194{
195        static int times = 0;
196        if (ev->type != GDK_KEY_PRESS)
197                return FALSE;
198        if (ev->key.keyval == GDK_f ||
199            ev->key.keyval == GDK_F) {
200                times++;
201                if (times == 3) {
202                        times = 0;
203                        start_screen_check ();
204                }
205        }
206        return FALSE;
207}
208
209/*the most important dialog in the whole application*/
210static void
211about_cb (GtkWidget *widget, gpointer data)
212{
213        static GtkWidget *about;
214        GtkWidget *hbox, *l;
215        char *authors[] = {
216          "George Lebl (jirka@5z.com)",
217          "Jacob Berkman (jberkman@andrew.cmu.edu)",
218          "Miguel de Icaza (miguel@kernel.org)",
219          "Federico Mena (quartic@gimp.org)",
220          "Tom Tromey (tromey@cygnus.com)",
221          "Ian Main (imain@gtk.org)",
222          "Elliot Lee (sopwith@redhat.com)",
223          "Owen Taylor (otaylor@redhat.com)",
224        N_("Many many others ..."),
225        /* ... from the Monty Pythons show...  */
226        N_("and finally, The Knights Who Say ... NI!"),
227          NULL
228          };
229
230        if (about) {
231                gdk_window_show (about->window);
232                gdk_window_raise (about->window);
233                return;
234        }
235
236#ifdef ENABLE_NLS
237        {
238                int i=0;
239                while (authors[i] != NULL) {
240                        authors[i]=_(authors[i]);
241                        i++;
242                }
243        }
244#endif
245       
246        about = gnome_about_new ( _("The GNOME Panel"), VERSION,
247                        _("(C) 1997-2000 the Free Software Foundation"),
248                        (const gchar **)authors,
249                        _("This program is responsible for launching "
250                        "other applications, embedding small applets "
251                        "within itself, world peace, and random X crashes."),
252                        "gnome-gegl2.png");
253        gtk_window_set_wmclass (GTK_WINDOW (about), "about_dialog", "Panel");
254        gtk_signal_connect (GTK_OBJECT (about), "destroy",
255                            GTK_SIGNAL_FUNC (gtk_widget_destroyed),
256                            &about);
257        gtk_signal_connect (GTK_OBJECT (about), "event",
258                            GTK_SIGNAL_FUNC (check_for_screen), NULL);
259
260        hbox = gtk_hbox_new (TRUE, 0);
261        l = gnome_href_new ("http://www.wfp.org/",
262                            _("End world hunger"));
263        gtk_box_pack_start (GTK_BOX (hbox), l, FALSE, FALSE, 0);
264        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (about)->vbox),
265                            hbox, TRUE, FALSE, 0);
266        gtk_widget_show_all (hbox);
267
268        if (commie_mode) {
269                l = gtk_label_new (_("Running in \"Lockdown\" mode.  This "
270                                     "means your system administrator has "
271                                     "prohibited any changes to the panel's "
272                                     "configuration to take place."));
273                gtk_widget_show (l);
274                gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (about)->vbox),
275                                    l, FALSE, FALSE, 0);
276        }
277
278        gtk_widget_show (about);
279}
280
281static void
282about_gnome_cb(GtkObject *object, char *program_path)
283{
284        if (gnome_execute_async (g_get_home_dir (), 1, &program_path)<0)
285                panel_error_dialog (_("Can't execute 'About GNOME'"));
286}
287
288static void
289activate_app_def (GtkWidget *widget, const char *item_loc)
290{
291        GnomeDesktopEntry *item = gnome_desktop_entry_load (item_loc);
292        if (item != NULL) {
293                char *curdir = g_get_current_dir ();
294                chdir (g_get_home_dir ());
295
296                gnome_desktop_entry_launch (item);
297                gnome_desktop_entry_free (item);
298
299                chdir (curdir);
300                g_free (curdir);
301        } else {
302                panel_error_dialog (_("Can't load entry"));
303        }
304}
305
306/* Copy a single file */
307static void
308copy_file_to_dir (const char *item, const char *to, mode_t mode)
309{
310        int fdin;
311        int fdout;
312        int chars;
313        char buf[1024];
314        char *toname;
315
316        fdin = open (item, O_RDONLY);
317        if (fdin < 0)
318                return;
319
320        toname = g_concat_dir_and_file (to, g_basename (item));
321        fdout = open (toname, O_WRONLY | O_CREAT, mode);
322        g_free (toname);
323        if (fdout < 0) {
324                close (fdin);
325                return;
326        }
327
328        while ((chars = read(fdin, buf, sizeof(buf))) > 0) {
329                write (fdout, buf, chars);
330        }
331
332
333        close (fdin);
334        close (fdout);
335}
336
337static void
338copy_fr_dir (DirRec *dr, const char *to)
339{
340        GSList *li;
341        char *file_name;
342        FILE *order_file = NULL;
343
344        g_return_if_fail (dr != NULL);
345        g_return_if_fail (to != NULL);
346
347        file_name = g_concat_dir_and_file (dr->frec.name, ".directory");
348        copy_file_to_dir (file_name, to, 0600);
349        g_free (file_name);
350
351        file_name = g_concat_dir_and_file (to, ".order");
352        order_file = fopen (file_name, "a");
353        g_free (file_name);
354
355        for (li = dr->recs; li != NULL; li = li->next) {
356                FileRec *fr = li->data;
357               
358                if (fr->type == FILE_REC_FILE) {
359                        copy_file_to_dir (fr->name, to, 0600);
360                } else if (fr->type == FILE_REC_DIR) {
361                        char *newdir = g_concat_dir_and_file (to, g_basename (fr->name));
362                        if (panel_file_exists (newdir) ||
363                            mkdir (newdir, 0700) == 0)
364                                copy_fr_dir ((DirRec *)fr, newdir);
365                        g_free (newdir);
366                } else if (fr->type == FILE_REC_EXTRA) {
367                        if (strcmp (g_basename (fr->name),
368                                    ".order") != 0)
369                                copy_file_to_dir (fr->name, to, 0600);
370                } else {
371                        continue;
372                }
373
374                if (order_file != NULL &&
375                    g_basename (fr->name) != NULL)
376                        fprintf (order_file, "%s\n", g_basename (fr->name));
377        }
378
379        if (order_file != NULL)
380                fclose (order_file);
381}
382
383static void
384add_app_to_personal (GtkWidget *widget, const char *item_loc)
385{
386        char *to;
387
388        to = gnome_util_home_file ("apps");
389
390        if (g_file_test (item_loc, G_FILE_TEST_ISDIR)) {
391                FileRec *fr = fr_get_dir (item_loc);
392                if (fr != NULL) {
393                        char *newdir = g_concat_dir_and_file (to, g_basename (fr->name));
394                        if (panel_file_exists (newdir) ||
395                            mkdir (newdir, 0700) == 0)
396                                copy_fr_dir ((DirRec *)fr, newdir);
397                        g_free(newdir);
398                }
399        } else {
400                copy_file_to_dir (item_loc, to, 0600);
401        }
402
403        g_free (to);
404}
405
406void
407panel_add_favourite (const char *source_dentry)
408{
409        add_app_to_personal (NULL, source_dentry);
410}
411
412static PanelWidget *
413get_panel_from_menu_data(GtkWidget *menu, gboolean must_have)
414{
415        g_return_val_if_fail (menu != NULL, NULL);
416        g_return_val_if_fail (GTK_IS_MENU(menu) || GTK_IS_MENU_ITEM(menu),
417                              NULL);
418
419        if(GTK_IS_MENU_ITEM(menu))
420                menu = menu->parent;
421
422        while(menu) {
423                PanelWidget *panel = gtk_object_get_data(GTK_OBJECT(menu),
424                                                         "menu_panel");
425                if(panel) {
426                        if(IS_PANEL_WIDGET(panel))
427                                return panel;
428                        else
429                                g_warning("Menu is on crack");
430                }
431                menu = GTK_MENU_SHELL(menu)->parent_menu_shell;
432        }
433        if (must_have) {
434                g_warning("Something went quite terribly wrong and we can't "
435                          "find where this menu belongs");
436                return panels->data;
437        } else {
438                return NULL;
439        }
440}
441
442static void
443setup_menu_panel(GtkWidget *menu)
444{
445        PanelWidget *menu_panel = gtk_object_get_data(GTK_OBJECT(menu),
446                                                      "menu_panel");
447        if(!menu_panel) {
448                menu_panel = get_panel_from_menu_data(menu, TRUE);
449                gtk_object_set_data(GTK_OBJECT(menu), "menu_panel", menu_panel);
450        }
451}
452
453static GtkWidget *
454menu_new(void)
455{
456        GtkWidget *ret;
457        ret = hack_scroll_menu_new ();
458        gtk_signal_connect(GTK_OBJECT(ret), "show",
459                           GTK_SIGNAL_FUNC(setup_menu_panel), NULL);
460
461        return ret;
462}
463
464
465/* the following is taken from gnome_stock, and beaten with a stick
466 * until it worked with ArtPixBufs and alpha channel, it scales down
467 * and makes a bi-level alpha channel at threshold of 0xff/2,
468 * dest is the destination and src is the source, it will be scaled according
469 * to their sizes */
470
471/* Then further hacked by Mark Crichton to use GdkPixBufs */
472
473static void
474scale_down (GtkWidget *window, GtkStateType state,
475            GdkPixbuf *dest, GdkPixbuf *src)
476{
477        unsigned char *p, *p2, *p3;
478        long x, y, w2, h2, xo, yo, x2, y2, i, x3, y3;
479        long yw, xw, ww, hw, r, g, b, r2, g2, b2;
480        int trans;
481        int wo, ho, w, h;
482        gboolean do_alpha, d_alpha;
483        int d_channels, do_channels, d_rowstride, do_rowstride;
484        guchar *d_pixels, *do_pixels;
485
486        guchar baser = 0xd6;
487        guchar baseg = 0xd6;
488        guchar baseb = 0xd6;
489
490        wo = gdk_pixbuf_get_width(src);
491        ho = gdk_pixbuf_get_height(src);
492        do_channels = gdk_pixbuf_get_n_channels(src);
493        do_pixels = gdk_pixbuf_get_pixels(src);
494        do_rowstride = gdk_pixbuf_get_rowstride(src);
495        do_alpha = gdk_pixbuf_get_has_alpha(src);
496
497        w = gdk_pixbuf_get_width(dest);
498        h = gdk_pixbuf_get_height(dest);
499        d_channels = gdk_pixbuf_get_n_channels(dest);
500        d_pixels = gdk_pixbuf_get_pixels(dest);
501        d_rowstride = gdk_pixbuf_get_rowstride(dest);
502        d_alpha = gdk_pixbuf_get_has_alpha(dest);
503
504        if (window) {
505                GtkStyle *style = gtk_widget_get_style(window);
506                baser = style->bg[state].red >> 8;
507                baseg = style->bg[state].green >> 8;
508                baseb = style->bg[state].blue >> 8;
509        }
510
511        ww = (wo << 8) / w;
512        hw = (ho << 8) / h;
513        h2 = h << 8;
514        w2 = w << 8;
515        for (y = 0; y < h2; y += 0x100) {
516                yo = (y * ho) / h;
517                y2 = yo & 0xff;
518                yo >>= 8;
519                p = d_pixels + (y>>8) * d_rowstride;
520                for (x = 0; x < w2; x += 0x100) {
521                        xo = (x * wo) / w;
522                        x2 = xo & 0xff;
523                        xo >>= 8;
524                        p2 = do_pixels + xo*do_channels +
525                                yo * do_rowstride;
526
527                        r2 = g2 = b2 = 0;
528                        yw = hw;
529                        y3 = y2;
530                        trans = 1;
531                        while (yw) {
532                                xw = ww;
533                                x3 = x2;
534                                p3 = p2;
535                                r = g = b = 0;
536                                while (xw) {
537                                        if ((0x100 - x3) < xw)
538                                                i = 0x100 - x3;
539                                        else
540                                                i = xw;
541                                        if(do_alpha &&
542                                           p3[3]<(0xff/2)) {
543                                                r += baser * i;
544                                                g += baseg * i;
545                                                b += baseb * i;
546                                        } else {
547                                                trans = 0;
548                                                r += p3[0] * i;
549                                                g += p3[1] * i;
550                                                b += p3[2] * i;
551                                        }
552                                        if(do_alpha)
553                                                p3 += 4;
554                                        else
555                                                p3 += 3;
556                                        xw -= i;
557                                        x3 = 0;
558                                }
559                                if ((0x100 - y3) < yw) {
560                                        r2 += r * (0x100 - y3);
561                                        g2 += g * (0x100 - y3);
562                                        b2 += b * (0x100 - y3);
563                                        yw -= 0x100 - y3;
564                                } else {
565                                        r2 += r * yw;
566                                        g2 += g * yw;
567                                        b2 += b * yw;
568                                        yw = 0;
569                                }
570                                y3 = 0;
571                                p2 += do_rowstride;
572                        }
573                        if (trans) {
574                                /* we leave garbage there but the
575                                 * alpha is 0 so we don't care */
576                                p+=3;
577                                if(d_alpha)
578                                        *(p++) = 0x00;
579                        } else {
580                                r2 /= ww * hw;
581                                g2 /= ww * hw;
582                                b2 /= ww * hw;
583                                *(p++) = r2 & 0xff;
584                                *(p++) = g2 & 0xff;
585                                *(p++) = b2 & 0xff;
586                                if(d_alpha)
587                                        *(p++) = 0xff;
588                        }
589                }
590        }
591}
592
593
594static void
595pixmap_unmap(GtkWidget *w, FakeIcon *fake)
596{
597        GtkWidget *parent = fake->fake->parent;
598
599        if(global_config.hungry_menus)
600                return;
601
602        /* don't kill the fake now, we'll kill it with the fake pixmap */
603        gtk_signal_disconnect_by_data(GTK_OBJECT(fake->fake), fake);
604        /* this must be destroy, it's owned by a parent and this will remove
605         * and unref it */
606        gtk_widget_destroy(fake->fake);
607
608        fake_pixmap_from_fake(fake);
609        gtk_container_add(GTK_CONTAINER(parent), fake->fake);
610}
611
612static void
613fake_destroyed(GtkWidget *w, FakeIcon *fake)
614{
615        /* XXX: we need to work right, so even though this should not be
616         * necessary it's here for correctness sake.  It seems we might not
617         * handle everything correctly and this may be needed */
618        icons_to_load = g_slist_remove (icons_to_load, fake);
619
620        g_free (fake->file);
621        fake->file = NULL;
622
623        g_free (fake);
624}
625
626static gboolean
627load_icons_handler (gpointer data)
628{
629        GtkWidget *parent;
630        GtkWidget *pixmap = NULL;
631        GtkWidget *toplevel;
632        GdkPixbuf *pb, *pb2;
633        GdkPixmap *gp;
634        GdkBitmap *gm;
635
636        FakeIcon *fake;
637
638        if (icons_to_load == NULL) {
639                load_icons_id = 0;
640                return FALSE;
641        }
642
643        fake = icons_to_load->data;
644        icons_to_load = g_slist_remove (icons_to_load, fake);
645
646        parent = fake->fake->parent;
647       
648        /* don't kill the fake now, we'll kill it with the pixmap */
649        gtk_signal_disconnect_by_data(GTK_OBJECT(fake->fake), fake);
650
651        /* destroy and not unref, as it's already inside a parent */
652        gtk_widget_destroy(fake->fake);
653        fake->fake = NULL;
654
655        pb = gdk_pixbuf_new_from_file (fake->file);
656        if (pb == NULL) {
657                g_free (fake->file);
658                fake->file = NULL;
659                g_free (fake);
660                return TRUE;
661        }
662       
663        pb2 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, gdk_pixbuf_get_has_alpha(pb),
664                             8, fake->size, fake->size);
665       
666        scale_down(parent, parent->state, pb2, pb);
667       
668        gdk_pixbuf_unref (pb);
669
670        gdk_pixbuf_render_pixmap_and_mask (pb2, &gp, &gm, 128);
671       
672        gdk_pixbuf_unref(pb2);
673        pixmap = gtk_pixmap_new(gp, gm);
674        gdk_pixmap_unref(gp);
675
676        if (gm != NULL)   /* Is this right?  Some icons dont seem to have alpha. */
677                gdk_bitmap_unref(gm);
678       
679        fake->fake = pixmap;
680        toplevel = gtk_widget_get_toplevel(parent);
681        gtk_signal_connect_while_alive(GTK_OBJECT(toplevel), "unmap",
682                                       GTK_SIGNAL_FUNC(pixmap_unmap),
683                                       fake,
684                                       GTK_OBJECT(pixmap));
685        gtk_signal_connect(GTK_OBJECT(pixmap), "destroy",
686                           GTK_SIGNAL_FUNC(fake_destroyed), fake);
687       
688        gtk_widget_show(pixmap);
689        gtk_container_add(GTK_CONTAINER(parent), pixmap);
690       
691        /* if still more we'll come back */
692        return TRUE;
693}
694
695static void
696fake_unmapped (GtkWidget *w, FakeIcon *fake)
697{
698        icons_to_load = g_slist_remove (icons_to_load, fake);
699}
700
701static void
702fake_mapped(GtkWidget *w, FakeIcon *fake)
703{
704        if(!g_slist_find(icons_to_load, fake))
705                icons_to_load = g_slist_append(icons_to_load, fake);
706        if(!load_icons_id)
707                load_icons_id = g_idle_add(load_icons_handler, NULL);
708}
709
710
711static void
712fake_mapped_fake(GtkWidget *w, FakeIcon *fake)
713{
714        GtkWidget *toplevel;
715        if(!g_slist_find(icons_to_load, fake))
716                icons_to_load = g_slist_append(icons_to_load, fake);
717        if(!load_icons_id)
718                load_icons_id = g_idle_add(load_icons_handler, NULL);
719
720        gtk_signal_disconnect_by_func(GTK_OBJECT(w),
721                                      GTK_SIGNAL_FUNC(fake_mapped_fake),
722                                      fake);
723
724        toplevel = gtk_widget_get_toplevel(w);
725        gtk_signal_connect_while_alive(GTK_OBJECT(toplevel), "map",
726                                       GTK_SIGNAL_FUNC(fake_mapped),
727                                       fake,
728                                       GTK_OBJECT(fake->fake));
729        gtk_signal_connect_while_alive(GTK_OBJECT(toplevel), "unmap",
730                                       GTK_SIGNAL_FUNC(fake_unmapped),
731                                       fake,
732                                       GTK_OBJECT(fake->fake));
733}
734
735static GtkWidget *
736fake_pixmap_from_fake(FakeIcon *fake)
737{
738        fake->fake = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
739        gtk_widget_show(fake->fake);
740        gtk_signal_connect(GTK_OBJECT(fake->fake), "map",
741                           GTK_SIGNAL_FUNC(fake_mapped_fake),
742                           fake);
743        gtk_signal_connect(GTK_OBJECT(fake->fake), "destroy",
744                           GTK_SIGNAL_FUNC(fake_destroyed),
745                           fake);
746
747        return fake->fake;
748}
749
750static GtkWidget *
751fake_pixmap_at_size (const char *file, int size)
752{
753        FakeIcon *fake;
754
755        if ( ! panel_file_exists(file))
756                return NULL;
757
758        fake = g_new0 (FakeIcon, 1);
759        fake->file = g_strdup (file);
760        fake->size = size;
761
762        return fake_pixmap_from_fake (fake);
763}
764
765/* replaces '/' with returns _'s, originally from gmenu */
766static void
767validate_for_filename(char *file)
768{
769        char *ptr;
770
771        g_return_if_fail (file != NULL);
772       
773        ptr = file;
774        while (*ptr != '\0') {
775                if (*ptr == '/')
776                        *ptr = '_';
777                ptr++;
778        }
779}
780
781static void
782really_add_new_menu_item (GtkWidget *d, int button, gpointer data)
783{
784        GnomeDEntryEdit *dedit = GNOME_DENTRY_EDIT(data);
785        char *file, *dir = gtk_object_get_data(GTK_OBJECT(d), "dir");
786        GnomeDesktopEntry *dentry;
787        FILE *fp;
788
789        if (button != 0) {
790                gtk_widget_destroy (d);
791                return;
792        }
793
794        g_return_if_fail (dir != NULL);
795
796        dentry = gnome_dentry_get_dentry (dedit);
797
798        if(dentry->exec == NULL ||
799           dentry->exec_length <= 0) {
800                gnome_desktop_entry_free (dentry);
801                panel_error_dialog (_("Cannot create an item with an empty "
802                                      "command"));
803                return;
804        }
805
806        if(string_empty (dentry->name)) {
807                g_free (dentry->name);
808                dentry->name = g_strdup (_("untitled"));
809        }
810
811        /* assume we are making a new file */
812        if (dentry->location == NULL) {
813                int i = 2;
814                char *name = g_strdup (dentry->name);
815
816                if (string_empty (name)) {
817                        g_free (name);
818                        name = g_strdup ("huh-no-name");
819                }
820
821                validate_for_filename (name);
822
823                dentry->location = g_strdup_printf ("%s/%s.desktop",
824                                                    dir, name);
825
826                while (panel_file_exists (dentry->location)) {
827                        g_free (dentry->location);
828                        dentry->location = g_strdup_printf ("%s/%s%d.desktop",
829                                                            dir, name,
830                                                            i ++);
831                }
832                g_free (name);
833        }
834
835        g_assert (dentry->location != NULL);
836
837        file = g_concat_dir_and_file (dir, ".order");
838        fp = fopen (file, "a");
839        if (fp != NULL) {
840                char *file2 = g_basename (dentry->location);
841                if (file2 != NULL)
842                        fprintf(fp, "%s\n", file2);
843                else
844                        g_warning (_("Could not get file from path: %s"),
845                                   dentry->location);
846                fclose (fp);
847        } else {
848                g_warning (_("Could not open .order file: %s"), file);
849        }
850        g_free (file);
851
852        /* open for append, which will not harm any file and we will see if
853         * we have write privilages */
854        fp = fopen (dentry->location, "a");
855        if(fp == NULL) {
856                panel_error_dialog (_("Could not open file '%s' for writing"),
857                                    dentry->location);
858                return;
859        }
860        fclose(fp);
861
862        gnome_desktop_entry_save(dentry);
863        gnome_desktop_entry_free(dentry);
864
865        gtk_widget_destroy(d);
866}
867
868static void
869add_new_app_to_menu (GtkWidget *widget, const char *item_loc)
870{
871        GtkWidget *dialog, *notebook;
872        GnomeDEntryEdit *dee;
873        GList *types;
874
875        dialog = gnome_dialog_new (_("Create menu item"),
876                                   GNOME_STOCK_BUTTON_OK,
877                                   GNOME_STOCK_BUTTON_CANCEL,
878                                   NULL);
879        gtk_window_set_wmclass (GTK_WINDOW (dialog),
880                               "create_menu_item", "Panel");
881        gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, TRUE);
882       
883        notebook = gtk_notebook_new ();
884        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), notebook,
885                            TRUE, TRUE, GNOME_PAD_SMALL);
886        dee = GNOME_DENTRY_EDIT (gnome_dentry_edit_new_notebook (GTK_NOTEBOOK (notebook)));
887        hack_dentry_edit (dee);
888
889        types = NULL;
890        types = g_list_append(types, "Application");
891        types = g_list_append(types, "URL");
892        types = g_list_append(types, "PanelApplet");
893        gtk_combo_set_popdown_strings (GTK_COMBO (dee->type_combo), types);
894        g_list_free(types);
895        types = NULL;
896
897#define SETUP_EDITABLE(entry_name)                                      \
898        gnome_dialog_editable_enters                                    \
899                (GNOME_DIALOG (dialog),                                 \
900                 GTK_EDITABLE (gnome_dentry_get_##entry_name##_entry (dee)));
901
902        SETUP_EDITABLE (name);
903        SETUP_EDITABLE (comment);
904        SETUP_EDITABLE (exec);
905        SETUP_EDITABLE (tryexec);
906        SETUP_EDITABLE (doc);
907
908#undef SETUP_EDITABLE
909       
910        gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (dee->type_combo)->entry),
911                            "Application");
912
913        gtk_object_set_data_full (GTK_OBJECT (dialog), "dir",
914                                  g_strdup (item_loc),
915                                  (GtkDestroyNotify)g_free);
916       
917        gtk_signal_connect (GTK_OBJECT (dialog), "clicked",
918                            GTK_SIGNAL_FUNC (really_add_new_menu_item),
919                            dee);
920
921        /* YAIKES, the problem here is that the notebook will attempt
922         * to destroy the dedit, so if we unref it in the close handler,
923         * it will be finalized by the time the notebook will destroy it,
924         * dedit is just a horrible thing */
925        gtk_signal_connect (GTK_OBJECT (dee), "destroy",
926                            GTK_SIGNAL_FUNC (gtk_object_unref),
927                            NULL);
928
929        gnome_dialog_close_hides (GNOME_DIALOG(dialog), FALSE);
930
931        gnome_dialog_set_default (GNOME_DIALOG(dialog), 0);
932
933        gtk_widget_show_all (dialog);
934        panel_set_dialog_layer (dialog);
935
936        gtk_widget_grab_focus (gnome_dentry_get_name_entry (dee));
937}
938
939static void
940remove_menuitem (GtkWidget *widget, ShowItemMenu *sim)
941{
942        const char *file;
943        char *dir, buf[256], *order_in_name, *order_out_name;
944        FILE *order_in_file, *order_out_file;
945
946        g_return_if_fail (sim->item_loc != NULL);
947        g_return_if_fail (sim->menuitem != NULL);
948
949        gtk_widget_hide (sim->menuitem);
950
951        if (unlink (sim->item_loc) < 0) {
952                panel_error_dialog(_("Could not remove the menu item %s: %s\n"),
953                                    sim->item_loc, g_strerror(errno));
954                return;
955        }
956
957        file = g_basename (sim->item_loc);
958        if (file == NULL) {
959                g_warning (_("Could not get file name from path: %s"),
960                          sim->item_loc);
961                return;
962        }
963
964        dir = g_dirname (sim->item_loc);
965        if (dir == NULL) {
966                g_warning (_("Could not get directory name from path: %s"),
967                          sim->item_loc);
968                return;
969        }
970       
971        order_in_name = g_concat_dir_and_file(dir, ".order");
972        order_in_file = fopen(order_in_name, "r");
973
974        if (order_in_file == NULL) {
975                /*no .order file so we can just leave*/
976                g_free (order_in_name);
977                g_free (dir);
978                return;
979        }
980
981        order_out_name = g_concat_dir_and_file(dir, ".order.tmp");
982        order_out_file = fopen(order_out_name, "w");
983
984        g_free (dir);
985
986        if (order_out_file == NULL) {
987                panel_error_dialog(_("Could not open .order file: %s\n%s"),
988                                   order_out_name,
989                                   g_unix_error_string(errno));
990
991                g_free (order_in_name);
992                g_free (order_out_name);
993                fclose (order_in_file);
994                return;
995        }
996
997        while (fgets (buf, sizeof(buf)-1, order_in_file) != NULL) {
998                g_strchomp (buf);  /* remove trailing '\n' */
999                if (strcmp (buf, file) != 0)
1000                        fprintf (order_out_file, "%s\n", buf);
1001        }
1002
1003        fclose (order_out_file);
1004        fclose (order_in_file);
1005
1006        if (unlink (order_in_name) < 0) {
1007                panel_error_dialog(_("Could not remove old order file %s: %s\n"),
1008                                    order_in_name, g_strerror(errno));
1009                g_free (order_out_name);
1010                g_free (order_in_name);
1011                return;
1012        }
1013
1014        if (rename (order_out_name, order_in_name) == -1) {
1015                panel_error_dialog(_("Could not rename tmp file: %s to %s\n%s"),
1016                                   order_out_name, order_in_name,
1017                                   g_unix_error_string(errno));
1018        }
1019
1020        g_free (order_out_name);
1021        g_free (order_in_name);
1022}
1023
1024static void
1025add_to_run_dialog (GtkWidget *widget, const char *item_loc)
1026{
1027        GnomeDesktopEntry *item =
1028                gnome_desktop_entry_load_unconditional (item_loc);
1029        if (item != NULL) {
1030                if (item->exec != NULL &&
1031                    item->exec[0] != NULL) {
1032                        char *s;
1033                        char **cmd = item->exec;
1034                        if (strcmp (cmd[0], "NO_XALF") == 0) {
1035                                cmd++;
1036                        }
1037                        s = g_strjoinv (" ", cmd);
1038                        show_run_dialog_with_text (s);
1039                        g_free (s);
1040                } else {
1041                        panel_error_dialog (_("No 'Exec' field in entry"));
1042                }
1043                gnome_desktop_entry_free (item);
1044        } else {
1045                panel_error_dialog (_("Can't load entry"));
1046        }
1047}
1048
1049static void
1050show_help_on (GtkWidget *widget, const char *item_loc)
1051{
1052        GnomeDesktopEntry *item =
1053                gnome_desktop_entry_load_unconditional (item_loc);
1054        if (item != NULL) {
1055                char *path = panel_gnome_kde_help_path (item->docpath);
1056                if (path != NULL) {
1057                        gnome_url_show (path);
1058                        g_free (path);
1059                }
1060                gnome_desktop_entry_free (item);
1061        } else {
1062                panel_error_dialog (_("Can't load entry"));
1063        }
1064}
1065
1066static void
1067add_app_to_panel (GtkWidget *widget, const char *item_loc)
1068{
1069        PanelWidget *panel = get_panel_from_menu_data (widget, TRUE);
1070        Launcher *launcher;
1071
1072        launcher = load_launcher_applet (item_loc, panel, 0, FALSE);
1073
1074        if (launcher != NULL)
1075                launcher_hoard (launcher);
1076}
1077
1078
1079static void
1080add_drawers_from_dir (const char *dirname, const char *name,
1081                      int pos, PanelWidget *panel)
1082{
1083        AppletInfo *info;
1084        Drawer *drawer;
1085        PanelWidget *newpanel;
1086        GnomeDesktopEntry *item_info;
1087        char *dentry_name;
1088        const char *subdir_name;
1089        char *pixmap_name;
1090        char *p;
1091        char *filename = NULL;
1092        char *mergedir;
1093        GSList *list, *li;
1094
1095        if(!panel_file_exists(dirname))
1096                return;
1097
1098        dentry_name = g_concat_dir_and_file (dirname,
1099                                             ".directory");
1100        item_info = gnome_desktop_entry_load (dentry_name);
1101        g_free (dentry_name);
1102
1103        if(!name)
1104                subdir_name = item_info ? item_info->name : NULL;
1105        else
1106                subdir_name = name;
1107        pixmap_name = item_info?item_info->icon:NULL;
1108
1109        if( ! load_drawer_applet (-1, pixmap_name, subdir_name,
1110                                  panel, pos, FALSE) ||
1111            applets_last == NULL) {
1112                g_warning("Can't load a drawer");
1113                return;
1114        }
1115        info = applets_last->data;
1116        g_assert(info!=NULL);
1117        if(info->type != APPLET_DRAWER) {
1118                g_warning("Something weird happened and we didn't get a drawer");
1119                return;
1120        }
1121       
1122        drawer = info->data;
1123        g_assert(drawer);
1124        newpanel = PANEL_WIDGET(BASEP_WIDGET(drawer->drawer)->panel);
1125
1126        mergedir = fr_get_mergedir(dirname);
1127       
1128        list = get_mfiles_from_menudir(dirname);
1129        for(li = list; li!= NULL; li = li->next) {
1130                MFile *mfile = li->data;
1131                struct stat s;
1132                GnomeDesktopEntry *dentry;
1133
1134                g_free (filename);
1135                if ( ! mfile->merged) {
1136                        filename = g_concat_dir_and_file(dirname, mfile->name);
1137                } else if (mergedir != NULL) {
1138                        filename = g_concat_dir_and_file(mergedir, mfile->name);
1139                } else {
1140                        filename = NULL;
1141                        continue;
1142                }
1143
1144                if (stat (filename, &s) != 0) {
1145                        continue;
1146                }
1147
1148                if (S_ISDIR (s.st_mode)) {
1149                        add_drawers_from_dir (filename, NULL, G_MAXINT/2,
1150                                              newpanel);
1151                        continue;
1152                }
1153                       
1154                p = strrchr(filename,'.');
1155                if (p && (strcmp(p,".desktop")==0 ||
1156                          strcmp(p,".kdelnk")==0)) {
1157                        /*we load the applet at the right
1158                          side, that is end of the drawer*/
1159                        dentry = gnome_desktop_entry_load (filename);
1160                        if (dentry) {
1161                                Launcher *launcher;
1162
1163                                launcher =
1164                                        load_launcher_applet_full (filename,
1165                                                                   dentry,
1166                                                                   newpanel,
1167                                                                   G_MAXINT/2,
1168                                                                   FALSE);
1169
1170                                if (launcher != NULL)
1171                                        launcher_hoard (launcher);
1172                        }
1173                }
1174        }
1175        g_free (filename);
1176        g_free (mergedir);
1177
1178        free_mfile_list (list);
1179}
1180
1181/*add a drawer with the contents of a menu to the panel*/
1182static void
1183add_menudrawer_to_panel(GtkWidget *w, gpointer data)
1184{
1185        MenuFinfo *mf = data;
1186        PanelWidget *panel = get_panel_from_menu_data (w, TRUE);
1187        g_return_if_fail(mf);
1188       
1189        add_drawers_from_dir (mf->menudir, mf->dir_name, 0, panel);
1190}
1191
1192static void
1193add_menu_to_panel (GtkWidget *widget, gpointer data)
1194{
1195        char *menudir = data;
1196        PanelWidget *panel;
1197        DistributionType distribution = get_distribution_type ();
1198        int flags = MAIN_MENU_SYSTEM_SUB | MAIN_MENU_USER_SUB |
1199                MAIN_MENU_APPLETS_SUB | MAIN_MENU_PANEL_SUB |
1200                MAIN_MENU_DESKTOP_SUB;
1201       
1202        /*guess distribution menus*/
1203        if (distribution != DISTRIBUTION_UNKNOWN)
1204                flags |= MAIN_MENU_DISTRIBUTION_SUB;
1205
1206        /*guess KDE menus*/
1207        if(panel_file_exists(kde_menudir))
1208                flags |= MAIN_MENU_KDE_SUB;
1209
1210        panel = get_panel_from_menu_data (widget, TRUE);
1211
1212        load_menu_applet (menudir, flags, TRUE, FALSE, NULL, panel, 0, FALSE);
1213}
1214
1215/*most of this function stolen from the real gtk_menu_popup*/
1216static void
1217restore_grabs(GtkWidget *w, gpointer data)
1218{
1219        GtkWidget *menu_item = data;
1220        GtkMenu *menu = GTK_MENU(menu_item->parent);
1221        GtkWidget *xgrab_shell;
1222        GtkWidget *parent;
1223        /* Find the last viewable ancestor, and make an X grab on it
1224         */
1225        parent = GTK_WIDGET (menu);
1226        xgrab_shell = NULL;
1227        while (parent) {
1228                gboolean viewable = TRUE;
1229                GtkWidget *tmp = parent;
1230
1231                while (tmp) {
1232                        if (!GTK_WIDGET_MAPPED (tmp)) {
1233                                viewable = FALSE;
1234                                break;
1235                        }
1236                        tmp = tmp->parent;
1237                }
1238
1239                if (viewable)
1240                        xgrab_shell = parent;
1241
1242                parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
1243        }
1244
1245        /*only grab if this HAD a grab before*/
1246        if (xgrab_shell && (GTK_MENU_SHELL (xgrab_shell)->have_xgrab)) {
1247                GdkCursor *cursor = gdk_cursor_new (GDK_ARROW);
1248
1249                GTK_MENU_SHELL (xgrab_shell)->have_xgrab =
1250                        (gdk_pointer_grab (xgrab_shell->window, TRUE,
1251                                           GDK_BUTTON_PRESS_MASK |
1252                                           GDK_BUTTON_RELEASE_MASK |
1253                                           GDK_ENTER_NOTIFY_MASK |
1254                                           GDK_LEAVE_NOTIFY_MASK,
1255                                           NULL, cursor, 0) == 0);
1256                gdk_cursor_destroy (cursor);
1257        }
1258       
1259        gtk_grab_add (GTK_WIDGET (menu));
1260}
1261
1262static void
1263ditem_properties_clicked (GtkWidget *w, int button, gpointer data)
1264{
1265        GnomeDEntryEdit *dee = gtk_object_get_user_data (GTK_OBJECT (w));
1266        GnomeDesktopEntry *dentry = data;
1267
1268        if (button == HELP_BUTTON) {
1269                panel_show_help ("launchers.html");
1270        } else if (button == REVERT_BUTTON) {
1271                if (dentry != NULL)
1272                        gnome_dentry_edit_set_dentry (dee, dentry);
1273                else
1274                        gnome_dentry_edit_clear (dee);
1275        } else {
1276                gnome_dialog_close (GNOME_DIALOG (w));
1277        }
1278}
1279
1280static gboolean
1281ditem_properties_apply_timeout (gpointer data)
1282{
1283        GtkObject *dedit = data;
1284        GnomeDesktopEntry *dentry;
1285
1286        gtk_object_remove_data (dedit, "apply_timeout");
1287
1288        dentry = gnome_dentry_get_dentry (GNOME_DENTRY_EDIT (dedit));
1289        dentry->location = g_strdup (gtk_object_get_data (dedit, "location"));
1290        gnome_desktop_entry_save (dentry);
1291        gnome_desktop_entry_free (dentry);
1292
1293        return FALSE;
1294}
1295
1296/*
1297 * Will save after 5 seconds of no changes.  If something is changed, the save
1298 * is postponed to another 5 seconds.  This seems to be a saner behaviour,
1299 * then just saving every N seconds.
1300 */
1301static void
1302ditem_properties_changed (GtkObject *dedit, gpointer data)
1303{
1304        gpointer timeout_data = gtk_object_get_data (dedit, "apply_timeout");
1305        guint timeout = GPOINTER_TO_UINT (timeout_data);
1306
1307        gtk_object_remove_data (dedit, "apply_timeout");
1308
1309        if (timeout != 0)
1310                gtk_timeout_remove (timeout);
1311
1312        /* Will save after 5 seconds */
1313        timeout = gtk_timeout_add (5 * 1000,
1314                                   ditem_properties_apply_timeout,
1315                                   dedit);
1316
1317        gtk_object_set_data (dedit, "apply_timeout",
1318                             GUINT_TO_POINTER (timeout));
1319}
1320
1321
1322static void
1323ditem_properties_close (GtkWidget *widget, gpointer data)
1324{
1325        GtkObject *dedit = data;
1326        gpointer timeout_data = gtk_object_get_data (dedit, "apply_timeout");
1327        guint timeout = GPOINTER_TO_UINT (timeout_data);
1328
1329        gtk_object_remove_data (dedit, "apply_timeout");
1330
1331        if (timeout != 0) {
1332                gtk_timeout_remove (timeout);
1333
1334                ditem_properties_apply_timeout (dedit);
1335        }
1336}
1337
1338static gboolean
1339is_item_writable (const ShowItemMenu *sim)
1340{
1341        errno = 0;
1342        if (sim->item_loc != NULL &&
1343            /*A HACK: but it works, don't have it edittable if it's redhat
1344              menus as they are auto generated!*/
1345            strstr (sim->item_loc,"/.gnome/apps-redhat/") == NULL &&
1346            /*if it's a kdelnk file, don't let it be editted*/
1347            ! is_ext (sim->item_loc, ".kdelnk") &&
1348            access (sim->item_loc, W_OK) == 0) {
1349#ifdef PANEL_DEBUG
1350                puts (sim->item_loc);
1351#endif
1352                /*file exists and is writable, we're in bussines*/
1353                return TRUE;
1354        } else if ((sim->item_loc == NULL ||
1355                    errno == ENOENT) &&
1356                   sim->mf != NULL) {
1357                /*the dentry isn't there, check if we can write the
1358                  directory*/
1359                if (access (sim->mf->menudir, W_OK) == 0 &&
1360                   /*A HACK: but it works, don't have it edittable if it's redhat
1361                     menus as they are auto generated!*/
1362                   strstr (sim->mf->menudir, ".gnome/apps-redhat/") == NULL)
1363                        return TRUE;
1364        }
1365        return FALSE;
1366}
1367
1368static void
1369set_ditem_sensitive (GnomeDialog *dialog,
1370                     GnomeDEntryEdit *dedit,
1371                     ShowItemMenu *sim)
1372{
1373        gboolean sensitive;
1374
1375        sensitive = is_item_writable (sim);
1376
1377        gtk_widget_set_sensitive (gnome_dentry_edit_child1 (dedit),
1378                                  sensitive);
1379        gtk_widget_set_sensitive (gnome_dentry_edit_child2 (dedit),
1380                                  sensitive);
1381
1382        gnome_dialog_set_sensitive (dialog, REVERT_BUTTON, sensitive);
1383}
1384
1385static void
1386edit_dentry (GtkWidget *widget, ShowItemMenu *sim)
1387{
1388        GtkWidget *dialog, *notebook;
1389        GtkObject *dedit;
1390        GnomeDesktopEntry *dentry;
1391        GList *types = NULL;
1392       
1393        g_return_if_fail (sim != NULL);
1394        g_return_if_fail (sim->item_loc != NULL);
1395
1396        dentry = gnome_desktop_entry_load_unconditional (sim->item_loc);
1397        /* We'll screw up a KDE menu entry if we edit it */
1398        if (dentry != NULL &&
1399            dentry->is_kde) {
1400                gnome_desktop_entry_free (dentry);
1401                return;
1402        }
1403
1404        /* watch the enum at the top of the file */
1405        dialog = gnome_dialog_new (_("Desktop entry properties"),
1406                                   GNOME_STOCK_BUTTON_HELP,
1407                                   _("Revert"),
1408                                   GNOME_STOCK_BUTTON_CLOSE,
1409                                   NULL);
1410        gnome_dialog_set_close (GNOME_DIALOG (dialog),
1411                                FALSE /* click_closes */);
1412
1413        notebook = gtk_notebook_new ();
1414        gtk_widget_show (notebook);
1415        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
1416                            notebook, TRUE, TRUE, 0);
1417
1418        gtk_window_set_wmclass(GTK_WINDOW(dialog),
1419                               "desktop_entry_properties","Panel");
1420        gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, TRUE);
1421       
1422        dedit = gnome_dentry_edit_new_notebook (GTK_NOTEBOOK (notebook));
1423        hack_dentry_edit (GNOME_DENTRY_EDIT (dedit));
1424
1425        types = NULL;
1426        types = g_list_append (types, "Application");
1427        types = g_list_append (types, "URL");
1428        types = g_list_append (types, "PanelApplet");
1429        gtk_combo_set_popdown_strings(GTK_COMBO(GNOME_DENTRY_EDIT(dedit)->type_combo), types);
1430        g_list_free(types);
1431        types = NULL;
1432
1433        /* This sucks, but there is no other way to do this with the current
1434           GnomeDEntry API.  */
1435
1436#define SETUP_EDITABLE(entry_name)                                      \
1437        gnome_dialog_editable_enters                                    \
1438                (GNOME_DIALOG (dialog),                                 \
1439                 GTK_EDITABLE (gnome_dentry_get_##entry_name##_entry    \
1440                               (GNOME_DENTRY_EDIT (dedit))));
1441
1442        SETUP_EDITABLE (name);
1443        SETUP_EDITABLE (comment);
1444        SETUP_EDITABLE (exec);
1445        SETUP_EDITABLE (tryexec);
1446        SETUP_EDITABLE (doc);
1447
1448#undef SETUP_EDITABLE
1449
1450        gtk_object_set_data_full (dedit, "location",
1451                                  g_strdup (sim->item_loc),
1452                                  (GtkDestroyNotify)g_free);
1453
1454        if (dentry != NULL)
1455                gnome_dentry_edit_set_dentry (GNOME_DENTRY_EDIT (dedit), dentry);
1456
1457        set_ditem_sensitive (GNOME_DIALOG (dialog),
1458                             GNOME_DENTRY_EDIT (dedit), sim);
1459
1460        gtk_signal_connect (GTK_OBJECT (dedit), "changed",
1461                            GTK_SIGNAL_FUNC (ditem_properties_changed),
1462                            NULL);
1463
1464        gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
1465                            GTK_SIGNAL_FUNC (ditem_properties_close),
1466                            dedit);
1467
1468        /* YAIKES, the problem here is that the notebook will attempt
1469         * to destroy the dedit, so if we unref it in the close handler,
1470         * it will be finalized by the time the notebook will destroy it,
1471         * dedit is just a horrible thing */
1472        gtk_signal_connect (GTK_OBJECT (dedit), "destroy",
1473                            GTK_SIGNAL_FUNC (gtk_object_unref),
1474                            NULL);
1475
1476        gtk_object_set_user_data (GTK_OBJECT (dialog), dedit);
1477
1478        if (dentry != NULL) {
1479                /* pass the dentry as the data to clicked */
1480                gtk_signal_connect_full (GTK_OBJECT (dialog), "clicked",
1481                                         GTK_SIGNAL_FUNC (ditem_properties_clicked),
1482                                         NULL,
1483                                         dentry,
1484                                         (GtkDestroyNotify) gnome_desktop_entry_free,
1485                                         FALSE, FALSE);
1486        } else {
1487                gtk_signal_connect (GTK_OBJECT (dialog), "clicked",
1488                                    GTK_SIGNAL_FUNC (ditem_properties_clicked),
1489                                    NULL);
1490        }
1491
1492        gtk_widget_show (dialog);
1493
1494        gtk_widget_grab_focus
1495                (gnome_dentry_get_name_entry (GNOME_DENTRY_EDIT (dedit)));
1496}
1497
1498static void
1499edit_direntry (GtkWidget *widget, ShowItemMenu *sim)
1500{
1501        GtkWidget *dialog, *notebook;
1502        GtkObject *dedit;
1503        char *dirfile = g_concat_dir_and_file (sim->mf->menudir, ".directory");
1504        GnomeDesktopEntry *dentry;
1505        GList *types = NULL;
1506
1507        dentry = gnome_desktop_entry_load_unconditional(dirfile);
1508        /* We'll screw up a KDE menu entry if we edit it */
1509        if (dentry != NULL &&
1510            dentry->is_kde) {
1511                gnome_desktop_entry_free (dentry);
1512                return;
1513        }
1514
1515        /* watch the enum at the top of the file */
1516        dialog = gnome_dialog_new (_("Desktop entry properties"),
1517                                   GNOME_STOCK_BUTTON_HELP,
1518                                   _("Revert"),
1519                                   GNOME_STOCK_BUTTON_CLOSE,
1520                                   NULL);
1521        gnome_dialog_set_close (GNOME_DIALOG (dialog),
1522                                FALSE /* click_closes */);
1523
1524        notebook = gtk_notebook_new ();
1525        gtk_widget_show (notebook);
1526        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
1527                            notebook, TRUE, TRUE, 0);
1528
1529        gtk_window_set_wmclass (GTK_WINDOW (dialog),
1530                                "desktop_entry_properties", "Panel");
1531        gtk_window_set_policy (GTK_WINDOW(dialog), FALSE, FALSE, TRUE);
1532       
1533        dedit = gnome_dentry_edit_new_notebook (GTK_NOTEBOOK (notebook));
1534        hack_dentry_edit (GNOME_DENTRY_EDIT (dedit));
1535
1536        types = NULL;
1537        types = g_list_append (types, "Directory");
1538        gtk_combo_set_popdown_strings (GTK_COMBO (GNOME_DENTRY_EDIT (dedit)->type_combo), types);
1539        g_list_free (types);
1540        types = NULL;
1541
1542        if (dentry != NULL) {
1543                gnome_dentry_edit_set_dentry (GNOME_DENTRY_EDIT (dedit), dentry);
1544                gtk_object_set_data_full (dedit, "location",
1545                                          g_strdup (dentry->location),
1546                                          (GtkDestroyNotify)g_free);
1547                g_free (dirfile);
1548                dirfile = NULL;
1549        } else {
1550                dentry = g_new0 (GnomeDesktopEntry, 1);
1551                if (sim->mf->dir_name == NULL)
1552                        dentry->name = g_strdup (_("Menu"));
1553                else
1554                        dentry->name = g_strdup (sim->mf->dir_name);
1555                dentry->type = g_strdup ("Directory");
1556                /*we don't have to free dirfile here it will be freed as if
1557                  we had strduped it here*/
1558                gtk_object_set_data_full (dedit, "location", dirfile,
1559                                          (GtkDestroyNotify)g_free);
1560                dirfile = NULL;
1561                gnome_dentry_edit_set_dentry(GNOME_DENTRY_EDIT(dedit), dentry);
1562        }
1563
1564        /* This sucks, but there is no other way to do this with the current
1565           GnomeDEntry API.  */
1566
1567#define SETUP_EDITABLE(entry_name)                                      \
1568        gnome_dialog_editable_enters                                    \
1569                (GNOME_DIALOG (dialog),                                 \
1570                 GTK_EDITABLE (gnome_dentry_get_##entry_name##_entry    \
1571                               (GNOME_DENTRY_EDIT (dedit))));
1572
1573        SETUP_EDITABLE (name);
1574        SETUP_EDITABLE (comment);
1575        SETUP_EDITABLE (exec);
1576        SETUP_EDITABLE (tryexec);
1577        SETUP_EDITABLE (doc);
1578
1579#undef SETUP_EDITABLE
1580
1581        gtk_widget_set_sensitive (GNOME_DENTRY_EDIT(dedit)->exec_entry, FALSE);
1582        gtk_widget_set_sensitive (GNOME_DENTRY_EDIT(dedit)->tryexec_entry, FALSE);
1583        gtk_widget_set_sensitive (GNOME_DENTRY_EDIT(dedit)->doc_entry, FALSE);
1584        gtk_widget_set_sensitive (GNOME_DENTRY_EDIT(dedit)->type_combo, FALSE);
1585        gtk_widget_set_sensitive (GNOME_DENTRY_EDIT(dedit)->terminal_button, FALSE);
1586
1587        set_ditem_sensitive (GNOME_DIALOG (dialog),
1588                             GNOME_DENTRY_EDIT (dedit), sim);
1589
1590        gtk_signal_connect (GTK_OBJECT (dedit), "changed",
1591                            GTK_SIGNAL_FUNC (ditem_properties_changed),
1592                            NULL);
1593
1594        gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
1595                            GTK_SIGNAL_FUNC (ditem_properties_close),
1596                            dedit);
1597
1598        /* YAIKES, the problem here is that the notebook will attempt
1599         * to destroy the dedit, so if we unref it in the close handler,
1600         * it will be finalized by the time the notebook will destroy it,
1601         * dedit is just a horrible thing */
1602        gtk_signal_connect (GTK_OBJECT (dedit), "destroy",
1603                            GTK_SIGNAL_FUNC (gtk_object_unref),
1604                            NULL);
1605
1606        gtk_object_set_user_data (GTK_OBJECT (dialog), dedit);
1607
1608        if (dentry != NULL) {
1609                /* pass the dentry as the data to clicked */
1610                gtk_signal_connect_full (GTK_OBJECT (dialog), "clicked",
1611                                         GTK_SIGNAL_FUNC (ditem_properties_clicked),
1612                                         NULL,
1613                                         dentry,
1614                                         (GtkDestroyNotify) gnome_desktop_entry_free,
1615                                         FALSE, FALSE);
1616        } else {
1617                gtk_signal_connect (GTK_OBJECT (dialog), "clicked",
1618                                    GTK_SIGNAL_FUNC (ditem_properties_clicked),
1619                                    NULL);
1620        }
1621
1622        gtk_widget_show(dialog);
1623
1624        gtk_widget_grab_focus
1625                (gnome_dentry_get_name_entry (GNOME_DENTRY_EDIT (dedit)));
1626}
1627
1628static void
1629show_item_menu (GtkWidget *item, GdkEventButton *bevent, ShowItemMenu *sim)
1630{
1631        GtkWidget *menuitem;
1632        char *tmp;
1633        GnomeDesktopEntry *ii;
1634
1635        if (sim->menu == NULL) {
1636                sim->menu = menu_new ();
1637
1638                gtk_object_set_data (GTK_OBJECT(sim->menu), "menu_panel",
1639                                     get_panel_from_menu_data (sim->menuitem,
1640                                                               TRUE));
1641               
1642                gtk_signal_connect(GTK_OBJECT(sim->menu),"deactivate",
1643                                   GTK_SIGNAL_FUNC(restore_grabs),
1644                                   item);
1645
1646                if (sim->type == 1) {
1647                        ii = gnome_desktop_entry_load_unconditional (sim->item_loc);
1648
1649                        menuitem = gtk_menu_item_new ();
1650                        gtk_widget_lock_accelerators (menuitem);
1651                        if ( ! sim->applet)
1652                                setup_menuitem (menuitem, 0,
1653                                                _("Add this launcher to panel"));
1654                        else
1655                                setup_menuitem (menuitem, 0,
1656                                                _("Add this applet as a launcher to panel"));
1657                        gtk_menu_append (GTK_MENU (sim->menu), menuitem);
1658                        gtk_signal_connect (GTK_OBJECT(menuitem), "activate",
1659                                            GTK_SIGNAL_FUNC(add_app_to_panel),
1660                                            (gpointer)sim->item_loc);
1661
1662                        if ( ! sim->applet) {
1663                                menuitem = gtk_menu_item_new ();
1664                                gtk_widget_lock_accelerators (menuitem);
1665                                setup_menuitem (menuitem, 0,
1666                                                _("Add this to Favorites menu"));
1667                                gtk_menu_append (GTK_MENU (sim->menu), menuitem);
1668                                gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
1669                                                   GTK_SIGNAL_FUNC(add_app_to_personal),
1670                                                   (gpointer)sim->item_loc);
1671                                /*ummmm slightly ugly but should work 99% of time*/
1672                                if (strstr(sim->item_loc,"/.gnome/apps/") != NULL)
1673                                        gtk_widget_set_sensitive(menuitem,FALSE);
1674                        }
1675
1676                        menuitem = gtk_menu_item_new ();
1677                        gtk_widget_lock_accelerators (menuitem);
1678                        setup_menuitem (menuitem, 0,
1679                                        _("Remove this item"));
1680                        gtk_menu_append (GTK_MENU (sim->menu), menuitem);
1681                        gtk_signal_connect (GTK_OBJECT(menuitem), "activate",
1682                                            GTK_SIGNAL_FUNC (remove_menuitem),
1683                                            sim);
1684                        tmp = g_dirname(sim->item_loc);
1685                        if (access (tmp, W_OK) != 0)
1686                                gtk_widget_set_sensitive(menuitem,FALSE);
1687                        g_free (tmp);
1688                        gtk_signal_connect_object (GTK_OBJECT (menuitem),
1689                                                   "activate",
1690                                                   GTK_SIGNAL_FUNC (gtk_menu_shell_deactivate),
1691                                                   GTK_OBJECT (item->parent));
1692
1693                        if ( ! sim->applet) {
1694                                menuitem = gtk_menu_item_new ();
1695                                gtk_widget_lock_accelerators (menuitem);
1696                                setup_menuitem (menuitem, 0,
1697                                                _("Put into run dialog"));
1698                                gtk_menu_append (GTK_MENU (sim->menu),
1699                                                 menuitem);
1700                                gtk_signal_connect
1701                                        (GTK_OBJECT(menuitem), "activate",
1702                                         GTK_SIGNAL_FUNC(add_to_run_dialog),
1703                                         (gpointer)sim->item_loc);
1704                                gtk_signal_connect_object
1705                                        (GTK_OBJECT(menuitem),
1706                                         "activate",
1707                                         GTK_SIGNAL_FUNC(gtk_menu_shell_deactivate),
1708                                         GTK_OBJECT(item->parent));
1709                        }
1710
1711                        if (ii != NULL)
1712                                tmp = panel_gnome_kde_help_path (ii->docpath);
1713                        else
1714                                tmp = NULL;
1715
1716                        if (tmp != NULL) {
1717                                char *title;
1718
1719                                g_free (tmp);
1720
1721                                menuitem = gtk_menu_item_new ();
1722                                gtk_widget_lock_accelerators (menuitem);
1723                                title = g_strdup_printf (_("Help on %s"),
1724                                                         ii->name != NULL ?
1725                                                         ii->name :
1726                                                         _("Application"));
1727                                setup_menuitem (menuitem, 0, title);
1728                                g_free (title);
1729                                gtk_menu_append (GTK_MENU (sim->menu),
1730                                                 menuitem);
1731                                gtk_signal_connect
1732                                        (GTK_OBJECT(menuitem), "activate",
1733                                         GTK_SIGNAL_FUNC(show_help_on),
1734                                         (gpointer)sim->item_loc);
1735                                gtk_signal_connect_object
1736                                        (GTK_OBJECT(menuitem),
1737                                         "activate",
1738                                         GTK_SIGNAL_FUNC(gtk_menu_shell_deactivate),
1739                                         GTK_OBJECT(item->parent));
1740                        }
1741
1742                        menuitem = gtk_menu_item_new ();
1743                        gtk_widget_lock_accelerators (menuitem);
1744                        /*when activated we must pop down the first menu*/
1745                        gtk_signal_connect_object(GTK_OBJECT(menuitem),
1746                                                  "activate",
1747                                                  GTK_SIGNAL_FUNC(gtk_menu_shell_deactivate),
1748                                                  GTK_OBJECT(item->parent));
1749                        gtk_signal_connect(GTK_OBJECT(menuitem),
1750                                           "activate",
1751                                           GTK_SIGNAL_FUNC(edit_dentry),
1752                                           sim);
1753                        setup_menuitem (menuitem, 0, _("Properties..."));
1754                        gtk_menu_append (GTK_MENU (sim->menu), menuitem);
1755
1756
1757                        gnome_desktop_entry_free (ii);
1758                }
1759               
1760                if (sim->mf != NULL) {
1761                        GtkWidget *submenu;
1762
1763                        if (sim->type == 0) {
1764                                submenu = sim->menu;
1765                        } else {
1766                                submenu = menu_new ();
1767
1768                                gtk_object_set_data
1769                                        (GTK_OBJECT(submenu), "menu_panel",
1770                                         get_panel_from_menu_data (sim->menuitem,
1771                                                                   TRUE));
1772
1773                                menuitem = gtk_menu_item_new ();
1774                                gtk_widget_lock_accelerators (menuitem);
1775                                setup_menuitem (menuitem, 0,
1776                                                _("Entire menu"));
1777                                gtk_menu_append (GTK_MENU (sim->menu), menuitem);
1778                                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
1779                                                           submenu);
1780                        }
1781
1782
1783                        menuitem = gtk_menu_item_new ();
1784                        gtk_widget_lock_accelerators (menuitem);
1785                        setup_menuitem (menuitem, 0,
1786                                        _("Add this as drawer to panel"));
1787                        gtk_menu_append (GTK_MENU (submenu), menuitem);
1788                        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
1789                                   GTK_SIGNAL_FUNC(add_menudrawer_to_panel),
1790                                   sim->mf);
1791
1792                        menuitem = gtk_menu_item_new ();
1793                        gtk_widget_lock_accelerators (menuitem);
1794                        setup_menuitem (menuitem, 0,
1795                                        _("Add this as menu to panel"));
1796                        gtk_menu_append (GTK_MENU (submenu), menuitem);
1797                        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
1798                                           GTK_SIGNAL_FUNC(add_menu_to_panel),
1799                                           sim->mf->menudir);
1800                        menuitem = gtk_menu_item_new ();
1801                        gtk_widget_lock_accelerators (menuitem);
1802                        setup_menuitem (menuitem, 0,
1803                                        _("Add this to Favorites menu"));
1804                        gtk_menu_append (GTK_MENU (submenu), menuitem);
1805                        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
1806                                           GTK_SIGNAL_FUNC(add_app_to_personal),
1807                                           sim->mf->menudir);
1808                        /*ummmm slightly ugly but should work 99% of time*/
1809                        if(strstr(sim->mf->menudir, "/.gnome/apps") != NULL)
1810                                gtk_widget_set_sensitive(menuitem, FALSE);
1811
1812                        menuitem = gtk_menu_item_new ();
1813                        gtk_widget_lock_accelerators (menuitem);
1814                        setup_menuitem (menuitem, 0,
1815                                        _("Add new item to this menu"));
1816                        gtk_menu_append (GTK_MENU (submenu), menuitem);
1817                        /*when activated we must pop down the first menu*/
1818                        gtk_signal_connect_object (GTK_OBJECT(menuitem),
1819                                                  "activate",
1820                                                  GTK_SIGNAL_FUNC(gtk_menu_shell_deactivate),
1821                                                  GTK_OBJECT(item->parent));
1822                        gtk_signal_connect (GTK_OBJECT(menuitem), "activate",
1823                                            GTK_SIGNAL_FUNC(add_new_app_to_menu),
1824                                            sim->mf->menudir);
1825                        if (access (sim->mf->menudir, W_OK) != 0)
1826                                gtk_widget_set_sensitive (menuitem, FALSE);
1827
1828
1829                        menuitem = gtk_menu_item_new ();
1830                        gtk_widget_lock_accelerators (menuitem);
1831                        /*when activated we must pop down the first menu*/
1832                        gtk_signal_connect_object(GTK_OBJECT(menuitem),
1833                                                  "activate",
1834                                                  GTK_SIGNAL_FUNC(gtk_menu_shell_deactivate),
1835                                                  GTK_OBJECT(item->parent));
1836                        gtk_signal_connect (GTK_OBJECT (menuitem),
1837                                            "activate",
1838                                            GTK_SIGNAL_FUNC (edit_direntry),
1839                                            sim);
1840                        setup_menuitem (menuitem, 0, _("Properties..."));
1841                        gtk_menu_append (GTK_MENU (submenu), menuitem);
1842                }
1843        }
1844       
1845        gtk_menu_popup (GTK_MENU (sim->menu),
1846                        NULL,
1847                        NULL,
1848                        NULL,
1849                        NULL,
1850                        bevent->button,
1851                        bevent->time);
1852}
1853
1854static gboolean
1855show_item_menu_b_cb(GtkWidget *w, GdkEvent *event, ShowItemMenu *sim)
1856{
1857        GdkEventButton *bevent = (GdkEventButton *)event;
1858        GtkWidget *item;
1859       
1860        if (event->type != GDK_BUTTON_PRESS)
1861                return FALSE;
1862
1863        /* no item menu in commie mode */
1864        if (commie_mode)
1865                return FALSE;
1866       
1867        item = w->parent->parent;
1868        show_item_menu (item, bevent, sim);
1869       
1870        return TRUE;
1871}
1872
1873static gboolean
1874show_item_menu_mi_cb (GtkWidget *w, GdkEvent *event, ShowItemMenu *sim)
1875{
1876        GdkEventButton *bevent = (GdkEventButton *)event;
1877
1878        /* no item menu in commie mode */
1879        if (commie_mode)
1880                return FALSE;
1881       
1882        if (event->type == GDK_BUTTON_PRESS &&
1883            bevent->button == 3)
1884                show_item_menu (w, bevent, sim);
1885       
1886        return FALSE;
1887}
1888
1889static void
1890destroy_item_menu(GtkWidget *w, ShowItemMenu *sim)
1891{
1892        /*NOTE: don't free item_loc or mf.. it's not ours and will be free'd
1893          elsewhere*/
1894        if (sim->menu != NULL)
1895                gtk_widget_unref (sim->menu);
1896        sim->menu = NULL;
1897        g_free (sim);
1898}
1899
1900/* This is a _horrible_ hack to have this here. This needs to be added to the
1901 * GTK+ menuing code in some manner.
1902 */
1903static void 
1904drag_end_menu_cb (GtkWidget *widget, GdkDragContext     *context)
1905{
1906  GtkWidget *xgrab_shell;
1907  GtkWidget *parent;
1908
1909  /* Find the last viewable ancestor, and make an X grab on it
1910   */
1911  parent = widget->parent;
1912  xgrab_shell = NULL;
1913  while (parent)
1914    {
1915      gboolean viewable = TRUE;
1916      GtkWidget *tmp = parent;
1917     
1918      while (tmp)
1919        {
1920          if (!GTK_WIDGET_MAPPED (tmp))
1921            {
1922              viewable = FALSE;
1923              break;
1924            }
1925          tmp = tmp->parent;
1926        }
1927     
1928      if (viewable)
1929        xgrab_shell = parent;
1930     
1931      parent = GTK_MENU_SHELL (parent)->parent_menu_shell;
1932    }
1933 
1934  if (xgrab_shell && !GTK_MENU(xgrab_shell)->torn_off)
1935    {
1936      GdkCursor *cursor = gdk_cursor_new (GDK_ARROW);
1937
1938      if ((gdk_pointer_grab (xgrab_shell->window, TRUE,
1939                             GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1940                             GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1941                             GDK_POINTER_MOTION_MASK,
1942                             NULL, cursor, GDK_CURRENT_TIME) == 0))
1943        {
1944          if (gdk_keyboard_grab (xgrab_shell->window, TRUE,
1945                                 GDK_CURRENT_TIME) == 0)
1946            GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
1947          else
1948            {
1949              gdk_pointer_ungrab (GDK_CURRENT_TIME);
1950            }
1951        }
1952
1953      gdk_cursor_destroy (cursor);
1954    }
1955}
1956
1957static void 
1958drag_data_get_menu_cb (GtkWidget *widget, GdkDragContext     *context,
1959                       GtkSelectionData   *selection_data, guint info,
1960                       guint time, char *item_loc)
1961{
1962        gchar *uri_list = g_strconcat ("file:", item_loc, "\r\n", NULL);
1963        gtk_selection_data_set (selection_data,
1964                                selection_data->target, 8, (guchar *)uri_list,
1965                                strlen(uri_list));
1966        g_free(uri_list);
1967}
1968
1969static void 
1970drag_data_get_string_cb (GtkWidget *widget, GdkDragContext     *context,
1971                         GtkSelectionData   *selection_data, guint info,
1972                         guint time, const char *string)
1973{
1974        gtk_selection_data_set (selection_data,
1975                                selection_data->target, 8, (guchar *)string,
1976                                strlen(string));
1977}
1978 
1979static void
1980setup_title_menuitem (GtkWidget *menuitem, GtkWidget *pixmap,
1981                      const char *title, MenuFinfo *mf)
1982{
1983        GtkWidget *label, *hbox=NULL, *align;
1984        IconSize size = global_config.use_large_icons
1985                ? MEDIUM_ICON_SIZE : SMALL_ICON_SIZE;
1986        gtk_widget_push_style (title_style);
1987        label = gtk_label_new (title);
1988        gtk_widget_pop_style ();
1989        gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5);
1990        gtk_widget_show (label);
1991
1992        if (gnome_preferences_get_menus_have_icons () ||
1993            global_config.show_dot_buttons) {
1994                hbox = gtk_hbox_new (FALSE, 0);
1995                gtk_widget_show (hbox);
1996                gtk_container_add (GTK_CONTAINER (menuitem), hbox);
1997        } else
1998                gtk_container_add (GTK_CONTAINER (menuitem), label);
1999       
2000        if (0) {
2001                align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
2002                gtk_widget_show (align);
2003                gtk_container_set_border_width (GTK_CONTAINER (align), 1);
2004
2005                if (pixmap) {
2006                        gtk_container_add (GTK_CONTAINER (align), pixmap);
2007                        gtk_widget_set_usize (align, size + 2, size - 4);
2008                        gtk_widget_show (pixmap);
2009                } else
2010                        gtk_widget_set_usize (align, size + 2, size - 4);
2011
2012                gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, FALSE, 0);
2013        }
2014
2015        if (gnome_preferences_get_menus_have_icons () ||
2016            global_config.show_dot_buttons)
2017                gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
2018        if(mf) {
2019                ShowItemMenu *sim = g_new0(ShowItemMenu,1);
2020                sim->mf = mf;/*make sure you don't free this,
2021                               it's not ours!*/
2022                sim->type = 0;
2023                sim->menuitem = menuitem;
2024                gtk_signal_connect(GTK_OBJECT(menuitem), "event",
2025                                   GTK_SIGNAL_FUNC(show_item_menu_mi_cb),
2026                                   sim);
2027                gtk_signal_connect(GTK_OBJECT(menuitem), "destroy",
2028                                   GTK_SIGNAL_FUNC(destroy_item_menu),
2029                                   sim);
2030                if(global_config.show_dot_buttons) {
2031                        GtkWidget *w = gtk_button_new_with_label(_("..."));
2032                        gtk_signal_connect(GTK_OBJECT(w), "event",
2033                                           GTK_SIGNAL_FUNC(show_item_menu_b_cb),
2034                                           sim);
2035                        gtk_widget_show(w);
2036                        gtk_box_pack_end (GTK_BOX (hbox), w, FALSE, FALSE, 0);
2037
2038                        /*this is not really a problem for large fonts but it
2039                          makes the button smaller*/
2040                        gtk_widget_set_usize (w, 0, 16);
2041                }
2042        }
2043
2044        gtk_widget_show (menuitem);
2045
2046}
2047
2048static void
2049setup_full_menuitem_with_size (GtkWidget *menuitem, GtkWidget *pixmap,
2050                               const char *title, const char *item_loc,
2051                               gboolean applet,
2052                               IconSize icon_size,
2053                               MenuFinfo *mf)
2054                               
2055{
2056        static GtkTargetEntry menu_item_targets[] = {
2057                { "text/uri-list", 0, 0 }
2058        };
2059
2060        GtkWidget *label, *hbox=NULL, *align;
2061
2062        label = gtk_label_new (title);
2063        gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5);
2064        gtk_widget_show (label);
2065       
2066        if (gnome_preferences_get_menus_have_icons () ||
2067            global_config.show_dot_buttons) {
2068                hbox = gtk_hbox_new (FALSE, 0);
2069                gtk_widget_show (hbox);
2070                gtk_container_add (GTK_CONTAINER (menuitem), hbox);
2071        } else
2072                gtk_container_add (GTK_CONTAINER (menuitem), label);
2073       
2074        if (gnome_preferences_get_menus_have_icons ()) {
2075                align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
2076                gtk_widget_show (align);
2077                gtk_container_set_border_width (GTK_CONTAINER (align), 1);
2078
2079                if (pixmap) {
2080                        gtk_container_add (GTK_CONTAINER (align), pixmap);
2081                        gtk_widget_set_usize (align, icon_size + 2,
2082                                              icon_size - 4);
2083                        gtk_widget_show (pixmap);
2084                } else
2085                        gtk_widget_set_usize (align, icon_size + 2,
2086                                              icon_size - 4);
2087
2088                gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, FALSE, 0);
2089        } else if(pixmap)
2090                gtk_widget_unref(pixmap);
2091
2092        if (gnome_preferences_get_menus_have_icons () ||
2093            global_config.show_dot_buttons)
2094                gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 4);
2095
2096        if (item_loc != NULL) {
2097                ShowItemMenu *sim = g_new0 (ShowItemMenu, 1);
2098                sim->type = 1;
2099                sim->item_loc = item_loc; /*make sure you don't free this,
2100                                            it's not ours!*/
2101                sim->applet = applet;
2102                sim->mf = mf;
2103                sim->menuitem = menuitem;
2104                gtk_signal_connect(GTK_OBJECT(menuitem), "event",
2105                                   GTK_SIGNAL_FUNC(show_item_menu_mi_cb),
2106                                   sim);
2107                gtk_signal_connect(GTK_OBJECT(menuitem), "destroy",
2108                                   GTK_SIGNAL_FUNC(destroy_item_menu),
2109                                   sim);
2110                if(global_config.show_dot_buttons) {
2111                        GtkWidget *w = gtk_button_new_with_label(_("..."));
2112                        gtk_signal_connect(GTK_OBJECT(w),"event",
2113                                           GTK_SIGNAL_FUNC(show_item_menu_b_cb),
2114                                           sim);
2115                        gtk_widget_show(w);
2116                        gtk_box_pack_end (GTK_BOX (hbox), w, FALSE, FALSE, 0);
2117                        /*this is not really a problem for large fonts but it
2118                          makes the button smaller*/
2119                        gtk_widget_set_usize (w, 0, 16);
2120                }
2121
2122                /*applets have their own drag'n'drop*/
2123                if ( ! applet && ! commie_mode) {
2124                        gtk_drag_source_set(menuitem,
2125                                            GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
2126                                            menu_item_targets, 1,
2127                                            GDK_ACTION_COPY);
2128
2129                        gtk_signal_connect(GTK_OBJECT(menuitem), "drag_data_get",
2130                                           drag_data_get_menu_cb,
2131                                           (gpointer)item_loc);
2132                        gtk_signal_connect(GTK_OBJECT(menuitem), "drag_end",
2133                                           drag_end_menu_cb, NULL);
2134                }
2135        }
2136
2137        gtk_widget_show (menuitem);
2138}
2139
2140static void
2141setup_full_menuitem (GtkWidget *menuitem, GtkWidget *pixmap,
2142                     const char *title, const char *item_loc,
2143                     gboolean applet)
2144{
2145        setup_full_menuitem_with_size (menuitem, pixmap, title,
2146                                       item_loc, applet, SMALL_ICON_SIZE,
2147                                       NULL);
2148}
2149
2150void
2151setup_menuitem (GtkWidget *menuitem, GtkWidget *pixmap, const char *title)
2152{
2153        setup_full_menuitem(menuitem, pixmap, title, NULL, FALSE);
2154}
2155
2156static void
2157setup_menuitem_with_size (GtkWidget *menuitem, GtkWidget *pixmap,
2158                          const char *title, int icon_size)
2159{
2160        setup_full_menuitem_with_size (menuitem, pixmap, title, NULL,
2161                                       FALSE, icon_size, NULL);
2162}
2163
2164static void
2165setup_directory_drag (GtkWidget *menuitem, const char *directory)
2166{
2167        static GtkTargetEntry menu_item_targets[] = {
2168                { "application/x-panel-directory", 0, 0 }
2169        };
2170
2171        gtk_drag_source_set(menuitem,
2172                            GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
2173                            menu_item_targets, 1,
2174                            GDK_ACTION_COPY);
2175       
2176        gtk_signal_connect_full(GTK_OBJECT(menuitem), "drag_data_get",
2177                           GTK_SIGNAL_FUNC (drag_data_get_string_cb), NULL,
2178                           g_strdup (directory), (GtkDestroyNotify)g_free,
2179                           FALSE, FALSE);
2180        gtk_signal_connect(GTK_OBJECT(menuitem), "drag_end",
2181                           GTK_SIGNAL_FUNC (drag_end_menu_cb), NULL);
2182}
2183
2184void
2185setup_internal_applet_drag (GtkWidget *menuitem, const char *applet_type)
2186{
2187        static GtkTargetEntry menu_item_targets[] = {
2188                { "application/x-panel-applet-internal", 0, 0 }
2189        };
2190       
2191        if (applet_type == NULL ||
2192            commie_mode)
2193                return;
2194       
2195        gtk_drag_source_set (menuitem,
2196                             GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
2197                             menu_item_targets, 1,
2198                             GDK_ACTION_COPY);
2199       
2200        gtk_signal_connect_full (GTK_OBJECT (menuitem), "drag_data_get",
2201                           GTK_SIGNAL_FUNC (drag_data_get_string_cb), NULL,
2202                           g_strdup (applet_type), (GtkDestroyNotify)g_free,
2203                           FALSE, FALSE);
2204        gtk_signal_connect (GTK_OBJECT (menuitem), "drag_end",
2205                            GTK_SIGNAL_FUNC (drag_end_menu_cb), NULL);
2206
2207}
2208
2209static void
2210setup_applet_drag (GtkWidget *menuitem, const char *goad_id)
2211{
2212        static GtkTargetEntry menu_item_targets[] = {
2213                { "application/x-panel-applet", 0, 0 }
2214        };
2215       
2216        if (goad_id == NULL)
2217                return;
2218       
2219        gtk_drag_source_set (menuitem,
2220                             GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
2221                             menu_item_targets, 1,
2222                             GDK_ACTION_COPY);
2223
2224        /*note: goad_id should be alive long enough!!*/
2225        gtk_signal_connect (GTK_OBJECT (menuitem), "drag_data_get",
2226                            GTK_SIGNAL_FUNC (drag_data_get_string_cb),
2227                            (gpointer)goad_id);
2228        gtk_signal_connect (GTK_OBJECT (menuitem), "drag_end",
2229                            GTK_SIGNAL_FUNC (drag_end_menu_cb), NULL);
2230
2231}
2232
2233static void
2234add_drawer_to_panel (GtkWidget *widget, gpointer data)
2235{
2236        load_drawer_applet (-1, NULL, NULL,
2237                            get_panel_from_menu_data(widget, TRUE), 0, FALSE);
2238}
2239
2240static void
2241add_logout_to_panel (GtkWidget *widget, gpointer data)
2242{
2243        load_logout_applet (get_panel_from_menu_data(widget, TRUE), 0, FALSE);
2244}
2245
2246static void
2247add_lock_to_panel (GtkWidget *widget, gpointer data)
2248{
2249        load_lock_applet (get_panel_from_menu_data(widget, TRUE), 0, FALSE);
2250}
2251
2252static void
2253add_run_to_panel (GtkWidget *widget, gpointer data)
2254{
2255        load_run_applet (get_panel_from_menu_data(widget, TRUE), 0, FALSE);
2256}
2257
2258static void
2259try_add_status_to_panel (GtkWidget *widget, gpointer data)
2260{
2261        if(!load_status_applet(get_panel_from_menu_data(widget, TRUE),
2262                               0, FALSE)) {
2263                GtkWidget *mbox;
2264                mbox = gnome_message_box_new(_("You already have a status "
2265                                               "dock on the panel. You can "
2266                                               "only have one"),
2267                                             GNOME_MESSAGE_BOX_INFO,
2268                                             GNOME_STOCK_BUTTON_CLOSE,
2269                                             NULL);
2270                gtk_window_set_wmclass(GTK_WINDOW(mbox),
2271                                       "no_more_status_dialog","Panel");
2272                gtk_widget_show_all (mbox);
2273                panel_set_dialog_layer (mbox);
2274        }
2275}
2276
2277static void
2278add_applet (GtkWidget *w, const char *item_loc)
2279{
2280        GnomeDesktopEntry *ii;
2281        char *goad_id;
2282
2283        ii = gnome_desktop_entry_load(item_loc);
2284        if (ii == NULL) {
2285                panel_error_dialog (_("Can't load entry"));
2286                return;
2287        }
2288
2289        goad_id = get_applet_goad_id_from_dentry(ii);
2290        gnome_desktop_entry_free(ii);
2291       
2292        if(!goad_id) {
2293                panel_error_dialog(_("Can't get goad_id from desktop entry!"));
2294                return;
2295        }
2296        load_extern_applet(goad_id, NULL,
2297                           get_panel_from_menu_data(w, TRUE),
2298                           -1, FALSE, FALSE);
2299
2300        g_free(goad_id);
2301}
2302
2303static void
2304add_launcher (GtkWidget *w, const char *item_loc)
2305{
2306        Launcher *launcher;
2307
2308        launcher = load_launcher_applet
2309                (item_loc, get_panel_from_menu_data (w, TRUE), 0, FALSE);
2310
2311        if (launcher != NULL)
2312                launcher_hoard (launcher);
2313}
2314
2315static void
2316add_favourites (GtkWidget *w, const char *item_loc)
2317{
2318        panel_add_favourite (item_loc);
2319}
2320
2321static void
2322destroy_mf(MenuFinfo *mf)
2323{
2324        if (mf->fr != NULL) {
2325                DirRec *dr = (DirRec *)mf->fr;
2326                mf->fr = NULL;
2327                dr->mfl = g_slist_remove(dr->mfl, mf);
2328        }
2329        g_free(mf->menudir);
2330        mf->menudir = NULL;
2331        g_free(mf->dir_name);
2332        mf->dir_name = NULL;
2333        g_free(mf->pixmap_name);
2334        mf->pixmap_name = NULL;
2335        g_free(mf);
2336}
2337
2338
2339static void
2340menu_destroy(GtkWidget *menu, gpointer data)
2341{
2342        GSList *mfl = gtk_object_get_data (GTK_OBJECT (menu), "mf");
2343        GSList *li;
2344        for (li = mfl; li != NULL; li = li->next) {
2345                MenuFinfo *mf = li->data;
2346                destroy_mf (mf);
2347        }
2348        g_slist_free (mfl);
2349        gtk_object_set_data (GTK_OBJECT (menu), "mf", NULL);
2350}
2351
2352/*reread the applet menu, not a submenu*/
2353static void
2354check_and_reread_applet(Menu *menu, gboolean main_menu)
2355{
2356        GSList *mfl, *list;
2357
2358        if (menu_need_reread (menu->menu)) {
2359                mfl = gtk_object_get_data (GTK_OBJECT (menu->menu), "mf");
2360
2361                /*that will be destroyed in add_menu_widget*/
2362                if(main_menu) {
2363                        add_menu_widget (menu, NULL, NULL, main_menu, TRUE);
2364                } else {
2365                        GSList *dirlist = NULL;
2366                        for(list = mfl; list != NULL;
2367                            list = list->next) {
2368                                MenuFinfo *mf = list->data;
2369                                dirlist = g_slist_append (dirlist,
2370                                                          g_strdup (mf->menudir));
2371                        }
2372                        add_menu_widget (menu, NULL, dirlist, main_menu, TRUE);
2373
2374                        g_slist_foreach (dirlist, (GFunc)g_free, NULL);
2375                        g_slist_free (dirlist);
2376                }
2377        }
2378}
2379
2380/* XXX: hmmm stolen GTK code, the gtk_menu_reposition only calls
2381   gtk_menu_position if the widget is drawable, but that's not the
2382   case when we want to do it*/
2383void
2384our_gtk_menu_position (GtkMenu *menu)
2385{
2386  GtkWidget *widget;
2387  GtkRequisition requisition;
2388  gint x, y;
2389 
2390  g_return_if_fail (menu != NULL);
2391  g_return_if_fail (GTK_IS_MENU (menu));
2392
2393  widget = GTK_WIDGET (menu);
2394
2395  gdk_window_get_pointer (NULL, &x, &y, NULL);
2396
2397  /* We need the requisition to figure out the right place to
2398   * popup the menu. In fact, we always need to ask here, since
2399   * if one a size_request was queued while we weren't popped up,
2400   * the requisition won't have been recomputed yet.
2401   */
2402  gtk_widget_size_request (widget, &requisition);
2403     
2404  if (menu->position_func)
2405    (* menu->position_func) (menu, &x, &y, menu->position_func_data);
2406  else
2407    {
2408      gint screen_width;
2409      gint screen_height;
2410      int screen_basex, screen_basey;
2411      int screen;
2412
2413      screen = multiscreen_screen_from_pos (x, y);
2414     
2415      if (screen < 0) {
2416              screen_width = gdk_screen_width ();
2417              screen_height = gdk_screen_height ();
2418              screen_basex = 0;
2419              screen_basey = 0;
2420      } else {
2421              screen_width = multiscreen_width (screen);
2422              screen_height = multiscreen_height (screen);
2423              screen_basex = multiscreen_x (screen);
2424              screen_basey = multiscreen_y (screen);
2425      }
2426
2427      x -= screen_basex;
2428      y -= screen_basey;
2429
2430      x -= 2;
2431      y -= 2;
2432     
2433      if ((x + requisition.width) > screen_width)
2434        x -= ((x + requisition.width) - screen_width);
2435      if (x < 0)
2436        x = 0;
2437      if ((y + requisition.height) > screen_height)
2438        y -= ((y + requisition.height) - screen_height);
2439      if (y < 0)
2440        y = 0;
2441
2442      x += screen_basex;
2443      y += screen_basey;
2444    }
2445 
2446  gtk_widget_set_uposition (GTK_MENU_SHELL (menu)->active ?
2447                                menu->toplevel : menu->tearoff_window,
2448                            x, y);
2449}
2450
2451/* Stolen from GTK+
2452 * Reparent the menu, taking care of the refcounting
2453 */
2454static void
2455my_gtk_menu_reparent (GtkMenu      *menu,
2456                      GtkWidget    *new_parent,
2457                      gboolean      unrealize)
2458{
2459  GtkObject *object = GTK_OBJECT (menu);
2460  GtkWidget *widget = GTK_WIDGET (menu);
2461  gboolean was_floating = GTK_OBJECT_FLOATING (object);
2462
2463  gtk_object_ref (object);
2464  gtk_object_sink (object);
2465
2466  if (unrealize)
2467    {
2468      gtk_object_ref (object);
2469      gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
2470      gtk_container_add (GTK_CONTAINER (new_parent), widget);
2471      gtk_object_unref (object);
2472    }
2473  else
2474    gtk_widget_reparent (GTK_WIDGET (menu), new_parent);
2475  gtk_widget_set_usize (new_parent, -1, -1);
2476 
2477  if (was_floating)
2478    GTK_OBJECT_SET_FLAGS (object, GTK_FLOATING);
2479  else
2480    gtk_object_unref (object);
2481}
2482
2483static gboolean
2484move_window_handler (gpointer data)
2485{
2486        int x, y, sx, sy, wx, wy, foox, fooy;
2487        GtkWidget *win = data;
2488
2489        data = gtk_object_get_data (GTK_OBJECT (win), "move_speed_x");
2490        sx = GPOINTER_TO_INT (data);
2491        data = gtk_object_get_data (GTK_OBJECT (win), "move_speed_y");
2492        sy = GPOINTER_TO_INT (data);
2493
2494        gdk_window_get_pointer (NULL, &x, &y, NULL);
2495        wx = win->allocation.x;
2496        wy = win->allocation.y;
2497
2498        foox = wx + (win->allocation.width / 2);
2499        fooy = wy + (win->allocation.height / 2);
2500
2501        if (sqrt ((foox - x)*(foox - x) + (fooy - y)*(fooy - y)) <
2502            MAX (win->allocation.width, win->allocation.height)) {
2503                if (foox < x) sx -= 5;
2504                else sx += 5;
2505                if (fooy < y) sy -= 5;
2506                else sy += 5;
2507        } else {
2508                sx /= 2;
2509                sy /= 2;
2510        }
2511       
2512        if (sx > 50) sx = 50;
2513        else if (sx < -50) sx = -50;
2514        if (sy > 50) sy = 50;
2515        else if (sy < -50) sy = -50;
2516
2517        wx += sx;
2518        wy += sy;
2519
2520        if (wx < 0) wx = 0;
2521        if (wy < 0) wy = 0;
2522        if (wx + win->allocation.width > gdk_screen_width ())
2523                wx = gdk_screen_width () - win->allocation.width;
2524        if (wy + win->allocation.height > gdk_screen_height ())
2525                wy = gdk_screen_height () - win->allocation.height;
2526
2527        gtk_widget_set_uposition (win, wx, wy);
2528        win->allocation.x = wx;
2529        win->allocation.y = wy;
2530
2531        data = GINT_TO_POINTER (sx);
2532        gtk_object_set_data (GTK_OBJECT (win), "move_speed_x", data);
2533        data = GINT_TO_POINTER (sy);
2534        gtk_object_set_data (GTK_OBJECT (win), "move_speed_y", data);
2535
2536        return TRUE;
2537}
2538
2539static void
2540move_window_destroyed (GtkWidget *win)
2541{
2542        gpointer data = gtk_object_get_data (GTK_OBJECT (win), "move_window_handler");
2543        int handler = GPOINTER_TO_INT (data);
2544
2545        if (handler != 0)
2546                gtk_timeout_remove (handler);
2547        gtk_object_remove_data (GTK_OBJECT (win), "move_window_handler");
2548}
2549
2550static void
2551doblah (GtkWidget *window)
2552{
2553        gpointer data = gtk_object_get_data (GTK_OBJECT (window), "move_window_handler");
2554        int handler = GPOINTER_TO_INT (data);
2555
2556        if (handler == 0) {
2557                handler = gtk_timeout_add (30, move_window_handler, window);
2558                data = GINT_TO_POINTER (handler);
2559                gtk_object_set_data (GTK_OBJECT (window), "move_window_handler", data);
2560                gtk_signal_connect (GTK_OBJECT (window), "destroy",
2561                                    GTK_SIGNAL_FUNC (move_window_destroyed),
2562                                    NULL);
2563        }
2564}
2565
2566/*mostly stolen from GTK+ */
2567static gboolean
2568my_gtk_menu_window_event (GtkWidget *window,
2569                          GdkEvent  *event,
2570                          GtkWidget *menu)
2571{
2572        gboolean handled = FALSE;
2573
2574        gtk_widget_ref (window);
2575        gtk_widget_ref (menu);
2576
2577        switch (event->type) {
2578                static int foo = 0;
2579        case GDK_KEY_PRESS:
2580                if((event->key.state & GDK_CONTROL_MASK) && foo < 4) {
2581                        switch (event->key.keyval) {
2582                        case GDK_r:
2583                        case GDK_R:
2584                                if(foo == 3) { doblah (window); } foo = 0; break;
2585                        case GDK_a:
2586                        case GDK_A:
2587                                if(foo == 2) { foo++; } else { foo = 0; } break;
2588                        case GDK_e:
2589                        case GDK_E:
2590                                if(foo == 1) { foo++; } else { foo = 0; } break;
2591                        case GDK_f:
2592                        case GDK_F:
2593                                if(foo == 0) { foo++; } else { foo = 0; } break;
2594                        default:
2595                                foo = 0;
2596                        }
2597                }
2598                /* fall thru */
2599        case GDK_KEY_RELEASE:
2600                gtk_widget_event (menu, event);
2601                handled = TRUE;
2602                break;
2603        default:
2604                break;
2605        }
2606
2607        gtk_widget_unref (window);
2608        gtk_widget_unref (menu);
2609
2610        return handled;
2611}
2612
2613static gulong wmclass_number = 0;
2614
2615static char *
2616get_unique_tearoff_wmclass (void)
2617{
2618        static char buf[256];
2619
2620        g_snprintf (buf, sizeof (buf), "panel_tearoff_%lu", wmclass_number++);
2621
2622        return buf;
2623}
2624
2625static void
2626show_tearoff_menu (GtkWidget *menu, const char *title, gboolean cursor_position,
2627                   int x, int y, const char *wmclass)
2628{
2629        GtkWidget *win;
2630        win = GTK_MENU(menu)->tearoff_window =
2631                gtk_window_new (GTK_WINDOW_TOPLEVEL);
2632        gtk_window_set_wmclass (GTK_WINDOW (win),
2633                                wmclass, "Panel");
2634        gtk_widget_set_app_paintable (win, TRUE);
2635        gtk_signal_connect (GTK_OBJECT (win), "event",
2636                            GTK_SIGNAL_FUNC (my_gtk_menu_window_event),
2637                            GTK_OBJECT (menu));
2638        gtk_widget_realize (win);
2639             
2640        gdk_window_set_title (win->window, title);
2641       
2642        gdk_window_set_decorations (win->window,
2643                                    GDK_DECOR_ALL |
2644                                    GDK_DECOR_RESIZEH |
2645                                    GDK_DECOR_MINIMIZE |
2646                                    GDK_DECOR_MAXIMIZE);
2647        gtk_window_set_policy (GTK_WINDOW (win), FALSE, FALSE, TRUE);
2648        my_gtk_menu_reparent (GTK_MENU (menu), win, FALSE);
2649        /* set sticky so that we mask the fact that we have no clue
2650           how to restore non sticky windows */
2651        gnome_win_hints_set_state (win, gnome_win_hints_get_state (win) |
2652                                   WIN_STATE_STICKY);
2653       
2654        GTK_MENU (menu)->torn_off = TRUE;
2655
2656        if (cursor_position)
2657                our_gtk_menu_position (GTK_MENU (menu));
2658        else
2659                gtk_widget_set_uposition (win, x, y);
2660
2661        gtk_widget_show (GTK_WIDGET (menu));
2662        gtk_widget_show (win);
2663}
2664
2665static void
2666tearoff_destroyed (GtkWidget *tearoff, TearoffMenu *tm)
2667{
2668        tearoffs = g_slist_remove(tearoffs, tm);
2669        g_free(tm->title);
2670        tm->title = NULL;
2671        g_free(tm->wmclass);
2672        tm->wmclass = NULL;
2673        g_free(tm->special);
2674        tm->special = NULL;
2675        g_free(tm);
2676}
2677
2678static void
2679tearoff_new_menu(GtkWidget *item, GtkWidget *menuw)
2680{
2681        GSList *mfl = gtk_object_get_data(GTK_OBJECT(menuw), "mf");
2682        GSList *list;
2683        GtkWidget *menu;
2684        GString *title;
2685        TearoffMenu *tm;
2686        char *wmclass;
2687        PanelWidget *menu_panel;
2688       
2689        if (mfl == NULL)
2690                return;
2691
2692        menu = menu_new();
2693
2694        menu_panel = get_panel_from_menu_data(menuw, TRUE);
2695
2696        /*set the panel to use as the data*/
2697        gtk_object_set_data(GTK_OBJECT(menu), "menu_panel", menu_panel);
2698
2699        gtk_signal_connect_object_while_alive(GTK_OBJECT(menu_panel),
2700                      "destroy", GTK_SIGNAL_FUNC(gtk_widget_unref),
2701                      GTK_OBJECT(menu));
2702       
2703        title = g_string_new(NULL);
2704
2705        for(list = mfl; list != NULL; list = list->next) {
2706                MenuFinfo *mf = list->data;
2707
2708                menu = create_menu_at_fr (menu,
2709                                          mf->fr,
2710                                          mf->applets,
2711                                          mf->launcher_add,
2712                                          mf->favourites_add,
2713                                          mf->dir_name,
2714                                          mf->pixmap_name,
2715                                          TRUE /*fake_submenus*/,
2716                                          FALSE /*force*/,
2717                                          TRUE /*title*/);
2718               
2719                if (list != mfl)
2720                        g_string_append_c (title, ' ');
2721                g_string_append (title, mf->dir_name);
2722        }
2723
2724        wmclass = get_unique_tearoff_wmclass ();
2725        show_tearoff_menu(menu, title->str, TRUE, 0, 0, wmclass);
2726
2727        tm = g_new0 (TearoffMenu, 1);
2728        tm->menu = menu;
2729        tm->mfl = gtk_object_get_data (GTK_OBJECT (menu), "mf");
2730        tm->special = NULL;
2731        tm->title = title->str;
2732        tm->wmclass = g_strdup (wmclass);
2733        gtk_signal_connect (GTK_OBJECT (menu), "destroy",
2734                            GTK_SIGNAL_FUNC (tearoff_destroyed), tm);
2735
2736        tearoffs = g_slist_prepend (tearoffs, tm);
2737
2738        g_string_free (title, FALSE);
2739
2740        need_complete_save = TRUE;
2741}
2742
2743static void
2744add_tearoff (GtkMenu *menu)
2745{
2746        GtkWidget *w;
2747
2748        if (!gnome_preferences_get_menus_have_tearoff ()){
2749                g_warning (_("Adding tearoff when tearoffs are disabled"));
2750                return;
2751        }
2752
2753        w = tearoff_item_new();
2754        gtk_widget_show(w);
2755        gtk_menu_prepend(menu, w);
2756       
2757        gtk_signal_connect(GTK_OBJECT(w), "activate",
2758                           GTK_SIGNAL_FUNC(tearoff_new_menu),
2759                           menu);
2760}
2761
2762/*BTW, this also updates the fr entires */
2763gboolean
2764menu_need_reread(GtkWidget *menuw)
2765{
2766        GSList *mfl = gtk_object_get_data(GTK_OBJECT(menuw), "mf");
2767        GSList *list;
2768        gboolean need_reread = FALSE;
2769
2770        /*if(!mfl)
2771          g_warning("Weird menu doesn't have mf entry");*/
2772
2773        if (GTK_MENU(menuw)->torn_off)
2774                return FALSE;
2775
2776        if (gtk_object_get_data(GTK_OBJECT(menuw), "need_reread")) {
2777                need_reread = TRUE;
2778                gtk_object_remove_data(GTK_OBJECT(menuw), "need_reread");
2779        }
2780       
2781        /*check if we need to reread this*/
2782        for(list = mfl; list != NULL; list = list->next) {
2783                MenuFinfo *mf = list->data;
2784                if(mf->fake_menu ||
2785                   mf->fr == NULL) {
2786                        if(mf->fr != NULL)
2787                                mf->fr = fr_replace(mf->fr);
2788                        else
2789                                mf->fr = fr_get_dir(mf->menudir);
2790                        need_reread = TRUE;
2791                } else {
2792                        FileRec *fr;
2793                        fr = fr_check_and_reread(mf->fr);
2794                        if(fr != mf->fr ||
2795                           fr == NULL) {
2796                                need_reread = TRUE;
2797                                mf->fr = fr;
2798                        }
2799                }
2800        }
2801
2802        return need_reread;
2803}
2804
2805void
2806submenu_to_display (GtkWidget *menuw, gpointer data)
2807{
2808        GSList *mfl, *list;
2809        gboolean add_launcher_hack;
2810        gboolean add_favourites_hack;
2811        gboolean favourites_hack;
2812
2813        if (GTK_MENU(menuw)->torn_off)
2814                return;
2815
2816        /*this no longer constitutes a bad hack, now it's purely cool :)*/
2817        if( ! menu_need_reread(menuw))
2818                return;
2819
2820        /* EEEEEK! hacks */
2821        add_launcher_hack =
2822                GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menuw),
2823                                                      "_add_launcher_menu_hack_"));
2824        add_favourites_hack =
2825                GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menuw),
2826                                                      "_add_favourites_menu_hack_"));
2827        favourites_hack =
2828                GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menuw),
2829                                                      "_favourites_menu_hack_"));
2830
2831        /* Note this MUST be destroy and not unref, unref would fuck
2832         * up here, we don't hold a reference to them, so we must
2833         * destroy them, menu shell will unref these */
2834        while(GTK_MENU_SHELL(menuw)->children)
2835                gtk_widget_destroy(GTK_MENU_SHELL(menuw)->children->data);
2836
2837        if (add_launcher_hack) {
2838                create_add_launcher_menu (menuw, TRUE /* fake_submenus */);
2839        } else if (add_favourites_hack) {
2840                create_add_favourites_menu (menuw, TRUE /* fake_submenus */);
2841        } else {
2842
2843                if (gnome_preferences_get_menus_have_tearoff ())
2844                        add_tearoff(GTK_MENU(menuw));
2845
2846                if (favourites_hack) {
2847                        start_favourites_menu (menuw, TRUE /* fake_submenus */);
2848                }
2849
2850                mfl = gtk_object_get_data(GTK_OBJECT(menuw), "mf");
2851
2852                gtk_object_set_data(GTK_OBJECT(menuw), "mf", NULL);
2853                for(list = mfl;
2854                    list != NULL;
2855                    list = list->next) {
2856                        MenuFinfo *mf = list->data;
2857
2858                        menuw = create_menu_at_fr (menuw,
2859                                                   mf->fr,
2860                                                   mf->applets,
2861                                                   mf->launcher_add,
2862                                                   mf->favourites_add,
2863                                                   mf->dir_name,
2864                                                   mf->pixmap_name,
2865                                                   TRUE /*fake_submenus*/,
2866                                                   FALSE /*force*/,
2867                                                   mf->title /*title*/);
2868                        destroy_mf(mf);
2869                }
2870                g_slist_free(mfl);
2871        }
2872
2873        our_gtk_menu_position(GTK_MENU(menuw));
2874}
2875
2876GtkWidget *
2877start_favourites_menu (GtkWidget *menu,
2878                       gboolean fake_submenus)
2879{
2880        GtkWidget *menuitem;
2881        GtkWidget *m;
2882
2883        if (menu == NULL) {
2884                menu = menu_new ();
2885
2886                if (gnome_preferences_get_menus_have_tearoff ())
2887                        add_tearoff(GTK_MENU(menu));
2888        }
2889
2890        /* Add the favourites stuff here */
2891        menuitem = gtk_menu_item_new ();
2892        gtk_widget_lock_accelerators (menuitem);
2893        setup_menuitem_try_pixmap (menuitem,
2894                                   "launcher-program.png",
2895                                   /* Add to favourites */
2896                                   _("Add from menu"),
2897                                   SMALL_ICON_SIZE);
2898        gtk_menu_append (GTK_MENU (menu), menuitem);
2899        m = create_add_favourites_menu (NULL,
2900                                        TRUE /*fake_submenus*/);
2901        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), m);
2902        gtk_signal_connect (GTK_OBJECT (m),"show",
2903                            GTK_SIGNAL_FUNC (submenu_to_display), NULL);
2904
2905        /* Eeeek, a hack, if this is set then the reloading
2906         * function will use start_favourites_menu */
2907        gtk_object_set_data (GTK_OBJECT (menu),
2908                             "_favourites_menu_hack_",
2909                             GINT_TO_POINTER (1));
2910
2911        return menu;
2912}
2913
2914
2915GtkWidget *
2916create_fake_menu_at (const char *menudir,
2917                     gboolean applets,
2918                     gboolean launcher_add,
2919                     gboolean favourites_add,
2920                     const char *dir_name,
2921                     const char *pixmap_name,
2922                     gboolean title)
2923{       
2924        MenuFinfo *mf;
2925        GtkWidget *menu;
2926        GSList *list;
2927       
2928        menu = menu_new ();
2929
2930        mf = g_new0 (MenuFinfo, 1);
2931        mf->menudir = g_strdup (menudir);
2932        mf->applets = applets;
2933        mf->launcher_add = launcher_add;
2934        mf->favourites_add = favourites_add;
2935        mf->dir_name = g_strdup (dir_name);
2936        mf->pixmap_name = g_strdup (pixmap_name);
2937        mf->fake_menu = TRUE;
2938        mf->title = title;
2939        mf->fr = NULL;
2940       
2941        list = g_slist_prepend(NULL, mf);
2942        gtk_object_set_data(GTK_OBJECT(menu), "mf", list);
2943       
2944        gtk_signal_connect(GTK_OBJECT(menu), "destroy",
2945                           GTK_SIGNAL_FUNC(menu_destroy), NULL);
2946       
2947        return menu;
2948}
2949
2950static gboolean
2951create_menuitem (GtkWidget *menu,
2952                 FileRec *fr,
2953                 gboolean applets,
2954                 gboolean launcher_add,
2955                 gboolean favourites_add,
2956                 gboolean fake_submenus,
2957                 gboolean *add_separator,
2958                 int *first_item,
2959                 MenuFinfo *mf)
2960{
2961        GtkWidget *menuitem, *sub, *pixmap;
2962        IconSize size = global_config.use_large_icons
2963                ? MEDIUM_ICON_SIZE : SMALL_ICON_SIZE;
2964        char *itemname;
2965       
2966        g_return_val_if_fail (fr != NULL, FALSE);
2967
2968        if(fr->type == FILE_REC_EXTRA)
2969                return FALSE;
2970
2971
2972        if(fr->type == FILE_REC_FILE && applets &&
2973           !fr->goad_id) {
2974                g_warning(_("Can't get goad_id for applet, ignoring it"));
2975                return FALSE;
2976        }
2977
2978        sub = NULL;
2979        if(fr->fullname) {
2980                itemname = g_strdup(fr->fullname);
2981        } else {
2982                char *p;
2983                itemname = g_strdup(g_basename(fr->name));
2984                p = strrchr(itemname, '.');
2985                if(p) *p = '\0';
2986        }
2987
2988        if(fr->type == FILE_REC_DIR) {
2989                if(fake_submenus)
2990                        sub = create_fake_menu_at (fr->name,
2991                                                   applets,
2992                                                   launcher_add,
2993                                                   favourites_add,
2994                                                   itemname,
2995                                                   fr->icon,
2996                                                   TRUE);
2997                else
2998                        sub = create_menu_at_fr (NULL, fr,
2999                                                 applets,
3000                                                 launcher_add,
3001                                                 favourites_add,
3002                                                 itemname,
3003                                                 fr->icon,
3004                                                 fake_submenus,
3005                                                 FALSE /*force*/,
3006                                                 TRUE /*title*/);
3007
3008                if (!sub) {
3009                        g_free(itemname);
3010                        return FALSE;
3011                }
3012        }
3013
3014        menuitem = gtk_menu_item_new ();
3015        gtk_widget_lock_accelerators (menuitem);
3016        if (sub) {
3017                gtk_menu_item_set_submenu (GTK_MENU_ITEM(menuitem), sub);
3018                gtk_signal_connect(GTK_OBJECT(sub), "show",
3019                                   GTK_SIGNAL_FUNC(submenu_to_display), NULL);
3020        }
3021
3022        pixmap = NULL;
3023        if (gnome_preferences_get_menus_have_icons ()) {
3024                if (fr->icon && panel_file_exists (fr->icon)) {
3025                        pixmap = fake_pixmap_at_size (fr->icon, size);
3026                        if (pixmap)
3027                                gtk_widget_show (pixmap);
3028                }
3029        }
3030
3031        if (sub == NULL &&
3032                   strstr(fr->name,"/applets/") &&
3033                   fr->goad_id != NULL) {
3034                setup_applet_drag (menuitem, fr->goad_id);
3035                setup_full_menuitem_with_size (menuitem, pixmap, itemname,
3036                                               fr->name, TRUE, size, mf);
3037        } else {
3038                /*setup the menuitem, pass item_loc if this is not
3039                  a submenu, so that the item can be added,
3040                  we can be sure that the FileRec will live that long,
3041                  (when it dies, the menu will not be used again, it will
3042                  be recreated at the next available opportunity)*/
3043                setup_full_menuitem_with_size (menuitem, pixmap, itemname,
3044                                               sub != NULL ? NULL : fr->name,
3045                                               FALSE, size, mf);
3046        }
3047
3048        if(*add_separator) {
3049                add_menu_separator(menu);
3050                (*first_item)++;
3051                *add_separator = FALSE;
3052        }
3053       
3054        if(fr->comment)
3055                gtk_tooltips_set_tip (panel_tooltips, menuitem,
3056                                      fr->comment, NULL);
3057        gtk_menu_append (GTK_MENU (menu), menuitem);
3058
3059        if(!sub) {
3060                if (launcher_add)
3061                        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
3062                                            GTK_SIGNAL_FUNC (add_launcher),
3063                                            fr->name);
3064                else if (favourites_add)
3065                        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
3066                                            GTK_SIGNAL_FUNC (add_favourites),
3067                                            fr->name);
3068                else if (applets)
3069                        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
3070                                            GTK_SIGNAL_FUNC (add_applet),
3071                                            fr->name);
3072                else
3073                        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
3074                                            GTK_SIGNAL_FUNC (activate_app_def),
3075                                            fr->name);
3076        }
3077
3078        g_free (itemname);
3079
3080        return TRUE;
3081}
3082
3083GtkWidget *
3084create_menu_at (GtkWidget *menu,
3085                const char *menudir,
3086                gboolean applets,
3087                gboolean launcher_add,
3088                gboolean favourites_add,
3089                const char *dir_name,
3090                const char *pixmap_name,
3091                gboolean fake_submenus,
3092                gboolean force,
3093                gboolean title)
3094{
3095        return create_menu_at_fr (menu,
3096                                  fr_get_dir (menudir),
3097                                  applets,
3098                                  launcher_add,
3099                                  favourites_add,
3100                                  dir_name,
3101                                  pixmap_name,
3102                                  fake_submenus,
3103                                  force,
3104                                  title);
3105}
3106
3107static GtkWidget *
3108create_menu_at_fr (GtkWidget *menu,
3109                   FileRec *fr,
3110                   gboolean applets,
3111                   gboolean launcher_add,
3112                   gboolean favourites_add,
3113                   const char *dir_name,
3114                   const char *pixmap_name,
3115                   gboolean fake_submenus,
3116                   gboolean force,
3117                   gboolean title)
3118{       
3119        GSList *li;
3120        GSList *mfl = NULL;
3121        gboolean add_separator = FALSE;
3122        int first_item = 0;
3123        GtkWidget *menuitem;
3124        MenuFinfo *mf = NULL;
3125        DirRec *dr = (DirRec *)fr;
3126        GtkWidget *pixmap;
3127        IconSize size = global_config.use_large_icons
3128                ? MEDIUM_ICON_SIZE : SMALL_ICON_SIZE;
3129
3130        g_return_val_if_fail(!(fr&&fr->type!=FILE_REC_DIR),menu);
3131       
3132        if( ! force &&
3133           fr == NULL)
3134                return menu;
3135
3136        /* unfilled out, but the pointer will be correct */
3137        mf = g_new0 (MenuFinfo, 1);
3138       
3139        /*get this info ONLY if we haven't gotten it already*/
3140        if(dir_name == NULL)
3141                dir_name = (fr&&fr->fullname)?fr->fullname:_("Menu");
3142        if(pixmap_name == NULL)
3143                pixmap_name = (fr&&fr->icon)?fr->icon:gnome_folder;
3144       
3145        if(!menu) {
3146                menu = menu_new ();
3147                if (gnome_preferences_get_menus_have_tearoff ()) {
3148                        add_tearoff(GTK_MENU(menu));
3149                        first_item++;
3150                }
3151                gtk_signal_connect(GTK_OBJECT(menu), "destroy",
3152                                   GTK_SIGNAL_FUNC(menu_destroy), NULL);
3153        } else {
3154                first_item = g_list_length(GTK_MENU_SHELL(menu)->children);
3155                mfl = gtk_object_get_data(GTK_OBJECT(menu), "mf");
3156                if(GTK_MENU_SHELL(menu)->children &&
3157                   !(GTK_MENU_SHELL(menu)->children->next == NULL &&
3158                     IS_TEAROFF_ITEM(GTK_MENU_SHELL(menu)->children->data)))
3159                        add_separator = TRUE;
3160        }
3161       
3162        if(fr) {
3163                /* Last added points to the last fr list item that was successfuly
3164                 * added as a menu item */
3165                GSList *last_added = NULL;
3166                for(li = dr->recs; li != NULL; li = li->next) {
3167                        FileRec *tfr = li->data;
3168                        FileRec *pfr = last_added ? last_added->data : NULL;
3169
3170                        /* Add a separator between merged and non-merged menuitems */
3171                        if (tfr->merged &&
3172                            pfr != NULL &&
3173                            ! pfr->merged) {
3174                                add_menu_separator(menu);
3175                        }
3176
3177                        if (tfr->type == FILE_REC_SEP)
3178                                add_menu_separator (menu);                             
3179                        else if (create_menuitem (menu, tfr,
3180                                                  applets,
3181                                                  launcher_add,
3182                                                  favourites_add,
3183                                                  fake_submenus,
3184                                                  &add_separator,
3185                                                  &first_item,
3186                                                  mf))
3187                                last_added = li;
3188                }
3189        }
3190
3191        mf->menudir = g_strdup (fr->name);
3192        mf->applets = applets;
3193        mf->launcher_add = launcher_add;
3194        mf->favourites_add = favourites_add;
3195        mf->dir_name = g_strdup (dir_name);
3196        mf->pixmap_name = g_strdup (pixmap_name);
3197        mf->fake_menu = FALSE;
3198        mf->title = title;
3199        mf->fr = fr;
3200        if (fr != NULL) {
3201                DirRec *dr = (DirRec *)fr;
3202                dr->mfl = g_slist_prepend (dr->mfl, mf);
3203        }
3204
3205        if (title && global_config.show_menu_titles) {
3206                char *menu_name;
3207
3208                /*if we actually added anything*/
3209                if (first_item < g_list_length(GTK_MENU_SHELL(menu)->children)) {
3210                        menuitem = gtk_menu_item_new();
3211                        gtk_widget_lock_accelerators (menuitem);
3212                        gtk_menu_insert(GTK_MENU(menu),menuitem,first_item);
3213                        gtk_widget_show(menuitem);
3214                        gtk_widget_set_sensitive(menuitem,FALSE);
3215                        if (dir_name == NULL)
3216                                menu_name = g_strdup (_("Menu"));
3217                        else
3218                                menu_name = g_strdup (dir_name);
3219                } else {
3220                        if (dir_name == NULL)
3221                                menu_name = g_strconcat (_("Menu"), _(" (empty)"), NULL);
3222                        else
3223                                menu_name = g_strconcat (dir_name, _(" (empty)"), NULL);
3224                }
3225
3226                pixmap = NULL;
3227                if (gnome_preferences_get_menus_have_icons ()) {
3228                        if (pixmap_name) {
3229                                pixmap = fake_pixmap_at_size (pixmap_name, size);
3230                        }
3231                        if (!pixmap && gnome_folder && panel_file_exists (gnome_folder)) {
3232                                pixmap = fake_pixmap_at_size (gnome_folder, size);
3233                        }
3234                }
3235
3236                if (pixmap != NULL)
3237                        gtk_widget_show (pixmap);
3238
3239                menuitem = title_item_new();
3240                gtk_widget_lock_accelerators (menuitem);
3241                setup_title_menuitem (menuitem, pixmap, menu_name, mf);
3242                gtk_menu_insert (GTK_MENU (menu), menuitem, first_item);
3243
3244                g_free (menu_name);
3245
3246                if ( ! commie_mode)
3247                        setup_directory_drag (menuitem, mf->menudir);
3248        }
3249
3250        /*add separator*/
3251        if (add_separator) {
3252                menuitem = gtk_menu_item_new();
3253                gtk_widget_lock_accelerators (menuitem);
3254                gtk_menu_insert(GTK_MENU(menu), menuitem, first_item);
3255                gtk_widget_show(menuitem);
3256                gtk_widget_set_sensitive(menuitem, FALSE);
3257                add_separator = FALSE;
3258        }
3259
3260        mfl = g_slist_append (mfl, mf);
3261
3262        gtk_object_set_data (GTK_OBJECT (menu), "mf", mfl);
3263
3264        return menu;
3265}
3266
3267static void
3268destroy_menu (GtkWidget *widget, gpointer data)
3269{
3270        Menu *menu = data;
3271        GtkWidget *prop_dialog = menu->prop_dialog;
3272
3273        menu->prop_dialog = NULL;
3274
3275        if (prop_dialog != NULL)
3276                gtk_widget_unref (prop_dialog);
3277
3278        menu->button = NULL;
3279
3280        if (menu->menu != NULL)
3281                gtk_widget_unref(menu->menu);
3282        menu->menu = NULL;
3283}
3284
3285static void
3286free_menu (gpointer data)
3287{
3288        Menu *menu = data;
3289
3290        g_free (menu->path);
3291        menu->path = NULL;
3292
3293        g_free (menu->custom_icon_file);
3294        menu->custom_icon_file = NULL;
3295
3296        g_free(menu);
3297}
3298
3299static void
3300menu_deactivate (GtkWidget *w, gpointer data)
3301{
3302        Menu *menu = data;
3303        GtkWidget *panel = get_panel_parent (menu->button);
3304
3305        /* allow the panel to hide again */
3306        if (IS_BASEP_WIDGET (panel))
3307                BASEP_WIDGET (panel)->autohide_inhibit = FALSE;
3308        BUTTON_WIDGET (menu->button)->in_button = FALSE;
3309        BUTTON_WIDGET (menu->button)->ignore_leave = FALSE;
3310        button_widget_up (BUTTON_WIDGET (menu->button));
3311        menu->age = 0;
3312}
3313
3314static GtkWidget *
3315create_applets_menu (GtkWidget *menu, gboolean fake_submenus, gboolean title)
3316{
3317        GtkWidget *applet_menu;
3318        char *menudir = gnome_datadir_file ("applets");
3319
3320        if (menudir == NULL ||
3321            ! g_file_test (menudir, G_FILE_TEST_ISDIR)) {
3322                g_free (menudir);
3323                return NULL;
3324        }
3325       
3326        applet_menu = create_menu_at (menu, menudir,
3327                                      TRUE /* applets */,
3328                                      FALSE /* launcher_add */,
3329                                      FALSE /* favourites_add */,
3330                                      _("Applets"),
3331                                      "gnome-applets.png",
3332                                      fake_submenus, FALSE, title);
3333        g_free (menudir);
3334        return applet_menu;
3335}
3336
3337static void
3338find_empty_pos_array (int screen, int posscore[3][3])
3339{
3340        GSList *li;
3341        int i,j;
3342        PanelData *pd;
3343        BasePWidget *basep;
3344       
3345        int tx, ty;
3346        int w, h;
3347        gfloat sw, sw2, sh, sh2;
3348
3349        sw2 = 2 * (sw = multiscreen_width (screen) / 3);
3350        sh2 = 2 * (sh = multiscreen_height (screen) / 3);
3351       
3352        for (li = panel_list; li != NULL; li = li->next) {
3353                pd = li->data;
3354
3355                if (IS_DRAWER_WIDGET(pd->panel) ||
3356                    IS_FOOBAR_WIDGET (pd->panel))
3357                        continue;
3358
3359                basep = BASEP_WIDGET (pd->panel);
3360               
3361                if (basep->screen != screen)
3362                        continue;
3363
3364                basep_widget_get_pos (basep, &tx, &ty);
3365                tx -= multiscreen_x (screen);
3366                ty -= multiscreen_y (screen);
3367                basep_widget_get_size (basep, &w, &h);
3368
3369                if (PANEL_WIDGET (basep->panel)->orient == PANEL_HORIZONTAL) {
3370                        j = MIN (ty / sh, 2);
3371                        ty = tx + w;
3372                        if (tx < sw) posscore[0][j]++;
3373                        if (tx < sw2 && ty > sw) posscore[1][j]++;
3374                        if (ty > sw2) posscore[2][j]++;
3375                } else {
3376                        i = MIN (tx / sw, 2);
3377                        tx = ty + h;
3378                        if (ty < sh) posscore[i][0]++;
3379                        if (ty < sh2 && tx > sh) posscore[i][1]++;
3380                        if (tx > sh2) posscore[i][2]++;
3381                }
3382        }
3383}
3384
3385static void
3386find_empty_pos (int screen, gint16 *x, gint16 *y)
3387{
3388        int posscore[3][3] = { {0,0,0}, {0,512,0}, {0,0,0}};
3389        int i, j, lowi= 0, lowj = 0;
3390
3391        find_empty_pos_array (screen, posscore);
3392
3393        for (j = 2; j >= 0; j--) {
3394                for (i = 0; i < 3; i++) {
3395                        if (posscore[i][j] < posscore[lowi][lowj]) {
3396                                lowi = i;
3397                                lowj = j;
3398                        }
3399                }
3400        }
3401
3402        *x = ((float)lowi * multiscreen_width (screen)) / 2.0;
3403        *y = ((float)lowj * multiscreen_height (screen)) / 2.0;
3404
3405        *x += multiscreen_x (screen);
3406        *y += multiscreen_y (screen);
3407}
3408
3409static BorderEdge
3410find_empty_edge (int screen)
3411{
3412        int posscore[3][3] = { {0,0,0}, {0,512,0}, {0,0,0}};
3413        int escore [4] = { 0, 0, 0, 0};
3414        BorderEdge edge = BORDER_BOTTOM;
3415        int low=512, i;
3416
3417        find_empty_pos_array (screen, posscore);
3418
3419        escore[BORDER_TOP] = posscore[0][0] + posscore[1][0] + posscore[2][0];
3420        escore[BORDER_RIGHT] = posscore[2][0] + posscore[2][1] + posscore[2][2];
3421        escore[BORDER_BOTTOM] = posscore[0][2] + posscore[1][2] + posscore[2][2];
3422        escore[BORDER_LEFT] = posscore[0][0] + posscore[0][1] + posscore[0][2];
3423       
3424        for (i = 0; i < 4; i++) {
3425                if (escore[i] < low) {
3426                        edge = i;
3427                        low = escore[i];
3428                }
3429        }
3430        return edge;
3431}
3432
3433static void
3434create_new_panel (GtkWidget *w, gpointer data)
3435{
3436        PanelType type = GPOINTER_TO_INT (data);
3437        GdkColor bcolor = {0, 0, 0, 1};
3438        gint16 x, y;
3439        GtkWidget *panel = NULL;
3440        PanelWidget *menu_panel;
3441        int screen;
3442
3443        g_return_if_fail (type != DRAWER_PANEL);
3444
3445        menu_panel = get_panel_from_menu_data (w, TRUE);
3446        if (menu_panel != NULL)
3447                screen = multiscreen_screen_from_panel
3448                        (menu_panel->panel_parent);
3449        else
3450                screen = 0;
3451
3452        switch (type) {
3453        case ALIGNED_PANEL:
3454                find_empty_pos (screen, &x, &y);
3455                panel = aligned_widget_new (screen,
3456                                            ALIGNED_LEFT,
3457                                            BORDER_TOP,
3458                                            BASEP_EXPLICIT_HIDE,
3459                                            BASEP_SHOWN,
3460                                            BASEP_LEVEL_DEFAULT,
3461                                            TRUE,
3462                                            SIZE_STANDARD,
3463                                            TRUE,
3464                                            TRUE,
3465                                            PANEL_BACK_NONE,
3466                                            NULL,
3467                                            TRUE, FALSE, TRUE,
3468                                            &bcolor);
3469                panel_setup (panel);
3470                gtk_widget_show (panel);
3471                basep_widget_set_pos (BASEP_WIDGET (panel), x, y);
3472                break;
3473        case EDGE_PANEL:
3474                panel = edge_widget_new (screen,
3475                                         find_empty_edge (screen),
3476                                         BASEP_EXPLICIT_HIDE,
3477                                         BASEP_SHOWN,
3478                                         BASEP_LEVEL_DEFAULT,
3479                                         TRUE,
3480                                         SIZE_STANDARD,
3481                                         TRUE,
3482                                         TRUE,
3483                                         PANEL_BACK_NONE,
3484                                         NULL,
3485                                         TRUE, FALSE, TRUE,
3486                                         &bcolor);
3487                panel_setup (panel);
3488                gtk_widget_show (panel);       
3489                break;
3490        case SLIDING_PANEL:
3491                find_empty_pos (screen, &x, &y);
3492                panel = sliding_widget_new (screen,
3493                                            SLIDING_ANCHOR_LEFT, 0,
3494                                            BORDER_TOP,
3495                                            BASEP_EXPLICIT_HIDE,
3496                                            BASEP_SHOWN,
3497                                            BASEP_LEVEL_DEFAULT,
3498                                            TRUE,
3499                                            SIZE_STANDARD,
3500                                            TRUE, TRUE,
3501                                            PANEL_BACK_NONE,
3502                                            NULL, TRUE, FALSE, TRUE,
3503                                            &bcolor);
3504                panel_setup (panel);
3505                gtk_widget_show (panel);       
3506                basep_widget_set_pos (BASEP_WIDGET (panel), x, y);
3507                break;
3508        case FLOATING_PANEL:
3509                find_empty_pos (screen, &x, &y);
3510                panel = floating_widget_new (screen,
3511                                             x, y,
3512                                             PANEL_VERTICAL,
3513                                             BASEP_EXPLICIT_HIDE,
3514                                             BASEP_SHOWN,
3515                                             BASEP_LEVEL_DEFAULT,
3516                                             FALSE,
3517                                             SIZE_STANDARD,
3518                                             TRUE, TRUE,
3519                                             PANEL_BACK_NONE,
3520                                             NULL, TRUE, FALSE, TRUE,
3521                                             &bcolor);
3522                panel_setup (panel);
3523                gtk_widget_show (panel);
3524                basep_widget_set_pos (BASEP_WIDGET (panel), x, y);
3525                break;
3526        case FOOBAR_PANEL: {
3527                GtkWidget *dialog;
3528                char *s;
3529                if (!foobar_widget_exists (screen)) {
3530                        panel = foobar_widget_new (screen);
3531
3532                        /* Don't translate the first part of this string */
3533                        s = conditional_get_string
3534                                ("/panel/Config/clock_format",
3535                                 _("%I:%M:%S %p"), NULL);
3536                        if (s != NULL)
3537                                foobar_widget_set_clock_format (FOOBAR_WIDGET (panel), s);
3538                        g_free (s);
3539
3540                        panel_setup (panel);
3541                        gtk_widget_show (panel);
3542                        break;
3543                }
3544                s = _("You can only have one menu panel at a time.");
3545               
3546                dialog = gnome_message_box_new (s,
3547                                                GNOME_MESSAGE_BOX_ERROR,
3548                                                GNOME_STOCK_BUTTON_OK,
3549                                                NULL);
3550                gtk_widget_show_all (dialog);
3551                panel_set_dialog_layer (dialog);
3552                break;
3553        }
3554        default: break;
3555        }
3556
3557        if (panel == NULL)
3558                return;
3559               
3560        panels_to_sync = TRUE;
3561}
3562
3563static GtkWidget * create_add_panel_submenu (gboolean tearoff);
3564
3565static void
3566add_panel_tearoff_new_menu(GtkWidget *w, gpointer data)
3567{
3568        TearoffMenu *tm;
3569        char *wmclass = get_unique_tearoff_wmclass ();
3570        GtkWidget *menu = create_add_panel_submenu (FALSE);
3571        PanelWidget *menu_panel;
3572
3573        menu_panel = get_panel_from_menu_data (w, TRUE);
3574
3575        /*set the panel to use as the data*/
3576        gtk_object_set_data (GTK_OBJECT (menu), "menu_panel", menu_panel);
3577        gtk_signal_connect_object_while_alive
3578                (GTK_OBJECT (menu_panel), "destroy",
3579                 GTK_SIGNAL_FUNC (gtk_widget_unref),
3580                 GTK_OBJECT(menu));
3581
3582        show_tearoff_menu (menu, _("Create panel"), TRUE, 0, 0, wmclass);
3583
3584        tm = g_new0 (TearoffMenu, 1);
3585        tm->menu = menu;
3586        tm->mfl = NULL;
3587        tm->title = g_strdup (_("Create panel"));
3588        tm->special = g_strdup ("ADD_PANEL");
3589        tm->wmclass = g_strdup (wmclass);
3590        gtk_signal_connect(GTK_OBJECT(menu), "destroy",
3591                           GTK_SIGNAL_FUNC(tearoff_destroyed), tm);
3592
3593        tearoffs = g_slist_prepend (tearoffs, tm);
3594}
3595
3596static GtkWidget *
3597create_add_panel_submenu (gboolean tearoff)
3598{
3599        GtkWidget *menu, *menuitem;
3600
3601        menu = menu_new ();
3602       
3603        if (tearoff &&
3604            gnome_preferences_get_menus_have_tearoff ()) {
3605                menuitem = tearoff_item_new ();
3606                gtk_widget_show (menuitem);
3607                gtk_menu_prepend (GTK_MENU (menu), menuitem);
3608       
3609                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
3610                                    GTK_SIGNAL_FUNC (add_panel_tearoff_new_menu),
3611                                    NULL);
3612        }
3613
3614        menuitem = gtk_menu_item_new ();
3615        setup_menuitem (menuitem, 0, _("Menu panel"));
3616        gtk_menu_append (GTK_MENU (menu), menuitem);
3617        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
3618                           GTK_SIGNAL_FUNC(create_new_panel),
3619                           GINT_TO_POINTER(FOOBAR_PANEL));
3620       
3621        menuitem = gtk_menu_item_new ();
3622        gtk_widget_lock_accelerators (menuitem);
3623        setup_menuitem (menuitem, 0, _("Edge panel"));
3624        gtk_menu_append (GTK_MENU (menu), menuitem);
3625        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
3626                           GTK_SIGNAL_FUNC(create_new_panel),
3627                           GINT_TO_POINTER(EDGE_PANEL));
3628
3629        menuitem = gtk_menu_item_new ();
3630        gtk_widget_lock_accelerators (menuitem);
3631        setup_menuitem (menuitem, 0, _("Aligned panel"));
3632        gtk_menu_append (GTK_MENU (menu), menuitem);
3633        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
3634                           GTK_SIGNAL_FUNC(create_new_panel),
3635                           GINT_TO_POINTER(ALIGNED_PANEL));
3636
3637        menuitem = gtk_menu_item_new ();
3638        gtk_widget_lock_accelerators (menuitem);
3639        setup_menuitem (menuitem, 0, _("Sliding panel"));
3640        gtk_menu_append (GTK_MENU (menu), menuitem);
3641        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
3642                           GTK_SIGNAL_FUNC(create_new_panel),
3643                           GINT_TO_POINTER(SLIDING_PANEL));
3644       
3645        menuitem = gtk_menu_item_new ();
3646        gtk_widget_lock_accelerators (menuitem);
3647        setup_menuitem (menuitem, 0, _("Floating panel"));
3648        gtk_menu_append (GTK_MENU (menu), menuitem);
3649        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
3650                           GTK_SIGNAL_FUNC(create_new_panel),
3651                           GINT_TO_POINTER(FLOATING_PANEL));
3652
3653        return menu;
3654}
3655
3656static void
3657setup_menuitem_try_pixmap (GtkWidget *menuitem, const char *try_file,
3658                           const char *title, IconSize icon_size)
3659{
3660        char *file = NULL;
3661
3662        if (!gnome_preferences_get_menus_have_icons ()) {
3663                setup_menuitem_with_size (menuitem,
3664                                          NULL /*pixmap */,
3665                                          title,
3666                                          icon_size);
3667                return;
3668        }
3669
3670        if (try_file) {
3671                file = gnome_pixmap_file (try_file);
3672                if (!file)
3673                        g_warning (_("Cannot find pixmap file %s"), try_file);
3674        }
3675       
3676        if (!file)
3677                setup_menuitem_with_size (menuitem,
3678                                          NULL /*pixmap */,
3679                                          title,
3680                                          icon_size);
3681        else
3682                setup_menuitem_with_size (menuitem,
3683                                          fake_pixmap_at_size(file, icon_size),
3684                                          title, icon_size);
3685        g_free (file);
3686}
3687         
3688
3689static GtkWidget *
3690create_system_menu (GtkWidget *menu, gboolean fake_submenus,
3691                    gboolean fake,
3692                    gboolean title,
3693                    gboolean launcher_add,
3694                    gboolean favourites_add)
3695{
3696        char *menudir = g_strdup ("/var/athena/menus");
3697
3698        if (menudir &&
3699            g_file_test (menudir, G_FILE_TEST_ISDIR)) {
3700                if(!fake || menu) {
3701                        menu = create_menu_at (menu, menudir,
3702                                               FALSE /* applets */,
3703                                               launcher_add,
3704                                               favourites_add,
3705                                               _("Programs"),
3706                                               "gnome-logo-icon-transparent.png",
3707                                               fake_submenus, FALSE, title);
3708                } else {
3709                        menu = create_fake_menu_at (menudir,
3710                                                    FALSE /* applets */,
3711                                                    launcher_add,
3712                                                    favourites_add,
3713                                                    _("Programs"),
3714                                                    "gnome-logo-icon-transparent.png",
3715                                                    title);
3716                }
3717        } else {
3718                /* show an error dialog for this only once, then just
3719                   use g_warning */
3720                static gboolean done_dialog = FALSE;
3721                if(!done_dialog) {
3722                        panel_error_dialog(_("No system menus found!"));
3723                        done_dialog = TRUE;
3724                } else
3725                        g_warning(_("No system menus found!"));
3726        }
3727        g_free (menudir);       
3728        return menu;
3729}
3730
3731static GtkWidget *
3732create_user_menu (const char *title, const char *dir, GtkWidget *menu,
3733                  const char *pixmap, gboolean fake_submenus,
3734                  gboolean force, gboolean fake, gboolean gottitle,
3735                  gboolean launcher_add,
3736                  gboolean favourites_add)
3737{
3738        char *menudir = gnome_util_home_file (dir);
3739        if (!panel_file_exists (menudir))
3740                mkdir (menudir, 0755);
3741        if (!g_file_test (menudir, G_FILE_TEST_ISDIR)) {
3742                g_warning(_("Can't create the user menu directory"));
3743                g_free (menudir);
3744                return menu;
3745        }
3746       
3747        if(!fake || menu) {
3748                menu = create_menu_at (menu, menudir,
3749                                       FALSE /* applets */,
3750                                       launcher_add,
3751                                       favourites_add,
3752                                       title, pixmap,
3753                                       fake_submenus,
3754                                       force, gottitle);
3755        } else {
3756                menu = create_fake_menu_at (menudir,
3757                                            FALSE /* applets */,
3758                                            launcher_add,
3759                                            favourites_add,
3760                                            title, pixmap, gottitle);
3761        }
3762        g_free (menudir);
3763        return menu;
3764}
3765
3766static GtkWidget *
3767create_distribution_menu (GtkWidget *menu,
3768                          gboolean fake_submenus,
3769                          gboolean fake,
3770                          gboolean title,
3771                          gboolean launcher_add,
3772                          gboolean favourites_add)
3773{
3774        const DistributionInfo *info = get_distribution_info ();
3775        gchar *pixmap_file, *menu_path;
3776
3777        if (!info)
3778                return NULL;
3779
3780        if (info->menu_icon != NULL)
3781                pixmap_file = gnome_pixmap_file (info->menu_icon);
3782        else
3783                pixmap_file = NULL;
3784
3785        if (info->menu_path [0] != '/')
3786                menu_path = gnome_util_home_file (info->menu_path);
3787        else
3788                menu_path = g_strdup (info->menu_path);
3789
3790        if (!fake || menu) {
3791                menu = create_menu_at (menu, menu_path,
3792                                       FALSE /* applets */,
3793                                       launcher_add,
3794                                       favourites_add,
3795                                       info->menu_name, pixmap_file,
3796                                       fake_submenus, FALSE, title);
3797        } else {
3798                menu = create_fake_menu_at (menu_path,
3799                                            FALSE /* applets */,
3800                                            launcher_add,
3801                                            favourites_add,
3802                                            info->menu_name, pixmap_file,
3803                                            title);
3804        }
3805
3806        g_free (pixmap_file);
3807        g_free (menu_path);
3808
3809        return menu;
3810}
3811
3812static GtkWidget *
3813create_kde_menu (GtkWidget *menu, gboolean fake_submenus,
3814                 gboolean force, gboolean fake, gboolean title,
3815                 gboolean launcher_add,
3816                 gboolean favourites_add)
3817{
3818        char *pixmap_name;
3819
3820        pixmap_name = g_concat_dir_and_file (kde_icondir, "exec.xpm");
3821
3822        if(!fake || menu) {
3823                menu = create_menu_at (menu,
3824                                       kde_menudir,
3825                                       FALSE /* applets */,
3826                                       launcher_add,
3827                                       favourites_add,
3828                                       _("KDE menus"),
3829                                       pixmap_name,
3830                                       fake_submenus,
3831                                       force, title);
3832        } else {
3833                menu = create_fake_menu_at (kde_menudir,
3834                                            FALSE /* applets */,
3835                                            launcher_add,
3836                                            favourites_add,
3837                                            _("KDE menus"),
3838                                            pixmap_name, title);
3839        }
3840        g_free (pixmap_name);
3841        return menu;
3842}
3843
3844static GtkWidget *
3845create_add_launcher_menu (GtkWidget *menu, gboolean fake_submenus)
3846{
3847        if (menu == NULL)
3848                menu = menu_new ();
3849
3850        /* Eeeek, a hack, if this is set then the reloading
3851         * function will use create_add_launcher_menu, rather then
3852         * the nomral way of reloading, as that would dump the
3853         * submenus */
3854        gtk_object_set_data (GTK_OBJECT (menu),
3855                             "_add_launcher_menu_hack_",
3856                             GINT_TO_POINTER (1));
3857
3858        create_system_menu (menu, fake_submenus, FALSE, TRUE, TRUE, FALSE);
3859        create_user_menu (_("Favorites"), "apps",
3860                          menu, "gnome-favorites.png",
3861                          fake_submenus, FALSE, FALSE, TRUE, TRUE, FALSE);
3862
3863        add_menu_separator (menu);
3864
3865        add_distribution_submenu (menu, fake_submenus,
3866                                  TRUE /*launcher_add */,
3867                                  FALSE /*favourites_add */);
3868        if (g_file_test (kde_menudir, G_FILE_TEST_ISDIR)) {
3869                add_kde_submenu (menu, fake_submenus,
3870                                 TRUE /*launcher_add */,
3871                                 FALSE /*favourites_add */);
3872        }
3873
3874        return menu;
3875}
3876
3877static GtkWidget *
3878create_add_favourites_menu (GtkWidget *menu, gboolean fake_submenus)
3879{
3880        if (menu == NULL)
3881                menu = menu_new ();
3882
3883        /* Eeeek, a hack, if this is set then the reloading
3884         * function will use create_add_favourites_menu, rather then
3885         * the nomral way of reloading, as that would dump the
3886         * submenus */
3887        gtk_object_set_data (GTK_OBJECT (menu),
3888                             "_add_favourites_menu_hack_",
3889                             GINT_TO_POINTER (1));
3890
3891        create_system_menu (menu, fake_submenus, FALSE, TRUE,
3892                            FALSE /*launcher_add */,
3893                            TRUE /*favourites_add */);
3894
3895        add_menu_separator (menu);
3896
3897        add_distribution_submenu (menu, fake_submenus,
3898                                  FALSE /*launcher_add */,
3899                                  TRUE /*favourites_add */);
3900        if (g_file_test (kde_menudir, G_FILE_TEST_ISDIR)) {
3901                add_kde_submenu (menu, fake_submenus,
3902                                 FALSE /*launcher_add */,
3903                                 TRUE /*favourites_add */);
3904        }
3905
3906        return menu;
3907}
3908
3909static void
3910remove_panel (GtkWidget *widget)
3911{
3912        status_unparent (widget);
3913        gtk_widget_destroy (widget);
3914}
3915
3916static void
3917remove_panel_accept (GtkWidget *w, GtkWidget *panelw)
3918{
3919        remove_panel (panelw);
3920}
3921
3922static void
3923remove_panel_query (GtkWidget *w, gpointer data)
3924{
3925        GtkWidget *dialog;
3926        GtkWidget *panelw;
3927        PanelWidget *panel;
3928
3929        panel = get_panel_from_menu_data(w, TRUE);
3930        panelw = panel->panel_parent;
3931
3932        if (!IS_DRAWER_WIDGET (panelw) && base_panels == 1) {
3933                panel_error_dialog (_("You cannot remove your last panel."));
3934                return;
3935        }
3936
3937        /* if there are no applets just remove the panel */
3938        if(!global_config.confirm_panel_remove || !panel->applet_list) {
3939                remove_panel (panelw);
3940                return;
3941        }
3942
3943        dialog = gnome_message_box_new (_("When a panel is removed, the panel "
3944                                          "and its\napplet settings are lost. "
3945                                          "Remove this panel?"),
3946                                        GNOME_MESSAGE_BOX_QUESTION,
3947                                        GNOME_STOCK_BUTTON_YES,
3948                                        GNOME_STOCK_BUTTON_NO,
3949                                        NULL);
3950       
3951        gnome_dialog_button_connect (GNOME_DIALOG(dialog), 0,
3952                                     GTK_SIGNAL_FUNC (remove_panel_accept),
3953                                     panelw);
3954        gtk_signal_connect_object_while_alive (GTK_OBJECT(panelw), "destroy",
3955                                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
3956                                               GTK_OBJECT(dialog));
3957        gtk_widget_show_all (dialog);
3958        panel_set_dialog_layer (dialog);
3959}
3960
3961static void
3962panel_tearoff_new_menu(GtkWidget *w, gpointer data)
3963{
3964        TearoffMenu *tm;
3965        char *wmclass = get_unique_tearoff_wmclass();
3966        GtkWidget *menu = NULL;
3967        PanelWidget *menu_panel;
3968
3969        int flags = GPOINTER_TO_INT (data);
3970
3971        menu_panel = get_panel_from_menu_data (w, TRUE);
3972
3973        menu = create_root_menu (NULL, TRUE, flags, FALSE,
3974                                 IS_BASEP_WIDGET (menu_panel->panel_parent),
3975                                 TRUE);
3976
3977        gtk_object_set_data (GTK_OBJECT(menu), "menu_panel", menu_panel);
3978        gtk_signal_connect_object_while_alive(GTK_OBJECT(menu_panel),
3979                      "destroy", GTK_SIGNAL_FUNC(gtk_widget_unref),
3980                      GTK_OBJECT(menu));
3981
3982        show_tearoff_menu(menu, _("Main Menu"),TRUE,0,0,wmclass);
3983
3984        tm = g_new0(TearoffMenu,1);
3985        tm->menu = menu;
3986        tm->mfl = NULL;
3987        tm->title = g_strdup(_("Main Menu"));
3988        tm->special = g_strdup_printf("PANEL:%d", flags);
3989        tm->wmclass = g_strdup(wmclass);
3990        gtk_signal_connect(GTK_OBJECT(menu), "destroy",
3991                           GTK_SIGNAL_FUNC(tearoff_destroyed), tm);
3992
3993        tearoffs = g_slist_prepend(tearoffs,tm);
3994}
3995
3996GtkWidget *
3997create_panel_root_menu(PanelWidget *panel, gboolean tearoff)
3998{
3999        GtkWidget *menu;
4000
4001        menu = create_root_menu (NULL, TRUE, global_config.menu_flags, tearoff,
4002                                 IS_BASEP_WIDGET (panel->panel_parent),
4003                                 TRUE);
4004
4005        gtk_object_set_data (GTK_OBJECT(menu), "menu_panel", panel);
4006
4007        return menu;
4008}
4009
4010static void
4011current_panel_config(GtkWidget *w, gpointer data)
4012{
4013        PanelWidget *panel = get_panel_from_menu_data(w, TRUE);
4014        GtkWidget *parent = panel->panel_parent;
4015        panel_config(parent);
4016}
4017
4018static void
4019ask_about_launcher_cb(GtkWidget *w, gpointer data)
4020{
4021        ask_about_launcher(NULL, get_panel_from_menu_data(w, TRUE), 0, FALSE);
4022}
4023
4024static void
4025ask_about_swallowing_cb(GtkWidget *w, gpointer data)
4026{
4027        ask_about_swallowing(get_panel_from_menu_data(w, TRUE), 0, FALSE);
4028}
4029
4030static void
4031convert_setup (BasePWidget *basep, GtkType type)
4032{
4033        basep->pos = gtk_type_new (type);
4034        basep->pos->basep = basep;
4035        basep_widget_pre_convert_hook (basep);
4036        basep_pos_connect_signals (basep);
4037        update_config_type (basep);
4038}
4039
4040static void
4041convert_to_panel(GtkWidget *widget, gpointer data)
4042{
4043        PanelType type = GPOINTER_TO_INT(data);
4044        PanelData *pd;
4045        int x, y;
4046        int w, h;
4047        BasePWidget *basep;
4048        BasePPos *old_pos;
4049        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4050
4051        g_return_if_fail(cur_panel != NULL);
4052        g_return_if_fail(IS_PANEL_WIDGET(cur_panel));
4053
4054        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4055                return;
4056
4057        g_assert (cur_panel->panel_parent);
4058        g_return_if_fail (IS_BASEP_WIDGET (cur_panel->panel_parent));
4059
4060        basep = BASEP_WIDGET(cur_panel->panel_parent);
4061
4062        pd = gtk_object_get_user_data (GTK_OBJECT (basep));
4063        if (pd->type == type)
4064                return;
4065
4066        basep_widget_get_pos (basep, &x, &y);
4067        basep_widget_get_size (basep, &w, &h);
4068
4069        old_pos = basep->pos;
4070        old_pos->basep = NULL;
4071        pd->type = type;
4072
4073        /* for now, just ignore non-border types */
4074        switch (type) {
4075        case EDGE_PANEL:
4076        {
4077                BorderEdge edge = BORDER_BOTTOM;
4078                convert_setup (basep, TYPE_EDGE_POS);
4079
4080                if (IS_BORDER_POS (old_pos))
4081                        edge = BORDER_POS (old_pos)->edge;
4082                else if (PANEL_WIDGET (cur_panel)->orient == PANEL_HORIZONTAL)
4083                        edge = (y - multiscreen_y (basep->screen) >
4084                                (multiscreen_height (basep->screen) / 2))
4085                                ? BORDER_BOTTOM : BORDER_TOP;
4086                else
4087                        edge = (x - multiscreen_x (basep->screen) >
4088                                (multiscreen_width (basep->screen) / 2))
4089                                ? BORDER_RIGHT : BORDER_LEFT;
4090
4091                border_widget_change_edge (BORDER_WIDGET (basep), edge);
4092                break;
4093        }
4094        case ALIGNED_PANEL:
4095        {
4096                gint mid, max;
4097                BorderEdge edge = BORDER_BOTTOM;
4098                AlignedAlignment align;
4099
4100                convert_setup (basep, TYPE_ALIGNED_POS);
4101
4102                if (IS_BORDER_POS (old_pos))
4103                        edge = BORDER_POS (old_pos)->edge;
4104                else if (PANEL_WIDGET (cur_panel)->orient == PANEL_HORIZONTAL)
4105                        edge = (y - multiscreen_y (basep->screen) >
4106                                (multiscreen_height (basep->screen) / 2))
4107                                ? BORDER_BOTTOM : BORDER_TOP;
4108                else
4109                        edge = (x - multiscreen_x (basep->screen) >
4110                                (multiscreen_width (basep->screen) / 2))
4111                                ? BORDER_RIGHT : BORDER_LEFT;
4112
4113                if (PANEL_WIDGET (cur_panel)->orient == PANEL_HORIZONTAL) {
4114                        mid = x + w / 2 - multiscreen_x (basep->screen);
4115                        max = multiscreen_width (basep->screen);
4116                } else {
4117                        mid = y + h / 2 - multiscreen_y (basep->screen);
4118                        max = multiscreen_height (basep->screen);
4119                }
4120       
4121                if (mid < max / 3)
4122                        align = ALIGNED_LEFT;
4123                else if (mid < 2 * (max / 3))
4124                        align = ALIGNED_CENTER;
4125                else
4126                        align = ALIGNED_RIGHT;
4127                aligned_widget_change_align_edge (
4128                        ALIGNED_WIDGET (basep), align, edge);
4129                break;
4130        }
4131        case SLIDING_PANEL:
4132        {
4133                gint val, max;
4134                BorderEdge edge = BORDER_BOTTOM;
4135                SlidingAnchor anchor;
4136                gint16 offset;
4137               
4138                convert_setup (basep, TYPE_SLIDING_POS);
4139               
4140                if (IS_BORDER_POS (old_pos))
4141                        edge = BORDER_POS (old_pos)->edge;
4142                else if (PANEL_WIDGET (cur_panel)->orient == PANEL_HORIZONTAL)
4143                        edge = (y - multiscreen_y (basep->screen) >
4144                                (multiscreen_height (basep->screen) / 2))
4145                                ? BORDER_BOTTOM : BORDER_TOP;
4146                else
4147                        edge = (x - multiscreen_x (basep->screen) >
4148                                (multiscreen_width (basep->screen) / 2))
4149                                ? BORDER_RIGHT : BORDER_LEFT;
4150               
4151                if (PANEL_WIDGET (cur_panel)->orient == PANEL_HORIZONTAL) {
4152                        val = x - multiscreen_x (basep->screen);
4153                        max = multiscreen_width (basep->screen);
4154                } else {
4155                        val = y - multiscreen_y (basep->screen);
4156                        max = multiscreen_height (basep->screen);
4157                }
4158               
4159                if (val > 0.9 * max) {
4160                        offset = max - val;
4161                        anchor = SLIDING_ANCHOR_RIGHT;
4162                } else {
4163                        offset = val;
4164                        anchor = SLIDING_ANCHOR_LEFT;
4165                }
4166
4167                sliding_widget_change_anchor_offset_edge (
4168                        SLIDING_WIDGET (basep), anchor, offset, edge);
4169               
4170                break;
4171        }
4172        case FLOATING_PANEL:
4173        {
4174                convert_setup (basep, TYPE_FLOATING_POS);
4175                floating_widget_change_coords (FLOATING_WIDGET (basep),
4176                                               x, y);
4177                break;
4178        }
4179        default:
4180                g_assert_not_reached ();
4181                break;
4182        }
4183
4184        gtk_object_unref (GTK_OBJECT (old_pos));
4185        gtk_widget_queue_resize (GTK_WIDGET (basep));
4186}
4187
4188static void
4189change_hiding_mode (GtkWidget *widget, gpointer data)
4190{
4191        BasePWidget *basep;
4192        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4193
4194        g_return_if_fail(cur_panel != NULL);
4195        g_return_if_fail(IS_PANEL_WIDGET(cur_panel));
4196
4197        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4198                return;
4199
4200        g_assert (cur_panel->panel_parent);
4201        g_return_if_fail (IS_BASEP_WIDGET (cur_panel->panel_parent));
4202
4203        basep = BASEP_WIDGET(cur_panel->panel_parent);
4204       
4205        basep_widget_change_params (basep,
4206                                    basep->screen,
4207                                    cur_panel->orient,
4208                                    cur_panel->sz,
4209                                    GPOINTER_TO_INT (data),
4210                                    basep->state,
4211                                    basep->level,
4212                                    basep->avoid_on_maximize,
4213                                    basep->hidebuttons_enabled,
4214                                    basep->hidebutton_pixmaps_enabled,
4215                                    cur_panel->back_type,
4216                                    cur_panel->back_pixmap,
4217                                    cur_panel->fit_pixmap_bg,
4218                                    cur_panel->strech_pixmap_bg,
4219                                    cur_panel->rotate_pixmap_bg,
4220                                    &cur_panel->back_color);
4221
4222        update_config_mode (basep);
4223}
4224
4225static void
4226change_level (GtkWidget *widget, gpointer data)
4227{
4228        BasePWidget *basep;
4229        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4230
4231        g_return_if_fail(cur_panel != NULL);
4232        g_return_if_fail(IS_PANEL_WIDGET(cur_panel));
4233
4234        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4235                return;
4236
4237        g_assert (cur_panel->panel_parent);
4238        g_return_if_fail (IS_BASEP_WIDGET (cur_panel->panel_parent));
4239
4240        basep = BASEP_WIDGET(cur_panel->panel_parent);
4241       
4242        basep_widget_change_params (basep,
4243                                    basep->screen,
4244                                    cur_panel->orient,
4245                                    cur_panel->sz,
4246                                    basep->mode,
4247                                    basep->state,
4248                                    GPOINTER_TO_INT (data),
4249                                    basep->avoid_on_maximize,
4250                                    basep->hidebuttons_enabled,
4251                                    basep->hidebutton_pixmaps_enabled,
4252                                    cur_panel->back_type,
4253                                    cur_panel->back_pixmap,
4254                                    cur_panel->fit_pixmap_bg,
4255                                    cur_panel->strech_pixmap_bg,
4256                                    cur_panel->rotate_pixmap_bg,
4257                                    &cur_panel->back_color);
4258       
4259        update_config_level (basep);
4260}
4261
4262static void
4263change_avoid_on_maximize (GtkWidget *widget, gpointer data)
4264{
4265        BasePWidget *basep;
4266        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4267
4268        g_return_if_fail(cur_panel != NULL);
4269        g_return_if_fail(IS_PANEL_WIDGET(cur_panel));
4270
4271        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4272                return;
4273
4274        g_assert (cur_panel->panel_parent);
4275        g_return_if_fail (IS_BASEP_WIDGET (cur_panel->panel_parent));
4276
4277        basep = BASEP_WIDGET(cur_panel->panel_parent);
4278       
4279        basep_widget_change_params (basep,
4280                                    basep->screen,
4281                                    cur_panel->orient,
4282                                    cur_panel->sz,
4283                                    basep->mode,
4284                                    basep->state,
4285                                    basep->level,
4286                                    GPOINTER_TO_INT (data),
4287                                    basep->hidebuttons_enabled,
4288                                    basep->hidebutton_pixmaps_enabled,
4289                                    cur_panel->back_type,
4290                                    cur_panel->back_pixmap,
4291                                    cur_panel->fit_pixmap_bg,
4292                                    cur_panel->strech_pixmap_bg,
4293                                    cur_panel->rotate_pixmap_bg,
4294                                    &cur_panel->back_color);
4295
4296        update_config_avoid_on_maximize (basep);
4297}
4298
4299static void
4300change_size (GtkWidget *widget, gpointer data)
4301{
4302        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4303        g_return_if_fail(cur_panel != NULL);
4304        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4305                return;
4306
4307        panel_widget_change_params (cur_panel,
4308                                    cur_panel->orient,
4309                                    GPOINTER_TO_INT (data),
4310                                    cur_panel->back_type,
4311                                    cur_panel->back_pixmap,
4312                                    cur_panel->fit_pixmap_bg,
4313                                    cur_panel->strech_pixmap_bg,
4314                                    cur_panel->rotate_pixmap_bg,
4315                                    cur_panel->no_padding_on_ends,
4316                                    &cur_panel->back_color);
4317}
4318
4319static void
4320change_orient (GtkWidget *widget, gpointer data)
4321{
4322
4323        BasePWidget *basep;
4324        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4325       
4326        g_return_if_fail(cur_panel != NULL);
4327        g_return_if_fail(IS_PANEL_WIDGET(cur_panel));
4328
4329        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4330                return;
4331
4332        g_assert (cur_panel->panel_parent);
4333        g_return_if_fail (IS_BASEP_WIDGET (cur_panel->panel_parent));
4334
4335        basep = BASEP_WIDGET(cur_panel->panel_parent);
4336       
4337        basep_widget_change_params (basep,
4338                                    basep->screen,
4339                                    GPOINTER_TO_INT (data),
4340                                    cur_panel->sz,
4341                                    basep->mode,
4342                                    basep->state,
4343                                    basep->level,
4344                                    basep->avoid_on_maximize,
4345                                    basep->hidebuttons_enabled,
4346                                    basep->hidebutton_pixmaps_enabled,
4347                                    cur_panel->back_type,
4348                                    cur_panel->back_pixmap,
4349                                    cur_panel->fit_pixmap_bg,
4350                                    cur_panel->strech_pixmap_bg,
4351                                    cur_panel->rotate_pixmap_bg,
4352                                    &cur_panel->back_color);
4353}
4354
4355static void
4356change_background (GtkWidget *widget, gpointer data)
4357{
4358        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4359        g_return_if_fail(cur_panel != NULL);
4360
4361        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4362                return;
4363
4364        panel_widget_change_params (cur_panel,
4365                                    cur_panel->orient,
4366                                    cur_panel->sz,
4367                                    GPOINTER_TO_INT (data),
4368                                    cur_panel->back_pixmap,
4369                                    cur_panel->fit_pixmap_bg,
4370                                    cur_panel->strech_pixmap_bg,
4371                                    cur_panel->rotate_pixmap_bg,
4372                                    cur_panel->no_padding_on_ends,
4373                                    &cur_panel->back_color);
4374}
4375
4376static void
4377change_hidebuttons (GtkWidget *widget, gpointer data)
4378{
4379        BasePWidget *basep;
4380        gboolean hidebutton_pixmaps_enabled, hidebuttons_enabled;
4381        PanelWidget *cur_panel = get_panel_from_menu_data(widget, TRUE);
4382
4383        g_return_if_fail(cur_panel != NULL);
4384        g_return_if_fail(IS_PANEL_WIDGET(cur_panel));
4385
4386        if (!GTK_CHECK_MENU_ITEM (widget)->active)
4387                return;
4388
4389        g_assert (cur_panel->panel_parent);
4390        g_return_if_fail (IS_BASEP_WIDGET (cur_panel->panel_parent));
4391
4392        basep = BASEP_WIDGET(cur_panel->panel_parent);
4393
4394        hidebuttons_enabled = basep->hidebuttons_enabled;
4395        hidebutton_pixmaps_enabled = basep->hidebutton_pixmaps_enabled;
4396
4397        switch (GPOINTER_TO_INT (data)) {
4398        case HIDEBUTTONS_NONE:
4399                hidebuttons_enabled = FALSE;
4400                break;
4401        case HIDEBUTTONS_PLAIN:
4402                hidebutton_pixmaps_enabled = FALSE;
4403                hidebuttons_enabled = TRUE;
4404                break;
4405        case HIDEBUTTONS_PIXMAP:
4406                hidebutton_pixmaps_enabled = TRUE;
4407                hidebuttons_enabled = TRUE;
4408                break;
4409        }
4410
4411        basep_widget_change_params (basep,
4412                                    basep->screen,
4413                                    cur_panel->orient,
4414                                    cur_panel->sz,
4415                                    basep->mode,
4416                                    basep->state,
4417                                    basep->level,
4418                                    basep->avoid_on_maximize,
4419                                    hidebuttons_enabled,
4420                                    hidebutton_pixmaps_enabled,
4421                                    cur_panel->back_type,
4422                                    cur_panel->back_pixmap,
4423                                    cur_panel->fit_pixmap_bg,
4424                                    cur_panel->strech_pixmap_bg,
4425                                    cur_panel->rotate_pixmap_bg,
4426                                    &cur_panel->back_color);
4427
4428        update_config_hidebuttons (basep);
4429}
4430
4431static void
4432show_x_on_panels(GtkWidget *menu, gpointer data)
4433{
4434        GtkWidget *pw;
4435        GtkWidget *types = gtk_object_get_data(GTK_OBJECT(menu), MENU_TYPES);
4436        GtkWidget *modes = gtk_object_get_data(GTK_OBJECT(menu), MENU_MODES);
4437        GtkWidget *orient = gtk_object_get_data (GTK_OBJECT (menu), MENU_ORIENTS);
4438        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4439        g_return_if_fail(cur_panel != NULL);
4440        g_return_if_fail(IS_PANEL_WIDGET(cur_panel));
4441        g_return_if_fail(types != NULL);
4442        g_return_if_fail(modes != NULL);
4443       
4444        pw = cur_panel->panel_parent;
4445        g_return_if_fail(pw != NULL);
4446       
4447        if(IS_DRAWER_WIDGET(pw)) {
4448                gtk_widget_hide(modes);
4449                gtk_widget_hide(types);
4450        } else {
4451                gtk_widget_show(modes);
4452                gtk_widget_show(types);
4453        }
4454
4455        if (IS_FLOATING_WIDGET (pw))
4456                gtk_widget_show (orient);
4457        else
4458                gtk_widget_hide (orient);
4459}
4460
4461static void
4462update_type_menu (GtkWidget *menu, gpointer data)
4463{
4464        char *s = NULL;
4465        GtkWidget *menuitem = NULL;
4466        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4467        GtkWidget *basep = cur_panel->panel_parent;
4468        if (IS_EDGE_WIDGET (basep))
4469                s = MENU_TYPE_EDGE;
4470        else if (IS_ALIGNED_WIDGET (basep))
4471                s = MENU_TYPE_ALIGNED;
4472        else if (IS_SLIDING_WIDGET (basep))
4473                s = MENU_TYPE_SLIDING;
4474        else if (IS_FLOATING_WIDGET (basep))
4475                s = MENU_TYPE_FLOATING;
4476        else
4477                return;
4478       
4479        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);                           
4480       
4481        if (menuitem)
4482                gtk_check_menu_item_set_active (
4483                        GTK_CHECK_MENU_ITEM (menuitem), TRUE);
4484}
4485
4486static void
4487update_level_menu (GtkWidget *menu, gpointer data)
4488{
4489        char *s = NULL;
4490        GtkWidget *menuitem = NULL;
4491        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4492        GtkWidget *basep = cur_panel->panel_parent;
4493
4494        /* sanity */
4495        if ( ! BASEP_WIDGET (basep))
4496                return;
4497
4498        switch (BASEP_WIDGET (basep)->level) {
4499        case BASEP_LEVEL_DEFAULT:
4500                s = MENU_LEVEL_DEFAULT;
4501                break;
4502        case BASEP_LEVEL_ABOVE:
4503                s = MENU_LEVEL_ABOVE;
4504                break;
4505        case BASEP_LEVEL_NORMAL:
4506                s = MENU_LEVEL_NORMAL;
4507                break;
4508        case BASEP_LEVEL_BELOW:
4509                s = MENU_LEVEL_BELOW;
4510                break;
4511        default:
4512                return;
4513        }
4514       
4515        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);                           
4516       
4517        if (menuitem != NULL)
4518                gtk_check_menu_item_set_active (
4519                        GTK_CHECK_MENU_ITEM (menuitem), TRUE);
4520}
4521
4522static void
4523update_avoid_on_maximize_menu (GtkWidget *menu, gpointer data)
4524{
4525        char *s = NULL;
4526        GtkWidget *menuitem = NULL;
4527        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4528        GtkWidget *basep = cur_panel->panel_parent;
4529
4530        /* sanity */
4531        if ( ! BASEP_WIDGET (basep))
4532                return;
4533
4534        if (BASEP_WIDGET (basep)->avoid_on_maximize) {
4535                s = MENU_AVOID_ON_MAX;
4536        } else {
4537                s = MENU_NO_AVOID_ON_MAX;
4538        }
4539       
4540        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);                           
4541       
4542        if (menuitem != NULL)
4543                gtk_check_menu_item_set_active (
4544                        GTK_CHECK_MENU_ITEM (menuitem), TRUE);
4545}
4546
4547static void
4548update_size_menu (GtkWidget *menu, gpointer data)
4549{
4550        GtkWidget *menuitem = NULL;
4551        char *s = NULL;
4552        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4553        switch (cur_panel->sz) {
4554        case SIZE_ULTRA_TINY:
4555                s = MENU_SIZE_ULTRA_TINY;
4556                break;
4557        case SIZE_TINY:
4558                s = MENU_SIZE_TINY;
4559                break;
4560        case SIZE_SMALL:
4561                s = MENU_SIZE_SMALL;
4562                break;
4563        case SIZE_STANDARD:
4564                s = MENU_SIZE_STANDARD;
4565                break;
4566        case SIZE_LARGE:
4567                s = MENU_SIZE_LARGE;
4568                break;
4569        case SIZE_HUGE:
4570                s = MENU_SIZE_HUGE;
4571                break;
4572        case SIZE_RIDICULOUS:
4573                s = MENU_SIZE_RIDICULOUS;
4574                break;
4575        default:
4576                return;
4577        }
4578
4579        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);
4580        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
4581                                        TRUE);
4582}
4583
4584
4585static void
4586update_back_menu (GtkWidget *menu, gpointer data)
4587{
4588        GtkWidget *menuitem = NULL;
4589        char *s = NULL;
4590        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4591        switch (cur_panel->back_type) {
4592        case PANEL_BACK_NONE:
4593                s = MENU_BACK_NONE;
4594                break;
4595        case PANEL_BACK_COLOR:
4596                s = MENU_BACK_COLOR;
4597                break;
4598        case PANEL_BACK_PIXMAP:
4599                s = MENU_BACK_PIXMAP;
4600                break;
4601        case PANEL_BACK_TRANSLUCENT:
4602                s = MENU_BACK_TRANSLUCENT;
4603                break;
4604        default:
4605                return;
4606        }
4607
4608        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);
4609        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
4610                                        TRUE);
4611        menuitem = gtk_object_get_data (GTK_OBJECT (menu), MENU_BACK_PIXMAP);
4612        gtk_widget_set_sensitive (menuitem, cur_panel->back_pixmap != NULL);
4613}
4614
4615static void
4616update_hidebutton_menu (GtkWidget *menu, gpointer data)
4617{
4618        char *s = NULL;
4619        GtkWidget *menuitem = NULL;
4620        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4621        BasePWidget *basep = BASEP_WIDGET(cur_panel->panel_parent);
4622
4623        if (!basep->hidebuttons_enabled)
4624                s = MENU_HIDEBUTTONS_NONE;
4625        else if (basep->hidebutton_pixmaps_enabled)
4626                s = MENU_HIDEBUTTONS_PIXMAP;
4627        else
4628                s = MENU_HIDEBUTTONS_PLAIN;
4629       
4630        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);
4631        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
4632                                        TRUE);
4633}
4634
4635static void
4636update_hiding_menu (GtkWidget *menu, gpointer data)
4637{
4638        char *s = NULL;
4639        GtkWidget *menuitem = NULL;
4640        PanelWidget *cur_panel = get_panel_from_menu_data(menu, TRUE);
4641        BasePWidget *basep = BASEP_WIDGET(cur_panel->panel_parent);
4642        s =  (basep->mode == BASEP_EXPLICIT_HIDE)
4643                ? MENU_MODE_EXPLICIT_HIDE
4644                : MENU_MODE_AUTO_HIDE;
4645
4646        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);
4647        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
4648                                        TRUE);
4649}
4650
4651static void
4652update_orient_menu (GtkWidget *menu, gpointer data)
4653{
4654        char *s = NULL;
4655        GtkWidget *menuitem = NULL;
4656        PanelWidget *cur_panel = get_panel_from_menu_data (menu, TRUE);
4657        BasePWidget *basep = BASEP_WIDGET (cur_panel->panel_parent);
4658        s = (PANEL_WIDGET (basep->panel)->orient == PANEL_HORIZONTAL)
4659                ? MENU_ORIENT_HORIZONTAL
4660                : MENU_ORIENT_VERTICAL;
4661
4662        menuitem = gtk_object_get_data (GTK_OBJECT (menu), s);
4663        gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
4664                                        TRUE);
4665}
4666
4667typedef struct {
4668        char *name;
4669        char *id;
4670        int i;
4671} NameIdEnum;
4672
4673static void
4674add_radios_to_menu (GtkWidget *menu, NameIdEnum *items,
4675                    GtkSignalFunc func)
4676{
4677        int i;
4678        GSList *radio_group = NULL;
4679        GtkWidget *menuitem;
4680
4681        for (i=0; items[i].name; i++) {
4682                menuitem = gtk_radio_menu_item_new (radio_group);
4683                gtk_widget_lock_accelerators (menuitem);
4684                radio_group = gtk_radio_menu_item_group (
4685                        GTK_RADIO_MENU_ITEM (menuitem));
4686                setup_menuitem (menuitem, NULL, _(items[i].name));
4687                gtk_menu_append (GTK_MENU (menu),
4688                                 menuitem);
4689                gtk_object_set_data (GTK_OBJECT (menu),
4690                                     items[i].id, menuitem);
4691                gtk_check_menu_item_set_show_toggle (
4692                        GTK_CHECK_MENU_ITEM (menuitem), TRUE);
4693                gtk_check_menu_item_set_active (
4694                        GTK_CHECK_MENU_ITEM (menuitem), FALSE);
4695                gtk_signal_connect (GTK_OBJECT (menuitem), "toggled",
4696                                    GTK_SIGNAL_FUNC (func),
4697                                    GINT_TO_POINTER (items[i].i));
4698        }
4699}
4700
4701static void
4702add_radio_menu (GtkWidget *menu, const char *menutext,
4703                NameIdEnum *items, const char *menu_key,
4704                GtkSignalFunc change_func,
4705                GtkSignalFunc update_func)
4706{
4707        GtkWidget *menuitem;
4708        GtkWidget *submenu;
4709
4710        menuitem = gtk_menu_item_new ();
4711        gtk_widget_lock_accelerators (menuitem);
4712        setup_menuitem (menuitem, NULL, menutext);
4713        gtk_menu_append (GTK_MENU (menu), menuitem);
4714        gtk_object_set_data (GTK_OBJECT (menu), menu_key, menuitem);
4715
4716        submenu = menu_new ();
4717        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4718        add_radios_to_menu (submenu, items, change_func);
4719        gtk_signal_connect (GTK_OBJECT (submenu), "show",
4720                            GTK_SIGNAL_FUNC (update_func),
4721                            NULL);
4722       
4723}
4724
4725static void
4726make_properties_submenu (GtkWidget *menu)
4727{
4728        NameIdEnum types[] = {
4729                { N_("Edge panel"), MENU_TYPE_EDGE, EDGE_PANEL },
4730                { N_("Aligned panel"), MENU_TYPE_ALIGNED, ALIGNED_PANEL },
4731                { N_("Sliding panel"), MENU_TYPE_SLIDING, SLIDING_PANEL },
4732                { N_("Floating panel"), MENU_TYPE_FLOATING, FLOATING_PANEL },
4733                { NULL, NULL, -1 }
4734        };
4735       
4736        NameIdEnum modes[] = {
4737                { N_("Explicit hide"), MENU_MODE_EXPLICIT_HIDE, BASEP_EXPLICIT_HIDE },
4738                { N_("Auto hide"), MENU_MODE_AUTO_HIDE, BASEP_AUTO_HIDE },
4739                { NULL, NULL, -1 }
4740        };
4741
4742        NameIdEnum hidebuttons[] = {
4743                { N_("With pixmap arrow"), MENU_HIDEBUTTONS_PIXMAP, HIDEBUTTONS_PIXMAP },
4744                { N_("Without pixmap"), MENU_HIDEBUTTONS_PLAIN, HIDEBUTTONS_PLAIN },
4745                { N_("None"), MENU_HIDEBUTTONS_NONE, HIDEBUTTONS_NONE },
4746                { NULL, NULL, -1 }
4747        };
4748
4749        NameIdEnum orients[] = {
4750                { N_("Horizontal"), MENU_ORIENT_HORIZONTAL, PANEL_HORIZONTAL },
4751                { N_("Vertical"), MENU_ORIENT_VERTICAL, PANEL_VERTICAL },
4752                { NULL, NULL, -1 }
4753        };
4754
4755        NameIdEnum sizes[] = {
4756                { N_("Ultra Tiny (12 pixels)"), MENU_SIZE_ULTRA_TINY, SIZE_ULTRA_TINY },
4757                { N_("Tiny (24 pixels)"), MENU_SIZE_TINY, SIZE_TINY },
4758                { N_("Small (36 pixels)"), MENU_SIZE_SMALL, SIZE_SMALL },
4759                { N_("Standard (48 pixels)"), MENU_SIZE_STANDARD, SIZE_STANDARD },
4760                { N_("Large (64 pixels)"), MENU_SIZE_LARGE, SIZE_LARGE },
4761                { N_("Huge (80 pixels)"), MENU_SIZE_HUGE, SIZE_HUGE },
4762                { N_("Ridiculous (128 pixels)"), MENU_SIZE_RIDICULOUS, SIZE_RIDICULOUS },
4763                { NULL, NULL, -1 }
4764        };
4765
4766        NameIdEnum backgrounds[] = {
4767                { N_("Standard"), MENU_BACK_NONE, PANEL_BACK_NONE },
4768                { N_("Color"), MENU_BACK_COLOR, PANEL_BACK_COLOR },
4769                { N_("Pixmap"), MENU_BACK_PIXMAP, PANEL_BACK_PIXMAP },
4770                { N_("Translucent"), MENU_BACK_TRANSLUCENT, PANEL_BACK_TRANSLUCENT },
4771                { NULL, NULL, -1 }
4772        };
4773
4774        NameIdEnum levels[] = {
4775                { N_("Default"), MENU_LEVEL_DEFAULT, BASEP_LEVEL_DEFAULT },
4776                { N_("Below"), MENU_LEVEL_BELOW, BASEP_LEVEL_BELOW },
4777                { N_("Normal"), MENU_LEVEL_NORMAL, BASEP_LEVEL_NORMAL },
4778                { N_("Above"), MENU_LEVEL_ABOVE, BASEP_LEVEL_ABOVE },
4779                { NULL, NULL, -1 }
4780        };
4781
4782        NameIdEnum avoid_on_maximize[] = {
4783                { N_("Avoid on maximize"), MENU_AVOID_ON_MAX, TRUE },
4784                { N_("Don't avoid on maximize"), MENU_NO_AVOID_ON_MAX, FALSE },
4785                { NULL, NULL, -1 }
4786        };
4787
4788        add_radio_menu (menu, _("Type"), types, MENU_TYPES,
4789                        convert_to_panel, update_type_menu);
4790
4791        add_radio_menu (menu, _("Hiding policy"), modes, MENU_MODES,
4792                        change_hiding_mode, update_hiding_menu);
4793
4794        add_radio_menu (menu, _("Hide buttons"), hidebuttons, MENU_HIDEBUTTONS,
4795                        change_hidebuttons, update_hidebutton_menu);
4796
4797        add_radio_menu (menu, _("Size"), sizes, MENU_SIZES,
4798                        change_size, update_size_menu);
4799
4800        add_radio_menu (menu, _("Orientation"), orients, MENU_ORIENTS,
4801                        change_orient, update_orient_menu);
4802
4803        add_radio_menu (menu, _("Background type"), backgrounds, MENU_BACKS,
4804                        change_background, update_back_menu);
4805
4806        add_radio_menu (menu, _("Level"), levels, MENU_LEVELS,
4807                        change_level, update_level_menu);
4808
4809        add_radio_menu (menu, _("Maximize mode"), avoid_on_maximize, MENU_MAXIMIZE_MODE,
4810                        change_avoid_on_maximize, update_avoid_on_maximize_menu);
4811       
4812        gtk_signal_connect (GTK_OBJECT (menu), "show",
4813                            GTK_SIGNAL_FUNC (show_x_on_panels),
4814                            NULL);
4815}
4816
4817static void
4818make_add_submenu (GtkWidget *menu, gboolean fake_submenus)
4819{
4820        GtkWidget *menuitem, *submenu, *submenuitem, *m;
4821
4822        /* Add Menu */
4823
4824        menuitem = gtk_menu_item_new ();
4825        gtk_widget_lock_accelerators (menuitem);
4826        setup_menuitem_try_pixmap (menuitem, "gnome-applets.png",
4827                                   _("Applet"), SMALL_ICON_SIZE);
4828        gtk_menu_append (GTK_MENU (menu), menuitem);
4829        m = create_applets_menu(NULL, fake_submenus, TRUE);
4830        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),m);
4831        gtk_signal_connect(GTK_OBJECT(m),"show",
4832                           GTK_SIGNAL_FUNC(submenu_to_display), NULL);
4833
4834        menuitem = gtk_menu_item_new ();
4835        gtk_widget_lock_accelerators (menuitem);
4836        setup_menuitem_try_pixmap (menuitem,
4837                                   "gnome-gmenu.png",
4838                                   _("Menu"), SMALL_ICON_SIZE);
4839        gtk_menu_append (GTK_MENU (menu), menuitem);
4840
4841        submenu = menu_new ();
4842        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4843
4844        submenuitem = gtk_menu_item_new ();
4845        gtk_widget_lock_accelerators (menuitem);
4846        setup_menuitem_try_pixmap (submenuitem,
4847                                   "gnome-logo-icon-transparent.png",
4848                                   _("Main menu"), SMALL_ICON_SIZE);
4849        gtk_menu_append (GTK_MENU (submenu), submenuitem);
4850        gtk_signal_connect(GTK_OBJECT(submenuitem), "activate",
4851                           GTK_SIGNAL_FUNC(add_menu_to_panel),
4852                           NULL);
4853        setup_internal_applet_drag(submenuitem, "MENU:MAIN");
4854
4855        submenuitem = gtk_menu_item_new ();
4856        gtk_widget_lock_accelerators (menuitem);
4857        setup_menuitem_try_pixmap (submenuitem,
4858                                   "gnome-logo-icon-transparent.png",
4859                                   _("Programs menu"), SMALL_ICON_SIZE);
4860        gtk_menu_append (GTK_MENU (submenu), submenuitem);
4861        gtk_signal_connect(GTK_OBJECT(submenuitem), "activate",
4862                           GTK_SIGNAL_FUNC(add_menu_to_panel),
4863                           "/var/athena/menus");
4864        setup_internal_applet_drag(submenuitem, "MENU:gnome/athena/menus");
4865
4866        submenuitem = gtk_menu_item_new ();
4867        gtk_widget_lock_accelerators (menuitem);
4868        setup_menuitem_try_pixmap (submenuitem, "gnome-favorites.png",
4869                                   _("Favorites menu"), SMALL_ICON_SIZE);
4870        gtk_menu_append (GTK_MENU (submenu), submenuitem);
4871        gtk_signal_connect(GTK_OBJECT(submenuitem), "activate",
4872                           GTK_SIGNAL_FUNC(add_menu_to_panel),
4873                           "~/.gnome/apps");
4874        setup_internal_applet_drag(submenuitem, "MENU:~/.gnome/apps");
4875
4876        menuitem = gtk_menu_item_new ();
4877        gtk_widget_lock_accelerators (menuitem);
4878        setup_menuitem_try_pixmap (menuitem,
4879                                   "launcher-program.png",
4880                                   _("Launcher..."), SMALL_ICON_SIZE);
4881        gtk_menu_append (GTK_MENU (menu), menuitem);
4882        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
4883                           GTK_SIGNAL_FUNC(ask_about_launcher_cb),NULL);
4884        setup_internal_applet_drag(menuitem, "LAUNCHER:ASK");
4885
4886        menuitem = gtk_menu_item_new ();
4887        gtk_widget_lock_accelerators (menuitem);
4888        setup_menuitem_try_pixmap (menuitem, "launcher-program.png",
4889                                   _("Launcher from menu"), SMALL_ICON_SIZE);
4890        gtk_menu_append (GTK_MENU (menu), menuitem);
4891        m = create_add_launcher_menu (NULL, fake_submenus);
4892        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), m);
4893        gtk_signal_connect (GTK_OBJECT (m),"show",
4894                           GTK_SIGNAL_FUNC (submenu_to_display), NULL);
4895
4896        menuitem = gtk_menu_item_new ();
4897        gtk_widget_lock_accelerators (menuitem);
4898        setup_menuitem_try_pixmap (menuitem,
4899                                   "panel-drawer.png",
4900                                   _("Drawer"), SMALL_ICON_SIZE);
4901        gtk_menu_append (GTK_MENU (menu), menuitem);
4902        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
4903                           (GtkSignalFunc) add_drawer_to_panel,
4904                           NULL);
4905        setup_internal_applet_drag(menuitem, "DRAWER:NEW");
4906
4907        menuitem = gtk_menu_item_new ();
4908        gtk_widget_lock_accelerators (menuitem);
4909        setup_menuitem_try_pixmap (menuitem,
4910                                   "gnome-term-night.png",
4911                                   _("Log out button"), SMALL_ICON_SIZE);
4912        gtk_menu_append (GTK_MENU (menu), menuitem);
4913        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
4914                           GTK_SIGNAL_FUNC(add_logout_to_panel),
4915                           NULL);
4916        setup_internal_applet_drag(menuitem, "LOGOUT:NEW");
4917       
4918        menuitem = gtk_menu_item_new ();
4919        gtk_widget_lock_accelerators (menuitem);
4920        setup_menuitem_try_pixmap (menuitem,
4921                                   "gnome-lockscreen.png",
4922                                   _("Lock button"), SMALL_ICON_SIZE);
4923        gtk_menu_append (GTK_MENU (menu), menuitem);
4924        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
4925                           GTK_SIGNAL_FUNC(add_lock_to_panel),
4926                           NULL);
4927        setup_internal_applet_drag(menuitem, "LOCK:NEW");
4928
4929        menuitem = gtk_menu_item_new ();
4930        gtk_widget_lock_accelerators (menuitem);
4931        setup_menuitem_try_pixmap (menuitem,
4932                                   "gnome-run.png",
4933                                   _("Run button"), SMALL_ICON_SIZE);
4934        gtk_menu_append (GTK_MENU (menu), menuitem);
4935        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
4936                           GTK_SIGNAL_FUNC(add_run_to_panel),
4937                           NULL);
4938        setup_internal_applet_drag(menuitem, "RUN:NEW");
4939
4940        menuitem = gtk_menu_item_new ();
4941        gtk_widget_lock_accelerators (menuitem);
4942        setup_menuitem (menuitem,
4943                        gnome_stock_pixmap_widget (menu,
4944                                                   GNOME_STOCK_PIXMAP_ADD),
4945                        _("Swallowed app..."));
4946        gtk_menu_append (GTK_MENU (menu), menuitem);
4947        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
4948                           GTK_SIGNAL_FUNC(ask_about_swallowing_cb),NULL);
4949        setup_internal_applet_drag(menuitem, "SWALLOW:ASK");
4950
4951        menuitem = gtk_menu_item_new ();
4952        gtk_widget_lock_accelerators (menuitem);
4953        setup_menuitem(menuitem, 0, _("Status dock"));
4954        gtk_menu_append (GTK_MENU (menu), menuitem);
4955        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
4956                           GTK_SIGNAL_FUNC(try_add_status_to_panel),NULL);
4957        setup_internal_applet_drag(menuitem, "STATUS:TRY");
4958}
4959
4960static void
4961add_to_panel_menu_tearoff_new_menu(GtkWidget *w, gpointer data)
4962{
4963        GtkWidget *menu;
4964        TearoffMenu *tm;
4965        char *wmclass = get_unique_tearoff_wmclass();
4966        PanelWidget *menu_panel;
4967
4968        menu = menu_new();
4969        make_add_submenu(menu, TRUE);
4970       
4971        /*set the panel to use as the data*/
4972        menu_panel = get_panel_from_menu_data(w, TRUE);
4973        gtk_object_set_data(GTK_OBJECT(menu), "menu_panel", menu_panel);
4974        gtk_signal_connect_object_while_alive(GTK_OBJECT(menu_panel),
4975                      "destroy", GTK_SIGNAL_FUNC(gtk_widget_unref),
4976                      GTK_OBJECT(menu));
4977        show_tearoff_menu(menu, _("Add to panel"),TRUE,0,0, wmclass);
4978
4979        tm = g_new0(TearoffMenu,1);
4980        tm->menu = menu;
4981        tm->mfl = NULL;
4982        tm->title = g_strdup(_("Add to panel"));
4983        tm->special = g_strdup("ADD_TO_PANEL");
4984        tm->wmclass = g_strdup(wmclass);
4985        gtk_signal_connect(GTK_OBJECT(menu), "destroy",
4986                           GTK_SIGNAL_FUNC(tearoff_destroyed), tm);
4987
4988        tearoffs = g_slist_prepend(tearoffs,tm);
4989}
4990
4991/* just run the gnome-panel-properties */
4992static void
4993panel_config_global(void)
4994{
4995        char *argv[2] = {"gnome-panel-properties-capplet", NULL};
4996        if (gnome_execute_async (g_get_home_dir (), 1, argv) < 0)
4997                panel_error_dialog(_("Cannot execute panel global properties"));
4998}
4999
5000static void
5001setup_remove_this_panel(GtkWidget *menu, GtkWidget *menuitem)
5002{
5003        PanelWidget *panel = get_panel_from_menu_data(menu, TRUE);
5004        GtkWidget *label;
5005
5006        g_assert(panel->panel_parent);
5007
5008        if(!GTK_MENU(menu)->torn_off &&
5009           !IS_DRAWER_WIDGET(panel->panel_parent) &&
5010           base_panels == 1)
5011                gtk_widget_set_sensitive(menuitem, FALSE);
5012        else
5013                gtk_widget_set_sensitive(menuitem, TRUE);
5014
5015        label = GTK_BIN(menuitem)->child;
5016        if(GTK_IS_BOX(label)) {
5017                GList *li, *list;
5018                list = gtk_container_children(GTK_CONTAINER(label));
5019                for(li = list; li; li = li->next) {
5020                        if(GTK_IS_LABEL(li->data)) {
5021                                label = li->data;
5022                                break;
5023                        }
5024                }
5025                g_list_free(list);
5026        }
5027        if(!GTK_IS_LABEL(label)) {
5028                g_warning("We can't find the label of a menu item");
5029                return;
5030        }
5031
5032
5033        /* this will not handle the case of menu being torn off
5034         * and then the confirm_panel_remove changed, but oh well */
5035        if((GTK_MENU(menu)->torn_off || panel->applet_list) &&
5036           global_config.confirm_panel_remove)
5037                gtk_label_set_text(GTK_LABEL(label), _("Remove this panel..."));
5038        else
5039                gtk_label_set_text(GTK_LABEL(label), _("Remove this panel"));
5040}
5041
5042static void
5043show_panel_help (GtkWidget *w, gpointer data)
5044{
5045        panel_show_help ("index.html");
5046}
5047
5048static void
5049panel_launch_gmenu (GtkWidget *widget, gpointer data)
5050{
5051        char *argv[2] = {"gmenu", NULL};
5052        if (gnome_execute_async (g_get_home_dir (), 2, argv) < 0)
5053                   panel_error_dialog (_("Cannot launch gmenu!"));
5054}
5055
5056void
5057make_panel_submenu (GtkWidget *menu, gboolean fake_submenus, gboolean is_basep)
5058{
5059        GtkWidget *menuitem, *submenu, *submenuitem;
5060
5061        if ( ! commie_mode) {
5062                menuitem = gtk_menu_item_new ();
5063                gtk_widget_lock_accelerators (menuitem);
5064                setup_menuitem (menuitem,
5065                                gnome_stock_pixmap_widget (menu,
5066                                                           GNOME_STOCK_PIXMAP_ADD),
5067                                _("Add to panel"));
5068                gtk_menu_append (GTK_MENU (menu), menuitem);
5069
5070                submenu = menu_new ();
5071                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
5072                                           submenu);
5073
5074                if (gnome_preferences_get_menus_have_tearoff ()) {
5075                        menuitem = tearoff_item_new();
5076                        gtk_widget_show(menuitem);
5077                        gtk_menu_prepend(GTK_MENU(submenu),menuitem);
5078
5079                        gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
5080                                           GTK_SIGNAL_FUNC(add_to_panel_menu_tearoff_new_menu),
5081                                           NULL);
5082                }
5083
5084                make_add_submenu (submenu, fake_submenus);
5085
5086                menuitem = gtk_menu_item_new ();
5087                gtk_widget_lock_accelerators (menuitem);
5088                setup_menuitem (menuitem,
5089                                gnome_stock_pixmap_widget (menu,
5090                                                           GNOME_STOCK_MENU_NEW),
5091                                _("Create panel"));
5092                gtk_menu_append (GTK_MENU (menu), menuitem);
5093                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
5094                                           create_add_panel_submenu(TRUE));
5095
5096                menuitem = gtk_menu_item_new ();
5097                gtk_widget_lock_accelerators (menuitem);
5098
5099                setup_menuitem (menuitem,
5100                                gnome_stock_pixmap_widget (NULL,
5101                                                           GNOME_STOCK_PIXMAP_REMOVE),
5102                                _("Remove this panel"));
5103                gtk_menu_append (GTK_MENU (menu), menuitem);
5104                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5105                                    GTK_SIGNAL_FUNC (remove_panel_query),
5106                                    NULL);
5107                gtk_signal_connect (GTK_OBJECT (menu), "show",
5108                                    GTK_SIGNAL_FUNC(setup_remove_this_panel),
5109                                    menuitem);
5110
5111                add_menu_separator(menu);
5112
5113                if (is_basep) {
5114                        menuitem = gtk_menu_item_new ();
5115                        gtk_widget_lock_accelerators (menuitem);
5116                        setup_menuitem (menuitem,
5117                                        gnome_stock_pixmap_widget (menu,
5118                                                                   GNOME_STOCK_MENU_PROP),
5119                                        _("Properties"));
5120                        gtk_menu_append (GTK_MENU (menu), menuitem);
5121
5122                        submenu = menu_new ();
5123                        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
5124
5125                        submenuitem = gtk_menu_item_new ();
5126                        gtk_widget_lock_accelerators (menuitem);
5127                        setup_menuitem (submenuitem,
5128                                        gnome_stock_pixmap_widget(submenu,
5129                                                                  GNOME_STOCK_MENU_PROP),
5130                                        _("All properties..."));
5131
5132                        gtk_menu_append (GTK_MENU (submenu), submenuitem);
5133                        gtk_signal_connect (GTK_OBJECT (submenuitem), "activate",
5134                                            GTK_SIGNAL_FUNC(current_panel_config),
5135                                            NULL);
5136
5137                        /*add_menu_separator (submenu);*/
5138                        make_properties_submenu (submenu);
5139                }
5140
5141                menuitem = gtk_menu_item_new ();
5142                gtk_widget_lock_accelerators (menuitem);
5143                setup_menuitem (menuitem,
5144                                gnome_stock_pixmap_widget(menu,
5145                                                          GNOME_STOCK_MENU_PREF),
5146                                _("Global Preferences..."));
5147                gtk_menu_append (GTK_MENU (menu), menuitem);
5148                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5149                                    GTK_SIGNAL_FUNC(panel_config_global),
5150                                    NULL);
5151
5152                menuitem = gtk_menu_item_new ();
5153                gtk_widget_lock_accelerators (menuitem);
5154                setup_menuitem_try_pixmap (menuitem,
5155                                           "gnome-gmenu.png",
5156                                           _("Edit menus..."), SMALL_ICON_SIZE);
5157                gtk_menu_append (GTK_MENU (menu), menuitem);
5158                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5159                                    GTK_SIGNAL_FUNC(panel_launch_gmenu),
5160                                    NULL);
5161
5162                if ( ! global_config.menu_check) {
5163                        menuitem = gtk_menu_item_new ();
5164                        gtk_widget_lock_accelerators (menuitem);
5165                        setup_menuitem (menuitem,
5166                                        NULL,
5167                                        _("Reread all menus"));
5168                        gtk_menu_append (GTK_MENU (menu), menuitem);
5169                        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5170                                            GTK_SIGNAL_FUNC (fr_force_reread),
5171                                            NULL);
5172                }
5173
5174                add_menu_separator (menu);
5175        }
5176
5177        menuitem = gtk_menu_item_new ();
5178        gtk_widget_lock_accelerators (menuitem);
5179        setup_menuitem (menuitem,
5180                        gnome_stock_pixmap_widget_at_size (
5181                                menu, GNOME_STOCK_PIXMAP_HELP,
5182                                SMALL_ICON_SIZE, SMALL_ICON_SIZE),
5183                        _("Panel Manual..."));
5184        gtk_menu_append (GTK_MENU (menu), menuitem);
5185        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5186                            GTK_SIGNAL_FUNC (show_panel_help), NULL);
5187}
5188
5189void
5190panel_lock (GtkWidget *widget, gpointer data)
5191{
5192        char *argv[2] = {"/usr/athena/bin/xlock", NULL};
5193        if (gnome_execute_async (g_get_home_dir (), 1, argv) < 0)
5194                panel_error_dialog (_("Cannot execute xscreensaver"));
5195}
5196
5197static void
5198panel_menu_tearoff_new_menu(GtkWidget *w, gpointer data)
5199{
5200        TearoffMenu *tm;
5201        char *wmclass = get_unique_tearoff_wmclass();
5202        PanelWidget *menu_panel = get_panel_from_menu_data(w, TRUE);
5203        GtkWidget *menu = create_panel_submenu (
5204                NULL, TRUE, FALSE, IS_BASEP_WIDGET (menu_panel->panel_parent));
5205               
5206        /*set the panel to use as the data*/
5207        gtk_object_set_data(GTK_OBJECT(menu), "menu_panel", menu_panel);
5208        gtk_signal_connect_object_while_alive(GTK_OBJECT(menu_panel),
5209                      "destroy", GTK_SIGNAL_FUNC(gtk_widget_unref),
5210                      GTK_OBJECT(menu));
5211
5212        show_tearoff_menu (menu, _("Panel"), TRUE, 0, 0, wmclass);
5213
5214        tm = g_new0(TearoffMenu,1);
5215        tm->menu = menu;
5216        tm->mfl = NULL;
5217        tm->title = g_strdup(_("Panel"));
5218        tm->special = g_strdup("PANEL_SUBMENU");
5219        tm->wmclass = g_strdup(wmclass);
5220        gtk_signal_connect(GTK_OBJECT(menu), "destroy",
5221                           GTK_SIGNAL_FUNC(tearoff_destroyed), tm);
5222
5223        tearoffs = g_slist_prepend(tearoffs,tm);
5224}
5225
5226static void
5227desktop_menu_tearoff_new_menu (GtkWidget *w, gpointer data)
5228{
5229        TearoffMenu *tm;
5230        char *wmclass = get_unique_tearoff_wmclass ();
5231        PanelWidget *menu_panel;
5232        GtkWidget *menu = create_desktop_menu (NULL, TRUE, FALSE);
5233
5234        /*set the panel to use as the data*/
5235        menu_panel = get_panel_from_menu_data(w, TRUE);
5236        gtk_object_set_data(GTK_OBJECT(menu), "menu_panel", menu_panel);
5237        gtk_signal_connect_object_while_alive(GTK_OBJECT(menu_panel),
5238                      "destroy", GTK_SIGNAL_FUNC(gtk_widget_unref),
5239                      GTK_OBJECT(menu));
5240
5241        show_tearoff_menu (menu, _("Desktop"), TRUE, 0, 0, wmclass);
5242
5243        tm = g_new0(TearoffMenu,1);
5244        tm->menu = menu;
5245        tm->mfl = NULL;
5246        tm->title = g_strdup(_("Desktop"));
5247        tm->special = g_strdup("DESKTOP");
5248        tm->wmclass = g_strdup(wmclass);
5249        gtk_signal_connect(GTK_OBJECT(menu), "destroy",
5250                           GTK_SIGNAL_FUNC(tearoff_destroyed), tm);
5251
5252        tearoffs = g_slist_prepend(tearoffs,tm);
5253}
5254
5255static GtkWidget *
5256create_panel_submenu(GtkWidget *menu, gboolean fake_submenus, gboolean tearoff,
5257                     gboolean is_basep)
5258{
5259        GtkWidget *menuitem;
5260        char *char_tmp;
5261
5262        if (!menu) {
5263                menu = menu_new();
5264        }
5265
5266        if(tearoff && gnome_preferences_get_menus_have_tearoff ()) {
5267                menuitem = tearoff_item_new();
5268                gtk_widget_show(menuitem);
5269                gtk_menu_prepend (GTK_MENU (menu), menuitem);
5270
5271                gtk_signal_connect(GTK_OBJECT(menuitem),"activate",
5272                                   GTK_SIGNAL_FUNC(panel_menu_tearoff_new_menu),
5273                                   NULL);
5274        }
5275
5276        make_panel_submenu (menu, fake_submenus, is_basep);
5277
5278        menuitem = gtk_menu_item_new ();
5279        gtk_widget_lock_accelerators (menuitem);
5280        setup_menuitem (menuitem,
5281                        gnome_stock_pixmap_widget(menu,
5282                                                  GNOME_STOCK_PIXMAP_ABOUT),
5283                        _("About the panel..."));
5284        gtk_menu_append (GTK_MENU (menu), menuitem);
5285        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5286                            GTK_SIGNAL_FUNC(about_cb),
5287                            NULL);
5288       
5289        char_tmp = panel_is_program_in_path("gnome-about");
5290        if(!char_tmp)
5291                char_tmp = panel_is_program_in_path ("guname");
5292
5293        if (char_tmp) {
5294                menuitem = gtk_menu_item_new ();
5295                gtk_widget_lock_accelerators (menuitem);
5296                setup_menuitem (menuitem,
5297                                gnome_stock_pixmap_widget(menu,
5298                                                          GNOME_STOCK_PIXMAP_ABOUT),
5299                                _("About GNOME..."));
5300                gtk_menu_append (GTK_MENU (menu), menuitem);
5301                gtk_signal_connect_full(GTK_OBJECT (menuitem), "activate",
5302                                        GTK_SIGNAL_FUNC(about_gnome_cb),NULL,
5303                                        char_tmp, (GtkDestroyNotify)g_free,
5304                                        FALSE,TRUE);
5305        }
5306        return menu;
5307}
5308
5309static void
5310run_cb (GtkWidget *w, gpointer data)
5311{
5312        show_run_dialog ();
5313}
5314
5315static GtkWidget *
5316create_desktop_menu (GtkWidget *menu, gboolean fake_submenus, gboolean tearoff)
5317{
5318        GtkWidget *menuitem;
5319        char *char_tmp;
5320        /* Panel entry */
5321
5322        if (menu == NULL) {
5323                menu = menu_new ();
5324        }
5325
5326        if(tearoff && gnome_preferences_get_menus_have_tearoff ()) {
5327                menuitem = tearoff_item_new();
5328                gtk_widget_show(menuitem);
5329                gtk_menu_prepend (GTK_MENU (menu), menuitem);
5330
5331                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5332                                    GTK_SIGNAL_FUNC(desktop_menu_tearoff_new_menu),
5333                                    NULL);
5334        }
5335
5336        char_tmp = panel_is_program_in_path ("xss");
5337        if (char_tmp) {
5338                menuitem = gtk_menu_item_new ();
5339                gtk_widget_lock_accelerators (menuitem);
5340                setup_menuitem_try_pixmap (menuitem,
5341                                           "gnome-lockscreen.png",
5342                                           _("Lock screen"), SMALL_ICON_SIZE);
5343                gtk_menu_append (GTK_MENU (menu), menuitem);
5344                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5345                                    GTK_SIGNAL_FUNC(panel_lock), 0);
5346                setup_internal_applet_drag(menuitem, "LOCK:NEW");
5347                gtk_tooltips_set_tip (panel_tooltips, menuitem,
5348                                      _("Lock the screen so that you can "
5349                                        "temporairly leave your computer"), NULL);
5350        }
5351        g_free (char_tmp);
5352
5353        menuitem = gtk_menu_item_new ();
5354        gtk_widget_lock_accelerators (menuitem);
5355        setup_menuitem_try_pixmap (menuitem,
5356                                   "logout-icon-menu.png",
5357                                   _("Log out"), SMALL_ICON_SIZE);
5358        gtk_menu_append (GTK_MENU (menu), menuitem);
5359        gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5360                            GTK_SIGNAL_FUNC(panel_quit), 0);
5361        setup_internal_applet_drag(menuitem, "LOGOUT:NEW");
5362        gtk_tooltips_set_tip (panel_tooltips, menuitem,
5363                              _("Log out of this session to log in as "
5364                                "a different user or to shut down your "
5365                                "computer"),
5366                              NULL);
5367
5368        return menu;
5369}
5370
5371static void
5372add_distribution_submenu (GtkWidget *root_menu, gboolean fake_submenus,
5373                          gboolean launcher_add,
5374                          gboolean favourites_add)
5375{
5376        GtkWidget *menu;
5377        GtkWidget *menuitem;
5378        const DistributionInfo *distribution_info = get_distribution_info ();
5379        IconSize size = global_config.use_large_icons
5380                ? MEDIUM_ICON_SIZE : SMALL_ICON_SIZE;
5381
5382        if (distribution_info == NULL)
5383                return;
5384
5385        menu = create_distribution_menu(NULL, fake_submenus,
5386                                        TRUE, TRUE, launcher_add,
5387                                        favourites_add);
5388        menuitem = gtk_menu_item_new ();
5389        gtk_widget_lock_accelerators (menuitem);
5390        setup_menuitem_try_pixmap (menuitem,
5391                                   distribution_info->menu_icon,
5392                                   _(distribution_info->menu_name), size);
5393        gtk_menu_append (GTK_MENU (root_menu), menuitem);
5394        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
5395                                   menu);
5396        if (distribution_info->menu_show_func)
5397                gtk_signal_connect(GTK_OBJECT(menu),"show",
5398                                   GTK_SIGNAL_FUNC(distribution_info->menu_show_func),
5399                                   menuitem);
5400        gtk_signal_connect(GTK_OBJECT(menu),"show",
5401                           GTK_SIGNAL_FUNC(submenu_to_display),
5402                           NULL);
5403}
5404
5405static void
5406add_kde_submenu (GtkWidget *root_menu, gboolean fake_submenus,
5407                 gboolean launcher_add,
5408                 gboolean favourites_add)
5409{
5410        GtkWidget *pixmap = NULL;
5411        GtkWidget *menu;
5412        GtkWidget *menuitem;
5413        char *pixmap_path;
5414        IconSize size = global_config.use_large_icons
5415                ? MEDIUM_ICON_SIZE : SMALL_ICON_SIZE;
5416
5417        menu = create_kde_menu (NULL, fake_submenus, TRUE, TRUE,
5418                                TRUE, launcher_add, favourites_add);
5419        pixmap_path = g_concat_dir_and_file (kde_icondir, "exec.xpm");
5420
5421        if (panel_file_exists(pixmap_path)) {
5422                pixmap = fake_pixmap_at_size (pixmap_path, size);
5423                if (pixmap)
5424                        gtk_widget_show (pixmap);
5425        }
5426        g_free (pixmap_path);
5427        menuitem = gtk_menu_item_new ();
5428        gtk_widget_lock_accelerators (menuitem);
5429        setup_menuitem_with_size (menuitem, pixmap, _("KDE menus"),
5430                                  size);
5431        gtk_menu_append (GTK_MENU (root_menu), menuitem);
5432        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
5433        gtk_signal_connect(GTK_OBJECT(menu),"show",
5434                           GTK_SIGNAL_FUNC(submenu_to_display), NULL);
5435}
5436
5437GtkWidget *
5438create_root_menu (GtkWidget *root_menu,
5439                  gboolean fake_submenus,
5440                  int flags,
5441                  gboolean tearoff,
5442                  gboolean is_basep,
5443                  gboolean title)
5444{
5445        GtkWidget *menu;
5446        GtkWidget *menuitem;
5447
5448        gboolean has_inline = (flags & (MAIN_MENU_SYSTEM |
5449                                        MAIN_MENU_USER |
5450                                        MAIN_MENU_APPLETS |
5451                                        MAIN_MENU_KDE));
5452
5453        gboolean has_subs = (flags & (MAIN_MENU_SYSTEM_SUB |
5454                                      MAIN_MENU_USER_SUB |
5455                                      MAIN_MENU_APPLETS_SUB |
5456                                      MAIN_MENU_KDE_SUB));
5457
5458        gboolean has_inline2 = (flags & (MAIN_MENU_DESKTOP |
5459                                         MAIN_MENU_PANEL));
5460        gboolean has_subs2 = (flags & (MAIN_MENU_DESKTOP_SUB |
5461                                       MAIN_MENU_PANEL_SUB));
5462
5463        IconSize size = global_config.use_large_icons
5464                ? MEDIUM_ICON_SIZE : SMALL_ICON_SIZE;
5465
5466        const DistributionInfo *distribution_info = get_distribution_info ();
5467
5468        if (distribution_info != NULL) {
5469                has_inline |= (flags & (MAIN_MENU_DISTRIBUTION));
5470                has_subs |= (flags & (MAIN_MENU_DISTRIBUTION_SUB));
5471        }
5472
5473
5474        if(!root_menu)
5475                root_menu = menu_new ();
5476        if (tearoff && gnome_preferences_get_menus_have_tearoff ()) {
5477                GtkWidget *menuitem = tearoff_item_new ();
5478                gtk_widget_show (menuitem);
5479                gtk_menu_prepend (GTK_MENU (root_menu), menuitem);
5480                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5481                                    GTK_SIGNAL_FUNC (panel_tearoff_new_menu),
5482                                    GINT_TO_POINTER(flags));
5483        }
5484       
5485        if (flags & MAIN_MENU_SYSTEM)
5486                create_system_menu(root_menu, fake_submenus,
5487                                   FALSE, title,
5488                                   FALSE /* launcher_add */,
5489                                   FALSE /* favourites_add */);
5490        if (flags & MAIN_MENU_USER)
5491                /* FIXME: add the add to favourites somehow here */
5492                create_user_menu(_("Favorites"), "apps",
5493                                 root_menu, "gnome-favorites.png",
5494                                 fake_submenus, FALSE, FALSE, title,
5495                                 FALSE /* launcher_add */,
5496                                 FALSE /* favourites_add */);
5497        /* in commie mode the applets menu doesn't make sense */
5498        if ( ! commie_mode &&
5499            flags & MAIN_MENU_APPLETS)
5500                create_applets_menu(root_menu, fake_submenus, title);
5501
5502        if (flags & MAIN_MENU_DISTRIBUTION &&
5503            distribution_info != NULL) {
5504                if (distribution_info->menu_show_func)
5505                        distribution_info->menu_show_func(NULL,NULL);
5506
5507                create_distribution_menu(root_menu, fake_submenus, FALSE,
5508                                         title,
5509                                         FALSE /* launcher_add */,
5510                                         FALSE /* favourites_add */);
5511        }
5512        if (flags & MAIN_MENU_KDE)
5513                create_kde_menu(root_menu, fake_submenus, FALSE, FALSE,
5514                                title,
5515                                FALSE /* launcher_add */,
5516                                FALSE /* favourites_add */);
5517
5518        /*others here*/
5519
5520        if (has_subs && has_inline)
5521                add_menu_separator (root_menu);
5522
5523       
5524        if (flags & MAIN_MENU_SYSTEM_SUB) {
5525                menu = create_system_menu(NULL, fake_submenus, TRUE,
5526                                          TRUE,
5527                                          FALSE /* launcher_add */,
5528                                          FALSE /* favourites_add */);
5529                menuitem = gtk_menu_item_new ();
5530                gtk_widget_lock_accelerators (menuitem);
5531                setup_menuitem_try_pixmap (menuitem,
5532                                           "gnome-logo-icon-transparent.png",
5533                                           _("Programs"), size);
5534                gtk_menu_append (GTK_MENU (root_menu), menuitem);
5535                if(menu) {
5536                        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
5537                                                   menu);
5538                        gtk_signal_connect(GTK_OBJECT(menu),"show",
5539                                           GTK_SIGNAL_FUNC(submenu_to_display),
5540                                           NULL);
5541                }
5542        }
5543
5544        if (flags & MAIN_MENU_USER_SUB) {
5545                menu = start_favourites_menu (NULL, fake_submenus);
5546                create_user_menu(_("Favorites"), "apps", menu,
5547                                 "gnome-favorites.png",
5548                                 fake_submenus, TRUE, TRUE, TRUE,
5549                                 FALSE /* launcher_add */,
5550                                 FALSE /* favourites_add */);
5551                menuitem = gtk_menu_item_new ();
5552                gtk_widget_lock_accelerators (menuitem);
5553                setup_menuitem_try_pixmap (menuitem, "gnome-favorites.png",
5554                                           _("Favorites"), size);
5555                gtk_menu_append (GTK_MENU (root_menu), menuitem);
5556                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
5557                gtk_signal_connect(GTK_OBJECT(menu),"show",
5558                                   GTK_SIGNAL_FUNC(submenu_to_display),
5559                                   NULL);
5560        }
5561        /* in commie mode the applets menu doesn't make sense */
5562        if ( ! commie_mode &&
5563            flags & MAIN_MENU_APPLETS_SUB) {
5564                menu = create_applets_menu(NULL, fake_submenus, FALSE);
5565                menuitem = gtk_menu_item_new ();
5566                gtk_widget_lock_accelerators (menuitem);
5567                setup_menuitem_try_pixmap (menuitem, "gnome-applets.png",
5568                                          _("Applets"), size);
5569                gtk_menu_append (GTK_MENU (root_menu), menuitem);
5570                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
5571                gtk_signal_connect(GTK_OBJECT(menu),"show",
5572                                   GTK_SIGNAL_FUNC(submenu_to_display),
5573                                   NULL);
5574        }
5575        if (flags & MAIN_MENU_DISTRIBUTION_SUB) {
5576                add_distribution_submenu (root_menu, fake_submenus,
5577                                          FALSE /*launcher_add */,
5578                                          FALSE /*favourites_add */);
5579        }
5580        if (flags & MAIN_MENU_KDE_SUB) {
5581                add_kde_submenu (root_menu, fake_submenus,
5582                                 FALSE /*launcher_add */,
5583                                 FALSE /*favourites_add */);
5584        }
5585
5586        if ( ! no_run_box) {
5587                menuitem = gtk_menu_item_new ();
5588                gtk_widget_lock_accelerators (menuitem);
5589                setup_menuitem_try_pixmap (menuitem, "gnome-run.png",
5590                                           _("Run..."), size);
5591                gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
5592                                    GTK_SIGNAL_FUNC (run_cb), NULL);
5593                gtk_menu_append (GTK_MENU (root_menu), menuitem);
5594                setup_internal_applet_drag(menuitem, "RUN:NEW");
5595                gtk_tooltips_set_tip (panel_tooltips, menuitem,
5596                                      _("Execute a command line"), NULL);
5597        }
5598
5599        if (((has_inline && !has_subs) || has_subs) && has_subs2)
5600                add_menu_separator (root_menu);
5601
5602        if (flags & MAIN_MENU_PANEL_SUB) {
5603                menu = create_panel_submenu (NULL, fake_submenus, TRUE, is_basep);
5604                menuitem = gtk_menu_item_new ();
5605                gtk_widget_lock_accelerators (menuitem);
5606                setup_menuitem_try_pixmap (menuitem, "gnome-panel.png",
5607                                           _("Panel"), SMALL_ICON_SIZE);
5608                gtk_menu_append (GTK_MENU (root_menu), menuitem);
5609                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
5610        }
5611        if (flags & MAIN_MENU_DESKTOP_SUB) {
5612                menu = create_desktop_menu (NULL, fake_submenus, TRUE);
5613                menuitem = gtk_menu_item_new ();
5614                gtk_widget_lock_accelerators (menuitem);
5615                setup_menuitem_try_pixmap (menuitem, "gnome-ccdesktop.png",
5616                                           _("Desktop"), SMALL_ICON_SIZE);
5617                gtk_menu_append (GTK_MENU (root_menu), menuitem);
5618                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
5619        }
5620
5621        if (!has_inline2)
5622                return root_menu;
5623
5624        if (has_subs2 || has_subs || has_inline)
5625                add_menu_separator (root_menu);
5626
5627        if (flags & MAIN_MENU_PANEL) {
5628                make_panel_submenu (root_menu, fake_submenus, is_basep);
5629        }
5630       
5631        if (flags & MAIN_MENU_DESKTOP) {
5632                if (flags & MAIN_MENU_PANEL)
5633                        add_menu_separator (root_menu);
5634                create_desktop_menu (root_menu, fake_submenus, FALSE);
5635        }
5636       
5637        return root_menu;
5638}
5639       
5640void
5641add_menu_widget (Menu *menu, PanelWidget *panel, GSList *menudirl,
5642                 gboolean main_menu, gboolean fake_subs)
5643{
5644        GSList *li;
5645
5646        /* one of these has to be there in order to get the panel of the
5647           applet */
5648        g_return_if_fail (menu->menu || panel);
5649
5650        if(menu->menu) {
5651                panel = get_panel_from_menu_data(menu->menu, TRUE);
5652                gtk_widget_unref(menu->menu);
5653                menu->menu = NULL;
5654        }
5655
5656        if(panel == NULL) {
5657                g_warning ("Menu is seriously weird");
5658                return;
5659        }
5660
5661        if (main_menu) {
5662                int flags;
5663                if (menu->global_main)
5664                        flags = global_config.menu_flags;
5665                else
5666                        flags = menu->main_menu_flags;
5667                menu->menu = create_root_menu(NULL,
5668                        fake_subs, flags, TRUE,
5669                        IS_BASEP_WIDGET (panel->panel_parent), TRUE);
5670
5671                gtk_tooltips_set_tip (panel_tooltips, menu->button,
5672                                      _("Main Menu"), NULL);
5673        } else {
5674                menu->menu = NULL;
5675                for(li = menudirl; li != NULL; li = li->next)
5676                        menu->menu = create_menu_at (menu->menu, li->data,
5677                                                     FALSE /* applets */,
5678                                                     FALSE /* launcher_add */,
5679                                                     FALSE /* favourites_add */,
5680                                                     NULL, NULL,
5681                                                     fake_subs, FALSE, TRUE);
5682
5683                /* FIXME: A more descriptive name would be better */
5684                gtk_tooltips_set_tip (panel_tooltips, menu->button,
5685                                      _("Menu"), NULL);
5686
5687                if(menu->menu == NULL) {
5688                        int flags;
5689                        if (menu->global_main)
5690                                flags = global_config.menu_flags;
5691                        else
5692                                flags = menu->main_menu_flags;
5693                        g_warning(_("Can't create menu, using main menu!"));
5694                        menu->menu = create_root_menu(NULL,
5695                                fake_subs, flags, TRUE,
5696                                IS_BASEP_WIDGET (panel->panel_parent),
5697                                TRUE);
5698                        gtk_tooltips_set_tip (panel_tooltips, menu->button,
5699                                              _("Main Menu"), NULL);
5700                }
5701
5702        }
5703        gtk_signal_connect (GTK_OBJECT (menu->menu), "deactivate",
5704                            GTK_SIGNAL_FUNC (menu_deactivate), menu);
5705
5706        gtk_object_set_data(GTK_OBJECT(menu->menu), "menu_panel", panel);
5707        gtk_signal_connect_object_while_alive(
5708              GTK_OBJECT(panel),
5709              "destroy", GTK_SIGNAL_FUNC(gtk_widget_unref),
5710              GTK_OBJECT(menu->menu));
5711}
5712
5713static void
5714menu_button_pressed (GtkWidget *widget, gpointer data)
5715{
5716        Menu *menu = data;
5717        GdkEventButton *bevent = (GdkEventButton*)gtk_get_current_event();
5718        GtkWidget *wpanel = get_panel_parent(menu->button);
5719        gboolean main_menu = (strcmp (menu->path, ".") == 0);
5720        int flags;
5721        const DistributionInfo *distribution_info = get_distribution_info ();
5722
5723        if (menu->global_main)
5724                flags = global_config.menu_flags;
5725        else
5726                flags = menu->main_menu_flags;
5727
5728        if (menu->menu == NULL) {
5729                char *this_menu = get_real_menu_path(menu->path);
5730                GSList *list = g_slist_append(NULL,this_menu);
5731               
5732                add_menu_widget(menu, PANEL_WIDGET(menu->button->parent),
5733                                list, strcmp(menu->path, ".")==0, TRUE);
5734               
5735                g_free(this_menu);
5736
5737                g_slist_free(list);
5738        } else {
5739                if(flags & MAIN_MENU_DISTRIBUTION &&
5740                   ! (flags & MAIN_MENU_DISTRIBUTION_SUB) &&
5741                   distribution_info != NULL &&
5742                   distribution_info->menu_show_func)
5743                        distribution_info->menu_show_func(NULL, NULL);
5744
5745                check_and_reread_applet(menu, main_menu);
5746        }
5747
5748        /*so that the panel doesn't pop down until we're
5749          done with the menu */
5750        if(IS_BASEP_WIDGET(wpanel)) {
5751                BASEP_WIDGET(wpanel)->autohide_inhibit = TRUE;
5752                basep_widget_autohide(BASEP_WIDGET(wpanel));
5753        }
5754
5755        BUTTON_WIDGET(menu->button)->ignore_leave = TRUE;
5756        gtk_grab_remove(menu->button);
5757
5758        menu->age = 0;
5759        gtk_menu_popup(GTK_MENU(menu->menu), 0, 0,
5760                       applet_menu_position,
5761                       menu->info, bevent->button, bevent->time);
5762        gdk_event_free((GdkEvent *)bevent);
5763}
5764
5765static void 
5766drag_data_get_cb (GtkWidget          *widget,
5767                  GdkDragContext     *context,
5768                  GtkSelectionData   *selection_data,
5769                  guint               info,
5770                  guint               time,
5771                  gpointer            data)
5772{
5773        char *foo;
5774
5775        foo = g_strdup_printf ("MENU:%d", find_applet (widget));
5776
5777        gtk_selection_data_set (selection_data,
5778                                selection_data->target, 8, (guchar *)foo,
5779                                strlen (foo));
5780
5781        g_free (foo);
5782}
5783
5784static Menu *
5785create_panel_menu (PanelWidget *panel, const char *menudir, gboolean main_menu,
5786                   PanelOrientType orient, int main_menu_flags,
5787                   gboolean global_main,
5788                   gboolean custom_icon, const char *custom_icon_file)
5789{
5790        static GtkTargetEntry dnd_targets[] = {
5791                { "application/x-panel-applet-internal", 0, 0 }
5792        };
5793        Menu *menu;
5794       
5795        char *pixmap_name;
5796
5797        menu = g_new0(Menu, 1);
5798
5799        menu->custom_icon = custom_icon;
5800        if ( ! string_empty (custom_icon_file))
5801                menu->custom_icon_file = g_strdup (custom_icon_file);
5802        else
5803                menu->custom_icon_file = NULL;
5804
5805        if (menu->custom_icon &&
5806            menu->custom_icon_file != NULL &&
5807            panel_file_exists (menu->custom_icon_file))
5808                pixmap_name = g_strdup (menu->custom_icon_file);
5809        else
5810                pixmap_name = get_pixmap (menudir, main_menu);
5811
5812        menu->main_menu_flags = main_menu_flags;
5813        menu->global_main = global_main;
5814
5815        /*make the pixmap*/
5816        menu->button = button_widget_new (pixmap_name, -1, MENU_TILE,
5817                                          TRUE, orient, _("Menu"));
5818
5819        /*A hack since this function only pretends to work on window
5820          widgets (which we actually kind of are) this will select
5821          some (already selected) events on the panel instead of
5822          the button window (where they are also selected) but
5823          we don't mind*/
5824        GTK_WIDGET_UNSET_FLAGS (menu->button, GTK_NO_WINDOW);
5825        gtk_drag_source_set (menu->button,
5826                             GDK_BUTTON1_MASK,
5827                             dnd_targets, 1,
5828                             GDK_ACTION_MOVE);
5829        GTK_WIDGET_SET_FLAGS (menu->button, GTK_NO_WINDOW);
5830
5831        if (main_menu)
5832                gtk_tooltips_set_tip (panel_tooltips, menu->button,
5833                                      _("Main Menu"), NULL);
5834        else
5835                /* FIXME: A more descriptive name would be better */
5836                gtk_tooltips_set_tip (panel_tooltips, menu->button,
5837                                      _("Menu"), NULL);
5838
5839        gtk_signal_connect (GTK_OBJECT (menu->button), "drag_data_get",
5840                            GTK_SIGNAL_FUNC (drag_data_get_cb),
5841                            NULL);
5842
5843        gtk_signal_connect_after (GTK_OBJECT (menu->button), "pressed",
5844                                  GTK_SIGNAL_FUNC (menu_button_pressed), menu);
5845        gtk_signal_connect (GTK_OBJECT (menu->button), "destroy",
5846                            GTK_SIGNAL_FUNC (destroy_menu), menu);
5847        gtk_widget_show(menu->button);
5848
5849        /*if we are allowed to be pigs and load all the menus to increase
5850          speed, load them*/
5851        if(global_config.hungry_menus) {
5852                GSList *list = g_slist_append(NULL, (gpointer)menudir);
5853                add_menu_widget(menu, panel, list, main_menu, TRUE);
5854                g_slist_free(list);
5855        }
5856
5857        g_free (pixmap_name);
5858
5859        return menu;
5860}
5861
5862static Menu *
5863create_menu_applet(PanelWidget *panel, const char *arguments,
5864                   PanelOrientType orient, int main_menu_flags,
5865                   gboolean global_main,
5866                   gboolean custom_icon, const char *custom_icon_file)
5867{
5868        Menu *menu;
5869        gboolean main_menu;
5870
5871        char *this_menu = get_real_menu_path(arguments);
5872
5873        if (this_menu == NULL)
5874                return NULL;
5875
5876        if(gnome_folder == NULL)
5877                gnome_folder = gnome_pixmap_file("gnome-folder.png");
5878
5879        main_menu = (string_empty (arguments) ||
5880                     (strcmp (arguments, ".") == 0));
5881
5882        menu = create_panel_menu (panel, this_menu, main_menu,
5883                                  orient, main_menu_flags, global_main,
5884                                  custom_icon, custom_icon_file);
5885        if (arguments && *arguments)
5886                menu->path = g_strdup(arguments);
5887        else
5888                menu->path = g_strdup(".");
5889
5890        gtk_object_set_user_data(GTK_OBJECT(menu->button), menu);
5891
5892        g_free (this_menu);
5893        return menu;
5894}
5895
5896void
5897set_menu_applet_orient(Menu *menu, PanelOrientType orient)
5898{
5899        g_return_if_fail(menu!=NULL);
5900
5901        button_widget_set_params(BUTTON_WIDGET(menu->button),
5902                                 MENU_TILE, TRUE, orient);
5903}
5904
5905void
5906load_menu_applet(const char *params, int main_menu_flags, gboolean global_main,
5907                 gboolean custom_icon, const char *custom_icon_file,
5908                 PanelWidget *panel, int pos, gboolean exactpos)
5909{
5910        Menu *menu;
5911
5912        menu = create_menu_applet(panel, params, ORIENT_UP,
5913                                  main_menu_flags, global_main,
5914                                  custom_icon, custom_icon_file);
5915
5916        if(menu != NULL) {
5917                char *tmp;
5918
5919                if(!register_toy(menu->button,
5920                                 menu, free_menu,
5921                                 panel, pos, exactpos, APPLET_MENU))
5922                        return;
5923
5924                menu->info = applets_last->data;
5925
5926                if ( ! commie_mode) {
5927                        applet_add_callback(menu->info, "properties",
5928                                            GNOME_STOCK_MENU_PROP,
5929                                            _("Properties..."));
5930                        if(params && strcmp(params, ".")==0 &&
5931                           (tmp = panel_is_program_in_path("gmenu")))  {
5932                                g_free(tmp);
5933                                applet_add_callback(menu->info, "edit_menus",
5934                                                    NULL, _("Edit menus..."));
5935                        }
5936                }
5937                applet_add_callback(applets_last->data, "help",
5938                                    GNOME_STOCK_PIXMAP_HELP,
5939                                    _("Help"));
5940        }
5941}
5942
5943void
5944save_tornoff (void)
5945{
5946        GSList *li;
5947        int i;
5948
5949        gnome_config_push_prefix (PANEL_CONFIG_PATH "panel/Config/");
5950
5951        gnome_config_set_int("tearoffs_count",g_slist_length(tearoffs));
5952
5953        gnome_config_pop_prefix ();
5954
5955        for(i = 0, li = tearoffs;
5956            li != NULL;
5957            i++, li = li->next) {
5958                TearoffMenu *tm = li->data;
5959                int x = 0, y = 0;
5960                GtkWidget *tw;
5961                int menu_panel = 0;
5962                int menu_panel_id = 0;
5963                PanelWidget *menu_panel_widget = NULL;
5964                GSList *l;
5965                char *s;
5966                int j;
5967
5968                s = g_strdup_printf ("%spanel/TornoffMenu_%d/",
5969                                     PANEL_CONFIG_PATH, i);
5970                gnome_config_push_prefix (s);
5971                g_free (s);
5972
5973                tw = GTK_MENU(tm->menu)->tearoff_window;
5974
5975                if (tw != NULL &&
5976                    tw->window != NULL) {
5977                        gdk_window_get_root_origin (tw->window, &x, &y);
5978                        /* unfortunately we must do this or set_uposition
5979                           will crap out */
5980                        if (x < 0)
5981                                x = 0;
5982                        if (y < 0)
5983                                y = 0;
5984                }
5985
5986                gnome_config_set_string ("title", tm->title);
5987                gnome_config_set_string ("wmclass", tm->wmclass);
5988                gnome_config_set_int ("x", x);
5989                gnome_config_set_int ("y", y);
5990
5991                menu_panel_widget = gtk_object_get_data(GTK_OBJECT(tm->menu),
5992                                                        "menu_panel");
5993                menu_panel = g_slist_index(panels, menu_panel_widget);
5994                if(menu_panel < 0)
5995                        menu_panel = 0;
5996                if (menu_panel_widget != NULL)
5997                        menu_panel_id = menu_panel_widget->unique_id;
5998
5999                gnome_config_set_int("menu_panel", menu_panel);
6000                gnome_config_set_int("menu_unique_panel_id", menu_panel_id);
6001
6002                gnome_config_set_int("workspace",
6003                                     gnome_win_hints_get_workspace(tw));
6004                gnome_config_set_int("hints",
6005                                     gnome_win_hints_get_hints(tw));
6006                gnome_config_set_int("state",
6007                                     gnome_win_hints_get_state(tw));
6008
6009                gnome_config_set_string("special",
6010                                        sure_string (tm->special));
6011
6012                gnome_config_set_int("mfl_count", g_slist_length(tm->mfl));
6013
6014                for(j=0,l=tm->mfl;l;j++,l=l->next) {
6015                        MenuFinfo *mf = l->data;
6016                        char name[256];
6017                        g_snprintf(name, sizeof (name), "name_%d", j);
6018                        gnome_config_set_string(name, mf->menudir);
6019                        g_snprintf(name, sizeof (name), "dir_name_%d", j);
6020                        gnome_config_set_string(name, mf->dir_name);
6021                        g_snprintf(name, sizeof (name), "pixmap_name_%d", j);
6022                        gnome_config_set_string(name, mf->pixmap_name);
6023                        g_snprintf(name, sizeof (name), "applets_%d", j);
6024                        gnome_config_set_bool(name, mf->applets);
6025                        g_snprintf(name, sizeof (name), "launcher_add_%d", j);
6026                        gnome_config_set_bool(name, mf->launcher_add);
6027                        g_snprintf(name, sizeof (name), "favourites_add_%d", j);
6028                        gnome_config_set_bool(name, mf->favourites_add);
6029                }
6030
6031                gnome_config_pop_prefix();
6032        }
6033}
6034
6035static GtkWidget *
6036create_special_menu(char *special, PanelWidget *menu_panel_widget)
6037{
6038        GtkWidget *menu = NULL;
6039
6040        if(strcmp(special, "ADD_PANEL")==0) {
6041                menu = create_add_panel_submenu(FALSE);
6042        } else if(strncmp(special, "PANEL", strlen("PANEL"))==0) {
6043                int flags;
6044                if(sscanf(special, "PANEL:%d", &flags) != 1)
6045                        flags = global_config.menu_flags;
6046                menu = create_root_menu (NULL, TRUE, flags, FALSE,
6047                                         IS_BASEP_WIDGET (menu_panel_widget->panel_parent),
6048                                         TRUE);
6049        } else if(strcmp(special, "DESKTOP")==0) {
6050                menu = create_desktop_menu (NULL, TRUE, FALSE);
6051        } else if(strcmp(special, "ADD_TO_PANEL")==0) {
6052                menu = menu_new();
6053                make_add_submenu(menu, TRUE);
6054        } else if(strcmp(special, "PANEL_SUBMENU")==0) {
6055                menu = create_panel_submenu (
6056                        NULL, TRUE, FALSE,
6057                        IS_BASEP_WIDGET (menu_panel_widget->panel_parent));
6058
6059        }
6060
6061        return menu;
6062}
6063
6064static void
6065load_tearoff_menu(void)
6066{
6067        GtkWidget *menu;
6068        char *title, *wmclass, *special;
6069        int x, y, i;
6070        int workspace, hints, state;
6071        int mfl_count;
6072        TearoffMenu *tm;
6073        gulong wmclass_num;
6074        PanelWidget *menu_panel_widget = NULL;
6075
6076        if ( ! conditional_true ("Conditional"))
6077                return;
6078
6079        title = conditional_get_string ("title", NULL, NULL);
6080        wmclass = conditional_get_string ("wmclass", NULL, NULL);
6081
6082        if(string_empty (title) ||
6083           string_empty (wmclass)) {
6084                g_free(title);
6085                g_free(wmclass);
6086                return;
6087        }
6088
6089        x = conditional_get_int ("x", 0, NULL);
6090        y = conditional_get_int ("y", 0, NULL);
6091        workspace = conditional_get_int ("workspace", 0, NULL);
6092        hints = conditional_get_int ("hints", 0, NULL);
6093        state = conditional_get_int ("state", 0, NULL);
6094
6095        i = conditional_get_int("menu_panel_id", -1, NULL);
6096        if (i < 0) {
6097                i = conditional_get_int("menu_panel", 0, NULL);
6098                if (i < 0)
6099                        i = 0;
6100                menu_panel_widget = g_slist_nth_data(panels, i);
6101        } else {
6102                menu_panel_widget = panel_widget_get_by_id (i);
6103        }
6104        if (menu_panel_widget == NULL)
6105                menu_panel_widget = panels->data;
6106        if ( ! IS_PANEL_WIDGET(menu_panel_widget))
6107                g_warning("panels list is on crack");
6108
6109        mfl_count = conditional_get_int("mfl_count", 0, NULL);
6110
6111        special = conditional_get_string("special", NULL, NULL);
6112        if (string_empty (special)) {
6113                g_free (special);
6114                special = NULL;
6115        }
6116
6117        /* find out the wmclass_number that was used
6118           for this wmclass and make our default one 1 higher
6119           so that we will always get unique wmclasses */
6120        wmclass_num = 0;
6121        sscanf (wmclass, "panel_tearoff_%lu", &wmclass_num);
6122        if (wmclass_num >= wmclass_number)
6123                wmclass_number = wmclass_num+1;
6124
6125        menu = NULL;
6126
6127        if (special != NULL) {
6128                menu = create_special_menu (special, menu_panel_widget);
6129        } else {
6130                for(i = 0; i < mfl_count; i++) {
6131                        char propname[256];
6132                        char *name;
6133                        gboolean applets;
6134                        gboolean launcher_add;
6135                        gboolean favourites_add;
6136                        char *dir_name;
6137                        char *pixmap_name;
6138
6139                        g_snprintf (propname, sizeof (propname), "name_%d", i);
6140                        name = conditional_get_string(propname, NULL, NULL);
6141                        g_snprintf (propname, sizeof (propname),
6142                                    "applets_%d", i);
6143                        applets = conditional_get_bool(propname, FALSE, NULL);
6144                        g_snprintf (propname, sizeof (propname),
6145                                    "launcher_add_%d", i);
6146                        launcher_add = conditional_get_bool(propname, FALSE, NULL);
6147                        g_snprintf (propname, sizeof (propname),
6148                                    "favourites_add_%d", i);
6149                        favourites_add = conditional_get_bool(propname, FALSE, NULL);
6150                        g_snprintf (propname, sizeof (propname),
6151                                    "dir_name_%d", i);
6152                        dir_name = conditional_get_string(propname, NULL, NULL);
6153                        g_snprintf (propname, sizeof (propname),
6154                                    "pixmap_name_%d", i);
6155                        pixmap_name = conditional_get_string(propname, NULL, NULL);
6156
6157                        if(!menu) {
6158                                menu = menu_new ();
6159                        }
6160
6161                        menu = create_menu_at (menu, name,
6162                                               applets,
6163                                               launcher_add,
6164                                               favourites_add,
6165                                               dir_name,
6166                                               pixmap_name, TRUE, FALSE, TRUE);
6167
6168                        g_free(name);
6169                        g_free(dir_name);
6170                        g_free(pixmap_name);
6171                }
6172
6173                if(menu != NULL&&
6174                   gtk_object_get_data (GTK_OBJECT (menu), "mf") == NULL) {
6175                        gtk_widget_unref (menu);
6176                        menu = NULL;
6177                }
6178        }
6179
6180        if (menu == NULL) {
6181                g_free (special);
6182                g_free (title);
6183                g_free (wmclass);
6184                return;
6185        }
6186
6187        /*set the panel to use as the data, or we will use current_panel*/
6188        gtk_object_set_data(GTK_OBJECT(menu), "menu_panel",
6189                            menu_panel_widget);
6190        gtk_signal_connect_object_while_alive(
6191              GTK_OBJECT(menu_panel_widget),
6192              "destroy", GTK_SIGNAL_FUNC(gtk_widget_unref),
6193              GTK_OBJECT(menu));
6194       
6195        /* This is so that we get size of the menu right */
6196        show_tearoff_menu (menu, title, FALSE, x, y, wmclass);
6197
6198        {
6199                GtkWidget *window = GTK_MENU(menu)->tearoff_window;
6200                gnome_win_hints_set_workspace(window,workspace);
6201                gnome_win_hints_set_hints(window,hints);
6202                gnome_win_hints_set_state(window,state);
6203        }
6204
6205        tm = g_new0(TearoffMenu,1);
6206        tm->menu = menu;
6207        tm->mfl = gtk_object_get_data(GTK_OBJECT(menu), "mf");
6208        tm->title = title;
6209        tm->special = special;
6210        tm->wmclass = wmclass;
6211        gtk_signal_connect(GTK_OBJECT(menu), "destroy",
6212                           GTK_SIGNAL_FUNC(tearoff_destroyed), tm);
6213
6214        tearoffs = g_slist_prepend(tearoffs,tm);
6215}
6216
6217void
6218load_tornoff(void)
6219{
6220        char *s;
6221        int i, length;
6222
6223        push_correct_global_prefix ();
6224        length = conditional_get_int("tearoffs_count", 0, NULL);
6225        gnome_config_pop_prefix();
6226
6227        for (i = 0; i < length; i++) {
6228                char *prefix;
6229                const char *sep;
6230
6231                prefix = get_correct_prefix (&sep);
6232                s = g_strdup_printf ("%spanel%s/TornoffMenu_%d/",
6233                                     prefix, sep, i);
6234                g_free (prefix);
6235                gnome_config_push_prefix (s);
6236                g_free (s);
6237
6238                load_tearoff_menu ();
6239
6240                gnome_config_pop_prefix ();
6241        }
6242}
6243
6244static void
6245menu_allocated (GtkWidget *menu, GtkAllocation *alloc)
6246{
6247        int screen = 0;
6248        PanelWidget *cur_panel = get_panel_from_menu_data (menu, FALSE);
6249        int x, y;
6250        GtkWidget *menutop;
6251
6252        menutop = GTK_MENU_SHELL (menu)->active ?
6253                GTK_MENU (menu)->toplevel : GTK_MENU (menu)->tearoff_window;
6254
6255        if (cur_panel == NULL) {
6256                screen = multiscreen_screen_from_pos (menutop->allocation.x,
6257                                                      menutop->allocation.y);
6258                if (screen < 0)
6259                        screen = multiscreen_screen_from_pos
6260                                (menutop->allocation.x +
6261                                   menutop->allocation.width,
6262                                 menutop->allocation.y);
6263                if (screen < 0)
6264                        screen = multiscreen_screen_from_pos
6265                                (menutop->allocation.x +
6266                                   menutop->allocation.width,
6267                                 menutop->allocation.y +
6268                                   menutop->allocation.height);
6269                if (screen < 0)
6270                        screen = multiscreen_screen_from_pos
6271                                (menutop->allocation.x,
6272                                 menutop->allocation.y +
6273                                   menutop->allocation.height);
6274                if (screen < 0)
6275                        screen = 0;
6276        } else if (IS_BASEP_WIDGET (cur_panel->panel_parent)) {
6277                screen = BASEP_WIDGET (cur_panel->panel_parent)->screen;
6278        } else if (IS_FOOBAR_WIDGET (cur_panel->panel_parent)) {
6279                screen = FOOBAR_WIDGET (cur_panel->panel_parent)->screen;
6280        }
6281
6282        scroll_menu_set_screen_size (SCROLL_MENU (menu),
6283                                     multiscreen_y (screen),
6284                                     multiscreen_y (screen) +
6285                                        multiscreen_height (screen));
6286
6287        x = menutop->allocation.x;
6288        y = menutop->allocation.y;
6289
6290        if (x + menutop->allocation.width >
6291            multiscreen_x (screen) + multiscreen_width (screen))
6292                x = multiscreen_x (screen) + multiscreen_width (screen) -
6293                        menutop->allocation.width;
6294        if (y + menutop->allocation.height >
6295            multiscreen_y (screen) + multiscreen_height (screen))
6296                y = multiscreen_y (screen) + multiscreen_height (screen) -
6297                        menutop->allocation.height;
6298
6299        if (x < multiscreen_x (screen))
6300                x = multiscreen_x (screen);
6301        if (y < multiscreen_y (screen))
6302                y = multiscreen_y (screen);
6303
6304        if (x != menutop->allocation.x ||
6305            y != menutop->allocation.y) {
6306                gtk_widget_set_uposition (menutop, x, y);
6307        }
6308}
6309
6310
6311/* Why the hell do we have a "hack", when we have scroll-menu in
6312 * our own codebase?  Well cuz I don't want to require panel code in
6313 * scroll-menu, since people copy it around */
6314GtkWidget *
6315hack_scroll_menu_new (void)
6316{
6317        GtkWidget *menu = scroll_menu_new ();
6318
6319        gtk_signal_connect_after (GTK_OBJECT (menu), "size_allocate",
6320                                  GTK_SIGNAL_FUNC (menu_allocated),
6321                                  NULL);
6322
6323        return menu;
6324}
Note: See TracBrowser for help on using the repository browser.