diff options
author | Perberos <[email protected]> | 2011-12-01 23:52:01 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-12-01 23:52:01 -0300 |
commit | 28a029a4990d2a84f9d6a0b890eba812ea503998 (patch) | |
tree | 7a69477d0dd6bf351801fa9698d95224e4fe47b6 /src/ui/tabpopup.c | |
download | marco-28a029a4990d2a84f9d6a0b890eba812ea503998.tar.bz2 marco-28a029a4990d2a84f9d6a0b890eba812ea503998.tar.xz |
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'src/ui/tabpopup.c')
-rw-r--r-- | src/ui/tabpopup.c | 967 |
1 files changed, 967 insertions, 0 deletions
diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c new file mode 100644 index 00000000..e0a55447 --- /dev/null +++ b/src/ui/tabpopup.c @@ -0,0 +1,967 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* Marco popup window thing showing windows you can tab to */ + +/* + * Copyright (C) 2001 Havoc Pennington + * Copyright (C) 2002 Red Hat, Inc. + * Copyright (C) 2005 Elijah Newren + * + * 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 of the + * License, or (at your option) any later version. + * + * 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. + * + * 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., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <config.h> + +#include "util.h" +#include "core.h" +#include "tabpopup.h" +/* FIXME these two includes are 100% broken ... + */ +#include "../core/workspace.h" +#include "../core/frame-private.h" +#include "draw-workspace.h" +#include <gtk/gtk.h> +#include <math.h> + +#define OUTSIDE_SELECT_RECT 2 +#define INSIDE_SELECT_RECT 2 + +typedef struct _TabEntry TabEntry; + +struct _TabEntry +{ + MetaTabEntryKey key; + char *title; + GdkPixbuf *icon, *dimmed_icon; + GtkWidget *widget; + GdkRectangle rect; + GdkRectangle inner_rect; + guint blank : 1; +}; + +struct _MetaTabPopup +{ + GtkWidget *window; + GtkWidget *label; + GList *current; + GList *entries; + TabEntry *current_selected_entry; + GtkWidget *outline_window; + gboolean outline; +}; + +static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf); +static void select_image (GtkWidget *widget); +static void unselect_image (GtkWidget *widget); + +static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace); +static void select_workspace (GtkWidget *widget); +static void unselect_workspace (GtkWidget *widget); + +static gboolean +outline_window_expose (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + MetaTabPopup *popup; + TabEntry *te; + GtkStyle *style; + GdkWindow *window; + cairo_t *cr; + + popup = data; + + if (!popup->outline || popup->current_selected_entry == NULL) + return FALSE; + + te = popup->current_selected_entry; + window = gtk_widget_get_window (widget); + style = gtk_widget_get_style (widget); + cr = gdk_cairo_create (window); + + cairo_set_line_width (cr, 1.0); + gdk_cairo_set_source_color (cr, &style->white); + + cairo_rectangle (cr, + 0.5, 0.5, + te->rect.width - 1, + te->rect.height - 1); + cairo_stroke (cr); + + cairo_rectangle (cr, + te->inner_rect.x - 0.5, te->inner_rect.y - 0.5, + te->inner_rect.width + 1, + te->inner_rect.height + 1); + cairo_stroke (cr); + + cairo_destroy (cr); + + return FALSE; +} + +static GdkPixbuf* +dimm_icon (GdkPixbuf *pixbuf) +{ + int x, y, pixel_stride, row_stride; + guchar *row, *pixels; + int w, h; + GdkPixbuf *dimmed_pixbuf; + + if (gdk_pixbuf_get_has_alpha (pixbuf)) + { + dimmed_pixbuf = gdk_pixbuf_copy (pixbuf); + } + else + { + dimmed_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); + } + + w = gdk_pixbuf_get_width (dimmed_pixbuf); + h = gdk_pixbuf_get_height (dimmed_pixbuf); + + pixel_stride = 4; + + row = gdk_pixbuf_get_pixels (dimmed_pixbuf); + row_stride = gdk_pixbuf_get_rowstride (dimmed_pixbuf); + + for (y = 0; y < h; y++) + { + pixels = row; + for (x = 0; x < w; x++) + { + pixels[3] /= 2; + pixels += pixel_stride; + } + row += row_stride; + } + return dimmed_pixbuf; +} + +static TabEntry* +tab_entry_new (const MetaTabEntry *entry, + gint screen_width, + gboolean outline) +{ + TabEntry *te; + + te = g_new (TabEntry, 1); + te->key = entry->key; + te->title = NULL; + if (entry->title) + { + gchar *str; + gchar *tmp; + gchar *formatter = "%s"; + + str = meta_g_utf8_strndup (entry->title, 4096); + + if (entry->hidden) + { + formatter = "[%s]"; + } + + tmp = g_markup_printf_escaped (formatter, str); + g_free (str); + str = tmp; + + if (entry->demands_attention) + { + /* Escape the whole line of text then markup the text and + * copy it back into the original buffer. + */ + tmp = g_strdup_printf ("<b>%s</b>", str); + g_free (str); + str = tmp; + } + + te->title=g_strdup(str); + + g_free (str); + } + te->widget = NULL; + te->icon = entry->icon; + te->blank = entry->blank; + te->dimmed_icon = NULL; + if (te->icon) + { + g_object_ref (G_OBJECT (te->icon)); + if (entry->hidden) + te->dimmed_icon = dimm_icon (entry->icon); + } + + if (outline) + { + te->rect.x = entry->rect.x; + te->rect.y = entry->rect.y; + te->rect.width = entry->rect.width; + te->rect.height = entry->rect.height; + + te->inner_rect.x = entry->inner_rect.x; + te->inner_rect.y = entry->inner_rect.y; + te->inner_rect.width = entry->inner_rect.width; + te->inner_rect.height = entry->inner_rect.height; + } + return te; +} + +MetaTabPopup* +meta_ui_tab_popup_new (const MetaTabEntry *entries, + int screen_number, + int entry_count, + int width, + gboolean outline) +{ + MetaTabPopup *popup; + int i, left, right, top, bottom; + int height; + GtkWidget *table; + GtkWidget *vbox; + GtkWidget *align; + GList *tmp; + GtkWidget *frame; + int max_label_width; /* the actual max width of the labels we create */ + AtkObject *obj; + GdkScreen *screen; + int screen_width; + + popup = g_new (MetaTabPopup, 1); + + popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP); + + screen = gdk_display_get_screen (gdk_display_get_default (), + screen_number); + gtk_window_set_screen (GTK_WINDOW (popup->outline_window), + screen); + + gtk_widget_set_app_paintable (popup->outline_window, TRUE); + gtk_widget_realize (popup->outline_window); + + g_signal_connect (G_OBJECT (popup->outline_window), "expose_event", + G_CALLBACK (outline_window_expose), popup); + + popup->window = gtk_window_new (GTK_WINDOW_POPUP); + + gtk_window_set_screen (GTK_WINDOW (popup->window), + screen); + + gtk_window_set_position (GTK_WINDOW (popup->window), + GTK_WIN_POS_CENTER_ALWAYS); + /* enable resizing, to get never-shrink behavior */ + gtk_window_set_resizable (GTK_WINDOW (popup->window), + TRUE); + popup->current = NULL; + popup->entries = NULL; + popup->current_selected_entry = NULL; + popup->outline = outline; + + screen_width = gdk_screen_get_width (screen); + for (i = 0; i < entry_count; ++i) + { + TabEntry* new_entry = tab_entry_new (&entries[i], screen_width, outline); + popup->entries = g_list_prepend (popup->entries, new_entry); + } + + popup->entries = g_list_reverse (popup->entries); + + g_assert (width > 0); + height = i / width; + if (i % width) + height += 1; + + table = gtk_table_new (height, width, FALSE); + vbox = gtk_vbox_new (FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); + gtk_container_set_border_width (GTK_CONTAINER (table), 1); + gtk_container_add (GTK_CONTAINER (popup->window), + frame); + gtk_container_add (GTK_CONTAINER (frame), + vbox); + + align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); + + gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0); + + gtk_container_add (GTK_CONTAINER (align), + table); + + popup->label = gtk_label_new (""); + + /* Set the accessible role of the label to a status bar so it + * will emit name changed events that can be used by screen + * readers. + */ + obj = gtk_widget_get_accessible (popup->label); + atk_object_set_role (obj, ATK_ROLE_STATUSBAR); + + gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3); + + gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0); + + max_label_width = 0; + top = 0; + bottom = 1; + tmp = popup->entries; + + while (tmp && top < height) + { + left = 0; + right = 1; + + while (tmp && left < width) + { + GtkWidget *image; + GtkRequisition req; + + TabEntry *te; + + te = tmp->data; + + if (te->blank) + { + /* just stick a widget here to avoid special cases */ + image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); + } + else if (outline) + { + if (te->dimmed_icon) + { + image = selectable_image_new (te->dimmed_icon); + } + else + { + image = selectable_image_new (te->icon); + } + + gtk_misc_set_padding (GTK_MISC (image), + INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1, + INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1); + gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5); + } + else + { + image = selectable_workspace_new ((MetaWorkspace *) te->key); + } + + te->widget = image; + + gtk_table_attach (GTK_TABLE (table), + te->widget, + left, right, top, bottom, + 0, 0, + 0, 0); + + /* Efficiency rules! */ + gtk_label_set_markup (GTK_LABEL (popup->label), + te->title); + gtk_widget_size_request (popup->label, &req); + max_label_width = MAX (max_label_width, req.width); + + tmp = tmp->next; + + ++left; + ++right; + } + + ++top; + ++bottom; + } + + /* remove all the temporary text */ + gtk_label_set_text (GTK_LABEL (popup->label), ""); + /* Make it so that we ellipsize if the text is too long */ + gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END); + + /* Limit the window size to no bigger than screen_width/4 */ + if (max_label_width>(screen_width/4)) + { + max_label_width = screen_width/4; + } + + max_label_width += 20; /* add random padding */ + + gtk_window_set_default_size (GTK_WINDOW (popup->window), + max_label_width, + -1); + + return popup; +} + +static void +free_tab_entry (gpointer data, gpointer user_data) +{ + TabEntry *te; + + te = data; + + g_free (te->title); + if (te->icon) + g_object_unref (G_OBJECT (te->icon)); + if (te->dimmed_icon) + g_object_unref (G_OBJECT (te->dimmed_icon)); + + g_free (te); +} + +void +meta_ui_tab_popup_free (MetaTabPopup *popup) +{ + meta_verbose ("Destroying tab popup window\n"); + + gtk_widget_destroy (popup->outline_window); + gtk_widget_destroy (popup->window); + + g_list_foreach (popup->entries, free_tab_entry, NULL); + + g_list_free (popup->entries); + + g_free (popup); +} + +void +meta_ui_tab_popup_set_showing (MetaTabPopup *popup, + gboolean showing) +{ + if (showing) + { + gtk_widget_show_all (popup->window); + } + else + { + if (GTK_WIDGET_VISIBLE (popup->window)) + { + meta_verbose ("Hiding tab popup window\n"); + gtk_widget_hide (popup->window); + meta_core_increment_event_serial (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + } + } +} + +static void +display_entry (MetaTabPopup *popup, + TabEntry *te) +{ + GdkRectangle rect; + GdkRegion *region; + GdkRegion *inner_region; + + + if (popup->current_selected_entry) + { + if (popup->outline) + unselect_image (popup->current_selected_entry->widget); + else + unselect_workspace (popup->current_selected_entry->widget); + } + + gtk_label_set_markup (GTK_LABEL (popup->label), te->title); + + if (popup->outline) + select_image (te->widget); + else + select_workspace (te->widget); + + if (popup->outline) + { + /* Do stuff behind gtk's back */ + gdk_window_hide (popup->outline_window->window); + meta_core_increment_event_serial (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); + + rect = te->rect; + rect.x = 0; + rect.y = 0; + + gdk_window_move_resize (popup->outline_window->window, + te->rect.x, te->rect.y, + te->rect.width, te->rect.height); + + gdk_window_set_background (popup->outline_window->window, + &popup->outline_window->style->black); + + region = gdk_region_rectangle (&rect); + inner_region = gdk_region_rectangle (&te->inner_rect); + gdk_region_subtract (region, inner_region); + gdk_region_destroy (inner_region); + + gdk_window_shape_combine_region (popup->outline_window->window, + region, + 0, 0); + + gdk_region_destroy (region); + + /* This should piss off gtk a bit, but we don't want to raise + * above the tab popup. So, instead of calling gtk_widget_show, + * we manually set the window as mapped and then manually map it + * with gdk functions. + */ + GTK_WIDGET_SET_FLAGS (popup->outline_window, GTK_MAPPED); + gdk_window_show_unraised (popup->outline_window->window); + } + + /* Must be before we handle an expose for the outline window */ + popup->current_selected_entry = te; +} + +void +meta_ui_tab_popup_forward (MetaTabPopup *popup) +{ + if (popup->current != NULL) + popup->current = popup->current->next; + + if (popup->current == NULL) + popup->current = popup->entries; + + if (popup->current != NULL) + { + TabEntry *te; + + te = popup->current->data; + + display_entry (popup, te); + } +} + +void +meta_ui_tab_popup_backward (MetaTabPopup *popup) +{ + if (popup->current != NULL) + popup->current = popup->current->prev; + + if (popup->current == NULL) + popup->current = g_list_last (popup->entries); + + if (popup->current != NULL) + { + TabEntry *te; + + te = popup->current->data; + + display_entry (popup, te); + } +} + +MetaTabEntryKey +meta_ui_tab_popup_get_selected (MetaTabPopup *popup) +{ + if (popup->current) + { + TabEntry *te; + + te = popup->current->data; + + return te->key; + } + else + return (MetaTabEntryKey)None; +} + +void +meta_ui_tab_popup_select (MetaTabPopup *popup, + MetaTabEntryKey key) +{ + GList *tmp; + + /* Note, "key" may not be in the list of entries; other code assumes + * it's OK to pass in a key that isn't. + */ + + tmp = popup->entries; + while (tmp != NULL) + { + TabEntry *te; + + te = tmp->data; + + if (te->key == key) + { + popup->current = tmp; + + display_entry (popup, te); + + return; + } + + tmp = tmp->next; + } +} + +#define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ()) +#define META_SELECT_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage)) + +typedef struct _MetaSelectImage MetaSelectImage; +typedef struct _MetaSelectImageClass MetaSelectImageClass; + +struct _MetaSelectImage +{ + GtkImage parent_instance; + guint selected : 1; +}; + +struct _MetaSelectImageClass +{ + GtkImageClass parent_class; +}; + + +static GType meta_select_image_get_type (void) G_GNUC_CONST; + +static GtkWidget* +selectable_image_new (GdkPixbuf *pixbuf) +{ + GtkWidget *w; + + w = g_object_new (meta_select_image_get_type (), NULL); + gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf); + + return w; +} + +static void +select_image (GtkWidget *widget) +{ + META_SELECT_IMAGE (widget)->selected = TRUE; + gtk_widget_queue_draw (widget); +} + +static void +unselect_image (GtkWidget *widget) +{ + META_SELECT_IMAGE (widget)->selected = FALSE; + gtk_widget_queue_draw (widget); +} + +static void meta_select_image_class_init (MetaSelectImageClass *klass); +static gboolean meta_select_image_expose_event (GtkWidget *widget, + GdkEventExpose *event); + +static GtkImageClass *parent_class; + +GType +meta_select_image_get_type (void) +{ + static GType image_type = 0; + + if (!image_type) + { + static const GTypeInfo image_info = + { + sizeof (MetaSelectImageClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) meta_select_image_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (MetaSelectImage), + 16, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0); + } + + return image_type; +} + +static void +meta_select_image_class_init (MetaSelectImageClass *klass) +{ + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek (gtk_image_get_type ()); + + widget_class = GTK_WIDGET_CLASS (klass); + + widget_class->expose_event = meta_select_image_expose_event; +} + +static gboolean +meta_select_image_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + if (META_SELECT_IMAGE (widget)->selected) + { + int x, y, w, h; + GtkMisc *misc; + GtkStyle *style; + GtkStateType state; + cairo_t *cr; + + misc = GTK_MISC (widget); + + x = (widget->allocation.x * (1.0 - misc->xalign) + + (widget->allocation.x + widget->allocation.width + - (widget->requisition.width - misc->xpad * 2)) * + misc->xalign) + 0.5; + y = (widget->allocation.y * (1.0 - misc->yalign) + + (widget->allocation.y + widget->allocation.height + - (widget->requisition.height - misc->ypad * 2)) * + misc->yalign) + 0.5; + + x -= INSIDE_SELECT_RECT + 1; + y -= INSIDE_SELECT_RECT + 1; + + w = widget->requisition.width - OUTSIDE_SELECT_RECT * 2 - 1; + h = widget->requisition.height - OUTSIDE_SELECT_RECT * 2 - 1; + + style = gtk_widget_get_style (widget); + state = gtk_widget_get_state (widget); + cr = gdk_cairo_create (widget->window); + + cairo_set_line_width (cr, 2.0); + gdk_cairo_set_source_color (cr, &style->fg[state]); + + cairo_rectangle (cr, x, y, w + 1, h + 1); + cairo_stroke (cr); + + cairo_set_line_width (cr, 1.0); +#if 0 + gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_SELECTED]); + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); +#endif + +#if 0 + gtk_paint_focus (widget->style, widget->window, + &event->area, widget, "meta-tab-image", + x, y, w, h); +#endif + + cairo_destroy (cr); + } + + return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); +} + +#define META_TYPE_SELECT_WORKSPACE (meta_select_workspace_get_type ()) +#define META_SELECT_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_WORKSPACE, MetaSelectWorkspace)) + +typedef struct _MetaSelectWorkspace MetaSelectWorkspace; +typedef struct _MetaSelectWorkspaceClass MetaSelectWorkspaceClass; + +struct _MetaSelectWorkspace +{ + GtkDrawingArea parent_instance; + MetaWorkspace *workspace; + guint selected : 1; +}; + +struct _MetaSelectWorkspaceClass +{ + GtkDrawingAreaClass parent_class; +}; + + +static GType meta_select_workspace_get_type (void) G_GNUC_CONST; + +#define SELECT_OUTLINE_WIDTH 2 +#define MINI_WORKSPACE_WIDTH 48 + +static GtkWidget* +selectable_workspace_new (MetaWorkspace *workspace) +{ + GtkWidget *widget; + double screen_aspect; + + widget = g_object_new (meta_select_workspace_get_type (), NULL); + + screen_aspect = (double) workspace->screen->rect.height / + (double) workspace->screen->rect.width; + + /* account for select rect */ + gtk_widget_set_size_request (widget, + MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2, + MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2); + + META_SELECT_WORKSPACE (widget)->workspace = workspace; + + return widget; +} + +static void +select_workspace (GtkWidget *widget) +{ + META_SELECT_WORKSPACE(widget)->selected = TRUE; + gtk_widget_queue_draw (widget); +} + +static void +unselect_workspace (GtkWidget *widget) +{ + META_SELECT_WORKSPACE (widget)->selected = FALSE; + gtk_widget_queue_draw (widget); +} + +static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass); + +static gboolean meta_select_workspace_expose_event (GtkWidget *widget, + GdkEventExpose *event); + +GType +meta_select_workspace_get_type (void) +{ + static GType workspace_type = 0; + + if (!workspace_type) + { + static const GTypeInfo workspace_info = + { + sizeof (MetaSelectWorkspaceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) meta_select_workspace_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (MetaSelectWorkspace), + 16, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + workspace_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, + "MetaSelectWorkspace", + &workspace_info, + 0); + } + + return workspace_type; +} + +static void +meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass) +{ + GtkWidgetClass *widget_class; + + widget_class = GTK_WIDGET_CLASS (klass); + + widget_class->expose_event = meta_select_workspace_expose_event; +} + +/** + * meta_convert_meta_to_wnck() converts a MetaWindow to a + * WnckWindowDisplayInfo window that is used to build a thumbnail of a + * workspace. + **/ +static WnckWindowDisplayInfo +meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen) +{ + WnckWindowDisplayInfo wnck_window; + wnck_window.icon = window->icon; + wnck_window.mini_icon = window->mini_icon; + + wnck_window.is_active = FALSE; + if (window == window->display->expected_focus_window) + wnck_window.is_active = TRUE; + + if (window->frame) + { + wnck_window.x = window->frame->rect.x; + wnck_window.y = window->frame->rect.y; + wnck_window.width = window->frame->rect.width; + wnck_window.height = window->frame->rect.height; + } + else + { + wnck_window.x = window->rect.x; + wnck_window.y = window->rect.y; + wnck_window.width = window->rect.width; + wnck_window.height = window->rect.height; + } + return wnck_window; +} + + +static gboolean +meta_select_workspace_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + MetaWorkspace *workspace; + WnckWindowDisplayInfo *windows; + GtkStyle *style; + cairo_t *cr; + int i, n_windows; + GList *tmp, *list; + + workspace = META_SELECT_WORKSPACE (widget)->workspace; + + list = meta_stack_list_windows (workspace->screen->stack, workspace); + n_windows = g_list_length (list); + windows = g_new (WnckWindowDisplayInfo, n_windows); + + tmp = list; + i = 0; + while (tmp != NULL) + { + MetaWindow *window; + gboolean ignoreable_sticky; + + window = tmp->data; + + ignoreable_sticky = window->on_all_workspaces && + workspace != workspace->screen->active_workspace; + + if (window->skip_pager || + !meta_window_showing_on_its_workspace (window) || + window->unmaps_pending || + ignoreable_sticky) + { + --n_windows; + } + else + { + windows[i] = meta_convert_meta_to_wnck (window, workspace->screen); + i++; + } + tmp = tmp->next; + } + + g_list_free (list); + + wnck_draw_workspace (widget, + widget->window, + SELECT_OUTLINE_WIDTH, + SELECT_OUTLINE_WIDTH, + widget->allocation.width - SELECT_OUTLINE_WIDTH * 2, + widget->allocation.height - SELECT_OUTLINE_WIDTH * 2, + workspace->screen->rect.width, + workspace->screen->rect.height, + NULL, + (workspace->screen->active_workspace == workspace), + windows, + n_windows); + + g_free (windows); + + if (META_SELECT_WORKSPACE (widget)->selected) + { + style = gtk_widget_get_style (widget); + cr = gdk_cairo_create (widget->window); + + gdk_cairo_set_source_color (cr, + &style->fg[gtk_widget_get_state (widget)]); + cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH); + + cairo_rectangle (cr, + SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0, + widget->allocation.width - SELECT_OUTLINE_WIDTH, + widget->allocation.height - SELECT_OUTLINE_WIDTH); + cairo_stroke (cr); + + cairo_destroy (cr); + } + + return TRUE; +} + |