Index: client.c =================================================================== --- client.c (revision 17010) +++ client.c (working copy) @@ -3138,10 +3138,15 @@ { if (xevent->xmotion.y_root - passdata->my > 15) { + /* to keep the distance from the edges of the window proportional. */ + double xratio, yratio; + xratio = (xevent->xmotion.x_root - c->x)/(double)c->width; + yratio = (xevent->xmotion.y_root - c->y)/(double)c->width; + clientToggleMaximized (c, WIN_STATE_MAXIMIZED, FALSE); passdata->move_resized = TRUE; passdata->ox = c->x; - passdata->mx = c->x + c->width / 2; + passdata->mx = c->x + c->width * xratio; passdata->oy = c->y; passdata->my = c->y - frameTop(c) / 2; toggled_maximize = TRUE; @@ -3823,6 +3828,7 @@ { ClientCycleData *passdata = (ClientCycleData *) data; Client *c = passdata->c; + Client *tmp; ScreenInfo *screen_info = c->screen_info; DisplayInfo *display_info = screen_info->display_info; XfceFilterStatus status = XEV_FILTER_STOP; @@ -3840,11 +3846,16 @@ switch (xevent->type) { case DestroyNotify: - gone |= (c == clientGetFromWindow (screen_info, ((XDestroyWindowEvent *) xevent)->window, WINDOW)); + tmp = clientGetFromWindow (screen_info, ((XDestroyWindowEvent *) xevent)->window, WINDOW); + gone |= (c == tmp); + tabwinRemoveClient(passdata->tabwin, tmp); status = XEV_FILTER_CONTINUE; /* Walk through */ case UnmapNotify: - gone |= (c == clientGetFromWindow (screen_info, ((XUnmapEvent *) xevent)->window, WINDOW)); + tmp = clientGetFromWindow (screen_info, ((XUnmapEvent *) xevent)->window, WINDOW); + gone |= (c == tmp); + tabwinRemoveClient(passdata->tabwin, tmp); + status = XEV_FILTER_CONTINUE; /* Walk through */ case KeyPress: @@ -3858,11 +3869,13 @@ { TRACE ("Cycle: previous"); c2 = clientGetPrevious (c, passdata->cycle_range); + tabwinSelectPrev(passdata->tabwin); } else { TRACE ("Cycle: next"); c2 = clientGetNext (c, passdata->cycle_range); + tabwinSelectNext(passdata->tabwin); } if (c2) { @@ -3874,16 +3887,13 @@ { /* Jump to the next one if the current has vanished! */ c = clientGetNext (c, passdata->cycle_range); + passdata->c = c; } if (c) { - GdkPixbuf *icon; - wireframeUpdate (c, passdata->wireframe); - icon = getAppIcon (display_info, c->window, 32, 32); - tabwinSetLabel (passdata->tabwin, icon, c->class.res_class, c->name); } else { @@ -3983,8 +3993,7 @@ TRACE ("entering cycle loop"); passdata.wireframe = wireframeCreate (passdata.c); icon = getAppIcon (display_info, passdata.c->window, 32, 32); - passdata.tabwin = tabwinCreate (passdata.c->screen_info->gscr, icon, - passdata.c->class.res_class, passdata.c->name); + passdata.tabwin = tabwinCreate (passdata.c->screen_info->gscr, c, passdata.cycle_range); xfce_push_event_filter (display_info->xfilter, clientCycle_event_filter, &passdata); gtk_main (); xfce_pop_event_filter (display_info->xfilter); Index: tabwin.c =================================================================== --- tabwin.c (revision 17010) +++ tabwin.c (working copy) @@ -22,148 +22,243 @@ #include #endif +#define WIN_ICON_SIZE 48 + #include #include #include #include #include #include "inline-tabwin-icon.h" +#include "icons.h" +#include "focus.h" #include "tabwin.h" + +static gboolean +paint_selected(GtkWidget *w, GdkEventExpose *event, gpointer data) +{ + gtk_paint_box(w->style, w->window, + GTK_STATE_SELECTED, + GTK_SHADOW_ETCHED_IN, + NULL, w, NULL, + w->allocation.x-3, + w->allocation.y-3, + w->allocation.width+3, + w->allocation.height+3); + return FALSE; +} + +static gchar * +pretty_string (const gchar *s) +{ + gchar *canonical; + gchar *markup; + + if (s) + { + canonical = g_strdup (s); + g_strcanon (canonical, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[]~!@#$%^&*()_+=-`", ' '); + g_strstrip (canonical); + *canonical = g_ascii_toupper (*canonical); + } + else + { + canonical = g_strdup(_("Unknown application!")); + } + markup = g_strdup_printf ("%s", canonical); + g_free (canonical); + return markup; +} + +static void +tabwinSetLabel(Tabwin *t, gchar *label) +{ + gchar *markup; + gchar *str; + + str = pretty_string(label); + markup = g_strconcat ("", str, "", NULL); + gtk_label_set_markup(GTK_LABEL(t->label), markup); + gtk_widget_modify_fg (t->label, GTK_STATE_NORMAL, &t->label->style->fg[GTK_STATE_SELECTED]); + + g_free(str); + g_free(markup); +} + +static void +tabwinSetSelected(Tabwin *t, GtkWidget *w) +{ + Client *c; + if (t->selected_callback) + g_signal_handler_disconnect(t->current->data, t->selected_callback); + t->selected_callback=g_signal_connect(G_OBJECT(w), "expose-event", G_CALLBACK(paint_selected), NULL); + c = g_object_get_data(G_OBJECT(w), "client-ptr-val"); + + tabwinSetLabel(t, c->name); +} + +static GtkWidget * +createWindowIcon(Client *c) +{ + GdkPixbuf *icon_pixbuf; + GtkWidget *icon; + + icon_pixbuf = getAppIcon(c->screen_info->display_info, c->window, WIN_ICON_SIZE, WIN_ICON_SIZE); + icon = gtk_image_new(); + g_object_set_data(G_OBJECT(icon), "client-ptr-val", c); + if (icon_pixbuf) + gtk_image_set_from_pixbuf(GTK_IMAGE(icon), icon_pixbuf); + else + gtk_image_set_from_stock(GTK_IMAGE(icon), "gtk-missing-image", GTK_ICON_SIZE_DIALOG); + return icon; +} + +static GtkWidget * +createWindowlist(GdkScreen *scr, Client *c, unsigned int cycle_range, Tabwin *t) +{ + GdkRectangle monitor_sz; + gint monitor; + GtkWidget *windowlist; + Client *c2 = NULL; + ScreenInfo *screen_info; + unsigned int grid_cols; + unsigned int n_clients; + unsigned int grid_rows; + int i=0, packpos=0; + GtkWidget *icon; + + screen_info = c->screen_info; + xfce_gdk_display_locate_monitor_with_pointer(screen_info->display_info->gdisplay, &monitor); + gdk_screen_get_monitor_geometry (scr, monitor, &monitor_sz); + /*add the width of the 7px border on each side*/ + grid_cols = (monitor_sz.width/(WIN_ICON_SIZE+14))*0.75; + printf("grid cols:%d\n", grid_cols); + printf("Monitor width %d\n\n\n\n\n", monitor_sz.width); + sleep(2); + + n_clients = screen_info->client_count; + grid_rows = n_clients/grid_cols + 1; + windowlist = gtk_table_new(grid_rows, grid_cols, FALSE); + + t->grid_cols = grid_cols; + t->grid_rows = grid_rows; + for (c2=c,i=0; c2 && i< n_clients; i++, c2=c2->next) + { + if (!clientSelectMask (c2, cycle_range, WINDOW_NORMAL | WINDOW_DIALOG | WINDOW_MODAL_DIALOG)) + continue; + icon = createWindowIcon(c2); + gtk_table_attach(GTK_TABLE(windowlist), GTK_WIDGET(icon), + packpos%grid_cols, packpos%grid_cols+1, + packpos/grid_cols, packpos/grid_cols + 1, + GTK_FILL, GTK_FILL, + 7,7); + packpos++; + t->head=g_list_append(t->head, icon); + } + /*circlify the list for easier cycling*/ + t->head->prev=g_list_last(t->head); + t->head->prev->next=t->head; + + t->current=t->head->next; + tabwinSetSelected(t, t->current->data); + return windowlist; +} + Tabwin * -tabwinCreate (GdkScreen *gscr, GdkPixbuf *icon, const gchar * class, const gchar * label) +tabwinCreate(GdkScreen *scr, Client *c, unsigned int cycle_range) { static GdkPixbuf *logo = NULL; Tabwin *tabwin; + GtkWidget *header; GtkWidget *frame; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *header; - + GtkWidget *vbox, *header_hbox; + GtkWidget *windowlist; + tabwin = g_new (Tabwin, 1); - + memset(tabwin, 0, sizeof(Tabwin)); if (!logo) { logo = xfce_inline_icon_at_size (tabwin_icon_data, 32, 32); g_object_ref (G_OBJECT (logo)); } - tabwin->window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_window_set_screen (GTK_WINDOW (tabwin->window), gscr); - gtk_container_set_border_width (GTK_CONTAINER (tabwin->window), 0); + + tabwin->window = gtk_window_new(GTK_WINDOW_POPUP); + gtk_window_set_screen(GTK_WINDOW(tabwin->window), scr); + gtk_container_set_border_width(GTK_CONTAINER(tabwin->window), 0); gtk_window_set_position (GTK_WINDOW (tabwin->window), GTK_WIN_POS_CENTER_ALWAYS); - gtk_window_set_default_size (GTK_WINDOW (tabwin->window), 400, -1); - gtk_widget_set_size_request (tabwin->window, 400, -1); - gtk_window_set_resizable (GTK_WINDOW (tabwin->window), FALSE); - - frame = gtk_frame_new (NULL); + frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_container_set_border_width (GTK_CONTAINER (frame), 0); gtk_container_add (GTK_CONTAINER (tabwin->window), frame); - gtk_widget_show (frame); vbox = gtk_vbox_new (FALSE, 5); - gtk_widget_show (vbox); gtk_container_set_border_width (GTK_CONTAINER (vbox), 5); gtk_container_add (GTK_CONTAINER (frame), vbox); - header = xfce_create_header (logo, _("Switch to ...")); - gtk_widget_show (header); + header = xfce_create_header (logo, _("Switch to:")); gtk_box_pack_start (GTK_BOX (vbox), header, FALSE, TRUE, 0); - + header_hbox = gtk_bin_get_child(GTK_BIN(header)); + tabwin->label = gtk_label_new(" "); + gtk_box_pack_start(GTK_BOX(header_hbox), tabwin->label, FALSE, FALSE, 0); + frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); gtk_container_set_border_width (GTK_CONTAINER (frame), 0); gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); - gtk_widget_show (frame); - hbox = gtk_hbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); - gtk_widget_show (hbox); - gtk_container_add (GTK_CONTAINER (frame), hbox); + windowlist = createWindowlist(scr, c, cycle_range, tabwin); + tabwin->container=windowlist; + gtk_container_add(GTK_CONTAINER(frame), windowlist); - tabwin->image = gtk_image_new (); - gtk_widget_show (tabwin->image); - gtk_box_pack_start (GTK_BOX (hbox), tabwin->image, FALSE, TRUE, 0); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_widget_show (vbox); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 2); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, TRUE, 0); - - tabwin->class = gtk_label_new (""); - gtk_label_set_use_markup (GTK_LABEL (tabwin->class), TRUE); - gtk_misc_set_alignment (GTK_MISC (tabwin->class), 0.0, 0.5); - gtk_widget_show (tabwin->class); - gtk_box_pack_start (GTK_BOX (vbox), tabwin->class, FALSE, TRUE, 0); - - tabwin->label = gtk_label_new (""); - gtk_label_set_use_markup (GTK_LABEL (tabwin->label), FALSE); - gtk_misc_set_alignment (GTK_MISC (tabwin->label), 0.0, 0.5); - gtk_widget_show (tabwin->label); - gtk_box_pack_start (GTK_BOX (vbox), tabwin->label, FALSE, TRUE, 0); - - tabwinSetLabel (tabwin, icon, class, label); - - gtk_widget_show (tabwin->window); - + gtk_widget_show_all(tabwin->window); return tabwin; } -/* Efficiency is definitely *not* the goal here! */ -static gchar * -pretty_string (const gchar *s) +void +tabwinRemoveClient(Tabwin *t, Client *c) { - gchar *canonical; - gchar *markup; + GList *tmp; + tmp=t->head; + do { + if (((Client *)g_object_get_data(tmp->data, "client-ptr-val")) == c) + { + if (tmp == t->current) + tabwinSelectNext(t); + gtk_container_remove(GTK_CONTAINER(t->container), tmp->data); + t->head = g_list_delete_link(t->head, tmp); + TRACE("Removed Client\n"); + } + /*since this is a circular list, hitting head signals end, not hitting NULL*/ + }while ((tmp=tmp->next) && (tmp!=t->head)); - if (s) - { - canonical = g_strdup (s); - g_strcanon (canonical, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", ' '); - g_strstrip (canonical); - *canonical = g_ascii_toupper (*canonical); - } - else - { - canonical = g_strdup(_("Unknown application!")); - } - markup = g_strdup_printf ("%s", canonical); - g_free (canonical); - return markup; } void -tabwinSetLabel (Tabwin * tabwin, GdkPixbuf *icon, const gchar * class, const gchar * label) +tabwinSelectNext (Tabwin * t) { - gchar* message; - - g_return_if_fail (tabwin != NULL); - - message = pretty_string (class); - gtk_label_set_use_markup (GTK_LABEL (tabwin->class), TRUE); - gtk_label_set_markup (GTK_LABEL (tabwin->class), message); - g_free (message); - gtk_label_set_text (GTK_LABEL (tabwin->label), label); + tabwinSetSelected(t, t->current->next->data); + t->current=t->current->next; + gtk_widget_queue_draw(t->window); +} - if (icon) - { - gtk_image_set_from_pixbuf (GTK_IMAGE (tabwin->image), icon); - g_object_unref(icon); - } - else - { - gtk_image_set_from_stock (GTK_IMAGE (tabwin->image), "gtk-missing-image", - GTK_ICON_SIZE_DIALOG); - } - - gtk_widget_queue_draw (tabwin->window); +void +tabwinSelectPrev (Tabwin *t) +{ + tabwinSetSelected(t, t->current->prev->data); + t->current=t->current->prev; + gtk_widget_queue_draw(t->window); } void tabwinDestroy (Tabwin * tabwin) { g_return_if_fail (tabwin != NULL); - + /* un-circlify the list so we don't infinitely loop + * while freeing*/ + tabwin->head->prev->next=NULL; + tabwin->head->prev=NULL; + g_list_free(tabwin->head); gtk_widget_destroy (tabwin->window); } Index: tabwin.h =================================================================== --- tabwin.h (revision 17010) +++ tabwin.h (working copy) @@ -32,14 +32,23 @@ typedef struct _Tabwin Tabwin; struct _Tabwin { + /*The below must be freed when destroying*/ GtkWidget *window; - GtkWidget *image; - GtkWidget *class; + GList *head; + /*these don't have to be*/ GtkWidget *label; + GtkWidget *container; + GList *current; + gulong selected_callback; + int grid_cols; + int grid_rows; }; -Tabwin *tabwinCreate (GdkScreen *, GdkPixbuf *, const gchar *, const gchar *); -void tabwinSetLabel (Tabwin *, GdkPixbuf *, const gchar *, const gchar *); +Tabwin *tabwinCreate (GdkScreen *, Client *c, unsigned int cycle_range); +void tabwinSelectNext (Tabwin *); +void tabwinSelectPrev (Tabwin *); +void tabwinRemoveClient(Tabwin *t, Client *c); void tabwinDestroy (Tabwin *); +void tabwinAppendClient(Tabwin *t, Client *c, int cycle_range); #endif /* INC_TABWIN_H */