/* Gnome panel: Initialization routines * (C) 1997 the Free Software Foundation * * Authors: Federico Mena * Miguel de Icaza * George Lebl */ #include #include #include #include #include #include #include #include "panel-include.h" #include "gnome-panel.h" #define PANEL_EVENT_MASK (GDK_BUTTON_PRESS_MASK | \ GDK_BUTTON_RELEASE_MASK | \ GDK_POINTER_MOTION_MASK | \ GDK_POINTER_MOTION_HINT_MASK) /*list of all panel widgets created*/ GSList *panel_list = NULL; static int panel_dragged = FALSE; static int panel_dragged_timeout = -1; static int panel_been_moved = FALSE; /*the number of base panels out there, never let it go below 1*/ int base_panels = 0; extern int config_sync_timeout; extern GSList *applets_to_sync; extern int panels_to_sync; extern int globals_to_sync; extern int need_complete_save; extern GlobalConfig global_config; extern GtkTooltips *panel_tooltips; /*???? this might be ugly, but I guess we can safely assume that we can only have one menu open and that nothing weird will happen to the panel that opened that menu whilethe user is looking over the choices*/ extern PanelWidget *current_panel; /*the types of stuff we accept*/ enum { TARGET_URL, TARGET_NETSCAPE_URL, TARGET_DIRECTORY, TARGET_COLOR, TARGET_APPLET, TARGET_APPLET_INTERNAL }; static GtkTargetEntry panel_drop_types[] = { { "text/uri-list", 0, TARGET_URL }, { "x-url/http", 0, TARGET_NETSCAPE_URL }, { "x-url/ftp", 0, TARGET_NETSCAPE_URL }, { "_NETSCAPE_URL", 0, TARGET_NETSCAPE_URL }, { "application/x-panel-directory", 0, TARGET_DIRECTORY }, { "application/x-panel-applet", 0, TARGET_APPLET }, { "application/x-panel-applet-internal", 0, TARGET_APPLET_INTERNAL }, { "application/x-color", 0, TARGET_COLOR } }; static gint n_panel_drop_types = sizeof(panel_drop_types) / sizeof(panel_drop_types[0]); static PanelData * get_lowest_level_master_pd(PanelWidget *panel) { GtkObject *parent; PanelData *pd; while(panel->master_widget) panel = PANEL_WIDGET(panel->master_widget->parent); parent = gtk_object_get_data(GTK_OBJECT(panel),PANEL_PARENT); g_return_val_if_fail(parent!=NULL,NULL); pd = gtk_object_get_user_data(parent); g_return_val_if_fail(pd!=NULL,NULL); return pd; } /*whoa ... what an ugly function!, it gets the right orient type for an applet on the panel for pd*/ PanelOrientType get_applet_orient(PanelWidget *panel) { PanelOrientType orient=ORIENT_UP; PanelOrientation porient; GtkWidget *panelw = gtk_object_get_data(GTK_OBJECT(panel), PANEL_PARENT); BasePWidget *basep = BASEP_WIDGET(panelw); PanelData *pd = gtk_object_get_user_data(GTK_OBJECT(panelw)); PanelData *tpd; switch(pd->type) { /*case FREE_PANEL: orient = (panel->orient==PANEL_VERTICAL)? ORIENT_RIGHT:ORIENT_UP; break;*/ case DRAWER_PANEL: porient = panel->orient; tpd = get_lowest_level_master_pd( PANEL_WIDGET(basep->panel)); switch(tpd->type){ /*case FREE_PANEL:*/ case DRAWER_PANEL: orient=(porient==PANEL_VERTICAL)? ORIENT_RIGHT:ORIENT_UP; break; case SNAPPED_PANEL: switch(SNAPPED_WIDGET(tpd->panel)->pos) { case SNAPPED_TOP: orient=(porient==PANEL_VERTICAL)? ORIENT_RIGHT:ORIENT_DOWN; break; case SNAPPED_BOTTOM: case SNAPPED_LEFT: orient=(porient==PANEL_VERTICAL)? ORIENT_RIGHT:ORIENT_UP; break; case SNAPPED_RIGHT: orient=(porient==PANEL_VERTICAL)? ORIENT_LEFT:ORIENT_UP; break; } break; case CORNER_PANEL: switch(CORNER_WIDGET(tpd->panel)->pos) { case CORNER_NE: orient=(porient==PANEL_VERTICAL)? ORIENT_LEFT:ORIENT_DOWN; break; case CORNER_SE: orient=(porient==PANEL_VERTICAL)? ORIENT_LEFT:ORIENT_UP; break; case CORNER_SW: orient=(porient==PANEL_VERTICAL)? ORIENT_RIGHT:ORIENT_UP; break; case CORNER_NW: orient=(porient==PANEL_VERTICAL)? ORIENT_RIGHT:ORIENT_DOWN; break; } default: break; } break; case SNAPPED_PANEL: switch(SNAPPED_WIDGET(panelw)->pos) { case SNAPPED_TOP: orient = ORIENT_DOWN; break; case SNAPPED_BOTTOM: orient = ORIENT_UP; break; case SNAPPED_LEFT: orient = ORIENT_RIGHT; break; case SNAPPED_RIGHT: orient = ORIENT_LEFT; break; } break; case CORNER_PANEL: if(panel->orient == PANEL_HORIZONTAL) { switch(CORNER_WIDGET(panelw)->pos) { case CORNER_SE: case CORNER_SW: orient = ORIENT_UP; break; case CORNER_NE: case CORNER_NW: orient = ORIENT_DOWN; break; } } else { /*vertical*/ switch(CORNER_WIDGET(panelw)->pos) { case CORNER_SE: case CORNER_NE: orient = ORIENT_LEFT; break; case CORNER_SW: case CORNER_NW: orient = ORIENT_RIGHT; break; } } default: break; } return orient; } static void change_window_cursor(GdkWindow *window, GdkCursorType cursor_type) { GdkCursor *cursor = gdk_cursor_new(cursor_type); gdk_window_set_cursor(window, cursor); gdk_cursor_destroy(cursor); } static void panel_realize(GtkWidget *widget, gpointer data) { change_window_cursor(widget->window, GDK_LEFT_PTR); basep_widget_enable_buttons(BASEP_WIDGET(widget)); /*FIXME: this seems to fix the panel size problems on startup (from a report) but I don't think it's right*/ gtk_widget_queue_resize(GTK_WIDGET(widget)); } /*we call this recursively*/ static void orient_change_foreach(GtkWidget *w, gpointer data); void orientation_change(AppletInfo *info, PanelWidget *panel) { if(info->type == APPLET_EXTERN) { Extern *ext = info->data; g_assert(ext); /*ingore this until we get an ior*/ if(ext->applet) { CORBA_Environment ev; CORBA_exception_init(&ev); GNOME_Applet_change_orient(ext->applet, get_applet_orient(panel), &ev); if(ev._major) panel_clean_applet(ext->info); CORBA_exception_free(&ev); } } else if(info->type == APPLET_MENU) { Menu *menu = info->data; set_menu_applet_orient(menu,get_applet_orient(panel)); } else if(info->type == APPLET_DRAWER) { Drawer *drawer = info->data; BasePWidget *basep = BASEP_WIDGET(drawer->drawer); set_drawer_applet_orient(drawer,get_applet_orient(panel)); gtk_widget_queue_resize(drawer->drawer); gtk_container_foreach(GTK_CONTAINER(basep->panel), orient_change_foreach, (gpointer)basep->panel); } else if(info->type == APPLET_SWALLOW) { Swallow *swallow = info->data; if(panel->orient == PANEL_VERTICAL) set_swallow_applet_orient(swallow,SWALLOW_VERTICAL); else set_swallow_applet_orient(swallow,SWALLOW_HORIZONTAL); } } static void orient_change_foreach(GtkWidget *w, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info"); PanelWidget *panel = data; orientation_change(info,panel); } static void panel_orient_change(GtkWidget *widget, PanelOrientation orient, gpointer data) { gtk_container_foreach(GTK_CONTAINER(widget),orient_change_foreach, widget); panels_to_sync = TRUE; /*update the configuration box if it is displayed*/ update_config_orient(gtk_object_get_data(GTK_OBJECT(widget), PANEL_PARENT)); } static void basep_pos_change(GtkWidget *widget, SnappedPos pos, gpointer data) { BasePWidget *basep = BASEP_WIDGET(widget); gtk_container_foreach(GTK_CONTAINER(basep->panel), orient_change_foreach, basep->panel); panels_to_sync = TRUE; /*update the configuration box if it is displayed*/ update_config_orient(widget); } void back_change(AppletInfo *info, PanelWidget *panel) { if(info->type == APPLET_EXTERN) { Extern *ext = info->data; g_assert(ext); /*ignore until we have a valid IOR*/ if(ext->applet) { GNOME_Panel_BackInfoType backing; CORBA_Environment ev; CORBA_exception_init(&ev); backing._d = panel->back_type; if(panel->back_type == PANEL_BACK_PIXMAP) backing._u.pmap = panel->back_pixmap; else if(panel->back_type == PANEL_BACK_COLOR) { backing._u.c.red = panel->back_color.red; backing._u.c.green = panel->back_color.green; backing._u.c.blue = panel->back_color.blue; } GNOME_Applet_back_change(ext->applet, &backing, &ev); if(ev._major) panel_clean_applet(ext->info); CORBA_exception_free(&ev); } } } static void back_change_foreach(GtkWidget *w, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info"); PanelWidget *panel = data; back_change(info,panel); } static void panel_back_change(GtkWidget *widget, PanelBackType type, char *pixmap, GdkColor *color) { gtk_container_foreach(GTK_CONTAINER(widget),back_change_foreach,widget); panels_to_sync = TRUE; /*update the configuration box if it is displayed*/ update_config_back(PANEL_WIDGET(widget)); } static void state_hide_foreach(GtkWidget *w, gpointer data); static void state_restore_foreach(GtkWidget *w, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info"); if(info->type == APPLET_DRAWER) { Drawer *drawer = info->data; DrawerWidget *dw = DRAWER_WIDGET(drawer->drawer); BasePWidget *basep = BASEP_WIDGET(drawer->drawer); if(dw->state == DRAWER_SHOWN) { drawer_widget_restore_state(dw); gtk_container_foreach(GTK_CONTAINER(basep->panel), state_restore_foreach, NULL); } else { /*it's hidden*/ dw->temp_hidden = FALSE; gtk_widget_size_allocate(drawer->drawer, &drawer->drawer->allocation); gtk_container_foreach(GTK_CONTAINER(basep->panel), state_hide_foreach, NULL); } } } static void state_hide_foreach(GtkWidget *w, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info"); if(info->type == APPLET_DRAWER) { Drawer *drawer = info->data; BasePWidget *basep = BASEP_WIDGET(drawer->drawer); DrawerWidget *dw = DRAWER_WIDGET(drawer->drawer); dw->temp_hidden = TRUE; gtk_widget_size_allocate(drawer->drawer, &drawer->drawer->allocation); gtk_container_foreach(GTK_CONTAINER(basep->panel), state_hide_foreach, NULL); } } static int snapped_state_change(GtkWidget *widget, SnappedState state, gpointer data) { SnappedWidget *snapped = SNAPPED_WIDGET(widget); if(state==SNAPPED_SHOWN) gtk_container_foreach(GTK_CONTAINER(BASEP_WIDGET(snapped)->panel), state_restore_foreach, (gpointer)widget); else gtk_container_foreach(GTK_CONTAINER(BASEP_WIDGET(snapped)->panel), state_hide_foreach, (gpointer)widget); panels_to_sync = TRUE; return TRUE; } static int corner_state_change(GtkWidget *widget, CornerState state, gpointer data) { CornerWidget *corner = CORNER_WIDGET(widget); if(state==CORNER_SHOWN) gtk_container_foreach(GTK_CONTAINER(BASEP_WIDGET(corner)->panel), state_restore_foreach, (gpointer)widget); else gtk_container_foreach(GTK_CONTAINER(BASEP_WIDGET(corner)->panel), state_hide_foreach, (gpointer)widget); panels_to_sync = TRUE; return TRUE; } static int drawer_state_change(GtkWidget *widget, DrawerState state, gpointer data) { DrawerWidget *drawer = DRAWER_WIDGET(widget); if(state==DRAWER_SHOWN) gtk_container_foreach(GTK_CONTAINER(BASEP_WIDGET(drawer)->panel), state_restore_foreach, (gpointer)widget); else gtk_container_foreach(GTK_CONTAINER(BASEP_WIDGET(drawer)->panel), state_hide_foreach, (gpointer)widget); panels_to_sync = TRUE; return TRUE; } static void queue_resize_foreach(GtkWidget *w, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info"); if(info->type == APPLET_DRAWER) { Drawer *drawer = info->data; BasePWidget *basep = BASEP_WIDGET(drawer->drawer); DrawerWidget *dw = DRAWER_WIDGET(drawer->drawer); if(dw->state == DRAWER_SHOWN && !dw->temp_hidden) { gtk_widget_queue_resize(drawer->drawer); /*gtk_container_foreach(GTK_CONTAINER(basep->panel), queue_resize_foreach, NULL);*/ } } } /*the following is slightly ugly .... but it works, I need to send the orient change in an idle handeler*/ static int panel_applet_added_idle(gpointer data) { AppletInfo *info = data; PanelWidget *panel; g_return_val_if_fail(info,FALSE); g_return_val_if_fail(info->widget,TRUE); g_return_val_if_fail(info->widget->parent,TRUE); panel = PANEL_WIDGET(info->widget->parent); orientation_change(info,panel); back_change(info,panel); return FALSE; } static void panel_applet_added(GtkWidget *widget, GtkWidget *applet, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(applet), "applet_info"); GtkWidget *panelw = gtk_object_get_data(GTK_OBJECT(widget), PANEL_PARENT); /*on a real add the info will be NULL as the only adding is done in register_toy and that doesn't add the info to the array until after the add, so we can be sure this was generated on a reparent*/ if(IS_SNAPPED_WIDGET(panelw) && info && info->type == APPLET_DRAWER) { Drawer *drawer = info->data; DrawerWidget *dw = DRAWER_WIDGET(drawer->drawer); if(dw->state == DRAWER_SHOWN) { SNAPPED_WIDGET(panelw)->drawers_open++; snapped_widget_pop_up(SNAPPED_WIDGET(panelw)); } } /*pop the panel up on addition*/ if(IS_SNAPPED_WIDGET(panelw)) { snapped_widget_pop_up(SNAPPED_WIDGET(panelw)); /*try to pop down though if the mouse is out*/ snapped_widget_queue_pop_down(SNAPPED_WIDGET(panelw)); } gtk_idle_add(panel_applet_added_idle,info); /*we will need to save this applet's config now*/ if(g_slist_find(applets_to_sync, info)==NULL) applets_to_sync = g_slist_prepend(applets_to_sync,info); } static void count_open_drawers(GtkWidget *w, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info"); int *count = data; if(info->type == APPLET_DRAWER) { Drawer *drawer = info->data; if(DRAWER_WIDGET(drawer->drawer)->state == DRAWER_SHOWN) (*count)++; } } static void panel_applet_removed(GtkWidget *widget, GtkWidget *applet, gpointer data) { GtkWidget *parentw = gtk_object_get_data(GTK_OBJECT(widget), PANEL_PARENT); AppletInfo *info = gtk_object_get_data(GTK_OBJECT(applet), "applet_info"); if(IS_SNAPPED_WIDGET(parentw)) { int drawers_open = 0; gtk_container_foreach(GTK_CONTAINER(widget), count_open_drawers, &drawers_open); SNAPPED_WIDGET(parentw)->drawers_open = drawers_open; snapped_widget_queue_pop_down(SNAPPED_WIDGET(parentw)); } /*we will need to save this applet's config now*/ if(g_slist_find(applets_to_sync, info)==NULL) applets_to_sync = g_slist_prepend(applets_to_sync,info); } static void menu_deactivate(GtkWidget *w, PanelData *pd) { pd->menu_age = 0; if(IS_SNAPPED_WIDGET(pd->panel)) SNAPPED_WIDGET(pd->panel)->autohide_inhibit = FALSE; } static void snapped_panel_move(SnappedWidget *snapped, double x, double y) { SnappedPos newloc; int minx, miny, maxx, maxy; gdk_window_get_geometry (GTK_WIDGET(snapped)->window, &minx, &miny, &maxx, &maxy, NULL); gdk_window_get_origin (GTK_WIDGET(snapped)->window, &minx, &miny); maxx += minx; maxy += miny; if (x >= minx && x <= maxx && y >= miny && y <= maxy) return; /*if in the inner 1/3rd, don't change to avoid fast flickery movement*/ if ( x>(gdk_screen_width()/3) && x<(2*gdk_screen_width()/3) && y>(gdk_screen_height()/3) && y<(2*gdk_screen_height()/3)) return; if ((x) * gdk_screen_height() > y * gdk_screen_width() ) { if(gdk_screen_height() * (gdk_screen_width()-(x)) > y * gdk_screen_width() ) newloc = SNAPPED_TOP; else newloc = SNAPPED_RIGHT; } else { if(gdk_screen_height() * (gdk_screen_width()-(x)) > y * gdk_screen_width() ) newloc = SNAPPED_LEFT; else newloc = SNAPPED_BOTTOM; } if(newloc != snapped->pos) snapped_widget_change_pos(snapped, newloc); } static void corner_panel_move(CornerWidget *corner, double x, double y) { CornerPos newloc; PanelOrientation neworient; int minx, miny, maxx, maxy; gdk_window_get_geometry (GTK_WIDGET(corner)->window, &minx, &miny, &maxx, &maxy, NULL); gdk_window_get_origin (GTK_WIDGET(corner)->window, &minx, &miny); maxx += minx; maxy += miny; if (x >= minx && x <= maxx && y >= miny && y <= maxy) return; /*if in the inner 1/3rd, don't change to avoid fast flickery movement*/ if ( x>(gdk_screen_width()/3) && x<(2*gdk_screen_width()/3) && y>(gdk_screen_height()/3) && y<(2*gdk_screen_height()/3)) return; if ((x) * gdk_screen_height() > y * gdk_screen_width() ) { if(gdk_screen_height() * (gdk_screen_width()-(x)) > y * gdk_screen_width() ) { neworient = PANEL_HORIZONTAL; if(x y * gdk_screen_width() ) { neworient = PANEL_VERTICAL; if(ypos || neworient != PANEL_WIDGET(BASEP_WIDGET(corner)->panel)->orient) corner_widget_change_pos_orient(corner, newloc, neworient); } static void move_panel_to_cursor(GtkWidget *w) { int x,y; gdk_window_get_pointer(NULL,&x,&y,NULL); if(IS_SNAPPED_WIDGET(w)) snapped_panel_move(SNAPPED_WIDGET(w),x,y); else corner_panel_move(CORNER_WIDGET(w),x,y); } static int panel_move_timeout(gpointer data) { if(panel_dragged && panel_been_moved) move_panel_to_cursor(data); panel_been_moved = FALSE; panel_dragged_timeout = -1; return FALSE; } static void panel_destroy(GtkWidget *widget, gpointer data) { PanelData *pd = gtk_object_get_user_data(GTK_OBJECT(widget)); kill_config_dialog(widget); if(IS_DRAWER_WIDGET(widget)) { PanelWidget *panel = PANEL_WIDGET(BASEP_WIDGET(widget)->panel); if(panel->master_widget) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(panel->master_widget), "applet_info"); Drawer *drawer = info->data; drawer->drawer = NULL; panel_clean_applet(info); } } else if(IS_SNAPPED_WIDGET(widget) || IS_CORNER_WIDGET(widget)) { /*this is a base panel and we just lost it*/ base_panels--; } if(pd->menu) gtk_widget_destroy(pd->menu); panel_list = g_slist_remove(panel_list,pd); g_free(pd); } static void panel_applet_move(GtkWidget *panel,GtkWidget *widget, gpointer data) { AppletInfo *info = gtk_object_get_data(GTK_OBJECT(widget), "applet_info"); if(g_slist_find(applets_to_sync, info)==NULL) applets_to_sync = g_slist_prepend(applets_to_sync,info); } static GtkWidget * panel_menu_get(PanelData *pd) { if(pd->menu) return pd->menu; pd->menu = create_panel_root_menu(pd->panel); gtk_signal_connect(GTK_OBJECT(pd->menu), "deactivate", GTK_SIGNAL_FUNC(menu_deactivate),pd); return pd->menu; } static int panel_event(GtkWidget *widget, GdkEvent *event, PanelData *pd) { GdkEventButton *bevent; switch (event->type) { case GDK_BUTTON_PRESS: bevent = (GdkEventButton *) event; switch(bevent->button) { case 3: /* fall through */ if(!panel_applet_in_drag) { GtkWidget *panel_menu; GtkWidget *rem; current_panel = PANEL_WIDGET(BASEP_WIDGET(widget)->panel); panel_menu = panel_menu_get(pd); rem = gtk_object_get_data(GTK_OBJECT(panel_menu), "remove_item"); if(IS_SNAPPED_WIDGET(widget)) { SnappedWidget *snapped = SNAPPED_WIDGET(widget); gtk_widget_set_sensitive(rem, base_panels > 1); snapped->autohide_inhibit = TRUE; snapped_widget_queue_pop_down(snapped); } else if(IS_CORNER_WIDGET(widget)) { gtk_widget_set_sensitive(rem, base_panels > 1); } else gtk_widget_set_sensitive(rem, TRUE); pd->menu_age = 0; gtk_menu_popup(GTK_MENU(panel_menu), NULL, NULL, global_config.off_panel_popups? panel_menu_position:NULL, widget, bevent->button, bevent->time); return TRUE; } break; case 2: /*this should probably be in snapped widget*/ if(!panel_dragged && (IS_SNAPPED_WIDGET(widget) || IS_CORNER_WIDGET(widget))) { GdkCursor *cursor = gdk_cursor_new (GDK_FLEUR); gtk_grab_add(widget); gdk_pointer_grab (widget->window, FALSE, PANEL_EVENT_MASK, NULL, cursor, bevent->time); gdk_cursor_destroy (cursor); if(IS_SNAPPED_WIDGET(widget)) SNAPPED_WIDGET(widget)->autohide_inhibit = TRUE; panel_dragged = TRUE; return TRUE; } if(IS_DRAWER_WIDGET(widget) && !panel_applet_in_drag) { BasePWidget *basep = BASEP_WIDGET(widget); PanelWidget *pw = PANEL_WIDGET(basep->panel); panel_widget_applet_drag_start(PANEL_WIDGET(pw->master_widget->parent), pw->master_widget); return TRUE; } break; default: break; } break; case GDK_BUTTON_RELEASE: bevent = (GdkEventButton *) event; if(panel_dragged) { if(IS_SNAPPED_WIDGET(widget)) { snapped_panel_move(SNAPPED_WIDGET(widget), bevent->x_root, bevent->y_root); SNAPPED_WIDGET(widget)->autohide_inhibit = FALSE; snapped_widget_queue_pop_down(SNAPPED_WIDGET(widget)); } else corner_panel_move(CORNER_WIDGET(widget), bevent->x_root, bevent->y_root); gdk_pointer_ungrab(bevent->time); gtk_grab_remove(widget); panel_dragged = FALSE; panel_dragged_timeout = -1; panel_been_moved = FALSE; return TRUE; } break; case GDK_MOTION_NOTIFY: if (panel_dragged) { if(panel_dragged_timeout==-1) { panel_been_moved = FALSE; move_panel_to_cursor(widget); panel_dragged_timeout = gtk_timeout_add (30,panel_move_timeout,widget); } else panel_been_moved = TRUE; } break; default: break; } return FALSE; } static int panel_sub_event_handler(GtkWidget *widget, GdkEvent *event, gpointer data) { GdkEventButton *bevent; switch (event->type) { /*pass these to the parent!*/ case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: case GDK_MOTION_NOTIFY: bevent = (GdkEventButton *) event; /*if the widget is a button we want to keep the button 1 events*/ if(!GTK_IS_BUTTON(widget) || bevent->button!=1) return gtk_widget_event(data, event); break; default: break; } return FALSE; } static void panel_widget_dnd_drop_internal (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time) { PanelWidget *panel; g_return_if_fail(widget!=NULL); g_return_if_fail(IS_PANEL_WIDGET(widget)); panel = PANEL_WIDGET (widget); switch (info) { case TARGET_URL: { GList *ltmp, *files; struct stat s; int pos = panel_widget_get_cursorloc(panel); files = gnome_uri_list_extract_filenames(selection_data->data); for(ltmp = files; ltmp; ltmp = g_list_next(ltmp)) { const char *mimetype, *p; mimetype = gnome_mime_type(ltmp->data); if(mimetype && (!strcmp(mimetype,"x-url/http") || !strcmp(mimetype,"x-url/ftp"))) { int pos = panel_widget_get_cursorloc(panel); char *exec[3] = { "gnome-moz-remote", NULL, NULL }; char *p; exec[1] = ltmp->data; p = g_strdup_printf("Open URL: %s", (char *)ltmp->data); load_launcher_applet_from_info(ltmp->data, p,exec,2, "netscape.png", panel,pos); g_free(p); } if(stat(ltmp->data, &s) != 0) { continue; } if(mimetype && !strncmp(mimetype, "image", sizeof("image")-1)) panel_widget_set_back_pixmap (panel, ltmp->data); else if(mimetype && !strcmp(mimetype, "application/x-gnome-app-info")) load_launcher_applet(ltmp->data, panel, pos); else if(S_ISDIR(s.st_mode)) { int flags = MAIN_MENU_SYSTEM|MAIN_MENU_USER; /*guess redhat menus*/ if(g_file_exists("/etc/X11/wmconfig")) flags |= MAIN_MENU_REDHAT|MAIN_MENU_REDHAT_SUB; load_menu_applet(ltmp->data, flags, panel, pos); } else if(S_IEXEC & s.st_mode) /*executable?*/ ask_about_launcher(ltmp->data,panel,pos); } gnome_uri_list_free_strings (files); break; } case TARGET_NETSCAPE_URL: { int pos = panel_widget_get_cursorloc(panel); char *exec[3] = { "gnome-moz-remote", NULL, NULL }; char *p; exec[1] = selection_data->data; p = g_strdup_printf("Open URL: %s",selection_data->data); load_launcher_applet_from_info(selection_data->data,p,exec,2, "netscape.png",panel,pos); g_free(p); break; } case TARGET_COLOR: { guint16 *dropped; GdkColor c; dropped = (guint16 *)selection_data->data; c.red = dropped[0]; c.green = dropped[1]; c.blue = dropped[2]; c.pixel = 0; panel_widget_set_back_color(panel, &c); break; } case TARGET_DIRECTORY: { int pos = panel_widget_get_cursorloc(panel); int flags = MAIN_MENU_SYSTEM|MAIN_MENU_USER; /*guess redhat menus*/ if(g_file_exists("/etc/X11/wmconfig")) flags |= MAIN_MENU_REDHAT|MAIN_MENU_REDHAT_SUB; load_menu_applet ((char *)selection_data->data,flags, panel, pos); break; } case TARGET_APPLET: { int pos = panel_widget_get_cursorloc(panel); char *goad_id = (char *)selection_data->data; if(!goad_id) return; load_extern_applet(goad_id,NULL,panel,pos,FALSE); break; } case TARGET_APPLET_INTERNAL: { int pos = panel_widget_get_cursorloc(panel); char *applet_type = (char *)selection_data->data; if(!applet_type) return; if(strcmp(applet_type,"MENU:MAIN")==0) { int flags = MAIN_MENU_SYSTEM|MAIN_MENU_USER; /*guess redhat menus*/ if(g_file_exists("/etc/X11/wmconfig")) flags |= MAIN_MENU_REDHAT|MAIN_MENU_REDHAT_SUB; load_menu_applet(NULL,flags, panel, pos); } else if(strcmp(applet_type,"DRAWER:NEW")==0) { load_drawer_applet(-1,NULL,NULL, panel, pos); } else if(strcmp(applet_type,"LOGOUT:NEW")==0) { load_logout_applet(panel, pos); } else if(strcmp(applet_type,"SWALLOW:ASK")==0) { ask_about_swallowing(panel,pos); } else if(strcmp(applet_type,"LAUNCHER:ASK")==0) { ask_about_launcher(NULL,panel,pos); } break; } } } static void panel_widget_setup(PanelWidget *panel) { gtk_signal_connect(GTK_OBJECT(panel), "applet_added", GTK_SIGNAL_FUNC(panel_applet_added), NULL); gtk_signal_connect(GTK_OBJECT(panel), "applet_removed", GTK_SIGNAL_FUNC(panel_applet_removed), NULL); gtk_signal_connect(GTK_OBJECT(panel), "applet_move", GTK_SIGNAL_FUNC(panel_applet_move), NULL); gtk_signal_connect(GTK_OBJECT(panel), "back_change", GTK_SIGNAL_FUNC(panel_back_change), NULL); gtk_signal_connect(GTK_OBJECT(panel), "drag_data_received", GTK_SIGNAL_FUNC(panel_widget_dnd_drop_internal), NULL); gtk_drag_dest_set (GTK_WIDGET (panel), GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, panel_drop_types, n_panel_drop_types, GDK_ACTION_COPY); } void panel_setup(GtkWidget *panelw) { PanelData *pd; BasePWidget *basep = BASEP_WIDGET(panelw); pd = g_new(PanelData,1); pd->menu = NULL; pd->menu_age = 0; pd->panel = panelw; if(IS_DRAWER_WIDGET(panelw)) pd->type = DRAWER_PANEL; else if(IS_SNAPPED_WIDGET(panelw)) pd->type = SNAPPED_PANEL; else if(IS_CORNER_WIDGET(panelw)) pd->type = CORNER_PANEL; else { g_warning("unknown panel type"); } panel_list = g_slist_append(panel_list,pd); gtk_object_set_user_data(GTK_OBJECT(panelw),pd); gtk_signal_connect(GTK_OBJECT(basep->hidebutton_e), "event", (GtkSignalFunc) panel_sub_event_handler, panelw); gtk_signal_connect(GTK_OBJECT(basep->hidebutton_w), "event", (GtkSignalFunc) panel_sub_event_handler, panelw); gtk_signal_connect(GTK_OBJECT(basep->hidebutton_n), "event", (GtkSignalFunc) panel_sub_event_handler, panelw); gtk_signal_connect(GTK_OBJECT(basep->hidebutton_s), "event", (GtkSignalFunc) panel_sub_event_handler, panelw); if(IS_DRAWER_WIDGET(panelw)) { PanelWidget *panel = PANEL_WIDGET(basep->panel); DrawerWidget *drawer = DRAWER_WIDGET(panelw); panel_widget_setup(panel); gtk_signal_connect(GTK_OBJECT(panel), "orient_change", GTK_SIGNAL_FUNC(panel_orient_change), NULL); gtk_signal_connect(GTK_OBJECT(panelw), "state_change", GTK_SIGNAL_FUNC(drawer_state_change), NULL); } else if(IS_SNAPPED_WIDGET(panelw)) { PanelWidget *panel = PANEL_WIDGET(BASEP_WIDGET(panelw)->panel); SnappedWidget *snapped = SNAPPED_WIDGET(panelw); panel_widget_setup(panel); gtk_signal_connect(GTK_OBJECT(panelw), "pos_change", GTK_SIGNAL_FUNC(basep_pos_change), NULL); gtk_signal_connect(GTK_OBJECT(panelw), "state_change", GTK_SIGNAL_FUNC(snapped_state_change), NULL); /*this is a base panel*/ base_panels++; } else if(IS_CORNER_WIDGET(panelw)) { PanelWidget *panel = PANEL_WIDGET(BASEP_WIDGET(panelw)->panel); CornerWidget *corner = CORNER_WIDGET(panelw); panel_widget_setup(panel); gtk_signal_connect(GTK_OBJECT(panel), "orient_change", GTK_SIGNAL_FUNC(panel_orient_change), NULL); gtk_signal_connect(GTK_OBJECT(panelw), "pos_change", GTK_SIGNAL_FUNC(basep_pos_change), NULL); gtk_signal_connect(GTK_OBJECT(panelw), "state_change", GTK_SIGNAL_FUNC(corner_state_change), NULL); /*this is a base panel*/ base_panels++; } else g_warning("unknown panel type"); basep_widget_disable_buttons(basep); gtk_signal_connect(GTK_OBJECT(panelw), "event", GTK_SIGNAL_FUNC(panel_event),pd); gtk_widget_set_events(panelw, gtk_widget_get_events(panelw) | PANEL_EVENT_MASK); gtk_signal_connect(GTK_OBJECT(panelw), "destroy", GTK_SIGNAL_FUNC(panel_destroy),NULL); if(GTK_WIDGET_REALIZED(GTK_WIDGET(panelw))) panel_realize(GTK_WIDGET(panelw),NULL); else gtk_signal_connect_after(GTK_OBJECT(panelw), "realize", GTK_SIGNAL_FUNC(panel_realize), NULL); } /*send state change to all the panels*/ void send_state_change(void) { GSList *list; for(list = panel_list; list != NULL; list = g_slist_next(list)) { PanelData *pd = list->data; if(IS_SNAPPED_WIDGET(pd->panel)) snapped_state_change(pd->panel, SNAPPED_WIDGET(pd->panel)->state, NULL); else if(IS_CORNER_WIDGET(pd->panel)) corner_state_change(pd->panel, CORNER_WIDGET(pd->panel)->state, NULL); } } /* Destroy all panels - called upon exit */ void destroy_all_panels(void) { GSList *list = panel_list; while (list) { PanelData *pd = list->data; GSList *tmp = list->next; gtk_widget_destroy (pd->panel); list = tmp; } g_slist_free (panel_list); panel_list = NULL; }