Newer
Older
Olivier Fourdan
committed
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Olivier Fourdan
committed
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Olivier Fourdan
committed
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#endif
#ifndef WIN_ICON_BORDER
#define WIN_ICON_BORDER 5
#endif
#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include "inline-tabwin-icon.h"
#include "icons.h"
#include "focus.h"
#include "tabwin.h"
static GdkColor *
get_color (GtkWidget * win, GtkStateType state_type)
{
g_return_val_if_fail (win != NULL, NULL);
g_return_val_if_fail (GTK_IS_WIDGET (win), NULL);
g_return_val_if_fail (GTK_WIDGET_REALIZED (win), NULL);
style = gtk_rc_get_style (win);
if (!style)
{
style = gtk_widget_get_style (win);
style = gtk_widget_get_default_style ();
return (&style->bg[state_type]);
}
paint_selected (GtkWidget * w, GdkEventExpose * event, gpointer data)
gtk_paint_box (w->style, w->window,
GTK_STATE_SELECTED,
GTK_SHADOW_IN,
w->allocation.x - WIN_ICON_BORDER,
w->allocation.y - WIN_ICON_BORDER,
w->allocation.width + 2 * WIN_ICON_BORDER,
w->allocation.height + 2 * WIN_ICON_BORDER);
Olivier Fourdan
committed
/* Efficiency is definitely *not* the goal here! */
static gchar *
Olivier Fourdan
committed
{
gchar *canonical;
Olivier Fourdan
committed
if (s)
{
canonical = g_ascii_strup (s, -1);
g_strcanon (canonical, "[]()0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", ' ');
Olivier Fourdan
committed
g_strstrip (canonical);
}
else
{
Olivier Fourdan
committed
canonical = g_strdup ("...");
Olivier Fourdan
committed
}
return canonical;
}
Olivier Fourdan
committed
tabwinSetLabel (Tabwin * t, gchar * class, gchar * label, int workspace)
Olivier Fourdan
committed
gchar *message;
message = pretty_string (class);
gtk_label_set_use_markup (GTK_LABEL (t->class), TRUE);
markup = g_strconcat ("<span size=\"larger\" weight=\"bold\">", message, "</span>", NULL);
Olivier Fourdan
committed
g_free (message);
gtk_label_set_markup (GTK_LABEL (t->class), markup);
Olivier Fourdan
committed
g_free (markup);
if (t->display_workspace)
{
message = g_strdup_printf ("[%i] - %s", workspace + 1, label);
}
else
{
message = g_strdup_printf ("%s", label);
}
Olivier Fourdan
committed
gtk_label_set_text (GTK_LABEL (t->label), message);
Olivier Fourdan
committed
g_free (message);
gchar *classname;
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");
if (FLAG_TEST (c->flags, CLIENT_FLAG_ICONIFIED))
{
classname = g_strdup_printf ("[ %s ]", c->class.res_class);
}
else
{
classname = g_strdup(c->class.res_class);
}
tabwinSetLabel (t, classname, c->name, c->win_workspace);
g_free (classname);
{
GdkPixbuf *icon_pixbuf;
Olivier Fourdan
committed
GdkPixbuf *icon_pixbuf_stated;
icon_pixbuf = getAppIcon (c->screen_info->display_info, c->window, WIN_ICON_SIZE, WIN_ICON_SIZE);
Olivier Fourdan
committed
icon_pixbuf_stated = NULL;
icon = gtk_image_new ();
g_object_set_data (G_OBJECT (icon), "client-ptr-val", c);
Olivier Fourdan
committed
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.25, TRUE);
Olivier Fourdan
committed
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_stock (GTK_IMAGE (icon), "gtk-missing-image", GTK_ICON_SIZE_DIALOG);
return icon;
}
static GtkWidget *
Olivier Fourdan
committed
createWindowlist (GdkScreen * scr, Client * current, Client * new, unsigned int cycle_range, Tabwin * t)
Olivier Fourdan
committed
Client *c2;
Olivier Fourdan
committed
GList *next;
unsigned int grid_cols;
unsigned int n_clients;
unsigned int grid_rows;
Olivier Fourdan
committed
g_return_val_if_fail (current != NULL, NULL);
Olivier Fourdan
committed
c2 = NULL;
next = NULL;
Olivier Fourdan
committed
screen_info = current->screen_info;
n_clients = screen_info->client_count;
g_return_val_if_fail (n_clients > 0, NULL);
getMouseXY (screen_info, screen_info->xroot, &msx, &msy);
monitor = find_monitor_at_point (scr, msx, msy);
gdk_screen_get_monitor_geometry (scr, monitor, &monitor_sz);
/* add the width of the border on each side */
grid_cols = (monitor_sz.width / (WIN_ICON_SIZE + 2 * WIN_ICON_BORDER)) * 0.75;
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;
/* pack the client icons */
Olivier Fourdan
committed
for (c2 = current, i = 0; c2 && i < n_clients; i++, c2 = c2->next)
if (!clientSelectMask (c2, cycle_range, WINDOW_REGULAR_FOCUSABLE))
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);
Olivier Fourdan
committed
if (c2 == new)
{
next = g_list_last (t->head);
}
if (next)
{
tabwinSetSelected (t, next->data);
}
Olivier Fourdan
committed
t->current = next;
Olivier Fourdan
committed
tabwinCreate (GdkScreen * scr, Client * current, Client * new, unsigned int cycle_range, gboolean display_workspace)
{
Tabwin *tabwin;
GtkWidget *colorbox1, *colorbox2;
Olivier Fourdan
committed
tabwin = g_new0 (Tabwin, 1);
tabwin->window = gtk_window_new (GTK_WINDOW_POPUP);
tabwin->display_workspace = display_workspace;
gtk_window_set_screen (GTK_WINDOW (tabwin->window), scr);
gtk_widget_set_name (GTK_WIDGET (tabwin->window), "xfwm4-tabwin");
gtk_widget_realize (GTK_WIDGET (tabwin->window));
gtk_container_set_border_width (GTK_CONTAINER (tabwin->window), 0);
gtk_window_set_position (GTK_WINDOW (tabwin->window), GTK_WIN_POS_CENTER_ALWAYS);
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);
colorbox1 = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (frame), colorbox1);
colorbox2 = gtk_event_box_new ();
gtk_container_set_border_width (GTK_CONTAINER (colorbox2), 3);
gtk_container_add (GTK_CONTAINER (colorbox1), colorbox2);
vbox = gtk_vbox_new (FALSE, 5);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
gtk_container_add (GTK_CONTAINER (colorbox2), vbox);
Olivier Fourdan
committed
tabwin->class = gtk_label_new (NULL);
gtk_label_set_use_markup (GTK_LABEL (tabwin->class), TRUE);
Olivier Fourdan
committed
gtk_label_set_justify (GTK_LABEL (tabwin->class), GTK_JUSTIFY_CENTER);
gtk_box_pack_start (GTK_BOX (vbox), tabwin->class, TRUE, TRUE, 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);
Olivier Fourdan
committed
tabwin->label = gtk_label_new ("");
gtk_label_set_use_markup (GTK_LABEL (tabwin->label), FALSE);
Olivier Fourdan
committed
gtk_label_set_justify (GTK_LABEL (tabwin->label), GTK_JUSTIFY_CENTER);
gtk_box_pack_start (GTK_BOX (vbox), tabwin->label, TRUE, TRUE, 0);
gtk_widget_set_size_request (GTK_WIDGET (tabwin->label), 240, -1);
Olivier Fourdan
committed
Olivier Fourdan
committed
windowlist = createWindowlist (scr, current, new, cycle_range, tabwin);
Olivier Fourdan
committed
tabwin->container = windowlist;
gtk_container_add (GTK_CONTAINER (frame), windowlist);
color = get_color (tabwin->window, GTK_STATE_SELECTED);
if (color)
{
gtk_widget_modify_bg (colorbox1, GTK_STATE_NORMAL, color);
}
Olivier Fourdan
committed
#if 0
if (GTK_CHECK_VERSION (2, 6, 2))
Olivier Fourdan
committed
{
Olivier Fourdan
committed
gtk_label_set_ellipsize (GTK_LABEL (tabwin->label), PANGO_ELLIPSIZE_END);
gtk_label_set_ellipsize (GTK_LABEL (tabwin->class), PANGO_ELLIPSIZE_END);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
#endif
Olivier Fourdan
committed
gtk_widget_show_all (GTK_WIDGET (tabwin->window));
Client *
tabwinGetSelected (Tabwin * t)
{
g_return_val_if_fail (t != NULL, NULL);
return (Client *) g_object_get_data (G_OBJECT (t->current->data), "client-ptr-val");
}
Client *
tabwinRemoveClient (Tabwin * t, Client * c)
Olivier Fourdan
committed
{
g_return_val_if_fail (t != NULL, NULL);
if (!tmp)
{
return NULL;
}
do
{
if (((Client *) g_object_get_data (tmp->data, "client-ptr-val")) == c)
Olivier Fourdan
committed
{
Olivier Fourdan
committed
}
gtk_container_remove (GTK_CONTAINER (t->container), tmp->data);
Olivier Fourdan
committed
t->head = g_list_delete_link (t->head, tmp);
Olivier Fourdan
committed
/* No need to look any further */
/* since this is a circular list, hitting head signals end, not hitting NULL */
}
while ((tmp) && (tmp = g_list_next (tmp)));
Olivier Fourdan
committed
}
tabwinSelectNext (Tabwin * t)
g_return_val_if_fail (t != NULL, NULL);
next = g_list_next(t->current);
if (!next)
{
next = t->head;
g_return_val_if_fail (next != NULL, NULL);
tabwinSetSelected (t, next->data);
t->current = next;
gtk_widget_queue_draw (t->window);
return tabwinGetSelected (t);
Olivier Fourdan
committed
g_return_val_if_fail (t != NULL, NULL);
prev = g_list_previous (t->current);
if (!prev)
{
prev = g_list_last (t->head);
g_return_val_if_fail (prev != NULL, NULL);
tabwinSetSelected (t, prev->data);
t->current = prev;
gtk_widget_queue_draw (t->window);
return tabwinGetSelected (t);
Olivier Fourdan
committed
Client *
tabwinGetHead (Tabwin * t)
{
g_return_val_if_fail (t != NULL, NULL);
if ((t->head) && (t->head->data))
{
return (Client *) g_object_get_data (G_OBJECT (t->head->data), "client-ptr-val");
}
return NULL;
}
gtk_widget_destroy (t->window);