[Xfce4-commits] [xfce/xfwm4] 03/05: Rework tabwin

noreply at xfce.org noreply at xfce.org
Sat Jan 24 22:41:07 CET 2015


This is an automated email from the git hooks/post-receive script.

olivier pushed a commit to branch master
in repository xfce/xfwm4.

commit 33c27c448fa623dd1d497eb3e72f9daf9d94ea36
Author: Olivier Fourdan <fourdan at xfce.org>
Date:   Sat Jan 24 21:33:46 2015 +0100

    Rework tabwin
    
    Tabwin code was quite inefficient as it would retrieve all icons and
    recompute all sizes for every tabwin widget.
    
    While it wouldn't show much with (relatively) tiny application icons, it
    became much more apparent with content preview.
    
    Move the icons to the tabwin class instead and reuse the same list for
    all the tabwin widgets, so that the computation is done only once.
    
    Also includes various code cleanup.
    
    Signed-off-by: Olivier Fourdan <fourdan at xfce.org>
---
 src/tabwin.c |  746 ++++++++++++++++++++++++++++++++++------------------------
 src/tabwin.h |   12 +-
 2 files changed, 442 insertions(+), 316 deletions(-)

diff --git a/src/tabwin.c b/src/tabwin.c
index 9ec6bb3..023018f 100644
--- a/src/tabwin.c
+++ b/src/tabwin.c
@@ -16,7 +16,7 @@
         MA 02110-1301, USA.
 
 
-        xfwm4    - (c) 2002-2011 Olivier Fourdan
+        xfwm4    - (c) 2002-2015 Olivier Fourdan
 
  */
 
@@ -28,8 +28,12 @@
 #define WIN_ICON_SIZE 48
 #endif
 
+#ifndef WIN_PREVIEW_SIZE
+#define WIN_PREVIEW_SIZE (5 * WIN_ICON_SIZE)
+#endif
+
 #ifndef LISTVIEW_WIN_ICON_SIZE
-#define LISTVIEW_WIN_ICON_SIZE 24
+#define LISTVIEW_WIN_ICON_SIZE (WIN_ICON_SIZE / 2)
 #endif
 
 #ifndef WIN_ICON_BORDER
@@ -60,6 +64,7 @@
 #include "focus.h"
 #include "tabwin.h"
 #include "settings.h"
+#include "compositor.h"
 
 static void tabwin_widget_class_init (TabwinWidgetClass *klass);
 
@@ -113,26 +118,26 @@ get_color (GtkWidget *win, GtkStateType state_type)
 }
 
 static gboolean
-tabwin_expose (GtkWidget *tbw, GdkEventExpose *event, gpointer data)
+tabwin_expose (GtkWidget *tabwin_widget, GdkEventExpose *event, gpointer data)
 {
     GdkScreen *screen;
     cairo_t *cr;
-    GdkColor *bg_normal = get_color(tbw, GTK_STATE_NORMAL);
-    GdkColor *bg_selected = get_color(tbw, GTK_STATE_SELECTED);
+    GdkColor *bg_normal = get_color (tabwin_widget, GTK_STATE_NORMAL);
+    GdkColor *bg_selected = get_color (tabwin_widget, GTK_STATE_SELECTED);
     gint border_width = WIN_BORDER_WIDTH;
     gdouble border_alpha = WIN_BORDER_ALPHA;
     gdouble alpha = WIN_ALPHA;
     gint border_radius = WIN_BORDER_RADIUS;
     gdouble degrees = G_PI / 180.0;
-    gdouble width = tbw->allocation.width;
-    gdouble height = tbw->allocation.height;
+    gdouble width = tabwin_widget->allocation.width;
+    gdouble height = tabwin_widget->allocation.height;
 
-    screen = gtk_widget_get_screen(GTK_WIDGET(tbw));
-    cr = gdk_cairo_create (tbw->window);
+    screen = gtk_widget_get_screen (GTK_WIDGET(tabwin_widget));
+    cr = gdk_cairo_create (tabwin_widget->window);
     if (G_UNLIKELY (cr == NULL))
       return FALSE;
 
-    gtk_widget_style_get (GTK_WIDGET (tbw),
+    gtk_widget_style_get (GTK_WIDGET (tabwin_widget),
                             "border-width", &border_width,
                             "border-alpha", &border_alpha,
                             "alpha", &alpha,
@@ -142,31 +147,53 @@ tabwin_expose (GtkWidget *tbw, GdkEventExpose *event, gpointer data)
 
     if (gdk_screen_is_composited (screen))
     {
-        cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
-        gdk_cairo_region(cr, event->region);
-        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0);
-        cairo_fill_preserve(cr);
-        cairo_clip(cr);
-        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+        cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+        gdk_cairo_region (cr, event->region);
+        cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
+        cairo_fill_preserve (cr);
+        cairo_clip (cr);
+        cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
         /* Draw a filled rounded rectangle with an outline */
-        cairo_arc (cr, width - border_radius - 0.5, border_radius + 0.5, border_radius, -90 * degrees, 0 * degrees);
-        cairo_arc (cr, width - border_radius - 0.5, height - border_radius - 0.5, border_radius, 0 * degrees, 90 * degrees);
-        cairo_arc (cr, border_radius + 0.5, height - border_radius - 0.5, border_radius, 90 * degrees, 180 * degrees);
-        cairo_arc (cr, border_radius + 0.5, border_radius + 0.5, border_radius, 180 * degrees, 270 * degrees);
+        cairo_arc (cr, width - border_radius - 0.5,
+                       border_radius + 0.5,
+                       border_radius,
+                       -90 * degrees,
+                         0 * degrees);
+        cairo_arc (cr, width - border_radius - 0.5,
+                       height - border_radius - 0.5,
+                       border_radius,
+                        0 * degrees,
+                       90 * degrees);
+        cairo_arc (cr, border_radius + 0.5,
+                       height - border_radius - 0.5,
+                       border_radius,
+                        90 * degrees,
+                       180 * degrees);
+        cairo_arc (cr, border_radius + 0.5,
+                       border_radius + 0.5,
+                       border_radius,
+                       180 * degrees,
+                       270 * degrees);
         cairo_close_path(cr);
-        cairo_set_source_rgba (cr, bg_normal->red/65535.0, bg_normal->green/65535.0, bg_normal->blue/65535.0, alpha);
+        cairo_set_source_rgba (cr, bg_normal->red / 65535.0,
+                                   bg_normal->green / 65535.0,
+                                   bg_normal->blue / 65535.0,
+                                   alpha);
         cairo_fill_preserve (cr);
-        cairo_set_source_rgba (cr, bg_selected->red/65535.0, bg_selected->green/65535.0, bg_selected->blue/65535.0, border_alpha);
+        cairo_set_source_rgba (cr, bg_selected->red / 65535.0,
+                                   bg_selected->green / 65535.0,
+                                   bg_selected->blue / 65535.0,
+                                   border_alpha);
         cairo_stroke (cr);
     }
     else
     {
-        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-        cairo_rectangle(cr, 0, 0, width, height);
-        gdk_cairo_set_source_color(cr, bg_normal);
+        cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+        cairo_rectangle (cr, 0, 0, width, height);
+        gdk_cairo_set_source_color (cr, bg_normal);
         cairo_fill_preserve (cr);
-        gdk_cairo_set_source_color(cr, bg_selected);
+        gdk_cairo_set_source_color (cr, bg_selected);
         cairo_stroke (cr);
     }
 
@@ -177,12 +204,12 @@ tabwin_expose (GtkWidget *tbw, GdkEventExpose *event, gpointer data)
 static gboolean
 paint_selected (GtkWidget *w, GdkEventExpose *event, gpointer user_data)
 {
-    TabwinWidget *tbw = user_data;
+    TabwinWidget *tabwin_widget = user_data;
 
     g_return_val_if_fail (GTK_IS_WIDGET(w), FALSE);
     TRACE ("entering paint_selected");
 
-    if (w == tbw->hovered)
+    if (w == tabwin_widget->hovered)
     {
         gtk_widget_set_state (w, GTK_STATE_ACTIVE);
     }
@@ -217,19 +244,19 @@ pretty_string (const gchar *s)
 }
 
 static void
-tabwinSetLabel (TabwinWidget *tbw, GtkWidget *buttonlabel, gchar *class, gchar *label, int workspace)
+tabwinSetLabel (TabwinWidget *tabwin_widget, GtkWidget *buttonlabel, gchar *class, gchar *label, int workspace)
 {
     gchar *message;
     PangoLayout *layout;
 
-    g_return_if_fail (tbw);
+    g_return_if_fail (tabwin_widget);
     TRACE ("entering tabwinSetLabel");
 
     message = pretty_string (class);
     gtk_label_set_text (GTK_LABEL (buttonlabel), message);
     g_free (message);
 
-    if (tbw->tabwin->display_workspace)
+    if (tabwin_widget->tabwin->display_workspace)
     {
         message = g_strdup_printf ("[%i] - %s", workspace + 1, label);
     }
@@ -238,9 +265,9 @@ tabwinSetLabel (TabwinWidget *tbw, GtkWidget *buttonlabel, gchar *class, gchar *
         message = g_strdup_printf ("%s", label);
     }
 
-    gtk_label_set_text (GTK_LABEL (tbw->label), message);
+    gtk_label_set_text (GTK_LABEL (tabwin_widget->label), message);
     /* Need to update the layout after setting the text */
-    layout = gtk_label_get_layout (GTK_LABEL(tbw->label));
+    layout = gtk_label_get_layout (GTK_LABEL(tabwin_widget->label));
     pango_layout_set_auto_dir (layout, FALSE);
     /* the layout belong to the gtk_label and must not be freed */
 
@@ -248,26 +275,26 @@ tabwinSetLabel (TabwinWidget *tbw, GtkWidget *buttonlabel, gchar *class, gchar *
 }
 
 static void
-tabwinSetSelected (TabwinWidget *tbw, GtkWidget *w, GtkWidget *l)
+tabwinSetSelected (TabwinWidget *tabwin_widget, GtkWidget *w, GtkWidget *l)
 {
     Client *c;
     gchar *classname;
 
-    g_return_if_fail (tbw);
+    g_return_if_fail (tabwin_widget);
     g_return_if_fail (GTK_IS_WIDGET(w));
     TRACE ("entering tabwinSetSelected");
 
-    if (tbw->selected && tbw->selected_callback)
+    if (tabwin_widget->selected && tabwin_widget->selected_callback)
     {
-        g_signal_handler_disconnect (tbw->selected, tbw->selected_callback);
+        g_signal_handler_disconnect (tabwin_widget->selected, tabwin_widget->selected_callback);
     }
-    tbw->selected = w;
-    tbw->selected_callback = g_signal_connect (G_OBJECT (tbw->selected),
+    tabwin_widget->selected = w;
+    tabwin_widget->selected_callback = g_signal_connect (G_OBJECT (tabwin_widget->selected),
                                                "expose-event",
                                                G_CALLBACK (paint_selected),
-                                               tbw);
+                                               tabwin_widget);
 
-    c = g_object_get_data (G_OBJECT (tbw->selected), "client-ptr-val");
+    c = g_object_get_data (G_OBJECT (tabwin_widget->selected), "client-ptr-val");
 
     if (c != NULL)
     {
@@ -278,80 +305,63 @@ tabwinSetSelected (TabwinWidget *tbw, GtkWidget *w, GtkWidget *l)
         }
 
         classname = g_strdup(c->class.res_class);
-        tabwinSetLabel (tbw, l, classname, c->name, c->win_workspace);
+        tabwinSetLabel (tabwin_widget, l, classname, c->name, c->win_workspace);
         g_free (classname);
     }
 }
 
 static Client *
-tabwinSelectWidget (Tabwin *t)
+tabwinSelectWidget (Tabwin *tabwin)
 {
     GList *tabwin_list, *widgets, *selected;
     GtkWidget *window_button, *buttonbox, *buttonlabel;
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
     Client *c;
 
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
     TRACE ("entering tabwinSelectWidget");
 
-    for (tabwin_list = t->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
+    for (tabwin_list = tabwin->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
     {
-        tbw = (TabwinWidget *) tabwin_list->data;
-        for (widgets = tbw->widgets; widgets; widgets = g_list_next (widgets))
+        tabwin_widget = (TabwinWidget *) tabwin_list->data;
+        for (widgets = tabwin_widget->widgets; widgets; widgets = g_list_next (widgets))
         {
             window_button = GTK_WIDGET (widgets->data);
             gtk_button_set_relief (GTK_BUTTON (window_button), GTK_RELIEF_NONE);
-            buttonbox = GTK_WIDGET( gtk_container_get_children(GTK_CONTAINER (window_button))[0].data );
-            buttonlabel = GTK_WIDGET( g_list_nth_data( gtk_container_get_children (GTK_CONTAINER(buttonbox)), 1) );
+            buttonbox = GTK_WIDGET (gtk_container_get_children (GTK_CONTAINER (window_button))[0].data );
+            buttonlabel = GTK_WIDGET (g_list_nth_data (gtk_container_get_children (GTK_CONTAINER(buttonbox)), 1) );
             gtk_label_set_text (GTK_LABEL (buttonlabel), "");
 
             if (gtk_widget_is_focus (window_button))
             {
                 c = g_object_get_data (G_OBJECT (window_button), "client-ptr-val");
-                selected = g_list_find (*t->client_list, c);
+                selected = g_list_find (*tabwin->client_list, c);
 
                 if (selected)
                 {
-                    t->selected = selected;
+                    tabwin->selected = selected;
                 }
 
-                tabwinSetSelected (tbw, window_button, buttonlabel);
-                gtk_widget_queue_draw (GTK_WIDGET (tbw));
+                tabwinSetSelected (tabwin_widget, window_button, buttonlabel);
+                gtk_widget_queue_draw (GTK_WIDGET (tabwin_widget));
             }
         }
     }
 
-    return tabwinGetSelected (t);
+    return tabwinGetSelected (tabwin);
 }
 
 static GtkWidget *
-createWindowIcon (Client *c, gint icon_size)
+createWindowIcon (GdkPixbuf *icon_pixbuf)
 {
-    GdkPixbuf *icon_pixbuf;
-    GdkPixbuf *icon_pixbuf_stated;
     GtkWidget *icon;
 
-    g_return_val_if_fail (c, NULL);
     TRACE ("entering createWindowIcon");
 
-    icon_pixbuf = getClientIcon (c, icon_size, icon_size);
-    icon_pixbuf_stated = NULL;
     icon = gtk_image_new ();
-
     if (icon_pixbuf)
     {
-        if (FLAG_TEST (c->flags, CLIENT_FLAG_ICONIFIED))
-        {
-            icon_pixbuf_stated = gdk_pixbuf_copy (icon_pixbuf);
-            gdk_pixbuf_saturate_and_pixelate (icon_pixbuf, icon_pixbuf_stated, 0.55, TRUE);
-            gtk_image_set_from_pixbuf (GTK_IMAGE (icon), icon_pixbuf_stated);
-            g_object_unref(icon_pixbuf_stated);
-        }
-        else
-        {
-            gtk_image_set_from_pixbuf (GTK_IMAGE (icon), icon_pixbuf);
-        }
-        g_object_unref(icon_pixbuf);
+        gtk_image_set_from_pixbuf (GTK_IMAGE (icon), icon_pixbuf);
     }
     else
     {
@@ -384,7 +394,9 @@ getMinMonitorHeight (ScreenInfo *screen_info)
         GdkRectangle monitor;
         gdk_screen_get_monitor_geometry (screen_info->gscr, i, &monitor);
         if (min_height == 0 || monitor.height < min_height)
+        {
             min_height = monitor.height;
+        }
     }
     return min_height;
 }
@@ -392,17 +404,17 @@ getMinMonitorHeight (ScreenInfo *screen_info)
 static gboolean
 cb_window_button_enter (GtkWidget *widget, GdkEvent *event, gpointer user_data)
 {
-    TabwinWidget *tbw = user_data;
+    TabwinWidget *tabwin_widget = user_data;
     Client *c;
     GtkWidget *buttonbox, *buttonlabel;
     gchar *classname;
 
     TRACE ("entering");
 
-    g_return_val_if_fail (tbw != NULL, FALSE);
+    g_return_val_if_fail (tabwin_widget != NULL, FALSE);
 
     /* keep track of which widget we're hovered over */
-    tbw->hovered = widget;
+    tabwin_widget->hovered = widget;
 
     c = g_object_get_data (G_OBJECT (widget), "client-ptr-val");
 
@@ -421,11 +433,11 @@ cb_window_button_enter (GtkWidget *widget, GdkEvent *event, gpointer user_data)
             return FALSE;
         }
 
-        buttonbox = GTK_WIDGET (gtk_container_get_children(GTK_CONTAINER(widget))[0].data);
-        buttonlabel = GTK_WIDGET (g_list_nth_data( gtk_container_get_children(GTK_CONTAINER(buttonbox)), 1));
+        buttonbox = GTK_WIDGET (gtk_container_get_children (GTK_CONTAINER (widget))[0].data);
+        buttonlabel = GTK_WIDGET (g_list_nth_data( gtk_container_get_children (GTK_CONTAINER (buttonbox)), 1));
 
         classname = g_strdup (c->class.res_class);
-        tabwinSetLabel (tbw, buttonlabel, classname, c->name, c->win_workspace);
+        tabwinSetLabel (tabwin_widget, buttonlabel, classname, c->name, c->win_workspace);
         g_free (classname);
     }
 
@@ -435,14 +447,14 @@ cb_window_button_enter (GtkWidget *widget, GdkEvent *event, gpointer user_data)
 static gboolean
 cb_window_button_leave (GtkWidget *widget, GdkEvent *event, gpointer user_data)
 {
-    TabwinWidget *tbw = user_data;
+    TabwinWidget *tabwin_widget = user_data;
     Client *c;
 
     TRACE ("entering");
 
-    g_return_val_if_fail (tbw != NULL, FALSE);
+    g_return_val_if_fail (tabwin_widget != NULL, FALSE);
 
-    tbw->hovered = NULL;
+    tabwin_widget->hovered = NULL;
 
     /* don't do anything if we have the focus */
     if (gtk_widget_is_focus (widget))
@@ -464,114 +476,95 @@ cb_window_button_leave (GtkWidget *widget, GdkEvent *event, gpointer user_data)
         }
 
         /* reselect the selected widget, it will clear everything else out */
-        tabwinSelectWidget (tbw->tabwin);
+        tabwinSelectWidget (tabwin_widget->tabwin);
     }
 
     return FALSE;
 }
 
 static GtkWidget *
-createWindowlist (ScreenInfo *screen_info, TabwinWidget *tbw)
+createWindowlist (ScreenInfo *screen_info, TabwinWidget *tabwin_widget)
 {
     Client *c;
     GList *client_list;
-    GtkWidget *windowlist, *icon, *selected, *window_button, *buttonbox, *buttonlabel, *selected_label;
-    int packpos, monitor_width, monitor_height, app_label_height, label_width;
-    Tabwin *t;
-    PangoLayout *layout;
-    gint icon_size = WIN_ICON_SIZE;
+    GList *icon_list;
+    GtkWidget *windowlist;
+    GtkWidget *icon;
+    GtkWidget *selected;
+    GtkWidget *window_button;
+    GtkWidget *buttonbox;
+    GtkWidget *buttonlabel;
+    GtkWidget *selected_label;
+    GdkPixbuf *icon_pixbuf;
+    gint packpos;
+    gint label_width;
+    gint size_request;
+    Tabwin *tabwin;
 
     TRACE ("entering createWindowlist");
+    g_return_val_if_fail (screen_info->client_count > 0, NULL);
 
     packpos = 0;
     c = NULL;
     selected = NULL;
-    t = tbw->tabwin;
-    monitor_width = getMinMonitorWidth (screen_info);
-    monitor_height = getMinMonitorHeight (screen_info);
-    g_return_val_if_fail (screen_info->client_count > 0, NULL);
-
-    gtk_widget_style_get (GTK_WIDGET (tbw), "icon-size", &icon_size, NULL);
-    tbw->widgets = NULL;
-
-    /* We need to account for changes to the font size in the user's
-     * appearance theme and gtkrc settings */
-    layout = gtk_widget_create_pango_layout (GTK_WIDGET (tbw), "");
-    pango_layout_get_pixel_size (layout, NULL, &app_label_height);
-    g_object_unref (layout);
-
-    if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
-    {
-        tbw->grid_cols = (monitor_width / (icon_size + app_label_height + 10)) * 0.75;
-        tbw->grid_rows = screen_info->client_count / tbw->grid_cols + 1;
-
-        /* If we run out of space, halve the icon size to make more room. */
-        while ((icon_size + app_label_height + 10) * tbw->grid_rows > monitor_height - app_label_height)
-        {
-            icon_size = icon_size / 2;
-            /* recalculate with new icon size */
-            tbw->grid_cols = (monitor_width / (icon_size + app_label_height + 10)) * 0.75;
-            tbw->grid_rows = screen_info->client_count / tbw->grid_cols + 1;
+    tabwin = tabwin_widget->tabwin;
+    tabwin_widget->widgets = NULL;
+    size_request = tabwin->icon_size + tabwin->label_height + 2 * WIN_ICON_BORDER;
 
-            /* Shrinking the icon too much makes it hard to see */
-            if (icon_size < 8)
-            {
-                icon_size = 8;
-                break;
-            }
-        }
-    }
-    else
-    {
-        icon_size = LISTVIEW_WIN_ICON_SIZE;
-        gtk_widget_style_get (GTK_WIDGET (tbw), "listview-icon-size", &icon_size, NULL);
-        tbw->grid_rows = (monitor_height / (icon_size + 2 * WIN_ICON_BORDER)) * 0.75;
-        tbw->grid_cols = screen_info->client_count / tbw->grid_rows + 1;
-    }
-
-    windowlist = gtk_table_new (tbw->grid_rows, tbw->grid_cols, FALSE);
+    windowlist = gtk_table_new (tabwin->grid_rows, tabwin->grid_cols, FALSE);
 
     /* pack the client icons */
-    for (client_list = *t->client_list; client_list; client_list = g_list_next (client_list))
+    icon_list = tabwin->icon_list;
+    for (client_list = *tabwin->client_list; client_list; client_list = g_list_next (client_list))
     {
         c = (Client *) client_list->data;
         TRACE ("createWindowlist: adding %s", c->name);
+        icon_pixbuf = (GdkPixbuf *) icon_list->data;
+        icon_list = g_list_next (icon_list);
 
         window_button = gtk_button_new ();
         gtk_button_set_relief (GTK_BUTTON (window_button), GTK_RELIEF_NONE);
         g_object_set_data (G_OBJECT (window_button), "client-ptr-val", c);
-        g_signal_connect (window_button, "enter-notify-event", G_CALLBACK (cb_window_button_enter), tbw);
-        g_signal_connect (window_button, "leave-notify-event", G_CALLBACK (cb_window_button_leave), tbw);
+        g_signal_connect (window_button, "enter-notify-event",
+                          G_CALLBACK (cb_window_button_enter), tabwin_widget);
+        g_signal_connect (window_button, "leave-notify-event",
+                          G_CALLBACK (cb_window_button_leave), tabwin_widget);
         gtk_widget_add_events (window_button, GDK_ENTER_NOTIFY_MASK);
 
+        icon = createWindowIcon (icon_pixbuf);
         if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
         {
-            gtk_widget_set_size_request (GTK_WIDGET (window_button),
-                                         icon_size + app_label_height + 10,
-                                         icon_size+app_label_height + 10);
+            gtk_widget_set_size_request (GTK_WIDGET (window_button), size_request, size_request);
             buttonbox = gtk_vbox_new (FALSE, 0);
             buttonlabel = gtk_label_new ("");
             gtk_misc_set_alignment (GTK_MISC (buttonlabel), 0.5, 1.0);
+
+            gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 1.0);
+            gtk_box_pack_start (GTK_BOX (buttonbox), icon, TRUE, TRUE, 0);
         }
         else
         {
-            label_width = monitor_width / (tbw->grid_cols + 1);
+            label_width = tabwin->monitor_width / (tabwin->grid_cols + 1);
 
-            if (icon_size < app_label_height)
-                gtk_widget_set_size_request (GTK_WIDGET (window_button), label_width, app_label_height+8);
+            if (tabwin->icon_size < tabwin->label_height)
+            {
+                gtk_widget_set_size_request (GTK_WIDGET (window_button),
+                                             label_width, tabwin->label_height + 8);
+            }
             else
-                gtk_widget_set_size_request (GTK_WIDGET (window_button), label_width, icon_size+8);
+            {
+                gtk_widget_set_size_request (GTK_WIDGET (window_button),
+                                             label_width, tabwin->icon_size + 8);
+            }
             buttonbox = gtk_hbox_new (FALSE, 6);
             buttonlabel = gtk_label_new (c->name);
             gtk_misc_set_alignment (GTK_MISC (buttonlabel), 0, 0.5);
-        }
 
+            gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.5);
+            gtk_box_pack_start (GTK_BOX (buttonbox), icon, FALSE, FALSE, 0);
+        }
         gtk_container_add (GTK_CONTAINER (window_button), buttonbox);
 
-        icon = createWindowIcon (c, icon_size);
-        gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 1.0);
-        gtk_box_pack_start (GTK_BOX (buttonbox), icon, TRUE, TRUE, 0);
-
         gtk_label_set_justify (GTK_LABEL (buttonlabel), GTK_JUSTIFY_CENTER);
         gtk_label_set_ellipsize (GTK_LABEL (buttonlabel), PANGO_ELLIPSIZE_END);
         gtk_box_pack_start (GTK_BOX (buttonbox), buttonlabel, TRUE, TRUE, 0);
@@ -579,21 +572,21 @@ createWindowlist (ScreenInfo *screen_info, TabwinWidget *tbw)
         if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
         {
             gtk_table_attach (GTK_TABLE (windowlist), GTK_WIDGET (window_button),
-                packpos % tbw->grid_cols, packpos % tbw->grid_cols + 1,
-                packpos / tbw->grid_cols, packpos / tbw->grid_cols + 1,
+                packpos % tabwin->grid_cols, packpos % tabwin->grid_cols + 1,
+                packpos / tabwin->grid_cols, packpos / tabwin->grid_cols + 1,
                 GTK_FILL, GTK_FILL, 2, 2);
         }
         else
         {
             gtk_table_attach (GTK_TABLE (windowlist), GTK_WIDGET (window_button),
-                packpos / tbw->grid_rows, packpos / tbw->grid_rows + 1,
-                packpos % tbw->grid_rows, packpos % tbw->grid_rows + 1,
+                packpos / tabwin->grid_rows, packpos / tabwin->grid_rows + 1,
+                packpos % tabwin->grid_rows, packpos % tabwin->grid_rows + 1,
                 GTK_FILL, GTK_FILL, 2, 2);
         }
 
-        tbw->widgets = g_list_append (tbw->widgets, window_button);
+        tabwin_widget->widgets = g_list_append (tabwin_widget->widgets, window_button);
         packpos++;
-        if (c == t->selected->data)
+        if (c == tabwin->selected->data)
         {
             selected = window_button;
             selected_label = buttonlabel;
@@ -602,36 +595,37 @@ createWindowlist (ScreenInfo *screen_info, TabwinWidget *tbw)
     }
     if (selected)
     {
-        tabwinSetSelected (tbw, selected, selected_label);
+        tabwinSetSelected (tabwin_widget, selected, selected_label);
     }
     return windowlist;
 }
 
 static gboolean
-tabwinConfigure (TabwinWidget *tbw, GdkEventConfigure *event)
+tabwinConfigure (TabwinWidget *tabwin_widget, GdkEventConfigure *event)
 {
+    Tabwin *tabwin;
     GtkWindow *window;
     GdkRectangle monitor;
     GdkScreen *screen;
     gint x, y;
 
-    g_return_val_if_fail (tbw != NULL, FALSE);
+    g_return_val_if_fail (tabwin_widget != NULL, FALSE);
     TRACE ("entering tabwinConfigure");
 
-    if ((tbw->width == event->width) && (tbw->height == event->height))
+    if ((tabwin_widget->width == event->width) && (tabwin_widget->height == event->height))
     {
         return FALSE;
     }
 
-    window = GTK_WINDOW(tbw);
+    window = GTK_WINDOW(tabwin_widget);
     screen = gtk_window_get_screen(window);
-    gdk_screen_get_monitor_geometry (screen, tbw->monitor_num, &monitor);
+    gdk_screen_get_monitor_geometry (screen, tabwin_widget->monitor_num, &monitor);
     x = monitor.x + (monitor.width - event->width) / 2;
     y = monitor.y + (monitor.height - event->height) / 2;
     gtk_window_move (window, x, y);
 
-    tbw->width = event->width;
-    tbw->height = event->height;
+    tabwin_widget->width = event->width;
+    tabwin_widget->height = event->height;
 
     return FALSE;
 }
@@ -642,53 +636,169 @@ tabwin_widget_class_init (TabwinWidgetClass *klass)
     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
     gtk_widget_class_install_style_property (widget_class,
-                                             g_param_spec_int("icon-size",
-                                                              "icon size",
-                                                               "the size of the application icon",
-                                                               24, 128,
-                                                               WIN_ICON_SIZE,
-                                                               G_PARAM_READABLE));
+                                             g_param_spec_int ("preview-size",
+                                                               "preview size",
+                                                                "the size of the application preview",
+                                                                24, 256,
+                                                                WIN_PREVIEW_SIZE,
+                                                                G_PARAM_READABLE));
+    gtk_widget_class_install_style_property (widget_class,
+                                             g_param_spec_int ("icon-size",
+                                                               "icon size",
+                                                                "the size of the application icon",
+                                                                24, 128,
+                                                                WIN_ICON_SIZE,
+                                                                G_PARAM_READABLE));
     gtk_widget_class_install_style_property (widget_class,
-                                             g_param_spec_int("listview-icon-size",
-                                                              "listview icon size",
+                                             g_param_spec_int ("listview-icon-size",
+                                                               "listview icon size",
                                                                "the size of the application icon in listview",
                                                                16, 48,
                                                                LISTVIEW_WIN_ICON_SIZE,
                                                                G_PARAM_READABLE));
     gtk_widget_class_install_style_property (widget_class,
-                                             g_param_spec_int("border-width",
-                                                              "border width",
+                                             g_param_spec_int ("border-width",
+                                                               "border width",
                                                                "the width of the colored border",
                                                                0, 8,
                                                                WIN_BORDER_WIDTH,
                                                                G_PARAM_READABLE));
     gtk_widget_class_install_style_property (widget_class,
-                                             g_param_spec_double("border-alpha",
-                                                              "border alpha",
-                                                               "the alpha of the colored border",
-                                                               0.0, 1.0,
-                                                               WIN_BORDER_ALPHA,
-                                                               G_PARAM_READABLE));
-    gtk_widget_class_install_style_property (widget_class,
-                                             g_param_spec_double("alpha",
-                                                              "alpha",
-                                                               "the alpha of the window",
-                                                               0.0, 1.0,
-                                                               WIN_ALPHA,
-                                                               G_PARAM_READABLE));
-    gtk_widget_class_install_style_property (widget_class,
-                                             g_param_spec_int("border-radius",
-                                                              "border radius",
+                                             g_param_spec_int ("border-radius",
+                                                               "border radius",
                                                                "the border radius of the window",
                                                                0, 20,
                                                                WIN_BORDER_RADIUS,
                                                                G_PARAM_READABLE));
+    gtk_widget_class_install_style_property (widget_class,
+                                             g_param_spec_double ("border-alpha",
+                                                                  "border alpha",
+                                                                  "the alpha of the colored border",
+                                                                  0.0, 1.0,
+                                                                  WIN_BORDER_ALPHA,
+                                                                  G_PARAM_READABLE));
+    gtk_widget_class_install_style_property (widget_class,
+                                             g_param_spec_double ("alpha",
+                                                                  "alpha",
+                                                                  "the alpha of the window",
+                                                                  0.0, 1.0,
+                                                                  WIN_ALPHA,
+                                                                  G_PARAM_READABLE));
+}
+
+void
+computeTabwinData (ScreenInfo *screen_info, TabwinWidget *tabwin_widget)
+{
+    Tabwin *tabwin;
+    GdkPixbuf *icon_pixbuf;
+    PangoLayout *layout;
+    GList *client_list;
+    gint packpos;
+    gint size_request;
+    gboolean preview;
+
+    TRACE ("entering computeTabwinData");
+    g_return_if_fail (GTK_IS_WIDGET(tabwin_widget));
+    g_return_if_fail (screen_info->client_count > 0);
+
+    tabwin = tabwin_widget->tabwin;
+    tabwin->monitor_width = getMinMonitorWidth (screen_info);
+    tabwin->monitor_height = getMinMonitorHeight (screen_info);
+    tabwin->label_height = 30;
+    preview = compositorWindowPixmapAvailable (screen_info);
+
+    /* We need to account for changes to the font size in the user's
+     * appearance theme and gtkrc settings */
+    layout = gtk_widget_create_pango_layout (GTK_WIDGET (tabwin_widget), "");
+    pango_layout_get_pixel_size (layout, NULL, &tabwin->label_height);
+    g_object_unref (layout);
+
+    if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
+    {
+        if (preview)
+        {
+            tabwin->icon_size = WIN_PREVIEW_SIZE;
+            gtk_widget_style_get (GTK_WIDGET (tabwin_widget),
+                                  "preview-size", &tabwin->icon_size, NULL);
+        }
+        else
+        {
+            tabwin->icon_size = WIN_ICON_SIZE;
+            gtk_widget_style_get (GTK_WIDGET (tabwin_widget),
+                                  "icon-size", &tabwin->icon_size, NULL);
+        }
+        size_request = tabwin->icon_size + tabwin->label_height + 2 * WIN_ICON_BORDER;
+        tabwin->grid_cols = (tabwin->monitor_width / (size_request)) * 0.75;
+        tabwin->grid_rows = screen_info->client_count / tabwin->grid_cols;
+
+        /* If we run out of space, halve the icon size to make more room. */
+        while ((size_request) * tabwin->grid_rows > tabwin->monitor_height - tabwin->label_height)
+        {
+            /* Disable preview otherwise it'd be too slow */
+            if (preview)
+            {
+                preview = FALSE;
+                /* switch back to regular icon size */
+                tabwin->icon_size = WIN_ICON_SIZE;
+                gtk_widget_style_get (GTK_WIDGET (tabwin_widget),
+                                      "icon-size", &tabwin->icon_size, NULL);
+            }
+            else
+            {
+                tabwin->icon_size = tabwin->icon_size / 2;
+            }
+            size_request = tabwin->icon_size + tabwin->label_height + 2 * WIN_ICON_BORDER;
+
+            /* Recalculate with new icon size */
+            tabwin->grid_cols = (tabwin->monitor_width / (size_request)) * 0.75;
+            tabwin->grid_rows = screen_info->client_count / tabwin->grid_cols + 1;
+
+            /* Shrinking the icon too much makes it hard to see */
+            if (tabwin->icon_size < 8)
+            {
+                tabwin->icon_size = 8;
+                break;
+            }
+        }
+    }
+    else
+    {
+        tabwin->icon_size = LISTVIEW_WIN_ICON_SIZE;
+        gtk_widget_style_get (GTK_WIDGET (tabwin_widget),
+                              "listview-icon-size", &tabwin->icon_size, NULL);
+    }
+
+    /* pack the client icons */
+    for (client_list = *tabwin->client_list; client_list; client_list = g_list_next (client_list))
+    {
+        Client *c = (Client *) client_list->data;
+
+        if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
+        {
+            if (preview)
+            {
+                icon_pixbuf = getClientIcon (c, tabwin->icon_size, tabwin->icon_size);
+            }
+            else
+            {
+                icon_pixbuf = getAppIcon (c->screen_info, c->window,
+                                          tabwin->icon_size, tabwin->icon_size);
+            }
+        }
+        else
+        {
+            /* No preview in list mode */
+            icon_pixbuf = getAppIcon (c->screen_info, c->window,
+                                      tabwin->icon_size, tabwin->icon_size);
+        }
+        tabwin->icon_list = g_list_append(tabwin->icon_list, icon_pixbuf);
+    }
 }
 
 static TabwinWidget *
 tabwinCreateWidget (Tabwin *tabwin, ScreenInfo *screen_info, gint monitor_num)
 {
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
     GdkScreen *screen;
     GtkWidget *vbox;
     GtkWidget *windowlist;
@@ -697,78 +807,86 @@ tabwinCreateWidget (Tabwin *tabwin, ScreenInfo *screen_info, gint monitor_num)
 
     TRACE ("entering tabwinCreateWidget for monitor %i", monitor_num);
 
-    tbw = g_object_new (tabwin_widget_get_type(), "type", GTK_WINDOW_POPUP, NULL);
+    tabwin_widget = g_object_new (tabwin_widget_get_type(), "type", GTK_WINDOW_POPUP, NULL);
 
-    tbw->width = -1;
-    tbw->height = -1;
-    tbw->monitor_num = monitor_num;
-    tbw->tabwin = tabwin;
-    tbw->selected = NULL;
-    tbw->selected_callback = 0;
+    tabwin_widget->monitor_num = monitor_num;
+    tabwin_widget->tabwin = tabwin;
+    tabwin_widget->selected = NULL;
+    tabwin_widget->selected_callback = 0;
+    tabwin_widget->width = -1;
+    tabwin_widget->height = -1;
 
-    gtk_window_set_screen (GTK_WINDOW (tbw), screen_info->gscr);
-    gtk_widget_set_name (GTK_WIDGET (tbw), "xfwm4-tabwin");
+    gtk_window_set_screen (GTK_WINDOW (tabwin_widget), screen_info->gscr);
+    gtk_widget_set_name (GTK_WIDGET (tabwin_widget), "xfwm4-tabwin");
 
     /* Check for compositing and set colormap for it */
-    screen = gtk_widget_get_screen(GTK_WIDGET(tbw));
-    if(gdk_screen_is_composited(screen)) {
-        GdkColormap *cmap = gdk_screen_get_rgba_colormap(screen);
+    screen = gtk_widget_get_screen (GTK_WIDGET (tabwin_widget));
+    if(gdk_screen_is_composited (screen)) {
+        GdkColormap *cmap = gdk_screen_get_rgba_colormap (screen);
         if(cmap)
-            gtk_widget_set_colormap(GTK_WIDGET(tbw), cmap);
+            gtk_widget_set_colormap (GTK_WIDGET (tabwin_widget), cmap);
     }
 
-    gtk_widget_style_get(GTK_WIDGET(tbw), "border-radius", &border_radius, NULL);
-    gtk_widget_realize (GTK_WIDGET (tbw));
-    gtk_container_set_border_width (GTK_CONTAINER (tbw), border_radius + 4);
-    gtk_widget_set_app_paintable(GTK_WIDGET(tbw), TRUE);
-    gtk_window_set_position (GTK_WINDOW (tbw), GTK_WIN_POS_NONE);
-    gdk_screen_get_monitor_geometry (screen_info->gscr, tbw->monitor_num, &monitor);
-    gtk_window_move (GTK_WINDOW(tbw), monitor.x + monitor.width / 2,
+    if (tabwin->icon_list == NULL)
+    {
+        computeTabwinData (screen_info, tabwin_widget);
+    }
+    gtk_widget_style_get (GTK_WIDGET(tabwin_widget), "border-radius", &border_radius, NULL);
+    gtk_widget_realize (GTK_WIDGET (tabwin_widget));
+    gtk_container_set_border_width (GTK_CONTAINER (tabwin_widget), border_radius + 4);
+    gtk_widget_set_app_paintable (GTK_WIDGET (tabwin_widget), TRUE);
+    gtk_window_set_position (GTK_WINDOW (tabwin_widget), GTK_WIN_POS_NONE);
+    gdk_screen_get_monitor_geometry (screen_info->gscr, tabwin_widget->monitor_num, &monitor);
+    gtk_window_move (GTK_WINDOW (tabwin_widget), monitor.x + monitor.width / 2,
                                       monitor.y + monitor.height / 2);
 
     vbox = gtk_vbox_new (FALSE, 3);
-    gtk_container_add (GTK_CONTAINER (tbw), vbox);
+    gtk_container_add (GTK_CONTAINER (tabwin_widget), vbox);
 
     if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
     {
-        tbw->label = gtk_label_new ("");
-        gtk_label_set_use_markup (GTK_LABEL (tbw->label), TRUE);
-        gtk_label_set_justify (GTK_LABEL (tbw->label), GTK_JUSTIFY_CENTER);
-        gtk_label_set_ellipsize (GTK_LABEL (tbw->label), PANGO_ELLIPSIZE_END);
-        gtk_box_pack_end (GTK_BOX (vbox), tbw->label, TRUE, TRUE, 0);
+        tabwin_widget->label = gtk_label_new ("");
+        gtk_label_set_use_markup (GTK_LABEL (tabwin_widget->label), TRUE);
+        gtk_label_set_justify (GTK_LABEL (tabwin_widget->label), GTK_JUSTIFY_CENTER);
+        gtk_label_set_ellipsize (GTK_LABEL (tabwin_widget->label), PANGO_ELLIPSIZE_END);
+        gtk_box_pack_end (GTK_BOX (vbox), tabwin_widget->label, TRUE, TRUE, 0);
     }
 
-    windowlist = createWindowlist (screen_info, tbw);
-    tbw->container = windowlist;
+    windowlist = createWindowlist (screen_info, tabwin_widget);
+    tabwin_widget->container = windowlist;
     gtk_box_pack_start (GTK_BOX (vbox), windowlist, TRUE, TRUE, 0);
 
-    g_signal_connect_swapped (tbw, "configure-event",
-                              GTK_SIGNAL_FUNC (tabwinConfigure), (gpointer) tbw);
-    g_signal_connect (tbw, "expose-event", GTK_SIGNAL_FUNC (tabwin_expose), (gpointer) tbw);
+    g_signal_connect_swapped (tabwin_widget, "configure-event",
+                              GTK_SIGNAL_FUNC (tabwinConfigure),
+                              (gpointer) tabwin_widget);
+
+    g_signal_connect (tabwin_widget, "expose-event",
+                      GTK_SIGNAL_FUNC (tabwin_expose),
+                      (gpointer) tabwin_widget);
 
-    gtk_widget_show_all (GTK_WIDGET (tbw));
+    gtk_widget_show_all (GTK_WIDGET (tabwin_widget));
 
-    return tbw;
+    return tabwin_widget;
 }
 
 static Client *
-tabwinChange2Selected (Tabwin *t, GList *selected)
+tabwinChange2Selected (Tabwin *tabwin, GList *selected)
 {
     GList *tabwin_list, *widgets;
     GtkWidget *window_button, *buttonbox, *buttonlabel;
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
     Client *c;
 
-    t->selected = selected;
-    for (tabwin_list = t->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
+    tabwin->selected = selected;
+    for (tabwin_list = tabwin->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
     {
-        tbw = (TabwinWidget *) tabwin_list->data;
-        for (widgets = tbw->widgets; widgets; widgets = g_list_next (widgets))
+        tabwin_widget = (TabwinWidget *) tabwin_list->data;
+        for (widgets = tabwin_widget->widgets; widgets; widgets = g_list_next (widgets))
         {
             window_button = GTK_WIDGET (widgets->data);
             gtk_button_set_relief (GTK_BUTTON (window_button), GTK_RELIEF_NONE);
-            buttonbox = GTK_WIDGET( gtk_container_get_children(GTK_CONTAINER(window_button))[0].data );
-            buttonlabel = GTK_WIDGET( g_list_nth_data( gtk_container_get_children(GTK_CONTAINER(buttonbox)), 1) );
+            buttonbox = GTK_WIDGET (gtk_container_get_children (GTK_CONTAINER (window_button))[0].data );
+            buttonlabel = GTK_WIDGET (g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (buttonbox)), 1) );
 
             c = g_object_get_data (G_OBJECT (window_button), "client-ptr-val");
 
@@ -777,18 +895,18 @@ tabwinChange2Selected (Tabwin *t, GList *selected)
                 /* don't clear label if mouse is inside the previously
                  * selected button */
                 if (c->screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID
-                    && window_button != tbw->hovered)
+                    && window_button != tabwin_widget->hovered)
                 {
                     gtk_label_set_text (GTK_LABEL (buttonlabel), "");
                 }
 
-                if (c == t->selected->data)
+                if (c == tabwin->selected->data)
                 {
                     gtk_widget_grab_focus (window_button);
-                    tabwinSetSelected (tbw, window_button, buttonlabel);
-                    gtk_widget_queue_draw (GTK_WIDGET(tbw));
+                    tabwinSetSelected (tabwin_widget, window_button, buttonlabel);
+                    gtk_widget_queue_draw (GTK_WIDGET (tabwin_widget));
                 }
-                else if (window_button == tbw->hovered)
+                else if (window_button == tabwin_widget->hovered)
                 {
                     gtk_widget_set_state (window_button, GTK_STATE_PRELIGHT);
                 }
@@ -799,7 +917,7 @@ tabwinChange2Selected (Tabwin *t, GList *selected)
             }
         }
     }
-    return tabwinGetSelected (t);
+    return tabwinGetSelected (tabwin);
 }
 
 Tabwin *
@@ -823,12 +941,14 @@ tabwinCreate (GList **client_list, GList *selected, gboolean display_workspace)
     tabwin->client_list = client_list;
     tabwin->selected = selected;
     tabwin->tabwin_list = NULL;
+    tabwin->icon_list = NULL;
+
     num_monitors = myScreenGetNumMonitors (screen_info);
     for (i = 0; i < num_monitors; i++)
     {
         gint monitor_index;
 
-        monitor_index = myScreenGetMonitorIndex(screen_info, i);
+        monitor_index = myScreenGetMonitorIndex (screen_info, i);
         win = tabwinCreateWidget (tabwin, screen_info, monitor_index);
         tabwin->tabwin_list  = g_list_append (tabwin->tabwin_list, win);
     }
@@ -837,165 +957,165 @@ tabwinCreate (GList **client_list, GList *selected, gboolean display_workspace)
 }
 
 Client *
-tabwinGetSelected (Tabwin *t)
+tabwinGetSelected (Tabwin *tabwin)
 {
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
     TRACE ("entering tabwinGetSelected");
 
-    if (t->selected)
+    if (tabwin->selected)
     {
-        return (Client *) t->selected->data;
+        return (Client *) tabwin->selected->data;
     }
 
     return NULL;
 }
 
 Client *
-tabwinRemoveClient (Tabwin *t, Client *c)
+tabwinRemoveClient (Tabwin *tabwin, Client *c)
 {
     GList *client_list, *tabwin_list, *widgets;
     GtkWidget *icon;
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
 
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
     g_return_val_if_fail (c != NULL, NULL);
     TRACE ("entering tabwinRemoveClient");
 
-    if (!*t->client_list)
+    if (!*tabwin->client_list)
     {
         return NULL;
     }
 
     /* First, remove the client from our own client list */
-    for (client_list = *t->client_list; client_list; client_list = g_list_next (client_list))
+    for (client_list = *tabwin->client_list; client_list; client_list = g_list_next (client_list))
     {
         if (client_list->data == c)
         {
-            if (client_list == t->selected)
+            if (client_list == tabwin->selected)
             {
-                tabwinSelectNext (t);
+                tabwinSelectNext (tabwin);
             }
-            *t->client_list = g_list_delete_link (*t->client_list, client_list);
+            *tabwin->client_list = g_list_delete_link (*tabwin->client_list, client_list);
             break;
         }
     }
 
     /* Second, remove the icon from all boxes */
-    for (tabwin_list = t->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
+    for (tabwin_list = tabwin->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
     {
-        tbw = (TabwinWidget *) tabwin_list->data;
-        for (widgets = tbw->widgets; widgets; widgets = g_list_next (widgets))
+        tabwin_widget = (TabwinWidget *) tabwin_list->data;
+        for (widgets = tabwin_widget->widgets; widgets; widgets = g_list_next (widgets))
         {
             icon = GTK_WIDGET (widgets->data);
             if (((Client *) g_object_get_data (G_OBJECT(icon), "client-ptr-val")) == c)
             {
-                gtk_container_remove (GTK_CONTAINER (tbw->container), icon);
-                tbw->widgets = g_list_delete_link (tbw->widgets, widgets);
+                gtk_container_remove (GTK_CONTAINER (tabwin_widget->container), icon);
+                tabwin_widget->widgets = g_list_delete_link (tabwin_widget->widgets, widgets);
             }
         }
     }
 
-    return tabwinGetSelected (t);
+    return tabwinGetSelected (tabwin);
 }
 
 Client *
-tabwinSelectHead (Tabwin *t)
+tabwinSelectHead (Tabwin *tabwin)
 {
     GList *head;
     GList *tabwin_list, *widgets;
     GtkWidget *window_button, *buttonbox, *buttonlabel;
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
 
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
     TRACE ("entering tabwinSelectFirst");
 
-    head = *t->client_list;
+    head = *tabwin->client_list;
     if (!head)
     {
         return NULL;
     }
-    t->selected = head;
-    for (tabwin_list = t->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
+    tabwin->selected = head;
+    for (tabwin_list = tabwin->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
     {
-        tbw = (TabwinWidget *) tabwin_list->data;
-        for (widgets = tbw->widgets; widgets; widgets = g_list_next (widgets))
+        tabwin_widget = (TabwinWidget *) tabwin_list->data;
+        for (widgets = tabwin_widget->widgets; widgets; widgets = g_list_next (widgets))
         {
             window_button = GTK_WIDGET (widgets->data);
-            buttonbox = GTK_WIDGET( gtk_container_get_children(GTK_CONTAINER(window_button))[0].data );
-            buttonlabel = GTK_WIDGET( g_list_nth_data( gtk_container_get_children(GTK_CONTAINER(buttonbox)), 1) );
-            if (((Client *) g_object_get_data (G_OBJECT(window_button), "client-ptr-val")) == head->data)
+            buttonbox = GTK_WIDGET (gtk_container_get_children (GTK_CONTAINER (window_button))[0].data );
+            buttonlabel = GTK_WIDGET (g_list_nth_data (gtk_container_get_children (GTK_CONTAINER (buttonbox)), 1) );
+            if (((Client *) g_object_get_data (G_OBJECT (window_button), "client-ptr-val")) == head->data)
             {
-                tabwinSetSelected (tbw, window_button, buttonlabel);
-                gtk_widget_queue_draw (GTK_WIDGET(tbw));
+                tabwinSetSelected (tabwin_widget, window_button, buttonlabel);
+                gtk_widget_queue_draw (GTK_WIDGET (tabwin_widget));
             }
         }
     }
 
-    return tabwinGetSelected (t);
+    return tabwinGetSelected (tabwin);
 }
 
 Client *
-tabwinSelectNext (Tabwin *t)
+tabwinSelectNext (Tabwin *tabwin)
 {
     GList *next;
 
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
     TRACE ("entering tabwinSelectNext");
 
-    next = g_list_next(t->selected);
+    next = g_list_next (tabwin->selected);
     if (!next)
     {
-        next = *t->client_list;
+        next = *tabwin->client_list;
         g_return_val_if_fail (next != NULL, NULL);
     }
-    return tabwinChange2Selected (t, next);
+    return tabwinChange2Selected (tabwin, next);
 }
 
 Client *
-tabwinSelectPrev (Tabwin *t)
+tabwinSelectPrev (Tabwin *tabwin)
 {
     GList *prev;
 
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
     TRACE ("entering tabwinSelectPrev");
 
-    prev = g_list_previous (t->selected);
+    prev = g_list_previous (tabwin->selected);
     if (!prev)
     {
-        prev = g_list_last (*t->client_list);
+        prev = g_list_last (*tabwin->client_list);
         g_return_val_if_fail (prev != NULL, NULL);
     }
-    return tabwinChange2Selected (t, prev);
+    return tabwinChange2Selected (tabwin, prev);
 }
 
 Client *
-tabwinSelectDelta (Tabwin *t, int row_delta, int col_delta)
+tabwinSelectDelta (Tabwin *tabwin, int row_delta, int col_delta)
 {
     GList *selected;
     int pos_current, col_current, row_current, nitems, cols, rows;
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
     Client *c;
     ScreenInfo *screen_info;
 
     TRACE ("entering tabwinSelectDelta");
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
 
-    tbw = (TabwinWidget *) t->tabwin_list->data;
-    pos_current = g_list_position (*t->client_list, t->selected);
-    nitems = g_list_length (*t->client_list);
+    tabwin_widget = (TabwinWidget *) tabwin->tabwin_list->data;
+    pos_current = g_list_position (*tabwin->client_list, tabwin->selected);
+    nitems = g_list_length (*tabwin->client_list);
 
-    if (t->selected)
+    if (tabwin->selected)
     {
-        c = (Client *)t->selected->data;
+        c = (Client *) tabwin->selected->data;
         screen_info = c->screen_info;
         if (!screen_info)
         {
             return NULL;
         }
     }
-    else if (t->client_list)
+    else if (tabwin->client_list)
     {
-        c = (Client *)t->client_list;
+        c = (Client *) tabwin->client_list;
         screen_info = c->screen_info;
         if (!screen_info)
         {
@@ -1010,14 +1130,14 @@ tabwinSelectDelta (Tabwin *t, int row_delta, int col_delta)
 
     if (screen_info->params->cycle_tabwin_mode == STANDARD_ICON_GRID)
     {
-        cols = MIN (nitems, tbw->grid_cols);
+        cols = MIN (nitems, tabwin->grid_cols);
         rows = (nitems - 1) / cols + 1;
         col_current = pos_current % cols;
         row_current = pos_current / cols;
     }
     else
     {
-        rows = MIN (nitems, tbw->grid_rows);
+        rows = MIN (nitems, tabwin->grid_rows);
         cols = (nitems - 1) / rows + 1;
         row_current = pos_current % rows;
         col_current = pos_current / rows;
@@ -1161,55 +1281,55 @@ tabwinSelectDelta (Tabwin *t, int row_delta, int col_delta)
         }
     }
 
-    selected = g_list_nth(*t->client_list, pos_current);
+    selected = g_list_nth (*tabwin->client_list, pos_current);
 
-    return tabwinChange2Selected (t, selected);
+    return tabwinChange2Selected (tabwin, selected);
 }
 
 Client*
-tabwinSelectHovered (Tabwin *t)
+tabwinSelectHovered (Tabwin *tabwin)
 {
     GList *tabwin_list, *selected;
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
     Client *c;
 
-    g_return_val_if_fail (t != NULL, NULL);
+    g_return_val_if_fail (tabwin != NULL, NULL);
     TRACE ("entering tabwinSelectHovered");
 
-    for (tabwin_list = t->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
+    for (tabwin_list = tabwin->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
     {
-        tbw = (TabwinWidget *) tabwin_list->data;
-        if (tbw->hovered)
+        tabwin_widget = (TabwinWidget *) tabwin_list->data;
+        if (tabwin_widget->hovered)
         {
-            gtk_widget_grab_focus (tbw->hovered);
-            c = g_object_get_data (G_OBJECT (tbw->hovered), "client-ptr-val");
-            selected = g_list_find (*t->client_list, c);
+            gtk_widget_grab_focus (tabwin_widget->hovered);
+            c = g_object_get_data (G_OBJECT (tabwin_widget->hovered), "client-ptr-val");
+            selected = g_list_find (*tabwin->client_list, c);
             if (selected)
             {
-                t->selected = selected;
+                tabwin->selected = selected;
             }
             return c;
         }
     }
 
-    return tabwinSelectWidget (t);
+    return tabwinSelectWidget (tabwin);
 }
 
 void
-tabwinDestroy (Tabwin *t)
+tabwinDestroy (Tabwin *tabwin)
 {
     GList *tabwin_list;
-    TabwinWidget *tbw;
+    TabwinWidget *tabwin_widget;
 
-    g_return_if_fail (t != NULL);
+    g_return_if_fail (tabwin != NULL);
     TRACE ("entering tabwinDestroy");
 
-    for (tabwin_list = t->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
+    for (tabwin_list = tabwin->tabwin_list; tabwin_list; tabwin_list = g_list_next (tabwin_list))
     {
-        tbw = (TabwinWidget *) tabwin_list->data;
-        g_list_free (tbw->widgets);
-        gtk_widget_destroy (GTK_WIDGET (tbw));
+        tabwin_widget = (TabwinWidget *) tabwin_list->data;
+        g_list_free (tabwin_widget->widgets);
+        gtk_widget_destroy (GTK_WIDGET (tabwin_widget));
     }
-    g_list_free (t->tabwin_list);
+    g_list_free_full (tabwin->icon_list, g_object_unref);
+    g_list_free (tabwin->tabwin_list);
 }
-
diff --git a/src/tabwin.h b/src/tabwin.h
index 2189ac3..7017810 100644
--- a/src/tabwin.h
+++ b/src/tabwin.h
@@ -46,7 +46,14 @@ struct _Tabwin
 {
     GList *tabwin_list;
     GList **client_list;
+    GList *icon_list;
     GList *selected;
+    gint monitor_width;
+    gint monitor_height;
+    gint grid_cols;
+    gint grid_rows;
+    gint icon_size;
+    gint label_height;
     gboolean display_workspace;
 };
 
@@ -64,10 +71,9 @@ struct _TabwinWidget
     GtkWidget *hovered;
 
     gulong selected_callback;
+    gint width;
+    gint height;
     gint monitor_num;
-    gint width, height;
-    gint grid_cols;
-    gint grid_rows;
 };
 
 struct _TabwinWidgetClass

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list