/* * GNOME panel swallow module. * (C) 1997 The Free Software Foundation * * Author: George Lebl */ #include #include #include #include #include #include #include #include #include "panel-include.h" #include "panel-widget.h" /* from gtkhandlebox.c */ #define DRAG_HANDLE_SIZE 10 extern PanelWidget *current_panel; static int ignore_x_error(Display* d, XErrorEvent* e) { fprintf(stderr, "ignore_x_error called\n"); return 0; } static int get_window_id(Window win, char *title, guint32 *wid) { Window root_return; Window parent_return; Window *children; unsigned int nchildren; unsigned int i; char *tit; int ret = FALSE; int (*oldErrorHandler)(Display*, XErrorEvent*); XQueryTree(GDK_DISPLAY(), win, &root_return, &parent_return, &children, &nchildren); oldErrorHandler = XSetErrorHandler(ignore_x_error); for(i=0;ititle, &(swallow->wid))) return TRUE; swallow->timeout = -1; gtk_socket_steal(GTK_SOCKET(swallow->socket),swallow->wid); return FALSE; } static int socket_realized(GtkWidget *w, gpointer data) { Swallow *swallow = gtk_object_get_user_data(GTK_OBJECT(w)); g_return_val_if_fail(swallow->title!=NULL,FALSE); if(!get_window_id(GDK_ROOT_WINDOW(),swallow->title, &swallow->wid)) swallow->timeout = gtk_timeout_add(500, (GtkFunction)socket_getwindow_timeout, swallow); else gtk_socket_steal(GTK_SOCKET(swallow->socket),swallow->wid); return FALSE; } static void socket_destroyed(GtkWidget *w, gpointer data) { Swallow *swallow = data; if(swallow->timeout!=-1) { gtk_timeout_remove(swallow->timeout); swallow->timeout = -1; } gtk_widget_destroy(swallow->ebox); g_free(swallow->title); g_free(swallow->path); g_free(swallow); } static int swallow_detached (GtkWidget *handle_box, gpointer data) { Swallow *swallow = gtk_object_get_data(GTK_OBJECT(handle_box), "swallow_obj"); if(GPOINTER_TO_INT(gtk_object_get_user_data (GTK_OBJECT(handle_box)))==SWALLOW_VERTICAL) { GTK_HANDLE_BOX(handle_box)->handle_position = GTK_POS_TOP; gtk_widget_set_usize( swallow->handle_box, swallow->width, DRAG_HANDLE_SIZE); } else { GTK_HANDLE_BOX(handle_box)->handle_position = GTK_POS_LEFT; gtk_widget_set_usize( handle_box, DRAG_HANDLE_SIZE, swallow->height ); } gtk_widget_queue_resize ( GTK_WIDGET(swallow->ebox) ); return FALSE; } static int swallow_attached (GtkWidget *handle_box, gpointer data) { Swallow *swallow = gtk_object_get_data(GTK_OBJECT(handle_box), "swallow_obj"); if(GPOINTER_TO_INT(gtk_object_get_user_data (GTK_OBJECT(handle_box)))== SWALLOW_VERTICAL) { GTK_HANDLE_BOX(handle_box)->handle_position = GTK_POS_TOP; gtk_widget_set_usize( handle_box, swallow->width, swallow->height + DRAG_HANDLE_SIZE); } else { GTK_HANDLE_BOX(handle_box)->handle_position = GTK_POS_LEFT; gtk_widget_set_usize( handle_box, swallow->width + DRAG_HANDLE_SIZE, swallow->height); } gtk_widget_queue_resize ( GTK_WIDGET(swallow->ebox) ); return FALSE; } static void really_add_swallow(GtkWidget *d,int button, gpointer data) { GtkWidget *title_e = gtk_object_get_data(GTK_OBJECT(d),"title_e"); GtkWidget *exec_e = gtk_object_get_data(GTK_OBJECT(d),"exec_e"); GtkWidget *width_s = gtk_object_get_data(GTK_OBJECT(d),"width_s"); GtkWidget *height_s = gtk_object_get_data(GTK_OBJECT(d),"height_s"); PanelWidget *panel = gtk_object_get_data(GTK_OBJECT(d),"panel"); int pos = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(d),"pos")); if(button!=0) { gtk_widget_destroy(d); return; } load_swallow_applet(gtk_entry_get_text(GTK_ENTRY(exec_e)), gtk_entry_get_text(GTK_ENTRY(title_e)), gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(width_s)), gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(height_s)), panel, pos); gtk_widget_destroy(d); } static void act_really_add_swallow(GtkWidget *w, gpointer data) { GtkWidget *d = data; /*just call the above handler for the dialog*/ really_add_swallow(d,0,NULL); } /*I couldn't resist the naming of this function*/ void ask_about_swallowing(PanelWidget *panel, int pos) { GtkWidget *d; GtkWidget *title_e; GtkWidget *exec_e; GtkWidget *width_s; GtkWidget *height_s; GtkWidget *w; GtkWidget *box, *i_box; GtkAdjustment *adj; d = gnome_dialog_new(_("Create swallow applet"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); gtk_window_set_wmclass(GTK_WINDOW(d), "create_swallow","Panel"); /*gtk_window_set_position(GTK_WINDOW(d), GTK_WIN_POS_CENTER);*/ gtk_window_set_policy(GTK_WINDOW(d), FALSE, FALSE, TRUE); gtk_object_set_data(GTK_OBJECT(d),"panel",panel); gtk_object_set_data(GTK_OBJECT(d),"pos",GINT_TO_POINTER(pos)); box = gtk_hbox_new(FALSE,GNOME_PAD_SMALL); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox),box, TRUE,TRUE,0); w = gtk_label_new(_("Title of application to swallow")); gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0); w = gnome_entry_new("swallow_title"); gtk_box_pack_start(GTK_BOX(box),w,TRUE,TRUE,0); title_e = gnome_entry_gtk_entry(GNOME_ENTRY(w)); gtk_signal_connect(GTK_OBJECT(title_e),"activate", GTK_SIGNAL_FUNC(act_really_add_swallow),d); box = gtk_hbox_new(FALSE,GNOME_PAD_SMALL); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox),box, TRUE,TRUE,0); w = gtk_label_new(_("Command (optional)")); gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0); w = gnome_file_entry_new("execute",_("Browse")); gtk_box_pack_start(GTK_BOX(box),w,TRUE,TRUE,0); exec_e = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (w)); gtk_signal_connect(GTK_OBJECT(exec_e),"activate", GTK_SIGNAL_FUNC(act_really_add_swallow),d); box = gtk_hbox_new(FALSE,GNOME_PAD_SMALL); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox),box, TRUE,TRUE,0); w = gtk_label_new(_("Width")); gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0); adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 5.0, 0.0); gtk_adjustment_set_value(adj, PANEL_MINIMUM_WIDTH); width_s = gtk_spin_button_new(adj,0,0); gtk_box_pack_start(GTK_BOX(box),width_s,FALSE,FALSE,0); i_box =gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(box), i_box, FALSE, FALSE, GNOME_PAD_SMALL); w = gtk_label_new(_("Height")); gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0); adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 5.0, 0.0); gtk_adjustment_set_value(adj, PANEL_MINIMUM_WIDTH); height_s = gtk_spin_button_new(adj,0,0); gtk_box_pack_start(GTK_BOX(box),height_s,FALSE,FALSE,0); gtk_signal_connect(GTK_OBJECT(d),"clicked", GTK_SIGNAL_FUNC(really_add_swallow),NULL); gtk_object_set_data(GTK_OBJECT(d),"title_e",title_e); gtk_object_set_data(GTK_OBJECT(d),"exec_e",exec_e); gtk_object_set_data(GTK_OBJECT(d),"width_s",width_s); gtk_object_set_data(GTK_OBJECT(d),"height_s",height_s); gnome_dialog_close_hides(GNOME_DIALOG(d),FALSE); gnome_dialog_set_default(GNOME_DIALOG(d),0); gtk_widget_grab_focus(title_e); gtk_widget_show_all(d); } static int ignore_1st_click(GtkWidget *w, GdkEvent *e) { GdkEventButton *be = (GdkEventButton *)e; if(e->type == GDK_BUTTON_PRESS && be->button == 1) { gtk_signal_emit_stop_by_name(GTK_OBJECT(w),"event"); return TRUE; } return FALSE; } static Swallow * create_swallow_applet(char *title, char *path, int width, int height, SwallowOrient orient) { Swallow *swallow; GtkWidget *w; GtkWidget *table; GtkWidget *handle_box; swallow = g_new(Swallow,1); swallow->ebox = gtk_event_box_new(); gtk_widget_show(swallow->ebox); swallow->socket=gtk_socket_new(); if(width != 0 || height != 0) gtk_widget_set_usize(swallow->socket, width, height); gtk_signal_connect_after(GTK_OBJECT(swallow->socket),"realize", GTK_SIGNAL_FUNC(socket_realized), NULL); gtk_signal_connect(GTK_OBJECT(swallow->socket),"destroy", GTK_SIGNAL_FUNC(socket_destroyed), swallow); swallow->handle_box = gtk_handle_box_new(); gtk_signal_connect(GTK_OBJECT(swallow->handle_box),"event", GTK_SIGNAL_FUNC(ignore_1st_click),NULL); gtk_container_add ( GTK_CONTAINER(swallow->ebox), swallow->handle_box ); w = gtk_frame_new(NULL); gtk_frame_set_shadow_type( GTK_FRAME(w), GTK_SHADOW_IN); gtk_container_add ( GTK_CONTAINER(swallow->handle_box), w ); gtk_widget_show ( swallow->handle_box ); /* FIXME: I want to add the title of the swallowed window. E.g. a Pager is "sticky", but having a pager in a handlebox is not -> clicking will change the desktop, but leave the pager behind :-( Below is one of the non working versions... */ /*gdk_window_set_title(GTK_HANDLE_BOX(swallow->handle_box)->float_window, g_strdup(title));*/ gtk_container_add ( GTK_CONTAINER(w), swallow->socket ); gtk_widget_show(swallow->socket); gtk_object_set_user_data(GTK_OBJECT(swallow->socket),swallow); swallow->title = g_strdup(title); swallow->path = path?g_strdup(path):NULL; swallow->width = width; swallow->height = height; swallow->wid = -1; swallow->timeout = -1; set_swallow_applet_orient(swallow, orient); return swallow; } void set_swallow_applet_orient(Swallow *swallow, SwallowOrient orient) { if (GTK_HANDLE_BOX(swallow->handle_box)->child_detached) { if(orient==SWALLOW_VERTICAL) { GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_TOP; gtk_widget_set_usize( swallow->handle_box, swallow->width, DRAG_HANDLE_SIZE); } else { GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_LEFT; gtk_widget_set_usize( swallow->handle_box, DRAG_HANDLE_SIZE, swallow->height ); } } else { if(orient==SWALLOW_VERTICAL) { GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_TOP; gtk_widget_set_usize( swallow->handle_box, swallow->width, swallow->height + DRAG_HANDLE_SIZE); } else { GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_LEFT; gtk_widget_set_usize( swallow->handle_box, swallow->width + DRAG_HANDLE_SIZE, swallow->height ); } } gtk_object_set_user_data(GTK_OBJECT(swallow->handle_box), GINT_TO_POINTER(orient)); } void load_swallow_applet(char *path, char *params, int width, int height, PanelWidget *panel, int pos) { Swallow *swallow; swallow = create_swallow_applet(params, path, width, height, SWALLOW_HORIZONTAL); if(!swallow) return; register_toy(swallow->ebox,swallow, panel, pos, APPLET_SWALLOW); if(path && *path) { char *p = strrchr(path,'.'); /*only if such a file exists and ends in a .desktop, should we try to launch it as such*/ if(p && strcmp(p,".desktop")==0 && g_file_exists(path)) { GnomeDesktopEntry *item; item = gnome_desktop_entry_load(path); gnome_desktop_entry_launch(item); gnome_desktop_entry_free(item); } else { char *s = g_strconcat("(true; ",path," &)",NULL); system(s); g_free(s); } } }