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

Revision 17167, 43.7 KB checked in by ghudson, 23 years ago (diff)
Merge with gnome-core 1.4.0.6.
Line 
1/* Gnome panel: Initialization routines
2 * (C) 1997,1998,1999,2000 the Free Software Foundation
3 * (C) 2000 Eazel, Inc.
4 *
5 * Authors: Federico Mena
6 *          Miguel de Icaza
7 *          George Lebl
8 */
9
10#include <config.h>
11#include <string.h>
12#include <signal.h>
13#include <unistd.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <sys/wait.h>
17#include <gnome.h>
18
19#include "panel-include.h"
20#include "gnome-run.h"
21#include "gnome-panel.h"
22
23/* nautilus uses this UTTER HACK to reset backgrounds, ugly ugly ugly,
24 * broken, ugly ugly, but whatever */
25#define RESET_IMAGE_NAME "/nautilus/backgrounds/reset.png"
26
27#define PANEL_EVENT_MASK (GDK_BUTTON_PRESS_MASK |               \
28                           GDK_BUTTON_RELEASE_MASK |            \
29                           GDK_POINTER_MOTION_MASK |            \
30                           GDK_POINTER_MOTION_HINT_MASK)
31
32/*list of all panel widgets created*/
33GSList *panel_list = NULL;
34
35static gboolean panel_dragged = FALSE;
36static int panel_dragged_timeout = -1;
37static gboolean panel_been_moved = FALSE;
38
39/*the number of base panels (corner/snapped) out there, never let it
40  go below 1*/
41int base_panels = 0;
42
43extern GSList *applets;
44extern GSList *applets_last;
45
46extern int config_sync_timeout;
47extern int applets_to_sync;
48extern int panels_to_sync;
49extern int need_complete_save;
50
51extern gboolean commie_mode;
52extern GlobalConfig global_config;
53
54extern GtkTooltips *panel_tooltips;
55
56extern char *kde_menudir;
57extern char *kde_icondir;
58extern char *kde_mini_icondir;
59
60
61/*the types of stuff we accept*/
62
63enum {
64        TARGET_URL,
65        TARGET_NETSCAPE_URL,
66        TARGET_DIRECTORY,
67        TARGET_COLOR,
68        TARGET_APPLET,
69        TARGET_APPLET_INTERNAL,
70        TARGET_ICON_INTERNAL,
71        TARGET_BGIMAGE
72};
73
74static GtkTargetEntry panel_drop_types[] = {
75        { "text/uri-list",       0, TARGET_URL },
76        { "x-url/http",          0, TARGET_NETSCAPE_URL },
77        { "x-url/ftp",           0, TARGET_NETSCAPE_URL },
78        { "_NETSCAPE_URL",       0, TARGET_NETSCAPE_URL },
79        { "application/x-panel-directory", 0, TARGET_DIRECTORY },
80        { "application/x-panel-applet", 0, TARGET_APPLET },
81        { "application/x-panel-applet-internal", 0, TARGET_APPLET_INTERNAL },
82        { "application/x-panel-icon-internal", 0, TARGET_ICON_INTERNAL },
83        { "application/x-color", 0, TARGET_COLOR },
84        { "property/bgimage",    0, TARGET_BGIMAGE }
85};
86
87static gint n_panel_drop_types =
88   sizeof(panel_drop_types) / sizeof(panel_drop_types[0]);
89
90static GtkTargetList *panel_target_list = NULL;
91
92
93static void
94change_window_cursor(GdkWindow *window, GdkCursorType cursor_type)
95{
96        GdkCursor *cursor = gdk_cursor_new(cursor_type);
97        gdk_window_set_cursor(window, cursor);
98        gdk_cursor_destroy(cursor);
99}
100
101static void
102panel_realize (GtkWidget *widget, gpointer data)
103{
104        change_window_cursor (widget->window, GDK_LEFT_PTR);
105       
106        if (IS_BASEP_WIDGET (widget))
107                basep_widget_enable_buttons(BASEP_WIDGET(widget));
108        else if (IS_FOOBAR_WIDGET (widget))
109                foobar_widget_update_winhints (FOOBAR_WIDGET(widget));
110
111        /*FIXME: this seems to fix the panel size problems on startup
112          (from a report) but I don't think it's right*/
113        gtk_widget_queue_resize (GTK_WIDGET (widget));
114}
115
116void
117freeze_changes (AppletInfo *info)
118{
119        if(info->type == APPLET_EXTERN) {
120                Extern *ext = info->data;
121                g_assert (ext != NULL);
122                /*ingore this until we get an ior*/
123                if (ext->applet != CORBA_OBJECT_NIL) {
124                        CORBA_Environment ev;
125                        CORBA_exception_init(&ev);
126                        GNOME_Applet_freeze_changes(ext->applet, &ev);
127                        if(ev._major) {
128                                extern_ref (ext);
129                                panel_clean_applet(info);
130                                ext->info = NULL;
131                                extern_unref (ext);
132                        }
133                        CORBA_exception_free(&ev);
134                }
135        }
136}
137
138void
139thaw_changes(AppletInfo *info)
140{
141        if(info->type == APPLET_EXTERN) {
142                Extern *ext = info->data;
143                g_assert (ext != NULL);
144                /*ingore this until we get an ior*/
145                if (ext->applet != CORBA_OBJECT_NIL) {
146                        CORBA_Environment ev;
147                        CORBA_exception_init (&ev);
148                        GNOME_Applet_thaw_changes (ext->applet, &ev);
149                        if(ev._major) {
150                                extern_ref (ext);
151                                panel_clean_applet (info);
152                                ext->info = NULL;
153                                extern_unref (ext);
154                        }
155                        CORBA_exception_free (&ev);
156                }
157        }
158}
159
160static void
161freeze_changes_foreach(GtkWidget *w, gpointer data)
162{
163        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
164        freeze_changes(info);
165}
166
167void
168panel_freeze_changes(PanelWidget *panel)
169{
170        gtk_container_foreach(GTK_CONTAINER(panel),
171                              freeze_changes_foreach, NULL);
172}
173
174static void
175thaw_changes_foreach(GtkWidget *w, gpointer data)
176{
177        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
178        thaw_changes(info);
179}
180
181void
182panel_thaw_changes(PanelWidget *panel)
183{
184        gtk_container_foreach(GTK_CONTAINER(panel),
185                              thaw_changes_foreach, NULL);
186}
187
188PanelOrientType
189get_applet_orient (PanelWidget *panel)
190{
191        GtkWidget *panelw;
192        g_return_val_if_fail(panel,ORIENT_UP);
193        g_return_val_if_fail(IS_PANEL_WIDGET(panel),ORIENT_UP);
194        g_return_val_if_fail(panel->panel_parent,ORIENT_UP);
195        panelw = panel->panel_parent;
196
197        if (IS_BASEP_WIDGET(panelw))
198                return basep_widget_get_applet_orient (BASEP_WIDGET(panelw));
199        else
200                return ORIENT_DOWN;
201}
202
203/*we call this recursively*/
204static void orient_change_foreach(GtkWidget *w, gpointer data);
205
206void
207orientation_change(AppletInfo *info, PanelWidget *panel)
208{
209        if(info->type == APPLET_EXTERN) {
210                Extern *ext = info->data;
211                int orient = get_applet_orient(panel);
212                g_assert(ext);
213                /*ingore this until we get an ior*/
214                if(ext->applet && ext->orient != orient) {
215                        CORBA_Environment ev;
216
217                        CORBA_exception_init(&ev);
218                        GNOME_Applet_change_orient(ext->applet,
219                                                   orient,
220                                                   &ev);
221                        if(ev._major) {
222                                extern_ref (ext);
223                                panel_clean_applet(info);
224                                ext->info = NULL;
225                                extern_unref (ext);
226                        }
227                        CORBA_exception_free(&ev);
228
229                        /* we have now sent this orientation thus we
230                           save it and don't send it again unless it
231                           changes */
232                        ext->orient = orient;
233
234                }
235        } else if(info->type == APPLET_MENU) {
236                Menu *menu = info->data;
237                set_menu_applet_orient(menu,get_applet_orient(panel));
238        } else if(info->type == APPLET_DRAWER) {
239                Drawer *drawer = info->data;
240                BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
241                set_drawer_applet_orient(drawer, get_applet_orient(panel));
242                gtk_widget_queue_resize(drawer->drawer);
243                gtk_container_foreach(GTK_CONTAINER(basep->panel),
244                                      orient_change_foreach,
245                                      (gpointer)basep->panel);
246        } else if(info->type == APPLET_SWALLOW) {
247                Swallow *swallow = info->data;
248
249                if(panel->orient == PANEL_VERTICAL)
250                        set_swallow_applet_orient(swallow,SWALLOW_VERTICAL);
251                else
252                        set_swallow_applet_orient(swallow,SWALLOW_HORIZONTAL);
253        } else if(info->type == APPLET_STATUS) {
254                StatusApplet *status = info->data;
255                if(status->orient != panel->orient) {
256                        status->orient = panel->orient;
257                        status_applet_update(status);
258                }
259        }
260}
261
262static void
263orient_change_foreach(GtkWidget *w, gpointer data)
264{
265        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
266        PanelWidget *panel = data;
267       
268        orientation_change(info,panel);
269}
270
271
272static void
273panel_orient_change(GtkWidget *widget,
274                    PanelOrientation orient,
275                    gpointer data)
276{
277        gtk_container_foreach(GTK_CONTAINER(widget),
278                              orient_change_foreach,
279                              widget);
280
281        if (IS_FLOATING_WIDGET (PANEL_WIDGET (widget)->panel_parent))
282                update_config_floating_orient (FLOATING_WIDGET (PANEL_WIDGET (widget)->panel_parent));
283
284        panels_to_sync = TRUE;
285}
286
287static void
288border_edge_change (BorderPos *border,
289                    BorderEdge edge,
290                    gpointer data)
291{
292        BasePWidget *basep = BASEP_WIDGET (data);
293        PanelWidget *panel = PANEL_WIDGET (basep->panel);
294        gtk_container_foreach (GTK_CONTAINER (panel),
295                               orient_change_foreach,
296                               panel);
297        panels_to_sync = TRUE;
298        update_config_edge (basep);
299}
300
301/*we call this recursively*/
302static void size_change_foreach(GtkWidget *w, gpointer data);
303
304void
305size_change(AppletInfo *info, PanelWidget *panel)
306{
307        if(info->type == APPLET_EXTERN) {
308                Extern *ext = info->data;
309                g_assert(ext);
310                /*ingore this until we get an ior*/
311                if(ext->applet) {
312                        CORBA_Environment ev;
313                        CORBA_exception_init(&ev);
314                        GNOME_Applet_change_size(ext->applet,
315                                                 panel->sz,
316                                                 &ev);
317                        if(ev._major) {
318                                extern_ref (ext);
319                                panel_clean_applet(info);
320                                ext->info = NULL;
321                                extern_unref (ext);
322                        }
323                        CORBA_exception_free(&ev);
324                }
325        } else if(info->type == APPLET_STATUS) {
326                StatusApplet *status = info->data;
327                status->size = panel->sz;
328                status_applet_update(status);
329        }
330}
331
332static void
333size_change_foreach(GtkWidget *w, gpointer data)
334{
335        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
336        PanelWidget *panel = data;
337       
338        size_change(info,panel);
339}
340
341
342static void
343panel_size_change(GtkWidget *widget,
344                  int sz,
345                  gpointer data)
346{
347        gtk_container_foreach(GTK_CONTAINER(widget), size_change_foreach,
348                              widget);
349        panels_to_sync = TRUE;
350        /*update the configuration box if it is displayed*/
351        update_config_size (PANEL_WIDGET (widget)->panel_parent);
352}
353
354void
355back_change (AppletInfo *info, PanelWidget *panel)
356{
357        if(info->type == APPLET_EXTERN) {
358                Extern *ext = info->data;
359                g_assert(ext);
360                /*ignore until we have a valid IOR*/
361                if(ext->applet) {
362                        GNOME_Panel_BackInfoType backing;
363                        CORBA_Environment ev;
364                        CORBA_exception_init(&ev);
365                        backing._d = panel->back_type;
366                        if(panel->back_type == PANEL_BACK_PIXMAP) {
367                                backing._u.pmap = panel->back_pixmap;
368                        } else if(panel->back_type == PANEL_BACK_COLOR) {
369                                backing._u.c.red = panel->back_color.red;
370                                backing._u.c.green = panel->back_color.green;
371                                backing._u.c.blue = panel->back_color.blue;
372                        }
373                        GNOME_Applet_back_change(ext->applet, &backing, &ev);
374                        if (ev._major) {
375                                extern_ref (ext);
376                                panel_clean_applet (info);
377                                ext->info = NULL;
378                                extern_unref (ext);
379                        }
380                        CORBA_exception_free(&ev);
381                }
382        }
383}
384
385
386static void
387back_change_foreach(GtkWidget *w, gpointer data)
388{
389        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
390        PanelWidget *panel = data;
391
392        back_change(info,panel);
393}
394
395static void
396panel_back_change(GtkWidget *widget,
397                  PanelBackType type,
398                  char *pixmap,
399                  GdkColor *color)
400{
401        gtk_container_foreach(GTK_CONTAINER(widget),back_change_foreach,widget);
402
403        panels_to_sync = TRUE;
404        /*update the configuration box if it is displayed*/
405        update_config_back(PANEL_WIDGET(widget));
406}
407
408static void state_hide_foreach(GtkWidget *w, gpointer data);
409
410static void
411state_restore_foreach(GtkWidget *w, gpointer data)
412{
413        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
414       
415        if(info->type == APPLET_DRAWER) {
416                Drawer *drawer = info->data;
417                BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
418
419                DRAWER_POS (basep->pos)->temp_hidden = FALSE;
420                gtk_widget_queue_resize (GTK_WIDGET (basep));
421
422                gtk_container_foreach (GTK_CONTAINER (basep->panel),
423                                       (basep->state == BASEP_SHOWN)
424                                       ? state_restore_foreach
425                                       : state_hide_foreach,
426                                       NULL);
427        }
428}
429
430static void
431state_hide_foreach(GtkWidget *w, gpointer data)
432{
433        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
434        if(info->type == APPLET_DRAWER) {
435                Drawer *drawer = info->data;
436                BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
437                GtkWidget *widget = GTK_WIDGET(basep);
438
439                DRAWER_POS (basep->pos)->temp_hidden = TRUE;
440                gtk_container_foreach(GTK_CONTAINER(basep->panel),
441                                      state_hide_foreach,
442                                      NULL);
443
444                gtk_widget_queue_resize (widget);
445
446                /* quickly hide the window from sight, the allocation
447                   and all that will get updated in the main loop */
448                if(widget->window) {
449                        gdk_window_move(widget->window,
450                                        -widget->allocation.width - 1,
451                                        -widget->allocation.height - 1);
452                }
453        }
454}
455
456static void
457queue_resize_foreach(GtkWidget *w, gpointer data)
458{
459        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
460
461        if(info->type == APPLET_DRAWER) {
462                Drawer *drawer = info->data;
463                BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
464               
465                if(basep->state == BASEP_SHOWN) {
466                        gtk_widget_queue_resize(w);
467                        gtk_container_foreach(GTK_CONTAINER(basep->panel),
468                                               queue_resize_foreach,
469                                               NULL);
470                }
471        }
472}
473
474static void
475basep_state_change(BasePWidget *basep,
476                   BasePState state,
477                   gpointer data)
478{
479        gtk_container_foreach (GTK_CONTAINER (basep->panel),
480                               (state == BASEP_SHOWN)
481                               ? state_restore_foreach
482                               : state_hide_foreach,
483                               (gpointer)basep);
484}
485
486/*static void
487basep_type_change(BasePWidget *basep,
488                  PanelType type,
489                  gpointer data)
490{
491        update_config_type(basep);
492        panels_to_sync = TRUE;
493}*/
494
495static void
496panel_applet_added(GtkWidget *widget, GtkWidget *applet, gpointer data)
497{
498        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(applet),
499                                               "applet_info");
500        GtkWidget *panelw = PANEL_WIDGET(widget)->panel_parent;
501       
502        /*on a real add the info will be NULL as the only adding
503          is done in register_toy and that doesn't add the info to the
504          array until after the add, so we can be sure this was
505          generated on a reparent*/
506        if((IS_BASEP_WIDGET(panelw) &&
507            !IS_DRAWER_WIDGET(panelw)) &&
508           info && info->type == APPLET_DRAWER) {
509                Drawer *drawer = info->data;
510                BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
511                if(basep->state == BASEP_SHOWN ||
512                   basep->state == BASEP_AUTO_HIDDEN) {
513                        BASEP_WIDGET(panelw)->drawers_open++;
514                        basep_widget_autoshow(BASEP_WIDGET(panelw));
515                }
516        }
517       
518        /*pop the panel up on addition*/
519        if(IS_BASEP_WIDGET(panelw)) {
520                basep_widget_autoshow(BASEP_WIDGET(panelw));
521                /*try to pop down though if the mouse is out*/
522                basep_widget_queue_autohide(BASEP_WIDGET(panelw));
523        }
524
525        freeze_changes(info);
526        orientation_change(info,PANEL_WIDGET(widget));
527        size_change(info,PANEL_WIDGET(widget));
528        back_change(info,PANEL_WIDGET(widget));
529        thaw_changes(info);
530
531        /*we will need to save this applet's config now*/
532        applets_to_sync = TRUE;
533}
534
535static void
536panel_applet_removed(GtkWidget *widget, GtkWidget *applet, gpointer data)
537{
538        GtkWidget *parentw = PANEL_WIDGET(widget)->panel_parent;
539        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(applet),
540                                               "applet_info");
541
542        /*we will need to save this applet's config now*/
543        applets_to_sync = TRUE;
544
545        if(info->type == APPLET_DRAWER) {
546                Drawer *drawer = info->data;
547                if((drawer->drawer) && (
548                        (BASEP_WIDGET(drawer->drawer)->state == BASEP_SHOWN) ||
549                        (BASEP_WIDGET(drawer->drawer)->state == BASEP_AUTO_HIDDEN))) {
550                        if(IS_BASEP_WIDGET(parentw)) {
551                                BASEP_WIDGET(parentw)->drawers_open--;
552                                basep_widget_queue_autohide(BASEP_WIDGET(parentw));
553                        }
554                }
555                /*it was a drawer so we need to save panels as well*/
556                panels_to_sync = TRUE;
557        }
558}
559
560static void
561menu_deactivate(GtkWidget *w, PanelData *pd)
562{
563        pd->menu_age = 0;
564        if(IS_BASEP_WIDGET(pd->panel))
565                BASEP_WIDGET(pd->panel)->autohide_inhibit = FALSE;
566}
567
568static void
569move_panel_to_cursor(GtkWidget *w)
570{
571        int x,y;
572        gdk_window_get_pointer(NULL,&x,&y,NULL);
573        if(IS_BASEP_WIDGET(w))
574                basep_widget_set_pos(BASEP_WIDGET(w),x,y);
575}
576
577static gboolean
578panel_move_timeout(gpointer data)
579{
580        if(panel_dragged && panel_been_moved)
581                move_panel_to_cursor(data);
582       
583        panel_been_moved = FALSE;
584        panel_dragged_timeout = -1;
585
586        return FALSE;
587}
588
589static void
590clean_kill_applets (PanelWidget *panel)
591{
592        GList *li;
593        for (li = panel->applet_list; li != NULL; li = li->next) {
594                AppletData *ad = li->data;
595                AppletInfo *info =
596                        gtk_object_get_data (GTK_OBJECT (ad->applet),
597                                             "applet_info");
598                if (info->type == APPLET_EXTERN) {
599                        Extern *ext = info->data;
600                        extern_save_last_position (ext, FALSE /* sync */);
601                        ext->clean_remove = TRUE;
602                } else if (info->type == APPLET_SWALLOW) {
603                        Swallow *swallow = info->data;
604                        swallow->clean_remove = TRUE;
605                }
606        }
607        gnome_config_sync ();
608}
609
610static void
611panel_destroy (GtkWidget *widget, gpointer data)
612{
613        PanelData *pd = gtk_object_get_user_data (GTK_OBJECT (widget));
614        PanelWidget *panel = NULL;
615
616        if (IS_BASEP_WIDGET (widget))
617                panel = PANEL_WIDGET(BASEP_WIDGET(widget)->panel);
618        else if (IS_FOOBAR_WIDGET (widget))
619                panel = PANEL_WIDGET (FOOBAR_WIDGET (widget)->panel);
620
621        clean_kill_applets (panel);
622               
623        kill_config_dialog(widget);
624
625        if (IS_DRAWER_WIDGET(widget)) {
626                GtkWidget *master_widget = panel->master_widget;
627
628                if (master_widget != NULL) {
629                        AppletInfo *info =
630                                gtk_object_get_data(GTK_OBJECT(master_widget),
631                                                    "applet_info");
632                        Drawer *drawer = info->data;
633                        drawer->drawer = NULL;
634                        panel_clean_applet (info);
635                        gtk_object_remove_data (GTK_OBJECT (master_widget),
636                                                "applet_info");
637                }
638        } else if ((IS_BASEP_WIDGET(widget)
639                    && !IS_DRAWER_WIDGET(widget))
640                   || IS_FOOBAR_WIDGET (widget)) {
641                /*this is a base panel and we just lost it*/
642                base_panels--;
643        }
644
645        if (pd->menu != NULL)
646                gtk_widget_unref (pd->menu);
647        pd->menu = NULL;
648
649        pd->panel = NULL;
650
651        panel_list = g_slist_remove (panel_list, pd);
652        g_free (pd);
653}
654
655static void
656panel_applet_move(PanelWidget *panel, GtkWidget *widget, gpointer data)
657{
658        applets_to_sync = TRUE;
659}
660
661static void
662panel_applet_draw(GtkWidget *panel, GtkWidget *widget, gpointer data)
663{
664        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(widget),
665                                               "applet_info");
666
667        g_return_if_fail(info!=NULL);
668
669        if(info->type == APPLET_EXTERN)
670                extern_send_draw(info->data);
671}
672
673static void
674panel_applet_about_to_die (GtkWidget *panel, GtkWidget *widget, gpointer data)
675{
676        AppletInfo *info = gtk_object_get_data (GTK_OBJECT (widget),
677                                                "applet_info");
678
679        g_return_if_fail (info != NULL);
680
681        /* this needs to be befor we null the widget field */
682        if (info->type == APPLET_EXTERN &&
683            info->data != NULL) {
684                extern_before_remove (info->data);
685        }
686}
687
688static GtkWidget *
689panel_menu_get (PanelWidget *panel, PanelData *pd)
690{
691        if (pd->menu != NULL)
692                return pd->menu;
693       
694        pd->menu = create_panel_root_menu (panel, TRUE);
695        gtk_signal_connect (GTK_OBJECT (pd->menu), "deactivate",
696                            GTK_SIGNAL_FUNC (menu_deactivate), pd);
697        return pd->menu;
698}
699
700GtkWidget *
701make_popup_panel_menu (PanelWidget *panel)
702{
703        GtkWidget *panelw;
704        PanelData *pd;
705        GtkWidget *menu;
706
707        if (!panel) {
708                panelw = ((PanelData *)panel_list->data)->panel;
709                if (IS_BASEP_WIDGET (panelw))
710                        panel = PANEL_WIDGET (BASEP_WIDGET (panelw)->panel);
711                else if (IS_FOOBAR_WIDGET (panelw))
712                        panel = PANEL_WIDGET (FOOBAR_WIDGET (panelw)->panel);
713        } else
714                panelw = panel->panel_parent;
715
716        pd = gtk_object_get_user_data (GTK_OBJECT (panelw));
717        menu = panel_menu_get (panel, pd);
718        gtk_object_set_data (GTK_OBJECT (menu), "menu_panel", panel);
719
720        pd->menu_age = 0;
721        return menu;
722}
723
724static gboolean
725panel_initiate_move (GtkWidget *widget, guint32 event_time)
726{
727        PanelWidget *panel = NULL;
728        BasePWidget *basep = NULL;
729
730        if (IS_BASEP_WIDGET (widget)) {
731                basep = BASEP_WIDGET (widget);
732                panel = PANEL_WIDGET (basep->panel);
733        } else if (IS_FOOBAR_WIDGET (widget)) {
734                panel = PANEL_WIDGET (FOOBAR_WIDGET (widget)->panel);
735        }
736
737        /*this should probably be in snapped widget*/
738        if(!panel_dragged &&
739           !IS_DRAWER_WIDGET (widget) &&
740           !IS_FOOBAR_WIDGET (widget)) {
741                GdkCursor *cursor = gdk_cursor_new (GDK_FLEUR);
742                gtk_grab_add(widget);
743                gdk_pointer_grab (widget->window,
744                                  FALSE,
745                                  PANEL_EVENT_MASK,
746                                  NULL,
747                                  cursor,
748                                  event_time);
749                gdk_cursor_destroy (cursor);
750
751                if (basep) {
752                        basep->autohide_inhibit = TRUE;
753                        basep_widget_init_offsets (basep);
754                }
755
756                panel_dragged = TRUE;
757                return TRUE;
758        } if(IS_DRAWER_WIDGET(widget) &&
759             !panel_applet_in_drag) {
760                panel_widget_applet_drag_start (
761                                                PANEL_WIDGET(panel->master_widget->parent),
762                                                panel->master_widget,
763                                                PW_DRAG_OFF_CURSOR);
764                return TRUE;
765        }
766
767        return FALSE;
768}
769       
770static gboolean
771panel_event(GtkWidget *widget, GdkEvent *event, PanelData *pd)
772{
773        PanelWidget *panel = NULL;
774        BasePWidget *basep = NULL;
775        GdkEventButton *bevent;
776
777        if (IS_BASEP_WIDGET (widget)) {
778                basep = BASEP_WIDGET (widget);
779                panel = PANEL_WIDGET (basep->panel);
780        } else if (IS_FOOBAR_WIDGET (widget)) {
781                panel = PANEL_WIDGET (FOOBAR_WIDGET (widget)->panel);
782        }
783
784        switch (event->type) {
785        case GDK_BUTTON_PRESS:
786                bevent = (GdkEventButton *) event;
787                switch(bevent->button) {
788                case 3:
789                        if(!panel_applet_in_drag) {
790                                GtkWidget *menu;
791
792                                menu = make_popup_panel_menu (panel);
793                                if (basep) {
794                                        basep->autohide_inhibit = TRUE;
795                                        basep_widget_autohide (basep);
796                                }
797
798                                gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
799                                                panel_menu_position,
800                                                widget, bevent->button,
801                                                bevent->time);
802                                return TRUE;
803                        }
804                        break;
805                case 2:
806                        if ( ! commie_mode)
807                                return panel_initiate_move (widget,
808                                                            bevent->time);
809                        break;
810                default: break;
811                }
812                break;
813
814        case GDK_BUTTON_RELEASE:
815                bevent = (GdkEventButton *) event;
816                if(panel_dragged) {
817                        if (!basep)
818                                return TRUE;
819                        basep_widget_set_pos(basep,
820                                             (gint16)bevent->x_root,
821                                             (gint16)bevent->y_root);
822                        basep->autohide_inhibit = FALSE;
823                        basep_widget_queue_autohide(BASEP_WIDGET(widget));
824
825                        gdk_pointer_ungrab(bevent->time);
826                        gtk_grab_remove(widget);
827                        panel_dragged = FALSE;
828                        panel_dragged_timeout = -1;
829                        panel_been_moved = FALSE;
830                        return TRUE;
831                }
832
833                break;
834        case GDK_MOTION_NOTIFY:
835                if (panel_dragged) {
836                        if(panel_dragged_timeout==-1) {
837                                panel_been_moved = FALSE;
838                                move_panel_to_cursor(widget);
839                                panel_dragged_timeout = gtk_timeout_add (30,panel_move_timeout,widget);
840                        } else
841                                panel_been_moved = TRUE;
842                }
843                break;
844
845        default:
846                break;
847        }
848
849        return FALSE;
850}
851
852static gboolean
853panel_widget_event (GtkWidget *widget, GdkEvent *event, GtkWidget *panelw)
854{
855        if (event->type == GDK_BUTTON_PRESS) {
856                GdkEventButton *bevent = (GdkEventButton *) event;
857
858                if (bevent->button == 1 ||
859                    bevent->button == 2)
860                        return panel_initiate_move (panelw, bevent->time);
861        }
862
863        return FALSE;
864}
865
866static gboolean
867panel_sub_event_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
868{
869        GdkEventButton *bevent;
870        switch (event->type) {
871                /*pass these to the parent!*/
872                case GDK_BUTTON_PRESS:
873                case GDK_BUTTON_RELEASE:
874                case GDK_MOTION_NOTIFY:
875                        bevent = (GdkEventButton *) event;
876                        /*if the widget is a button we want to keep the
877                          button 1 events*/
878                        if(!GTK_IS_BUTTON(widget) || bevent->button!=1)
879                                return gtk_widget_event(data, event);
880
881                        break;
882
883                default:
884                        break;
885        }
886
887        return FALSE;
888}
889
890static gchar *
891extract_filename (const gchar* uri)
892{
893        /* file uri with a hostname */
894        if (strncmp (uri, "file://", strlen ("file://")) == 0) {
895                char *hostname = g_strdup (&uri[strlen("file://")]);
896                char *p = strchr (hostname, '/');
897                char *path;
898                char localhostname[1024];
899                /* if we can't find the '/' this uri is bad */
900                if(p == NULL) {
901                        g_free (hostname);
902                        return NULL;
903                }
904                /* if no hostname */
905                if(p == hostname)
906                        return hostname;
907
908                path = g_strdup (p);
909                *p = '\0';
910
911                /* if really local */
912                if (strcasecmp_no_locale (hostname, "localhost") == 0 ||
913                    strcasecmp_no_locale (hostname, "localhost.localdomain") == 0) {
914                        g_free (hostname);
915                        return path;
916                }
917
918                /* ok get the hostname */
919                if (gethostname (localhostname,
920                                 sizeof (localhostname)) < 0) {
921                        strcpy (localhostname, "");
922                }
923
924                /* if really local */
925                if (localhostname[0] &&
926                    strcasecmp_no_locale (hostname, localhostname) == 0) {
927                        g_free (hostname);
928                        return path;
929                }
930               
931                g_free (hostname);
932                g_free (path);
933                return NULL;
934
935        /* if the file doesn't have the //, we take it containing
936           a local path */
937        } else if (strncmp(uri, "file:", strlen("file:"))==0) {
938                const char *path = &uri[strlen("file:")];
939                /* if empty bad */
940                if(!*path) return NULL;
941                return g_strdup(path);
942        }
943        return NULL;
944}
945
946static void
947drop_url(PanelWidget *panel, int pos, const char *url)
948{
949        char *p;
950
951        g_return_if_fail (url != NULL);
952
953        p = g_strdup_printf (_("Open URL: %s"), url);
954        load_launcher_applet_from_info_url (url, p, url, "gnome-globe.png",
955                                            panel, pos, TRUE);
956        g_free (p);
957}
958
959static void
960drop_menu (PanelWidget *panel, int pos, const char *dir)
961{
962        int flags = MAIN_MENU_SYSTEM | MAIN_MENU_USER;
963        DistributionType distribution = get_distribution_type ();
964
965        /*guess distribution menus*/
966        if(distribution != DISTRIBUTION_UNKNOWN)
967                flags |= MAIN_MENU_DISTRIBUTION_SUB;
968        /* Guess KDE menus */
969        if(panel_file_exists(kde_menudir))
970                flags |= MAIN_MENU_KDE_SUB;
971        load_menu_applet (dir, flags, TRUE, FALSE, NULL, panel, pos, TRUE);
972}
973
974static void
975drop_directory (PanelWidget *panel, int pos, const char *dir)
976{
977        char *tmp;
978
979        tmp = g_concat_dir_and_file (dir, ".directory");
980        if (panel_file_exists (tmp)) {
981                g_free (tmp);
982                drop_menu (panel, pos, dir);
983                return;
984        }
985        g_free (tmp);
986
987        tmp = g_concat_dir_and_file (dir, ".order");
988        if (panel_file_exists (tmp)) {
989                g_free (tmp);
990                drop_menu (panel, pos, dir);
991                return;
992        }
993        g_free (tmp);
994
995        tmp = panel_is_program_in_path ("nautilus");
996        if (tmp != NULL) {
997                /* nautilus */
998                char *exec[] = { "nautilus", NULL, NULL };
999                exec[1] = (char *)dir;
1000
1001                g_free (tmp);
1002
1003                load_launcher_applet_from_info (g_basename (dir),
1004                                                dir,
1005                                                exec,
1006                                                2,
1007                                                "gnome-folder.png",
1008                                                panel,
1009                                                pos,
1010                                                TRUE);
1011        } else {
1012                tmp = panel_is_program_in_path ("gmc-client");
1013                if (tmp != NULL) {
1014                        /* gmc */
1015                        char *exec[] = {
1016                                "gmc-client",
1017                                "--create-directory",
1018                                NULL,
1019                                NULL };
1020                        exec[2] = (char *)dir;
1021
1022                        g_free (tmp);
1023
1024                        load_launcher_applet_from_info (g_basename (dir),
1025                                                        dir,
1026                                                        exec,
1027                                                        3,
1028                                                        "gnome-folder.png",
1029                                                        panel,
1030                                                        pos,
1031                                                        TRUE);
1032                } else {
1033                        drop_menu (panel, pos, dir);
1034                }
1035        }
1036}
1037
1038static void
1039drop_urilist (PanelWidget *panel, int pos, char *urilist,
1040              gboolean background_drops)
1041{
1042        GList *li, *files;
1043        struct stat s;
1044
1045        files = gnome_uri_list_extract_uris(urilist);
1046
1047        for(li = files; li; li = li->next) {
1048                char *uri;
1049                const char *mimetype;
1050                char *filename;
1051
1052                uri = li->data;
1053
1054                if (strncmp (uri, "http:", strlen ("http:")) == 0 ||
1055                    strncmp (uri, "https:", strlen ("https:")) == 0 ||
1056                    strncmp (uri, "ftp:", strlen ("ftp:")) == 0 ||
1057                    strncmp (uri, "gopher:", strlen ("gopher:")) == 0 ||
1058                    strncmp (uri, "ghelp:", strlen ("ghelp:")) == 0 ||
1059                    strncmp (uri, "man:", strlen ("man:")) == 0 ||
1060                    strncmp (uri, "info:", strlen ("info:")) == 0) {
1061                        drop_url (panel, pos, uri);
1062                        continue;
1063                }
1064
1065                filename = extract_filename (li->data);
1066                if(filename == NULL)
1067                        continue;
1068
1069                if(stat(filename, &s) != 0) {
1070                        g_free(filename);
1071                        continue;
1072                }
1073
1074                mimetype = gnome_mime_type(filename);
1075
1076                if (background_drops &&
1077                    mimetype != NULL &&
1078                    strncmp(mimetype, "image", sizeof("image")-1) == 0) {
1079                        panel_widget_set_back_pixmap (panel, filename);
1080                } else if (mimetype != NULL &&
1081                          (strcmp(mimetype, "application/x-gnome-app-info") == 0 ||
1082                           strcmp(mimetype, "application/x-kde-app-info") == 0)) {
1083                        Launcher *launcher;
1084
1085                        launcher = load_launcher_applet (filename, panel, pos, TRUE);
1086
1087                        if (launcher != NULL)
1088                                launcher_hoard (launcher);
1089                } else if (S_ISDIR(s.st_mode)) {
1090                        drop_directory (panel, pos, filename);
1091                } else if (S_IEXEC & s.st_mode) /*executable?*/
1092                        ask_about_launcher (filename, panel, pos, TRUE);
1093                g_free (filename);
1094        }
1095
1096        gnome_uri_list_free_strings (files);
1097}
1098
1099static void
1100drop_bgimage (PanelWidget *panel, const char *bgimage)
1101{
1102        char *filename;
1103
1104        filename = extract_filename (bgimage);
1105        if (filename != NULL) {
1106                /* an incredible hack, no, worse, INCREDIBLE FUCKING HACK,
1107                 * whatever, we need to work with nautilus on this one */
1108                if (strstr (filename, RESET_IMAGE_NAME) != NULL) {
1109                        panel_widget_change_params (panel,
1110                                                    panel->orient,
1111                                                    panel->sz,
1112                                                    PANEL_BACK_NONE,
1113                                                    panel->back_pixmap,
1114                                                    panel->fit_pixmap_bg,
1115                                                    panel->strech_pixmap_bg,
1116                                                    panel->rotate_pixmap_bg,
1117                                                    panel->no_padding_on_ends,
1118                                                    &panel->back_color);
1119                } else {
1120                        panel_widget_set_back_pixmap (panel, filename);
1121                }
1122
1123                g_free (filename);
1124        }
1125}
1126
1127static void
1128drop_internal_icon (PanelWidget *panel, int pos, const char *icon_name,
1129                    int action)
1130{
1131        Launcher *old_launcher, *launcher;
1132
1133        if (icon_name == NULL)
1134                return;
1135
1136        if (action == GDK_ACTION_MOVE) {
1137                old_launcher = find_launcher (icon_name);
1138        } else {
1139                old_launcher = NULL;
1140        }
1141
1142        launcher = load_launcher_applet (icon_name, panel, pos, TRUE);
1143
1144        if (launcher != NULL) {
1145                launcher_hoard (launcher);
1146
1147                if (old_launcher != NULL &&
1148                    old_launcher->button != NULL)
1149                        gtk_widget_destroy (old_launcher->button);
1150        }
1151}
1152
1153static void
1154move_applet (PanelWidget *panel, int pos, int applet_num)
1155{
1156        AppletInfo *info = g_slist_nth_data (applets, applet_num);
1157
1158        if (pos < 0)
1159                pos = 0;
1160
1161        if (info != NULL &&
1162            info->widget != NULL &&
1163            info->widget->parent != NULL &&
1164            IS_PANEL_WIDGET (info->widget->parent)) {
1165                GSList *forb;
1166                forb = gtk_object_get_data (GTK_OBJECT (info->widget),
1167                                            PANEL_APPLET_FORBIDDEN_PANELS);
1168                if ( ! g_slist_find (forb, panel))
1169                        panel_widget_reparent (PANEL_WIDGET (info->widget->parent),
1170                                               panel,
1171                                               info->widget,
1172                                               pos);
1173        }
1174}
1175
1176static void
1177drop_internal_applet (PanelWidget *panel, int pos, const char *applet_type,
1178                      int action)
1179{
1180        int applet_num = -1;
1181        gboolean remove_applet = FALSE;
1182
1183        if (applet_type == NULL)
1184                return;
1185
1186        if (sscanf (applet_type, "MENU:%d", &applet_num) == 1 ||
1187            sscanf (applet_type, "DRAWER:%d", &applet_num) == 1 ||
1188            sscanf (applet_type, "SWALLOW:%d", &applet_num) == 1) {
1189                if (action != GDK_ACTION_MOVE)
1190                        g_warning ("Only MOVE supported for menus/drawers/swallows");
1191                move_applet (panel, pos, applet_num);
1192
1193        } else if (strncmp (applet_type, "MENU:", strlen("MENU:")) == 0) {
1194                const char *menu = &applet_type[strlen ("MENU:")];
1195                if (strcmp (menu, "MAIN") == 0)
1196                        drop_menu (panel, pos, NULL);
1197                else
1198                        drop_menu (panel, pos, menu);
1199
1200        } else if (strcmp(applet_type,"DRAWER:NEW")==0) {
1201                load_drawer_applet(-1, NULL, NULL, panel, pos, TRUE);
1202
1203        } else if (strcmp (applet_type, "LOGOUT:NEW") == 0) {
1204                load_logout_applet (panel, pos, TRUE);
1205
1206        } else if (sscanf (applet_type, "LOGOUT:%d", &applet_num) == 1) {
1207                load_logout_applet (panel, pos, TRUE);
1208                remove_applet = TRUE;
1209
1210        } else if (strcmp (applet_type, "LOCK:NEW") == 0) {
1211                load_lock_applet (panel, pos, TRUE);
1212
1213        } else if (sscanf (applet_type, "LOCK:%d", &applet_num) == 1) {
1214                load_lock_applet (panel, pos, TRUE);
1215                remove_applet = TRUE;
1216
1217        } else if (strcmp (applet_type, "SWALLOW:ASK") == 0) {
1218                ask_about_swallowing(panel, pos, TRUE);
1219
1220        } else if(strcmp(applet_type,"LAUNCHER:ASK")==0) {
1221                ask_about_launcher(NULL, panel, pos, TRUE);
1222
1223        } else if(strcmp(applet_type,"STATUS:TRY")==0) {
1224                load_status_applet(panel, pos, TRUE);
1225
1226        } else if(strcmp(applet_type,"RUN:NEW")==0) {
1227                load_run_applet(panel, pos, TRUE);
1228
1229        } else if (sscanf (applet_type, "RUN:%d", &applet_num) == 1) {
1230                load_run_applet(panel, pos, TRUE);
1231                remove_applet = TRUE;
1232        }
1233
1234        if (remove_applet &&
1235            action == GDK_ACTION_MOVE) {
1236                AppletInfo *info = g_slist_nth_data (applets, applet_num);
1237
1238                if (info != NULL)
1239                        panel_clean_applet (info);
1240        }
1241}
1242
1243static void
1244drop_color(PanelWidget *panel, int pos, guint16 *dropped)
1245{
1246        GdkColor c;
1247
1248        if(!dropped) return;
1249
1250        c.red = dropped[0];
1251        c.green = dropped[1];
1252        c.blue = dropped[2];
1253        c.pixel = 0;
1254
1255        panel_widget_set_back_color(panel, &c);
1256}
1257
1258static gboolean
1259is_this_drop_ok (GtkWidget *widget, GdkDragContext *context, guint *info,
1260                 GdkAtom *ret_atom)
1261{
1262        GtkWidget *panel; /*PanelWidget*/
1263        GList *li;
1264
1265        g_return_val_if_fail (widget != NULL, FALSE);
1266        g_return_val_if_fail (IS_BASEP_WIDGET (widget) ||
1267                              IS_FOOBAR_WIDGET (widget), FALSE);
1268
1269        if(!(context->actions & (GDK_ACTION_COPY|GDK_ACTION_MOVE)))
1270                return FALSE;
1271
1272        if (IS_BASEP_WIDGET (widget))
1273                panel = BASEP_WIDGET (widget)->panel;
1274        else
1275                panel = FOOBAR_WIDGET (widget)->panel;
1276
1277        if (panel_target_list == NULL)
1278                panel_target_list = gtk_target_list_new (panel_drop_types,
1279                                                         n_panel_drop_types);
1280        for (li = context->targets; li; li = li->next) {
1281                guint temp_info;
1282                if (gtk_target_list_find (panel_target_list,
1283                                          GPOINTER_TO_UINT(li->data),
1284                                          &temp_info)) {
1285                        if ((temp_info == TARGET_COLOR ||
1286                             temp_info == TARGET_BGIMAGE) &&
1287                            IS_FOOBAR_WIDGET (widget))
1288                                return FALSE;
1289                        if (info != NULL)
1290                                *info = temp_info;
1291                        if (ret_atom != NULL)
1292                                *ret_atom = GPOINTER_TO_UINT(li->data);
1293                        break;
1294                }
1295        }
1296        /* if we haven't found it */
1297        if (li == NULL)
1298                return FALSE;
1299        return TRUE;
1300}
1301
1302static void
1303do_highlight (GtkWidget *widget, gboolean highlight)
1304{
1305        gboolean have_drag;
1306        have_drag = GPOINTER_TO_INT(gtk_object_get_data (GTK_OBJECT (widget),
1307                                                         "have-drag"));
1308        if(highlight) {
1309                if(!have_drag) {
1310                        gtk_object_set_data (GTK_OBJECT (widget), "have-drag",
1311                                             GINT_TO_POINTER (TRUE));
1312                        gtk_drag_highlight (widget);
1313                }
1314        } else {
1315                if(have_drag) {
1316                        gtk_object_remove_data (GTK_OBJECT (widget),
1317                                                "have-drag");
1318                        gtk_drag_unhighlight (widget);
1319                }
1320        }
1321}
1322
1323
1324static gboolean
1325drag_motion_cb (GtkWidget          *widget,
1326                GdkDragContext     *context,
1327                gint                x,
1328                gint                y,
1329                guint               time)
1330{
1331        guint info;
1332
1333        if ( ! is_this_drop_ok (widget, context, &info, NULL))
1334                return FALSE;
1335
1336        /* check forbiddenness */
1337        if (info == TARGET_APPLET_INTERNAL) {
1338                GtkWidget *source_widget;
1339
1340                source_widget = gtk_drag_get_source_widget (context);
1341                if (source_widget != NULL &&
1342                    IS_BUTTON_WIDGET (source_widget)) {
1343                        GSList *forb;
1344                        PanelWidget *panel = NULL;
1345
1346                        if (IS_BASEP_WIDGET (widget)) {
1347                                BasePWidget *basep =
1348                                        BASEP_WIDGET (widget);
1349                                panel = PANEL_WIDGET (basep->panel);
1350                        } else if (IS_FOOBAR_WIDGET (widget)) {
1351                                panel = PANEL_WIDGET (FOOBAR_WIDGET (widget)->panel);
1352                        }
1353                        forb = gtk_object_get_data (GTK_OBJECT (source_widget),
1354                                                    PANEL_APPLET_FORBIDDEN_PANELS);
1355                        if (panel != NULL &&
1356                            g_slist_find (forb, panel) != NULL)
1357                                return FALSE;
1358                }
1359        }
1360
1361        /* always prefer copy, except for internal icons/applets,
1362         * where we prefer move */
1363        if (info == TARGET_ICON_INTERNAL ||
1364            info == TARGET_APPLET_INTERNAL) {
1365                if (context->actions & GDK_ACTION_MOVE) {
1366                        gdk_drag_status (context, GDK_ACTION_MOVE, time);
1367                } else {
1368                        gdk_drag_status (context, context->suggested_action, time);
1369                }
1370        } else if (context->actions & GDK_ACTION_COPY) {
1371                gdk_drag_status (context, GDK_ACTION_COPY, time);
1372        } else {
1373                gdk_drag_status (context, context->suggested_action, time);
1374        }
1375
1376        do_highlight (widget, TRUE);
1377
1378        if (IS_BASEP_WIDGET (widget)) {
1379                basep_widget_autoshow (BASEP_WIDGET (widget));
1380                basep_widget_queue_autohide (BASEP_WIDGET (widget));
1381        }
1382
1383        return TRUE;
1384}
1385
1386static gboolean
1387drag_drop_cb (GtkWidget         *widget,
1388              GdkDragContext    *context,
1389              gint               x,
1390              gint               y,
1391              guint              time,
1392              Launcher          *launcher)
1393{
1394        GdkAtom ret_atom = 0;
1395
1396        if ( ! is_this_drop_ok (widget, context, NULL, &ret_atom))
1397                return FALSE;
1398
1399        gtk_drag_get_data(widget, context,
1400                          ret_atom, time);
1401
1402        return TRUE;
1403}
1404
1405static void 
1406drag_leave_cb (GtkWidget        *widget,
1407               GdkDragContext   *context,
1408               guint             time,
1409               Launcher         *launcher)
1410{
1411        do_highlight (widget, FALSE);
1412}
1413
1414static void
1415drag_data_recieved_cb (GtkWidget        *widget,
1416                       GdkDragContext   *context,
1417                       gint              x,
1418                       gint              y,
1419                       GtkSelectionData *selection_data,
1420                       guint             info,
1421                       guint             time)
1422{
1423        PanelWidget *panel;
1424        int pos;
1425
1426        g_return_if_fail(widget!=NULL);
1427        g_return_if_fail (IS_BASEP_WIDGET (widget) ||
1428                          IS_FOOBAR_WIDGET (widget));
1429
1430        /* we use this only to really find out the info, we already
1431           know this is an ok drop site and the info that got passed
1432           to us is bogus (it's always 0 in fact) */
1433        if ( ! is_this_drop_ok (widget, context, &info, NULL)) {
1434                gtk_drag_finish (context, FALSE, FALSE, time);
1435                return;
1436        }
1437
1438        if (IS_BASEP_WIDGET (widget))
1439                panel = PANEL_WIDGET (BASEP_WIDGET (widget)->panel);
1440        else
1441                panel = PANEL_WIDGET (FOOBAR_WIDGET (widget)->panel);
1442
1443        pos = panel_widget_get_cursorloc(panel);
1444       
1445        /* -1 passed to register_toy will turn on the insert_at_pos
1446           flag for panel_widget_add_full, which will not place it
1447           after the first applet */
1448        if(pos < 0)
1449                pos = -1;
1450        else if(pos > panel->size)
1451                pos = panel->size;
1452
1453        switch (info) {
1454        case TARGET_URL:
1455                drop_urilist (panel, pos, (char *)selection_data->data,
1456                              IS_FOOBAR_WIDGET(widget) ? FALSE : TRUE);
1457                break;
1458        case TARGET_NETSCAPE_URL:
1459                drop_url (panel, pos, (char *)selection_data->data);
1460                break;
1461        case TARGET_COLOR:
1462                drop_color (panel, pos, (guint16 *)selection_data->data);
1463                break;
1464        case TARGET_BGIMAGE:
1465                if ( ! IS_FOOBAR_WIDGET(widget))
1466                        drop_bgimage (panel, (char *)selection_data->data);
1467                break;
1468        case TARGET_DIRECTORY:
1469                drop_directory (panel, pos, (char *)selection_data->data);
1470                break;
1471        case TARGET_APPLET:
1472                if ( ! selection_data->data) {
1473                        gtk_drag_finish (context, FALSE, FALSE, time);
1474                        return;
1475                }
1476                load_extern_applet ((char *)selection_data->data, NULL,
1477                                    panel, pos, TRUE, FALSE);
1478                break;
1479        case TARGET_APPLET_INTERNAL:
1480                drop_internal_applet (panel, pos, (char *)selection_data->data,
1481                                      context->action);
1482                break;
1483        case TARGET_ICON_INTERNAL:
1484                drop_internal_icon (panel, pos, (char *)selection_data->data,
1485                                    context->action);
1486                break;
1487        default:
1488                gtk_drag_finish (context, FALSE, FALSE, time);
1489                return;
1490        }
1491
1492        gtk_drag_finish (context, TRUE, FALSE, time);
1493}
1494
1495static void
1496panel_widget_setup(PanelWidget *panel)
1497{
1498        gtk_signal_connect(GTK_OBJECT(panel),
1499                           "applet_added",
1500                           GTK_SIGNAL_FUNC(panel_applet_added),
1501                           NULL);
1502        gtk_signal_connect(GTK_OBJECT(panel),
1503                           "applet_removed",
1504                           GTK_SIGNAL_FUNC(panel_applet_removed),
1505                           NULL);
1506        gtk_signal_connect(GTK_OBJECT(panel),
1507                           "applet_move",
1508                           GTK_SIGNAL_FUNC(panel_applet_move),
1509                           NULL);
1510        gtk_signal_connect(GTK_OBJECT(panel),
1511                           "applet_draw",
1512                           GTK_SIGNAL_FUNC(panel_applet_draw),
1513                           NULL);
1514        gtk_signal_connect(GTK_OBJECT(panel),
1515                           "applet_about_to_die",
1516                           GTK_SIGNAL_FUNC(panel_applet_about_to_die),
1517                           NULL);
1518        gtk_signal_connect(GTK_OBJECT(panel),
1519                           "back_change",
1520                           GTK_SIGNAL_FUNC(panel_back_change),
1521                           NULL);
1522        gtk_signal_connect(GTK_OBJECT(panel),
1523                           "size_change",
1524                           GTK_SIGNAL_FUNC(panel_size_change),
1525                           NULL);
1526        gtk_signal_connect (GTK_OBJECT (panel),
1527                            "orient_change",
1528                            GTK_SIGNAL_FUNC (panel_orient_change),
1529                            NULL);
1530}
1531
1532void
1533basep_pos_connect_signals (BasePWidget *basep)
1534{
1535        if (IS_BORDER_WIDGET (basep)) {
1536                gtk_signal_connect (GTK_OBJECT (basep->pos),
1537                                    "edge_change",
1538                                    GTK_SIGNAL_FUNC (border_edge_change),
1539                                    basep);
1540        }
1541
1542        if (IS_ALIGNED_WIDGET (basep))
1543                gtk_signal_connect_object (GTK_OBJECT (basep->pos),
1544                                           "align_change",
1545                                           GTK_SIGNAL_FUNC (update_config_align),
1546                                           GTK_OBJECT (basep));
1547        else if (IS_FLOATING_WIDGET (basep))
1548                gtk_signal_connect_object (GTK_OBJECT (basep->pos),
1549                                           "floating_coords_change",
1550                                           GTK_SIGNAL_FUNC (update_config_floating_pos),
1551                                           GTK_OBJECT(basep));
1552        else if (IS_SLIDING_WIDGET (basep)) {
1553                gtk_signal_connect_object (GTK_OBJECT (basep->pos),
1554                                           "anchor_change",
1555                                           GTK_SIGNAL_FUNC (update_config_anchor),
1556                                           GTK_OBJECT(basep));
1557                gtk_signal_connect_object (GTK_OBJECT (basep->pos),
1558                                           "offset_change",
1559                                           GTK_SIGNAL_FUNC (update_config_offset),
1560                                           GTK_OBJECT (basep));
1561        }
1562}
1563
1564static void
1565drawer_orient_change_foreach(GtkWidget *w, gpointer data)
1566{
1567        AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
1568        PanelWidget *panel = data;
1569       
1570        if(info->type == APPLET_DRAWER)
1571                orientation_change(info, panel);
1572}
1573
1574static void
1575panelw_size_alloc(BasePWidget *basep, GtkAllocation *alloc, gpointer data)
1576{
1577        if(!GTK_WIDGET_REALIZED(basep))
1578                return;
1579
1580        if(IS_DRAWER_WIDGET(basep)) {
1581                gtk_container_foreach(GTK_CONTAINER(basep->panel),
1582                                      orient_change_foreach,
1583                                      basep->panel);
1584        } else if(IS_FLOATING_WIDGET(basep)) {
1585                gtk_container_foreach(GTK_CONTAINER(basep->panel),
1586                                      orient_change_foreach,
1587                                      basep->panel);
1588                update_config_floating_pos_limits(basep);
1589        } else if(IS_ALIGNED_WIDGET(basep)) {
1590                gtk_container_foreach(GTK_CONTAINER(basep->panel),
1591                                      drawer_orient_change_foreach,
1592                                      basep->panel);
1593        } else if(IS_SLIDING_WIDGET(basep)) {
1594                gtk_container_foreach(GTK_CONTAINER(basep->panel),
1595                                      drawer_orient_change_foreach,
1596                                      basep->panel);
1597                update_config_offset_limit(basep);
1598        }
1599}
1600
1601void
1602panel_setup(GtkWidget *panelw)
1603{
1604        PanelData *pd;
1605        BasePWidget *basep = NULL;
1606        PanelWidget *panel = NULL;
1607
1608        g_return_if_fail(panelw);
1609
1610        if (IS_BASEP_WIDGET (panelw)) {
1611                basep = BASEP_WIDGET(panelw);
1612                panel = PANEL_WIDGET(basep->panel);
1613        } else if (IS_FOOBAR_WIDGET (panelw)) {
1614                panel = PANEL_WIDGET (FOOBAR_WIDGET (panelw)->panel);
1615        }
1616
1617        pd = g_new(PanelData,1);
1618        pd->menu = NULL;
1619        pd->menu_age = 0;
1620        pd->panel = panelw;
1621
1622        if (IS_FOOBAR_WIDGET (panelw) ||
1623            (IS_BASEP_WIDGET (panelw) &&
1624             !IS_DRAWER_WIDGET (panelw)))
1625                base_panels++;
1626       
1627        if(IS_EDGE_WIDGET(panelw))
1628                pd->type = EDGE_PANEL;
1629        else if(IS_DRAWER_WIDGET(panelw))
1630                pd->type = DRAWER_PANEL;
1631        else if(IS_ALIGNED_WIDGET(panelw))
1632                pd->type = ALIGNED_PANEL;
1633        else if(IS_SLIDING_WIDGET(panelw))
1634                pd->type = SLIDING_PANEL;
1635        else if(IS_FLOATING_WIDGET(panelw))
1636                pd->type = FLOATING_PANEL;
1637        else if(IS_FOOBAR_WIDGET(panelw))
1638                pd->type = FOOBAR_PANEL;
1639        else
1640                g_warning("unknown panel type");
1641       
1642        panel_list = g_slist_append(panel_list,pd);
1643       
1644        gtk_object_set_user_data(GTK_OBJECT(panelw),pd);
1645
1646        panel_widget_setup(panel);
1647
1648        if (basep) {
1649                gtk_signal_connect(GTK_OBJECT(basep->hidebutton_e), "event",
1650                                   (GtkSignalFunc) panel_sub_event_handler,
1651                                   panelw);
1652                gtk_signal_connect(GTK_OBJECT(basep->hidebutton_w), "event",
1653                                   (GtkSignalFunc) panel_sub_event_handler,
1654                                   panelw);
1655                gtk_signal_connect(GTK_OBJECT(basep->hidebutton_n), "event",
1656                                   (GtkSignalFunc) panel_sub_event_handler,
1657                                   panelw);
1658                gtk_signal_connect(GTK_OBJECT(basep->hidebutton_s), "event",
1659                                   (GtkSignalFunc) panel_sub_event_handler,
1660                                   panelw);
1661                gtk_signal_connect (GTK_OBJECT (basep),
1662                                    "state_change",
1663                                    GTK_SIGNAL_FUNC (basep_state_change),
1664                                    NULL);
1665                basep_pos_connect_signals (basep);
1666                basep_widget_disable_buttons(basep);
1667
1668                gtk_signal_connect_after(GTK_OBJECT(panelw), "size_allocate",
1669                                         GTK_SIGNAL_FUNC(panelw_size_alloc),
1670                                         NULL);
1671        }
1672
1673        gtk_signal_connect(GTK_OBJECT(panelw),
1674                           "drag_data_received",
1675                           GTK_SIGNAL_FUNC(drag_data_recieved_cb),
1676                           NULL);
1677        gtk_signal_connect(GTK_OBJECT(panelw),
1678                           "drag_motion",
1679                           GTK_SIGNAL_FUNC(drag_motion_cb),
1680                           NULL);
1681        gtk_signal_connect(GTK_OBJECT(panelw),
1682                           "drag_leave",
1683                           GTK_SIGNAL_FUNC(drag_leave_cb),
1684                           NULL);
1685        gtk_signal_connect(GTK_OBJECT(panelw),
1686                           "drag_drop",
1687                           GTK_SIGNAL_FUNC(drag_drop_cb),
1688                           NULL);
1689
1690        gtk_drag_dest_set (GTK_WIDGET (panelw),
1691                           0, NULL, 0, 0);
1692
1693        gtk_signal_connect (GTK_OBJECT (panelw), "event",
1694                           GTK_SIGNAL_FUNC (panel_event), pd);
1695        gtk_signal_connect (GTK_OBJECT (panel), "event",
1696                           GTK_SIGNAL_FUNC (panel_widget_event), panelw);
1697       
1698        gtk_widget_set_events(panelw,
1699                              gtk_widget_get_events(panelw) |
1700                              PANEL_EVENT_MASK);
1701 
1702        gtk_signal_connect (GTK_OBJECT (panelw), "destroy",
1703                            GTK_SIGNAL_FUNC (panel_destroy), NULL);
1704
1705
1706        if(GTK_WIDGET_REALIZED(GTK_WIDGET(panelw)))
1707                panel_realize(GTK_WIDGET(panelw),NULL);
1708        else
1709                gtk_signal_connect_after(GTK_OBJECT(panelw), "realize",
1710                                         GTK_SIGNAL_FUNC(panel_realize),
1711                                         NULL);
1712}
1713
1714/*send state change to all the panels*/
1715void
1716send_state_change(void)
1717{
1718        GSList *list;
1719        for(list = panel_list; list != NULL; list = g_slist_next(list)) {
1720                PanelData *pd = list->data;
1721                if(IS_BASEP_WIDGET (pd->panel) && !IS_DRAWER_WIDGET(pd->panel))
1722                        basep_state_change(BASEP_WIDGET(pd->panel),
1723                                           BASEP_WIDGET(pd->panel)->state,
1724                                           NULL);
1725        }
1726}
1727
1728PanelData *
1729panel_data_by_id (int id)
1730{
1731        GSList *list;
1732        for(list = panel_list; list != NULL; list = g_slist_next(list)) {
1733                PanelData *pd = list->data;
1734                int pd_id = -1;
1735
1736                if (IS_BASEP_WIDGET (pd->panel))
1737                       pd_id = PANEL_WIDGET (BASEP_WIDGET (pd->panel)->panel)->unique_id;
1738                else if (IS_FOOBAR_WIDGET (pd->panel))
1739                       pd_id = PANEL_WIDGET (FOOBAR_WIDGET (pd->panel)->panel)->unique_id;
1740
1741                if (id == pd_id)
1742                        return pd;
1743        }
1744        return NULL;
1745}
1746
1747void
1748panel_set_id (GtkWidget *widget, int id)
1749{
1750        if (IS_BASEP_WIDGET (widget))
1751                PANEL_WIDGET (BASEP_WIDGET (widget)->panel)->unique_id = id;
1752        else if (IS_FOOBAR_WIDGET (widget))
1753                PANEL_WIDGET (FOOBAR_WIDGET (widget)->panel)->unique_id = id;
1754}
1755
1756void
1757status_unparent (GtkWidget *widget)
1758{
1759        GList *li;
1760        PanelWidget *panel = NULL;
1761        if (IS_BASEP_WIDGET (widget))
1762                panel = PANEL_WIDGET(BASEP_WIDGET(widget)->panel);
1763        else if (IS_FOOBAR_WIDGET (widget))
1764                panel = PANEL_WIDGET (FOOBAR_WIDGET (widget)->panel);
1765        for(li=panel->applet_list;li;li=li->next) {
1766                AppletData *ad = li->data;
1767                AppletInfo *info = gtk_object_get_data(GTK_OBJECT(ad->applet),
1768                                                       "applet_info");
1769                if(info->type == APPLET_STATUS) {
1770                        status_applet_put_offscreen(info->data);
1771                } else if(info->type == APPLET_DRAWER) {
1772                        Drawer *dr = info->data;
1773                        status_unparent(dr->drawer);
1774                }
1775        }
1776}
1777
Note: See TracBrowser for help on using the repository browser.