00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <config.h>
00027
00028 #include "util.h"
00029 #include "core.h"
00030 #include "tabpopup.h"
00031
00032
00033 #include "../core/workspace.h"
00034 #include "../core/frame-private.h"
00035 #include "draw-workspace.h"
00036 #include <gtk/gtk.h>
00037 #include <math.h>
00038
00039 #define OUTSIDE_SELECT_RECT 2
00040 #define INSIDE_SELECT_RECT 2
00041
00042 typedef struct _TabEntry TabEntry;
00043
00044 struct _TabEntry
00045 {
00046 MetaTabEntryKey key;
00047 char *title;
00048 GdkPixbuf *icon, *dimmed_icon;
00049 GtkWidget *widget;
00050 GdkRectangle rect;
00051 GdkRectangle inner_rect;
00052 guint blank : 1;
00053 };
00054
00055 struct _MetaTabPopup
00056 {
00057 GtkWidget *window;
00058 GtkWidget *label;
00059 GList *current;
00060 GList *entries;
00061 TabEntry *current_selected_entry;
00062 GtkWidget *outline_window;
00063 gboolean outline;
00064 };
00065
00066 static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
00067 static void select_image (GtkWidget *widget);
00068 static void unselect_image (GtkWidget *widget);
00069
00070 static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace);
00071 static void select_workspace (GtkWidget *widget);
00072 static void unselect_workspace (GtkWidget *widget);
00073
00074 static gboolean
00075 outline_window_expose (GtkWidget *widget,
00076 GdkEventExpose *event,
00077 gpointer data)
00078 {
00079 MetaTabPopup *popup;
00080 TabEntry *te;
00081
00082 popup = data;
00083
00084 if (!popup->outline || popup->current_selected_entry == NULL)
00085 return FALSE;
00086
00087 te = popup->current_selected_entry;
00088
00089 gdk_draw_rectangle (widget->window,
00090 widget->style->white_gc,
00091 FALSE,
00092 0, 0,
00093 te->rect.width - 1,
00094 te->rect.height - 1);
00095
00096 gdk_draw_rectangle (widget->window,
00097 widget->style->white_gc,
00098 FALSE,
00099 te->inner_rect.x - 1, te->inner_rect.y - 1,
00100 te->inner_rect.width + 1,
00101 te->inner_rect.height + 1);
00102
00103 return FALSE;
00104 }
00105
00106 static GdkPixbuf*
00107 dimm_icon (GdkPixbuf *pixbuf)
00108 {
00109 int x, y, pixel_stride, row_stride;
00110 guchar *row, *pixels;
00111 int w, h;
00112 GdkPixbuf *dimmed_pixbuf;
00113
00114 if (gdk_pixbuf_get_has_alpha (pixbuf))
00115 {
00116 dimmed_pixbuf = gdk_pixbuf_copy (pixbuf);
00117 }
00118 else
00119 {
00120 dimmed_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
00121 }
00122
00123 w = gdk_pixbuf_get_width (dimmed_pixbuf);
00124 h = gdk_pixbuf_get_height (dimmed_pixbuf);
00125
00126 pixel_stride = 4;
00127
00128 row = gdk_pixbuf_get_pixels (dimmed_pixbuf);
00129 row_stride = gdk_pixbuf_get_rowstride (dimmed_pixbuf);
00130
00131 for (y = 0; y < h; y++)
00132 {
00133 pixels = row;
00134 for (x = 0; x < w; x++)
00135 {
00136 pixels[3] /= 2;
00137 pixels += pixel_stride;
00138 }
00139 row += row_stride;
00140 }
00141 return dimmed_pixbuf;
00142 }
00143
00144 static TabEntry*
00145 tab_entry_new (const MetaTabEntry *entry,
00146 gint screen_width,
00147 gboolean outline)
00148 {
00149 TabEntry *te;
00150
00151 te = g_new (TabEntry, 1);
00152 te->key = entry->key;
00153 te->title = NULL;
00154 if (entry->title)
00155 {
00156 gchar *str;
00157 gchar *tmp;
00158 gchar *formatter = "%s";
00159
00160 str = meta_g_utf8_strndup (entry->title, 4096);
00161
00162 if (entry->hidden)
00163 {
00164 formatter = "[%s]";
00165 }
00166
00167 tmp = g_markup_printf_escaped (formatter, str);
00168 g_free (str);
00169 str = tmp;
00170
00171 if (entry->demands_attention)
00172 {
00173
00174
00175
00176 tmp = g_strdup_printf ("<b>%s</b>", str);
00177 g_free (str);
00178 str = tmp;
00179 }
00180
00181 te->title=g_strdup(str);
00182
00183 g_free (str);
00184 }
00185 te->widget = NULL;
00186 te->icon = entry->icon;
00187 te->blank = entry->blank;
00188 te->dimmed_icon = NULL;
00189 if (te->icon)
00190 {
00191 g_object_ref (G_OBJECT (te->icon));
00192 if (entry->hidden)
00193 te->dimmed_icon = dimm_icon (entry->icon);
00194 }
00195
00196 if (outline)
00197 {
00198 te->rect.x = entry->rect.x;
00199 te->rect.y = entry->rect.y;
00200 te->rect.width = entry->rect.width;
00201 te->rect.height = entry->rect.height;
00202
00203 te->inner_rect.x = entry->inner_rect.x;
00204 te->inner_rect.y = entry->inner_rect.y;
00205 te->inner_rect.width = entry->inner_rect.width;
00206 te->inner_rect.height = entry->inner_rect.height;
00207 }
00208 return te;
00209 }
00210
00211 MetaTabPopup*
00212 meta_ui_tab_popup_new (const MetaTabEntry *entries,
00213 int screen_number,
00214 int entry_count,
00215 int width,
00216 gboolean outline)
00217 {
00218 MetaTabPopup *popup;
00219 int i, left, right, top, bottom;
00220 int height;
00221 GtkWidget *table;
00222 GtkWidget *vbox;
00223 GtkWidget *align;
00224 GList *tmp;
00225 GtkWidget *frame;
00226 int max_label_width;
00227 AtkObject *obj;
00228 GdkScreen *screen;
00229 int screen_width;
00230
00231 popup = g_new (MetaTabPopup, 1);
00232
00233 popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP);
00234
00235 screen = gdk_display_get_screen (gdk_display_get_default (),
00236 screen_number);
00237 gtk_window_set_screen (GTK_WINDOW (popup->outline_window),
00238 screen);
00239
00240 gtk_widget_set_app_paintable (popup->outline_window, TRUE);
00241 gtk_widget_realize (popup->outline_window);
00242
00243 g_signal_connect (G_OBJECT (popup->outline_window), "expose_event",
00244 G_CALLBACK (outline_window_expose), popup);
00245
00246 popup->window = gtk_window_new (GTK_WINDOW_POPUP);
00247
00248 gtk_window_set_screen (GTK_WINDOW (popup->window),
00249 screen);
00250
00251 gtk_window_set_position (GTK_WINDOW (popup->window),
00252 GTK_WIN_POS_CENTER_ALWAYS);
00253
00254 gtk_window_set_resizable (GTK_WINDOW (popup->window),
00255 TRUE);
00256 popup->current = NULL;
00257 popup->entries = NULL;
00258 popup->current_selected_entry = NULL;
00259 popup->outline = outline;
00260
00261 screen_width = gdk_screen_get_width (screen);
00262 for (i = 0; i < entry_count; ++i)
00263 {
00264 TabEntry* new_entry = tab_entry_new (&entries[i], screen_width, outline);
00265 popup->entries = g_list_prepend (popup->entries, new_entry);
00266 }
00267
00268 popup->entries = g_list_reverse (popup->entries);
00269
00270 g_assert (width > 0);
00271 height = i / width;
00272 if (i % width)
00273 height += 1;
00274
00275 table = gtk_table_new (height, width, FALSE);
00276 vbox = gtk_vbox_new (FALSE, 0);
00277
00278 frame = gtk_frame_new (NULL);
00279 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
00280 gtk_container_set_border_width (GTK_CONTAINER (table), 1);
00281 gtk_container_add (GTK_CONTAINER (popup->window),
00282 frame);
00283 gtk_container_add (GTK_CONTAINER (frame),
00284 vbox);
00285
00286 align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
00287
00288 gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
00289
00290 gtk_container_add (GTK_CONTAINER (align),
00291 table);
00292
00293 popup->label = gtk_label_new ("");
00294
00295
00296
00297
00298
00299 obj = gtk_widget_get_accessible (popup->label);
00300 atk_object_set_role (obj, ATK_ROLE_STATUSBAR);
00301
00302 gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3);
00303
00304 gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0);
00305
00306 max_label_width = 0;
00307 top = 0;
00308 bottom = 1;
00309 tmp = popup->entries;
00310
00311 while (tmp && top < height)
00312 {
00313 left = 0;
00314 right = 1;
00315
00316 while (tmp && left < width)
00317 {
00318 GtkWidget *image;
00319 GtkRequisition req;
00320
00321 TabEntry *te;
00322
00323 te = tmp->data;
00324
00325 if (te->blank)
00326 {
00327
00328 image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
00329 }
00330 else if (outline)
00331 {
00332 if (te->dimmed_icon)
00333 {
00334 image = selectable_image_new (te->dimmed_icon);
00335 }
00336 else
00337 {
00338 image = selectable_image_new (te->icon);
00339 }
00340
00341 gtk_misc_set_padding (GTK_MISC (image),
00342 INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1,
00343 INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1);
00344 gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
00345 }
00346 else
00347 {
00348 image = selectable_workspace_new ((MetaWorkspace *) te->key);
00349 }
00350
00351 te->widget = image;
00352
00353 gtk_table_attach (GTK_TABLE (table),
00354 te->widget,
00355 left, right, top, bottom,
00356 0, 0,
00357 0, 0);
00358
00359
00360 gtk_label_set_markup (GTK_LABEL (popup->label),
00361 te->title);
00362 gtk_widget_size_request (popup->label, &req);
00363 max_label_width = MAX (max_label_width, req.width);
00364
00365 tmp = tmp->next;
00366
00367 ++left;
00368 ++right;
00369 }
00370
00371 ++top;
00372 ++bottom;
00373 }
00374
00375
00376 gtk_label_set_text (GTK_LABEL (popup->label), "");
00377
00378 gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END);
00379
00380
00381 if (max_label_width>(screen_width/4))
00382 {
00383 max_label_width = screen_width/4;
00384 }
00385
00386 max_label_width += 20;
00387
00388 gtk_window_set_default_size (GTK_WINDOW (popup->window),
00389 max_label_width,
00390 -1);
00391
00392 return popup;
00393 }
00394
00395 static void
00396 free_tab_entry (gpointer data, gpointer user_data)
00397 {
00398 TabEntry *te;
00399
00400 te = data;
00401
00402 g_free (te->title);
00403 if (te->icon)
00404 g_object_unref (G_OBJECT (te->icon));
00405 if (te->dimmed_icon)
00406 g_object_unref (G_OBJECT (te->dimmed_icon));
00407
00408 g_free (te);
00409 }
00410
00411 void
00412 meta_ui_tab_popup_free (MetaTabPopup *popup)
00413 {
00414 meta_verbose ("Destroying tab popup window\n");
00415
00416 gtk_widget_destroy (popup->outline_window);
00417 gtk_widget_destroy (popup->window);
00418
00419 g_list_foreach (popup->entries, free_tab_entry, NULL);
00420
00421 g_list_free (popup->entries);
00422
00423 g_free (popup);
00424 }
00425
00426 void
00427 meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
00428 gboolean showing)
00429 {
00430 if (showing)
00431 {
00432 gtk_widget_show_all (popup->window);
00433 }
00434 else
00435 {
00436 if (GTK_WIDGET_VISIBLE (popup->window))
00437 {
00438 meta_verbose ("Hiding tab popup window\n");
00439 gtk_widget_hide (popup->window);
00440 meta_core_increment_event_serial (gdk_display);
00441 }
00442 }
00443 }
00444
00445 static void
00446 display_entry (MetaTabPopup *popup,
00447 TabEntry *te)
00448 {
00449 GdkRectangle rect;
00450 GdkRegion *region;
00451 GdkRegion *inner_region;
00452
00453
00454 if (popup->current_selected_entry)
00455 {
00456 if (popup->outline)
00457 unselect_image (popup->current_selected_entry->widget);
00458 else
00459 unselect_workspace (popup->current_selected_entry->widget);
00460 }
00461
00462 gtk_label_set_markup (GTK_LABEL (popup->label), te->title);
00463
00464 if (popup->outline)
00465 select_image (te->widget);
00466 else
00467 select_workspace (te->widget);
00468
00469 if (popup->outline)
00470 {
00471
00472 gdk_window_hide (popup->outline_window->window);
00473 meta_core_increment_event_serial (gdk_display);
00474
00475 rect = te->rect;
00476 rect.x = 0;
00477 rect.y = 0;
00478
00479 gdk_window_move_resize (popup->outline_window->window,
00480 te->rect.x, te->rect.y,
00481 te->rect.width, te->rect.height);
00482
00483 gdk_window_set_background (popup->outline_window->window,
00484 &popup->outline_window->style->black);
00485
00486 region = gdk_region_rectangle (&rect);
00487 inner_region = gdk_region_rectangle (&te->inner_rect);
00488 gdk_region_subtract (region, inner_region);
00489 gdk_region_destroy (inner_region);
00490
00491 gdk_window_shape_combine_region (popup->outline_window->window,
00492 region,
00493 0, 0);
00494
00495 gdk_region_destroy (region);
00496
00497
00498
00499
00500
00501
00502 GTK_WIDGET_SET_FLAGS (popup->outline_window, GTK_MAPPED);
00503 gdk_window_show_unraised (popup->outline_window->window);
00504 }
00505
00506
00507 popup->current_selected_entry = te;
00508 }
00509
00510 void
00511 meta_ui_tab_popup_forward (MetaTabPopup *popup)
00512 {
00513 if (popup->current != NULL)
00514 popup->current = popup->current->next;
00515
00516 if (popup->current == NULL)
00517 popup->current = popup->entries;
00518
00519 if (popup->current != NULL)
00520 {
00521 TabEntry *te;
00522
00523 te = popup->current->data;
00524
00525 display_entry (popup, te);
00526 }
00527 }
00528
00529 void
00530 meta_ui_tab_popup_backward (MetaTabPopup *popup)
00531 {
00532 if (popup->current != NULL)
00533 popup->current = popup->current->prev;
00534
00535 if (popup->current == NULL)
00536 popup->current = g_list_last (popup->entries);
00537
00538 if (popup->current != NULL)
00539 {
00540 TabEntry *te;
00541
00542 te = popup->current->data;
00543
00544 display_entry (popup, te);
00545 }
00546 }
00547
00548 MetaTabEntryKey
00549 meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
00550 {
00551 if (popup->current)
00552 {
00553 TabEntry *te;
00554
00555 te = popup->current->data;
00556
00557 return te->key;
00558 }
00559 else
00560 return (MetaTabEntryKey)None;
00561 }
00562
00563 void
00564 meta_ui_tab_popup_select (MetaTabPopup *popup,
00565 MetaTabEntryKey key)
00566 {
00567 GList *tmp;
00568
00569
00570
00571
00572
00573 tmp = popup->entries;
00574 while (tmp != NULL)
00575 {
00576 TabEntry *te;
00577
00578 te = tmp->data;
00579
00580 if (te->key == key)
00581 {
00582 popup->current = tmp;
00583
00584 display_entry (popup, te);
00585
00586 return;
00587 }
00588
00589 tmp = tmp->next;
00590 }
00591 }
00592
00593 #define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ())
00594 #define META_SELECT_IMAGE(obj) (GTK_CHECK_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage))
00595
00596 typedef struct _MetaSelectImage MetaSelectImage;
00597 typedef struct _MetaSelectImageClass MetaSelectImageClass;
00598
00599 struct _MetaSelectImage
00600 {
00601 GtkImage parent_instance;
00602 guint selected : 1;
00603 };
00604
00605 struct _MetaSelectImageClass
00606 {
00607 GtkImageClass parent_class;
00608 };
00609
00610
00611 static GType meta_select_image_get_type (void) G_GNUC_CONST;
00612
00613 static GtkWidget*
00614 selectable_image_new (GdkPixbuf *pixbuf)
00615 {
00616 GtkWidget *w;
00617
00618 w = g_object_new (meta_select_image_get_type (), NULL);
00619 gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf);
00620
00621 return w;
00622 }
00623
00624 static void
00625 select_image (GtkWidget *widget)
00626 {
00627 META_SELECT_IMAGE (widget)->selected = TRUE;
00628 gtk_widget_queue_draw (widget);
00629 }
00630
00631 static void
00632 unselect_image (GtkWidget *widget)
00633 {
00634 META_SELECT_IMAGE (widget)->selected = FALSE;
00635 gtk_widget_queue_draw (widget);
00636 }
00637
00638 static void meta_select_image_class_init (MetaSelectImageClass *klass);
00639 static gboolean meta_select_image_expose_event (GtkWidget *widget,
00640 GdkEventExpose *event);
00641
00642 static GtkImageClass *parent_class;
00643
00644 GType
00645 meta_select_image_get_type (void)
00646 {
00647 static GtkType image_type = 0;
00648
00649 if (!image_type)
00650 {
00651 static const GTypeInfo image_info =
00652 {
00653 sizeof (MetaSelectImageClass),
00654 NULL,
00655 NULL,
00656 (GClassInitFunc) meta_select_image_class_init,
00657 NULL,
00658 NULL,
00659 sizeof (MetaSelectImage),
00660 16,
00661 (GInstanceInitFunc) NULL,
00662 };
00663
00664 image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0);
00665 }
00666
00667 return image_type;
00668 }
00669
00670 static void
00671 meta_select_image_class_init (MetaSelectImageClass *klass)
00672 {
00673 GtkWidgetClass *widget_class;
00674
00675 parent_class = gtk_type_class (gtk_image_get_type ());
00676
00677 widget_class = GTK_WIDGET_CLASS (klass);
00678
00679 widget_class->expose_event = meta_select_image_expose_event;
00680 }
00681
00682 static gboolean
00683 meta_select_image_expose_event (GtkWidget *widget,
00684 GdkEventExpose *event)
00685 {
00686 if (META_SELECT_IMAGE (widget)->selected)
00687 {
00688 int x, y, w, h;
00689 GtkMisc *misc;
00690
00691 misc = GTK_MISC (widget);
00692
00693 x = (widget->allocation.x * (1.0 - misc->xalign) +
00694 (widget->allocation.x + widget->allocation.width
00695 - (widget->requisition.width - misc->xpad * 2)) *
00696 misc->xalign) + 0.5;
00697 y = (widget->allocation.y * (1.0 - misc->yalign) +
00698 (widget->allocation.y + widget->allocation.height
00699 - (widget->requisition.height - misc->ypad * 2)) *
00700 misc->yalign) + 0.5;
00701
00702 x -= INSIDE_SELECT_RECT + 1;
00703 y -= INSIDE_SELECT_RECT + 1;
00704
00705 w = widget->requisition.width - OUTSIDE_SELECT_RECT * 2 - 1;
00706 h = widget->requisition.height - OUTSIDE_SELECT_RECT * 2 - 1;
00707
00708 gdk_draw_rectangle (widget->window,
00709 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
00710 FALSE,
00711 x, y, w, h);
00712 gdk_draw_rectangle (widget->window,
00713 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
00714 FALSE,
00715 x - 1, y - 1, w + 2, h + 2);
00716
00717 #if 0
00718 gdk_draw_rectangle (widget->window,
00719 widget->style->bg_gc[GTK_STATE_SELECTED],
00720 TRUE,
00721 x, y, w, h);
00722 #endif
00723 #if 0
00724 gtk_paint_focus (widget->style, widget->window,
00725 &event->area, widget, "meta-tab-image",
00726 x, y, w, h);
00727 #endif
00728 }
00729
00730 return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
00731 }
00732
00733 #define META_TYPE_SELECT_WORKSPACE (meta_select_workspace_get_type ())
00734 #define META_SELECT_WORKSPACE(obj) (GTK_CHECK_CAST ((obj), META_TYPE_SELECT_WORKSPACE, MetaSelectWorkspace))
00735
00736 typedef struct _MetaSelectWorkspace MetaSelectWorkspace;
00737 typedef struct _MetaSelectWorkspaceClass MetaSelectWorkspaceClass;
00738
00739 struct _MetaSelectWorkspace
00740 {
00741 GtkDrawingArea parent_instance;
00742 MetaWorkspace *workspace;
00743 guint selected : 1;
00744 };
00745
00746 struct _MetaSelectWorkspaceClass
00747 {
00748 GtkDrawingAreaClass parent_class;
00749 };
00750
00751
00752 static GType meta_select_workspace_get_type (void) G_GNUC_CONST;
00753
00754 #define SELECT_OUTLINE_WIDTH 2
00755 #define MINI_WORKSPACE_WIDTH 48
00756
00757 static GtkWidget*
00758 selectable_workspace_new (MetaWorkspace *workspace)
00759 {
00760 GtkWidget *widget;
00761 double screen_aspect;
00762
00763 widget = g_object_new (meta_select_workspace_get_type (), NULL);
00764
00765 screen_aspect = (double) workspace->screen->rect.height /
00766 (double) workspace->screen->rect.width;
00767
00768
00769 gtk_widget_set_size_request (widget,
00770 MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2,
00771 MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2);
00772
00773 META_SELECT_WORKSPACE (widget)->workspace = workspace;
00774
00775 return widget;
00776 }
00777
00778 static void
00779 select_workspace (GtkWidget *widget)
00780 {
00781 META_SELECT_WORKSPACE(widget)->selected = TRUE;
00782 gtk_widget_queue_draw (widget);
00783 }
00784
00785 static void
00786 unselect_workspace (GtkWidget *widget)
00787 {
00788 META_SELECT_WORKSPACE (widget)->selected = FALSE;
00789 gtk_widget_queue_draw (widget);
00790 }
00791
00792 static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass);
00793
00794 static gboolean meta_select_workspace_expose_event (GtkWidget *widget,
00795 GdkEventExpose *event);
00796
00797 GType
00798 meta_select_workspace_get_type (void)
00799 {
00800 static GtkType workspace_type = 0;
00801
00802 if (!workspace_type)
00803 {
00804 static const GTypeInfo workspace_info =
00805 {
00806 sizeof (MetaSelectWorkspaceClass),
00807 NULL,
00808 NULL,
00809 (GClassInitFunc) meta_select_workspace_class_init,
00810 NULL,
00811 NULL,
00812 sizeof (MetaSelectWorkspace),
00813 16,
00814 (GInstanceInitFunc) NULL,
00815 };
00816
00817 workspace_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
00818 "MetaSelectWorkspace",
00819 &workspace_info,
00820 0);
00821 }
00822
00823 return workspace_type;
00824 }
00825
00826 static void
00827 meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass)
00828 {
00829 GtkWidgetClass *widget_class;
00830
00831 widget_class = GTK_WIDGET_CLASS (klass);
00832
00833 widget_class->expose_event = meta_select_workspace_expose_event;
00834 }
00835
00841 static WnckWindowDisplayInfo
00842 meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
00843 {
00844 WnckWindowDisplayInfo wnck_window;
00845 wnck_window.icon = window->icon;
00846 wnck_window.mini_icon = window->mini_icon;
00847
00848 wnck_window.is_active = FALSE;
00849 if (window == window->display->expected_focus_window)
00850 wnck_window.is_active = TRUE;
00851
00852 if (window->frame)
00853 {
00854 wnck_window.x = window->frame->rect.x;
00855 wnck_window.y = window->frame->rect.y;
00856 wnck_window.width = window->frame->rect.width;
00857 wnck_window.height = window->frame->rect.height;
00858 }
00859 else
00860 {
00861 wnck_window.x = window->rect.x;
00862 wnck_window.y = window->rect.y;
00863 wnck_window.width = window->rect.width;
00864 wnck_window.height = window->rect.height;
00865 }
00866 return wnck_window;
00867 }
00868
00869
00870 static gboolean
00871 meta_select_workspace_expose_event (GtkWidget *widget,
00872 GdkEventExpose *event)
00873 {
00874 MetaWorkspace *workspace;
00875 WnckWindowDisplayInfo *windows;
00876 int i, n_windows;
00877 GList *tmp, *list;
00878
00879 workspace = META_SELECT_WORKSPACE (widget)->workspace;
00880
00881 list = meta_stack_list_windows (workspace->screen->stack, workspace);
00882 n_windows = g_list_length (list);
00883 windows = g_new (WnckWindowDisplayInfo, n_windows);
00884
00885 tmp = list;
00886 i = 0;
00887 while (tmp != NULL)
00888 {
00889 MetaWindow *window;
00890 gboolean ignoreable_sticky;
00891
00892 window = tmp->data;
00893
00894 ignoreable_sticky = window->on_all_workspaces &&
00895 workspace != workspace->screen->active_workspace;
00896
00897 if (window->skip_pager ||
00898 !meta_window_showing_on_its_workspace (window) ||
00899 window->unmaps_pending ||
00900 ignoreable_sticky)
00901 {
00902 --n_windows;
00903 }
00904 else
00905 {
00906 windows[i] = meta_convert_meta_to_wnck (window, workspace->screen);
00907 i++;
00908 }
00909 tmp = tmp->next;
00910 }
00911
00912 g_list_free (list);
00913
00914 wnck_draw_workspace (widget,
00915 widget->window,
00916 SELECT_OUTLINE_WIDTH,
00917 SELECT_OUTLINE_WIDTH,
00918 widget->allocation.width - SELECT_OUTLINE_WIDTH * 2,
00919 widget->allocation.height - SELECT_OUTLINE_WIDTH * 2,
00920 workspace->screen->rect.width,
00921 workspace->screen->rect.height,
00922 NULL,
00923 (workspace->screen->active_workspace == workspace),
00924 windows,
00925 n_windows);
00926
00927 g_free (windows);
00928
00929 if (META_SELECT_WORKSPACE (widget)->selected)
00930 {
00931 i = SELECT_OUTLINE_WIDTH - 1;
00932 while (i >= 0)
00933 {
00934 gdk_draw_rectangle (widget->window,
00935 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
00936 FALSE,
00937 i,
00938 i,
00939 widget->allocation.width - i * 2 - 1,
00940 widget->allocation.height - i * 2 - 1);
00941
00942 --i;
00943 }
00944 }
00945
00946 return TRUE;
00947 }
00948