Index: tasklist.c =================================================================== --- libwnck/tasklist.c (révision 1379) +++ libwnck/tasklist.c (copie de travail) @@ -35,6 +35,7 @@ #include "workspace.h" #include "xutils.h" #include "private.h" +#include "obox.h" /** * SECTION:tasklist @@ -118,6 +119,7 @@ struct _WnckTask GtkWidget *button; GtkWidget *image; GtkWidget *label; + GtkWidget *obox; WnckTaskType type; @@ -198,6 +200,9 @@ struct _WnckTasklistPrivate GHashTable *class_group_hash; GHashTable *win_hash; + gboolean vertical_mode; + gboolean rotated; + gint max_button_width; gint max_button_height; @@ -677,6 +682,9 @@ wnck_tasklist_init (WnckTasklist *taskli tasklist->priv->class_group_hash = g_hash_table_new (NULL, NULL); tasklist->priv->win_hash = g_hash_table_new (NULL, NULL); + tasklist->priv->vertical_mode = FALSE; + tasklist->priv->rotated = FALSE; + tasklist->priv->max_button_width = 0; tasklist->priv->max_button_height = 0; @@ -1000,6 +1008,31 @@ wnck_tasklist_set_include_all_workspaces } /** + * wnck_tasklist_set_vertical_mode: + * @tasklist: a #WnckTasklist. + * @vertical_mode: whether to put @tasklist in vertical mode. + * + * Activates or deactivates the vertical mode of @tasklist according to + * @vertical_mode. The vertical mode is a specific mode for #WnckTasklist + * widgets, to be used when they are on vertical panels, for example. The task + * buttons will be rotated if there is not enough space for them to be + * horizontal, and the size hints will return a value for the height instead of + * the width. + */ +void +wnck_tasklist_set_vertical_mode (WnckTasklist *tasklist, + gboolean vertical_mode) +{ + g_return_if_fail (WNCK_IS_TASKLIST (tasklist)); + + if (tasklist->priv->vertical_mode == vertical_mode) + return; + + tasklist->priv->vertical_mode = vertical_mode; + gtk_widget_queue_resize (GTK_WIDGET (tasklist)); +} + +/** * wnck_tasklist_set_grouping_limit: * @tasklist: a #WnckTasklist. * @limit: a size in pixels. @@ -1231,28 +1264,48 @@ wnck_task_get_highest_scored (GList return g_list_remove (ungrouped_class_groups, best_task); } -static int -wnck_tasklist_get_button_size (GtkWidget *widget) +/* This function returns value that are valid for an horizontal button. + * If the button gets rotated, returned values should be swapped */ +static void +wnck_tasklist_get_button_size (GtkWidget *widget, + int *width, + int *height) { PangoContext *context; PangoFontMetrics *metrics; - gint char_width; - gint text_width; - gint width; + int ascent; + int descent; + int char_width; + int text_width; + int focus_width = 0; + int focus_pad = 0; + int thickness; gtk_widget_ensure_style (widget); context = gtk_widget_get_pango_context (widget); metrics = pango_context_get_metrics (context, widget->style->font_desc, pango_context_get_language (context)); + ascent = pango_font_metrics_get_ascent (metrics); + descent = pango_font_metrics_get_descent (metrics); char_width = pango_font_metrics_get_approximate_char_width (metrics); pango_font_metrics_unref (metrics); + text_width = PANGO_PIXELS (TASKLIST_TEXT_MAX_WIDTH * char_width); - width = text_width + 2 * TASKLIST_BUTTON_PADDING - + MINI_ICON_SIZE + 2 * TASKLIST_BUTTON_PADDING; + gtk_widget_style_get (widget, + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, + NULL); + + thickness = MAX (widget->style->ythickness, widget->style->xthickness); + + *width = text_width + 2 * TASKLIST_BUTTON_PADDING + + MINI_ICON_SIZE + 2 * TASKLIST_BUTTON_PADDING + + 2 * (focus_width + focus_pad + thickness); - return width; + *height = MAX (MINI_ICON_SIZE, PANGO_PIXELS (ascent + descent)) + + 2 * (focus_width + focus_pad + thickness); } static void @@ -1260,41 +1313,45 @@ wnck_tasklist_size_request (GtkWidget GtkRequisition *requisition) { WnckTasklist *tasklist; - GtkRequisition child_req; GtkAllocation fake_allocation; int max_height = 1; int max_width = 1; - /* int u_width, u_height; */ + int grouping_limit; + gboolean vertical_orientation; GList *l; + + /* for size hints */ + int *n_rows_or_cols; /* this points to n_cols in horizontal mode, + and n_rows in vertical mode. The size hints depends + on the number of rows in vertical mode. */ + int last_n_rows_or_cols; + int max_size_for_button; + int min_size_for_button; GArray *array; GList *ungrouped_class_groups; int n_windows; int n_startup_sequences; int n_rows; - int n_cols, last_n_cols; + int n_cols; int n_grouped_buttons; gboolean score_set; int val; WnckTask *class_group_task; int lowest_range; - int grouping_limit; tasklist = WNCK_TASKLIST (widget); - /* Calculate max needed height and width of the buttons */ + /* we need to request the size of the buttons to get the labels properly + * aligned. FIXME: why? */ #define GET_MAX_WIDTH_HEIGHT_FROM_BUTTONS(list) \ l = list; \ while (l != NULL) \ { \ + GtkRequisition child_req; \ WnckTask *task = WNCK_TASK (l->data); \ \ gtk_widget_size_request (task->button, &child_req); \ \ - max_height = MAX (child_req.height, \ - max_height); \ - max_width = MAX (child_req.width, \ - max_width); \ - \ l = l->next; \ } @@ -1302,17 +1359,47 @@ wnck_tasklist_size_request (GtkWidget GET_MAX_WIDTH_HEIGHT_FROM_BUTTONS (tasklist->priv->class_groups) GET_MAX_WIDTH_HEIGHT_FROM_BUTTONS (tasklist->priv->startup_sequences) - /* Note that the fact that we nearly don't care about the width/height - * requested by the buttons makes it possible to hide/show the label/image - * in wnck_task_size_allocated(). If we really cared about those, this - * wouldn't work since our call to gtk_widget_size_request() does not take - * into account the hidden widgets. - */ - tasklist->priv->max_button_width = wnck_tasklist_get_button_size (widget); + wnck_tasklist_get_button_size (widget, &max_width, &max_height); + + grouping_limit = MIN (tasklist->priv->grouping_limit, max_width); + + tasklist->priv->max_button_width = max_width; tasklist->priv->max_button_height = max_height; - fake_allocation.width = GTK_WIDGET (tasklist)->allocation.width; - fake_allocation.height = GTK_WIDGET (tasklist)->allocation.height; + /* if we're in vertical mode, the width will most often not change, so we + * can assume the current width is okay */ + if (tasklist->priv->vertical_mode && + GTK_WIDGET (tasklist)->allocation.width < grouping_limit) + vertical_orientation = TRUE; + else + vertical_orientation = FALSE; + + /* changing orientation is just rotating everything */ + if (!tasklist->priv->vertical_mode || vertical_orientation) + { + n_rows_or_cols = &n_cols; + min_size_for_button = grouping_limit; + max_size_for_button = tasklist->priv->max_button_width; + } + else + { + n_rows_or_cols = &n_rows; + min_size_for_button = max_height; + max_size_for_button = max_height; + } + + if (!vertical_orientation) + { + fake_allocation.width = GTK_WIDGET (tasklist)->allocation.width; + fake_allocation.height = GTK_WIDGET (tasklist)->allocation.height; + } + else + { + /* swap width and height, since changing orientation means just rotating + * everything */ + fake_allocation.width = GTK_WIDGET (tasklist)->allocation.height; + fake_allocation.height = GTK_WIDGET (tasklist)->allocation.width; + } array = g_array_new (FALSE, FALSE, sizeof (int)); @@ -1324,26 +1411,32 @@ wnck_tasklist_size_request (GtkWidget ungrouped_class_groups = g_list_copy (tasklist->priv->class_groups); score_set = FALSE; - grouping_limit = MIN (tasklist->priv->grouping_limit, - tasklist->priv->max_button_width); - /* Try ungrouped mode */ - wnck_tasklist_layout (&fake_allocation, - tasklist->priv->max_button_width, - tasklist->priv->max_button_height, - n_windows + n_startup_sequences, - &n_cols, &n_rows); + if (!tasklist->priv->vertical_mode || vertical_orientation) + { + wnck_tasklist_layout (&fake_allocation, + tasklist->priv->max_button_width, + tasklist->priv->max_button_height, + n_windows + n_startup_sequences, + &n_cols, &n_rows); + } + else + { + /* We want all tasks in one high column. */ + n_cols = 1; + n_rows = n_windows + n_startup_sequences; + } - last_n_cols = G_MAXINT; + last_n_rows_or_cols = G_MAXINT; lowest_range = G_MAXINT; if (tasklist->priv->grouping != WNCK_TASKLIST_ALWAYS_GROUP) { - val = n_cols * tasklist->priv->max_button_width; + val = *n_rows_or_cols * max_size_for_button; g_array_insert_val (array, array->len, val); - val = n_cols * grouping_limit; + val = *n_rows_or_cols * min_size_for_button; g_array_insert_val (array, array->len, val); - last_n_cols = n_cols; + last_n_rows_or_cols = *n_rows_or_cols; lowest_range = val; } @@ -1365,27 +1449,28 @@ wnck_tasklist_size_request (GtkWidget tasklist->priv->max_button_height, n_startup_sequences + n_windows - n_grouped_buttons, &n_cols, &n_rows); - if (n_cols != last_n_cols && + if (*n_rows_or_cols != last_n_rows_or_cols && (tasklist->priv->grouping == WNCK_TASKLIST_AUTO_GROUP || ungrouped_class_groups == NULL)) { - val = n_cols * tasklist->priv->max_button_width; + val = *n_rows_or_cols * max_size_for_button; + if (val >= lowest_range) { /* Overlaps old range */ g_assert (array->len > 0); - lowest_range = n_cols * grouping_limit; + lowest_range = *n_rows_or_cols * min_size_for_button; g_array_index(array, int, array->len-1) = lowest_range; } else { /* Full new range */ g_array_insert_val (array, array->len, val); - val = n_cols * grouping_limit; + val = *n_rows_or_cols * min_size_for_button; g_array_insert_val (array, array->len, val); lowest_range = val; } - last_n_cols = n_cols; + last_n_rows_or_cols = *n_rows_or_cols; } } @@ -1408,8 +1493,16 @@ wnck_tasklist_size_request (GtkWidget tasklist->priv->size_hints = (int *)g_array_free (array, FALSE); - requisition->width = tasklist->priv->size_hints[0]; - requisition->height = fake_allocation.height; + if (!tasklist->priv->vertical_mode) + { + requisition->width = tasklist->priv->size_hints[0]; + requisition->height = n_rows * tasklist->priv->max_button_height; + } + else + { + requisition->width = fake_allocation.width; + requisition->height = tasklist->priv->size_hints[0]; + } } /** @@ -1444,17 +1537,29 @@ wnck_task_size_allocated (GtkWidget gpointer data) { WnckTask *task = WNCK_TASK (data); - int min_image_width; + int min_image_size; + int size; - min_image_width = MINI_ICON_SIZE + - 2 * widget->style->xthickness + - 2 * TASKLIST_BUTTON_PADDING; + if (!task->tasklist->priv->rotated) + { + size = allocation->width; + min_image_size = MINI_ICON_SIZE + + 2 * widget->style->xthickness + + 2 * TASKLIST_BUTTON_PADDING; + } + else + { + size = allocation->height; + min_image_size = MINI_ICON_SIZE + + 2 * widget->style->ythickness + + 2 * TASKLIST_BUTTON_PADDING; + } - if ((allocation->width < min_image_width + 2 * TASKLIST_BUTTON_PADDING) && - (allocation->width >= min_image_width)) { + if ((size < min_image_size + 2 * TASKLIST_BUTTON_PADDING) && + (size >= min_image_size)) { gtk_widget_show (task->image); gtk_widget_hide (task->label); - } else if (allocation->width < min_image_width) { + } else if (size < min_image_size) { gtk_widget_hide (task->image); gtk_widget_show (task->label); } else { @@ -1467,6 +1572,7 @@ static void wnck_tasklist_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { + GtkAllocation maybe_rotated_allocation; GtkAllocation child_allocation; WnckTasklist *tasklist; WnckTask *class_group_task; @@ -1485,6 +1591,7 @@ wnck_tasklist_size_allocate (GtkWidget GList *visible_tasks = NULL; GList *windows_sorted = NULL; int grouping_limit; + gdouble angle; tasklist = WNCK_TASKLIST (widget); @@ -1497,8 +1604,45 @@ wnck_tasklist_size_allocate (GtkWidget grouping_limit = MIN (tasklist->priv->grouping_limit, tasklist->priv->max_button_width); + //FIXME: initial size is wrong in vertical mode + if (gtk_widget_get_realized (widget) && + tasklist->priv->vertical_mode && allocation->width < grouping_limit) + { + GdkScreen *screen; + int xpos; + int ypos; + + tasklist->priv->rotated = TRUE; + + gdk_window_get_origin (widget->window, &xpos, &ypos); + + //FIXME: is not updated when panel changes from right to left + screen = _wnck_screen_get_gdk_screen (tasklist->priv->screen); + if (xpos + (allocation->x + allocation->width) / 2 + < gdk_screen_get_width (screen) / 2) + angle = 90; + else + angle = 270; + } + else + { + tasklist->priv->rotated = FALSE; + angle = 0; + } + + if (!tasklist->priv->rotated) + { + maybe_rotated_allocation.width = allocation->width; + maybe_rotated_allocation.height = allocation->height; + } + else + { + maybe_rotated_allocation.width = allocation->height; + maybe_rotated_allocation.height = allocation->width; + } + /* Try ungrouped mode */ - button_width = wnck_tasklist_layout (allocation, + button_width = wnck_tasklist_layout (&maybe_rotated_allocation, tasklist->priv->max_button_width, tasklist->priv->max_button_height, n_startup_sequences + n_windows, @@ -1532,8 +1676,8 @@ wnck_tasklist_size_allocate (GtkWidget { win_task = WNCK_TASK (l->data); - gtk_widget_set_child_visible (GTK_WIDGET (win_task->button), FALSE); - + gtk_widget_set_child_visible (GTK_WIDGET (win_task->button), + FALSE); cleanup_screenshots (win_task); l = l->next; @@ -1541,13 +1685,14 @@ wnck_tasklist_size_allocate (GtkWidget } else { - visible_tasks = g_list_prepend (visible_tasks, class_group_task->windows->data); - gtk_widget_set_child_visible (GTK_WIDGET (class_group_task->button), FALSE); - + visible_tasks = g_list_prepend (visible_tasks, + class_group_task->windows->data); + gtk_widget_set_child_visible (GTK_WIDGET (class_group_task->button), + FALSE); cleanup_screenshots (class_group_task); } - button_width = wnck_tasklist_layout (allocation, + button_width = wnck_tasklist_layout (&maybe_rotated_allocation, tasklist->priv->max_button_width, tasklist->priv->max_button_height, n_startup_sequences + n_windows - n_grouped_buttons, @@ -1560,34 +1705,45 @@ wnck_tasklist_size_allocate (GtkWidget { class_group_task = WNCK_TASK (l->data); - visible_tasks = g_list_concat (visible_tasks, g_list_copy (class_group_task->windows)); - gtk_widget_set_child_visible (GTK_WIDGET (class_group_task->button), FALSE); - + visible_tasks = g_list_concat (visible_tasks, + g_list_copy (class_group_task->windows)); + gtk_widget_set_child_visible (GTK_WIDGET (class_group_task->button), + FALSE); cleanup_screenshots (class_group_task); l = l->next; } /* Add all windows that are ungrouped because they don't belong to any class * group */ l = tasklist->priv->windows_without_class_group; while (l != NULL) { WnckTask *task; task = WNCK_TASK (l->data); visible_tasks = g_list_append (visible_tasks, task); l = l->next; } /* Add all startup sequences */ - visible_tasks = g_list_concat (visible_tasks, g_list_copy (tasklist->priv->startup_sequences)); + visible_tasks = g_list_concat (visible_tasks, + g_list_copy (tasklist->priv->startup_sequences)); /* Sort */ visible_tasks = g_list_sort (visible_tasks, wnck_task_compare); /* Allocate children */ + if (tasklist->priv->rotated) + { + int buf; + + buf = n_rows; + n_rows = n_cols; + n_cols = buf; + } + l = visible_tasks; i = 0; total_width = tasklist->priv->max_button_width * n_cols; @@ -1586,12 +1742,40 @@ wnck_tasklist_size_allocate (GtkWidget while (l != NULL) { WnckTask *task = WNCK_TASK (l->data); - int row = i % n_rows; - int col = i / n_rows; + int row; + int col; + + if (!tasklist->priv->rotated) + { + row = i % n_rows; + col = i / n_rows; + } + else + { + row = i % n_cols; + col = i / n_cols; + } if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) col = n_cols - col - 1; + if (angle == 270) + { + int buf; + + buf = row; + row = col; + col = n_cols - buf - 1; + } + else if (angle == 90) + { + int buf; + + buf = row; + row = n_rows - col - 1; + col = buf; + } + child_allocation.x = total_width*col / n_cols; child_allocation.y = allocation->height*row / n_rows; child_allocation.width = total_width*(col + 1) / n_cols - child_allocation.x; @@ -1602,6 +1786,29 @@ wnck_tasklist_size_allocate (GtkWidget gtk_widget_size_allocate (task->button, &child_allocation); gtk_widget_set_child_visible (GTK_WIDGET (task->button), TRUE); + wnck_obox_set_orientation (WNCK_OBOX (task->obox), + tasklist->priv->rotated ? + GTK_ORIENTATION_VERTICAL : + GTK_ORIENTATION_HORIZONTAL); + //FIXME: this is wrong for japanese! + wnck_obox_set_reverse_order (WNCK_OBOX (task->obox), angle == 90); + if (angle == 0) + { + gtk_label_set_ellipsize (GTK_LABEL (task->label), + PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment (GTK_MISC (task->label), 0.0, 0.5); + } + else + { + //FIXME: This is a workaround because GTK+ is not nice with us and + //doesn't accept rotated + ellipsized text. + gtk_label_set_ellipsize (GTK_LABEL (task->label), + PANGO_ELLIPSIZE_NONE); + gtk_misc_set_alignment (GTK_MISC (task->label), 0.5, + angle == 90 ? 1.0 : 0.0); + } + gtk_label_set_angle (GTK_LABEL (task->label), angle); + if (task->type != WNCK_TASK_STARTUP_SEQUENCE) { GList *ll; @@ -2605,7 +2812,8 @@ wnck_task_position_menu (GtkMenu *menu gboolean *push_in, gpointer user_data) { - GtkWidget *widget = GTK_WIDGET (user_data); + WnckTask *task = WNCK_TASK (user_data); + GtkWidget *widget = task->button; GtkRequisition requisition; gint menu_xpos; gint menu_ypos; @@ -2619,7 +2827,7 @@ wnck_task_position_menu (GtkMenu *menu menu_xpos += widget->allocation.x; menu_ypos += widget->allocation.y; - if (menu_ypos > gdk_screen_height () / 2) + if (menu_ypos > gdk_screen_get_height (_wnck_screen_get_gdk_screen (task->tasklist->priv->screen)) / 2) menu_ypos -= requisition.height; else menu_ypos += widget->allocation.height; @@ -3007,7 +3215,7 @@ wnck_task_popup_menu (WnckTask *task, gtk_widget_show (menu); gtk_menu_popup (GTK_MENU (menu), NULL, NULL, - wnck_task_position_menu, task->button, + wnck_task_position_menu, task, 1, gtk_get_current_event_time ()); } @@ -3613,7 +3821,7 @@ wnck_task_button_press_event (GtkWidget gtk_widget_show (task->action_menu); gtk_menu_popup (GTK_MENU (task->action_menu), NULL, NULL, - wnck_task_position_menu, task->button, + wnck_task_position_menu, task, event->button, gtk_get_current_event_time ()); @@ -3638,7 +3846,6 @@ wnck_task_expose (GtkWidget *widg static void wnck_task_create_widgets (WnckTask *task, GtkReliefStyle relief) { - GtkWidget *hbox; GdkPixbuf *pixbuf; char *text; static GQuark disable_sound_quark = 0; @@ -3678,7 +3885,7 @@ wnck_task_create_widgets (WnckTask *task gtk_drag_dest_set (GTK_WIDGET (task->button), 0, NULL, 0, GDK_ACTION_DEFAULT); - hbox = gtk_hbox_new (FALSE, 0); + task->obox = wnck_obox_new (); pixbuf = wnck_task_get_icon (task); if (pixbuf) @@ -3705,13 +3912,13 @@ wnck_task_create_widgets (WnckTask *task gtk_widget_show (task->label); - gtk_box_pack_start (GTK_BOX (hbox), task->image, FALSE, FALSE, + gtk_box_pack_start (GTK_BOX (task->obox), task->image, FALSE, FALSE, TASKLIST_BUTTON_PADDING); - gtk_box_pack_start (GTK_BOX (hbox), task->label, TRUE, TRUE, + gtk_box_pack_start (GTK_BOX (task->obox), task->label, TRUE, TRUE, TASKLIST_BUTTON_PADDING); - gtk_container_add (GTK_CONTAINER (task->button), hbox); - gtk_widget_show (hbox); + gtk_container_add (GTK_CONTAINER (task->button), task->obox); + gtk_widget_show (task->obox); g_free (text); text = wnck_task_get_text (task, FALSE, FALSE); Index: tasklist.h =================================================================== --- libwnck/tasklist.h (révision 1378) +++ libwnck/tasklist.h (copie de travail) @@ -98,6 +98,9 @@ void wnck_tasklist_set_include_all_works gboolean include_all_workspaces); void wnck_tasklist_set_button_relief (WnckTasklist *tasklist, GtkReliefStyle relief); +void wnck_tasklist_set_vertical_mode (WnckTasklist *tasklist, + gboolean vertical_mode); + #ifndef WNCK_DISABLE_DEPRECATED void wnck_tasklist_set_minimum_width (WnckTasklist *tasklist, gint size); gint wnck_tasklist_get_minimum_width (WnckTasklist *tasklist); Index: obox.c =================================================================== --- libwnck/obox.c (révision 0) +++ libwnck/obox.c (révision 0) @@ -0,0 +1,151 @@ +/* OBox Copyright (C) 2002 Red Hat Inc. based on GtkHBox */ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "obox.h" + +#include +#include + +static void wnck_obox_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void wnck_obox_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); + + +G_DEFINE_TYPE (WnckOBox, wnck_obox, GTK_TYPE_BOX) + +static void +wnck_obox_class_init (WnckOBoxClass *class) +{ + GtkWidgetClass *widget_class; + + widget_class = (GtkWidgetClass*) class; + + widget_class->size_request = wnck_obox_size_request; + widget_class->size_allocate = wnck_obox_size_allocate; +} + +static void +wnck_obox_init (WnckOBox *obox) +{ + obox->orientation = GTK_ORIENTATION_HORIZONTAL; + obox->reverse_order = FALSE; +} + +GtkWidget* +wnck_obox_new (void) +{ + WnckOBox *obox; + + obox = g_object_new (WNCK_TYPE_OBOX, NULL); + + return GTK_WIDGET (obox); +} + +static GtkWidgetClass* +get_class (WnckOBox *obox) +{ + GtkWidgetClass *klass; + + switch (obox->orientation) + { + case GTK_ORIENTATION_HORIZONTAL: + klass = GTK_WIDGET_CLASS (gtk_type_class (GTK_TYPE_HBOX)); + break; + case GTK_ORIENTATION_VERTICAL: + klass = GTK_WIDGET_CLASS (gtk_type_class (GTK_TYPE_VBOX)); + break; + default: + g_assert_not_reached (); + klass = NULL; + break; + } + + return klass; +} + +static void +wnck_obox_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkWidgetClass *klass; + WnckOBox *obox; + + obox = WNCK_OBOX (widget); + + klass = get_class (obox); + + klass->size_request (widget, requisition); +} + +static void +wnck_obox_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkWidgetClass *klass; + WnckOBox *obox; + + obox = WNCK_OBOX (widget); + + klass = get_class (obox); + + klass->size_allocate (widget, allocation); +} + +void +wnck_obox_set_orientation (WnckOBox *obox, + GtkOrientation orientation) +{ + g_return_if_fail (WNCK_IS_OBOX (obox)); + + if (obox->orientation == orientation) + return; + + g_print ("new orientation: %d\n", orientation); + obox->orientation = orientation; + + gtk_widget_queue_resize (GTK_WIDGET (obox)); +} + +void +wnck_obox_set_reverse_order (WnckOBox *obox, + gboolean reverse_order) +{ + GtkBox *box; + + g_return_if_fail (WNCK_IS_OBOX (obox)); + + if (obox->reverse_order == reverse_order) + return; + + g_print ("reverse order: %d\n", reverse_order); + obox->reverse_order = reverse_order; + box = GTK_BOX (obox); + box->children = g_list_reverse (box->children); + + gtk_widget_queue_resize (GTK_WIDGET (obox)); +} Index: obox.h =================================================================== --- libwnck/obox.h (révision 0) +++ libwnck/obox.h (révision 0) @@ -0,0 +1,75 @@ +/* OBox Copyright (C) 2002 Red Hat Inc. based on GtkHBox */ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __WNCK_OBOX_H__ +#define __WNCK_OBOX_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define WNCK_TYPE_OBOX (wnck_obox_get_type ()) +#define WNCK_OBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WNCK_TYPE_OBOX, WnckOBox)) +#define WNCK_OBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WNCK_TYPE_OBOX, WnckOBoxClass)) +#define WNCK_IS_OBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WNCK_TYPE_OBOX)) +#define WNCK_IS_OBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WNCK_TYPE_OBOX)) +#define WNCK_OBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WNCK_TYPE_OBOX, WnckOBoxClass)) + + +typedef struct _WnckOBox WnckOBox; +typedef struct _WnckOBoxClass WnckOBoxClass; + +struct _WnckOBox +{ + GtkBox box; + + GtkOrientation orientation; + gboolean reverse_order; +}; + +struct _WnckOBoxClass +{ + GtkBoxClass parent_class; +}; + + +GType wnck_obox_get_type (void) G_GNUC_CONST; +GtkWidget* wnck_obox_new (void); + +void wnck_obox_set_orientation (WnckOBox *obox, + GtkOrientation orientation); +void wnck_obox_set_reverse_order (WnckOBox *obox, + gboolean reverse_order); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __WNCK_OBOX_H__ */ Index: Makefile.am =================================================================== --- libwnck/Makefile.am.rotate-window-list 2010-03-09 04:56:30.000000000 +0300 +++ libwnck/Makefile.am 2010-03-09 13:03:22.000000000 +0300 @@ -55,6 +55,8 @@ $(wnck_built_cfiles) \ $(wnck_sources) \ inlinepixbufs.h \ + obox.c \ + obox.h \ private.h \ xutils.c \ xutils.h \