Bugzilla – Attachment 207836 Details for
Bug 377784
Mail view reflows dozens of times on some mails
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
IDP Log In
|
Forgot Password
Mail that flickers a lot while loading.
evolution-mail-that-flickers-on-formatting.txt (text/plain), 66.57 KB, created by
Hans Petter Jansson
on 2008-04-14 21:37:51 UTC
(
hide
)
Description:
Mail that flickers a lot while loading.
Filename:
MIME Type:
Creator:
Hans Petter Jansson
Created:
2008-04-14 21:37:51 UTC
Size:
66.57 KB
patch
obsolete
>From svn-commits-list-bounces@gnome.org Thu Apr 3 23:09:21 2008 >Return-path: <svn-commits-list-bounces@gnome.org> >Envelope-to: hpj@copyleft.no >Delivery-date: Thu, 03 Apr 2008 23:09:21 +0200 >Received: from mailnull by mail9.copyleft.no with spam (Exim 4.60 > (FreeBSD)) (envelope-from <svn-commits-list-bounces@gnome.org>) id > 1JhWgT-000Hon-26 for hpj@copyleft.no; Thu, 03 Apr 2008 23:09:21 +0200 >Received: from menubar.gnome.org ([209.132.176.177]) by mail9.copyleft.no > with esmtp (Exim 4.60 (FreeBSD)) (envelope-from > <svn-commits-list-bounces@gnome.org>) id 1JhWgR-000Hl4-BV for > hpj@copyleft.no; Thu, 03 Apr 2008 23:09:21 +0200 >Received: from menubar.gnome.org (localhost.localdomain [127.0.0.1]) by > menubar.gnome.org (Postfix) with ESMTP id 4B32B75038C; Thu, 3 Apr 2008 > 21:09:17 +0000 (GMT) >X-Original-To: svn-commits-list@gnome.org >Delivered-To: svn-commits-list@gnome.org >Received: from localhost (localhost.localdomain [127.0.0.1]) by > menubar.gnome.org (Postfix) with ESMTP id 070A8750333 for > <svn-commits-list@gnome.org>; Thu, 3 Apr 2008 21:09:14 +0000 (GMT) >X-Virus-Scanned: by amavisd-new at gnome.org >X-Spam-Flag: NO >X-Spam-Score: -1.426 >X-Spam-Level: >X-Spam-Status: No, score=-1.426 tagged_above=-999 required=2 > tests=[BAYES_00=-2.599, FORGED_RCVD_HELO=0.135, NO_REAL_NAME=0.961, > TW_GD=0.077] >X-Amavis-OS-Fingerprint: Linux 2.6, seldom 2.4 (older, 4) (up: 3445 hrs), > (distance 18, link: ethernet/modem), [91.189.93.3] >Received: from menubar.gnome.org ([127.0.0.1]) by localhost > (menubar.gnome.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id > wqmkH-qby7dr for <svn-commits-list@gnome.org>; Thu, 3 Apr 2008 21:09:07 > +0000 (GMT) >Received: from socket.gnome.org (cobalt.canonical.com [91.189.93.3]) by > menubar.gnome.org (Postfix) with ESMTP id C26D875012F for > <svn-commits-list@gnome.org>; Thu, 3 Apr 2008 21:09:06 +0000 (GMT) >Received: by socket.gnome.org (Postfix, from userid 6355) id EEF8F9AC11D; > Thu, 3 Apr 2008 22:09:04 +0100 (BST) >From: halfline@svn.gnome.org >To: svn-commits-list@gnome.org >Subject: gdm r6100 - in trunk: . gui/simple-greeter >MIME-Version: 1.0 >keywords: gdm >Message-Id: <20080403210904.EEF8F9AC11D@socket.gnome.org> >Date: Thu, 3 Apr 2008 22:09:04 +0100 (BST) >X-Topics: gdm >X-BeenThere: svn-commits-list@gnome.org >X-Mailman-Version: 2.1.8 >Precedence: list >List-Id: SVN commits <svn-commits-list.gnome.org> >List-Unsubscribe: > <http://mail.gnome.org/mailman/listinfo/svn-commits-list>, > <mailto:svn-commits-list-request@gnome.org?subject=unsubscribe> >List-Archive: </archives/svn-commits-list> >List-Post: <mailto:svn-commits-list@gnome.org> >List-Help: <mailto:svn-commits-list-request@gnome.org?subject=help> >List-Subscribe: <http://mail.gnome.org/mailman/listinfo/svn-commits-list>, > <mailto:svn-commits-list-request@gnome.org?subject=subscribe> >Content-Type: text/plain; charset="us-ascii" >Sender: svn-commits-list-bounces@gnome.org >Errors-To: svn-commits-list-bounces@gnome.org >X-Criteria: ViaPrimary >X-Bogocaught-Centralized-famine: No >X-Evolution-Source: imap://hpj%40alcatraz.copyleft.no@alcatraz.copyleft.no/ >Content-Transfer-Encoding: 8bit > >Author: halfline >Date: Thu Apr 3 22:09:04 2008 >New Revision: 6100 >URL: http://svn.gnome.org/viewvc/gdm?rev=6100&view=rev > >Log: >2008-04-03 Ray Strode <rstrode@redhat.com> > > * gui/simple-greeter/gdm-scrollable-widget.[ch]: > * gui/simple-greeter/Makefile.am: > * gui/simple-greeter/gdm-chooser-widget.c: > (struct GdmChooserWidgetPrivate), > (get_path_to_active_row), (on_shrink_animation_step), > (on_shrink_animation_complete), > (get_height_of_row_at_path), > (get_normalized_position_of_row_at_path), > (start_shrink_animation), > (on_grow_animation_complete), > (get_height_of_screen), (start_grow_animation), > (start_grow_animation), (gdm_chooser_widget_grow), > (gdm_chooser_widget_shrink), > (gdm_chooser_widget_class_init), (gdm_chooser_widget_init), > (gdm_chooser_widget_finalize): > Do chooser widget animation in a different, smoother way > using a special widget that's like GtkScrolledWindow, but > can animation instead of removing items from the list one > by one > > >Added: > trunk/gui/simple-greeter/gdm-scrollable-widget.c > trunk/gui/simple-greeter/gdm-scrollable-widget.h >Modified: > trunk/ChangeLog > trunk/gui/simple-greeter/Makefile.am > trunk/gui/simple-greeter/gdm-chooser-widget.c > >Modified: trunk/gui/simple-greeter/Makefile.am >============================================================================== >--- trunk/gui/simple-greeter/Makefile.am (original) >+++ trunk/gui/simple-greeter/Makefile.am Thu Apr 3 22:09:04 2008 >@@ -72,6 +72,8 @@ > gdm-timer.c \ > gdm-greeter-login-window.h \ > gdm-greeter-login-window.c \ >+ gdm-scrollable-widget.h \ >+ gdm-scrollable-widget.c \ > gdm-chooser-widget.h \ > gdm-chooser-widget.c \ > gdm-sessions.h \ >@@ -109,6 +111,8 @@ > gdm-cell-renderer-timer.c \ > gdm-timer.h \ > gdm-timer.c \ >+ gdm-scrollable-widget.h \ >+ gdm-scrollable-widget.c \ > gdm-chooser-widget.h \ > gdm-chooser-widget.c \ > gdm-language-chooser-widget.h \ >@@ -151,6 +155,8 @@ > gdm-cell-renderer-timer.c \ > gdm-timer.h \ > gdm-timer.c \ >+ gdm-scrollable-widget.h \ >+ gdm-scrollable-widget.c \ > gdm-chooser-widget.h \ > gdm-chooser-widget.c \ > gdm-languages.h \ >@@ -183,6 +189,8 @@ > gdm-timer.c \ > gdm-cell-renderer-timer.h \ > gdm-cell-renderer-timer.c \ >+ gdm-scrollable-widget.h \ >+ gdm-scrollable-widget.c \ > gdm-chooser-widget.h \ > gdm-chooser-widget.c \ > gdm-user-chooser-widget.h \ >@@ -229,6 +237,8 @@ > gdm-timer.c \ > gdm-cell-renderer-timer.h \ > gdm-cell-renderer-timer.c \ >+ gdm-scrollable-widget.h \ >+ gdm-scrollable-widget.c \ > gdm-chooser-widget.h \ > gdm-chooser-widget.c \ > gdm-greeter-client.h \ > >Modified: trunk/gui/simple-greeter/gdm-chooser-widget.c >============================================================================== >--- trunk/gui/simple-greeter/gdm-chooser-widget.c (original) >+++ trunk/gui/simple-greeter/gdm-chooser-widget.c Thu Apr 3 22:09:04 2008 >@@ -35,6 +35,7 @@ > #include <gtk/gtk.h> > > #include "gdm-chooser-widget.h" >+#include "gdm-scrollable-widget.h" > #include "gdm-cell-renderer-timer.h" > #include "gdm-timer.h" > >@@ -55,7 +56,7 @@ > { > GtkWidget *frame; > GtkWidget *frame_alignment; >- GtkWidget *scrolled_window; >+ GtkWidget *scrollable_widget; > > GtkWidget *items_view; > GtkListStore *list_store; >@@ -67,8 +68,6 @@ > > GtkTreeRowReference *active_row; > GtkTreeRowReference *separator_row; >- GtkTreeRowReference *top_edge_row; /* Only around for shrink */ >- GtkTreeRowReference *bottom_edge_row; /* animations */ > > GHashTable *rows_with_timers; > >@@ -85,9 +84,6 @@ > gint number_of_rows_with_images; > gint number_of_active_timers; > >- GdmTimer *grow_animation_timer; >- GdmTimer *shrink_animation_timer; >- > guint update_idle_id; > guint timer_animation_timeout_id; > >@@ -97,6 +93,7 @@ > GdmChooserWidgetPosition separator_position; > GdmChooserWidgetState state; > >+ double active_row_normalized_position; > }; > > enum { >@@ -375,258 +372,173 @@ > *path = sorted_path; > } > >-static gboolean >-shrink_edge_toward_active_row (GdmChooserWidget *widget, >- GtkTreeRowReference **edge_row) >+static GtkTreePath * >+get_path_to_active_row (GdmChooserWidget *widget) > { >- GtkTreePath *active_path; >- GtkTreePath *edge_path; >- GtkTreeIter edge_iter; >- gboolean edge_is_hidden; >- int relative_position; >- >- active_path = gtk_tree_row_reference_get_path (widget->priv->active_row); >- translate_base_path_to_sorted_path (widget, &active_path); >- >- g_assert (*edge_row != NULL); >- edge_path = gtk_tree_row_reference_get_path (*edge_row); >- g_assert (edge_path != NULL); >- relative_position = gtk_tree_path_compare (edge_path, active_path); >- if (relative_position != 0 && >- gtk_tree_model_get_iter (GTK_TREE_MODEL (widget->priv->model_sorter), >- &edge_iter, edge_path)) { >- GtkTreeIter filtered_iter; >- GtkTreeIter iter; >- >- if (relative_position < 0) { >- gtk_tree_path_next (edge_path); >- } else { >- if (!gtk_tree_path_prev (edge_path)) { >- edge_is_hidden = TRUE; >- goto out; >- } >- } >- gtk_tree_row_reference_free (*edge_row); >+ GtkTreePath *path; > >- *edge_row = gtk_tree_row_reference_new (GTK_TREE_MODEL (widget->priv->model_sorter), >- edge_path); >+ if (widget->priv->active_row == NULL) { >+ return NULL; >+ } > >- gtk_tree_model_sort_convert_iter_to_child_iter (widget->priv->model_sorter, >- &filtered_iter, &edge_iter); >- gtk_tree_model_filter_convert_iter_to_child_iter (widget->priv->model_filter, >- &iter, &filtered_iter); >- gtk_list_store_set (GTK_LIST_STORE (widget->priv->list_store), >- &iter, >- CHOOSER_ITEM_IS_VISIBLE_COLUMN, FALSE, >- -1); >+ path= gtk_tree_row_reference_get_path (widget->priv->active_row); > >- edge_is_hidden = FALSE; >- } else { >- edge_is_hidden = TRUE; >+ if (path == NULL) { >+ return NULL; > } >-out: >- gtk_tree_path_free (active_path); >- gtk_tree_path_free (edge_path); > >- return edge_is_hidden; >+ translate_base_path_to_sorted_path (widget, &path); >+ >+ return path; > } > >-static gboolean >-run_shrink_animation (GdmChooserWidget *widget, >- int number_of_iterations) >+static void >+on_shrink_animation_step (GdmScrollableWidget *scrollable_widget, >+ double progress, >+ GdmChooserWidget *widget) > { >- gboolean is_done; >- >- is_done = FALSE; >- >- if (widget->priv->top_edge_row != NULL) { >- is_done = shrink_edge_toward_active_row (widget, >- &widget->priv->top_edge_row); >- } >+ GtkTreePath *active_row_path; >+ const double final_alignment = 0.5; >+ double row_alignment; > >- if (widget->priv->bottom_edge_row != NULL) { >- is_done = is_done && >- shrink_edge_toward_active_row (widget, >- &widget->priv->bottom_edge_row); >- } >- >- number_of_iterations--; >- >- if (number_of_iterations != 0) { >- is_done = run_shrink_animation (widget, number_of_iterations); >- } >+ active_row_path = get_path_to_active_row (widget); >+ row_alignment = widget->priv->active_row_normalized_position + progress * (final_alignment - widget->priv->active_row_normalized_position); > >- return is_done; >+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget->priv->items_view), >+ active_row_path, NULL, TRUE, row_alignment, 0.0); >+ gtk_tree_path_free (active_row_path); > } > >-static int >-get_number_of_on_screen_rows (GdmChooserWidget *widget) >+static void >+set_inactive_items_visible (GdmChooserWidget *widget, >+ gboolean should_show) > { >- GtkTreePath *start_path; >- GtkTreePath *end_path; >- int *start_index; >- int *end_index; >- int number_of_rows; >- >- if (!gtk_tree_view_get_visible_range (GTK_TREE_VIEW (widget->priv->items_view), >- &start_path, &end_path)) { >- return 0; >- } >- >- start_index = gtk_tree_path_get_indices (start_path); >- end_index = gtk_tree_path_get_indices (end_path); >+ GtkTreeModel *model; >+ char *active_item_id; >+ GtkTreeIter active_item_iter; >+ GtkTreeIter iter; > >- number_of_rows = *end_index - *start_index; >+ model = GTK_TREE_MODEL (widget->priv->list_store); > >- gtk_tree_path_free (start_path); >- gtk_tree_path_free (end_path); >+ if (!gtk_tree_model_get_iter_first (model, &iter)) { >+ return; >+ } > >- return number_of_rows; >-} >+ active_item_id = get_active_item_id (widget, &active_item_iter); > >-static gboolean >-run_grow_animation (GdmChooserWidget *widget, >- int number_of_iterations) >-{ >- gboolean is_done; >- GtkTreePath *path; >- GtkTreeIter iter; >- gboolean is_visible; >+ do { >+ gboolean is_active; > >- is_done = FALSE; >+ is_active = FALSE; >+ if (active_item_id != NULL) { >+ char *id; > >- path = gtk_tree_path_new_first (); >+ gtk_tree_model_get (model, &iter, >+ CHOOSER_ID_COLUMN, &id, -1); > >- do { >- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (widget->priv->list_store), >- &iter, path)) { >- is_done = TRUE; >- break; >+ if (strcmp (active_item_id, id) == 0) { >+ is_active = TRUE; >+ g_free (active_item_id); >+ active_item_id = NULL; >+ } >+ g_free (id); > } > >- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), >- &iter, CHOOSER_ITEM_IS_VISIBLE_COLUMN, >- &is_visible, -1); >- >- if (is_visible) { >- gtk_tree_path_next (path); >+ if (!is_active) { >+ gtk_list_store_set (widget->priv->list_store, >+ &iter, >+ CHOOSER_ITEM_IS_VISIBLE_COLUMN, should_show, >+ -1); > } else { >- gtk_list_store_set (GTK_LIST_STORE (widget->priv->list_store), >+ gtk_list_store_set (widget->priv->list_store, > &iter, > CHOOSER_ITEM_IS_VISIBLE_COLUMN, TRUE, > -1); > } >- } while (is_visible); >- >- gtk_tree_path_free (path); >- >- number_of_iterations--; >- >- if (number_of_iterations != 0) { >- is_done = run_grow_animation (widget, number_of_iterations); >- } >+ } while (gtk_tree_model_iter_next (model, &iter)); > >- return is_done; >+ g_free (active_item_id); > } > > static void >-on_shrink_animation_tick (GdmChooserWidget *widget, >- double progress) >+on_shrink_animation_complete (GdmScrollableWidget *scrollable_widget, >+ GdmChooserWidget *widget) > { >- int number_of_iterations; >- int number_of_visible_rows; >- int number_of_rows; >- int number_of_rows_to_be_gone; >- int number_of_rows_gone; >- >- if (widget->priv->state != GDM_CHOOSER_WIDGET_STATE_SHRINKING) { >- return; >- } >- >- number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); >- >- if (number_of_visible_rows <= 1) { >- gdm_timer_stop (widget->priv->shrink_animation_timer); >- return; >- } >- >- number_of_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->list_store), NULL); >- >- number_of_rows_to_be_gone = progress * number_of_rows; >- number_of_rows_gone = number_of_rows - number_of_visible_rows; >- >- number_of_iterations = number_of_rows_to_be_gone - number_of_rows_gone; >+ g_assert (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_SHRINKING); > >- if (number_of_iterations <= 0) { >- return; >- } >+ widget->priv->active_row_normalized_position = 0.5; >+ set_inactive_items_visible (GDM_CHOOSER_WIDGET (widget), FALSE); >+ widget->priv->state = GDM_CHOOSER_WIDGET_STATE_SHRUNK; > >- if (run_shrink_animation (widget, number_of_iterations)) { >- gdm_timer_stop (widget->priv->shrink_animation_timer); >+ if (widget->priv->emit_activated_after_resize_animation) { >+ g_signal_emit (widget, signals[ACTIVATED], 0); >+ widget->priv->emit_activated_after_resize_animation = FALSE; > } > } > >-static void >-on_grow_animation_tick (GdmChooserWidget *widget, >- double progress) >+static int >+get_height_of_row_at_path (GdmChooserWidget *widget, >+ GtkTreePath *path) > { >- int number_of_iterations; >- int number_of_visible_rows; >- int number_of_rows; >- int number_of_rows_wanted; >- >- if (widget->priv->state != GDM_CHOOSER_WIDGET_STATE_GROWING) { >- return; >- } >- >- number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); >- number_of_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->list_store), NULL); >+ GdkRectangle area; > >- if (number_of_visible_rows == number_of_rows) { >- gdm_timer_stop (widget->priv->shrink_animation_timer); >- return; >- } >+ gtk_tree_view_get_background_area (GTK_TREE_VIEW (widget->priv->items_view), >+ path, NULL, &area); > >- number_of_rows_wanted = progress * number_of_rows; >+ return area.height; >+} > >- number_of_iterations = number_of_rows_wanted - number_of_visible_rows; >+static double >+get_normalized_position_of_row_at_path (GdmChooserWidget *widget, >+ GtkTreePath *path) >+{ >+ GdkRectangle area_of_row_at_path; >+ GdkRectangle area_of_visible_rows; > >- if (number_of_iterations <= 0) { >- return; >- } >+ gtk_tree_view_get_background_area (GTK_TREE_VIEW (widget->priv->items_view), >+ path, NULL, &area_of_row_at_path); > >- if (run_grow_animation (widget, number_of_iterations)) { >- gdm_timer_stop (widget->priv->shrink_animation_timer); >- } >+ gtk_tree_view_convert_tree_to_widget_coords (GTK_TREE_VIEW (widget->priv->items_view), >+ area_of_visible_rows.x, >+ area_of_visible_rows.y, >+ &area_of_visible_rows.x, >+ &area_of_visible_rows.y); >+ return ((double) area_of_row_at_path.y) / widget->priv->items_view->allocation.height; > } > > static void >-on_shrink_animation_stop (GdmChooserWidget *widget) >+start_shrink_animation (GdmChooserWidget *widget) > { >+ GtkTreePath *active_row_path; >+ int active_row_height; >+ int number_of_visible_rows; > >- g_assert (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_SHRINKING); >- widget->priv->state = GDM_CHOOSER_WIDGET_STATE_SHRUNK; >- >- if (widget->priv->top_edge_row != NULL) { >- gtk_tree_row_reference_free (widget->priv->top_edge_row); >- widget->priv->top_edge_row = NULL; >- } >+ g_assert (widget->priv->active_row != NULL); > >- if (widget->priv->bottom_edge_row != NULL) { >- gtk_tree_row_reference_free (widget->priv->bottom_edge_row); >- widget->priv->bottom_edge_row = NULL; >- } >+ number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); > >- if (widget->priv->emit_activated_after_resize_animation) { >- g_signal_emit (widget, signals[ACTIVATED], 0); >- widget->priv->emit_activated_after_resize_animation = FALSE; >- } >+ if (number_of_visible_rows <= 1) { >+ on_shrink_animation_complete (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), >+ widget); >+ return; >+ } > >- gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE); >+ active_row_path = get_path_to_active_row (widget); >+ active_row_height = get_height_of_row_at_path (widget, active_row_path); >+ widget->priv->active_row_normalized_position = get_normalized_position_of_row_at_path (widget, active_row_path); >+ gtk_tree_path_free (active_row_path); >+ >+ gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), >+ active_row_height, >+ (GdmScrollableWidgetSlideStepFunc) >+ on_shrink_animation_step, widget, >+ (GdmScrollableWidgetSlideDoneFunc) >+ on_shrink_animation_complete, widget); > } > > static void >-on_grow_animation_stop (GdmChooserWidget *widget) >+on_grow_animation_complete (GdmScrollableWidget *scrollable_widget, >+ GdmChooserWidget *widget) > { > g_assert (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWING); > widget->priv->state = GDM_CHOOSER_WIDGET_STATE_GROWN; >@@ -635,149 +547,44 @@ > g_signal_emit (widget, signals[ACTIVATED], 0); > widget->priv->emit_activated_after_resize_animation = FALSE; > } >- >- gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE); > } > >-static void >-start_shrink_animation (GdmChooserWidget *widget) >+static int >+get_height_of_screen (GdmChooserWidget *widget) > { >- GtkTreePath *edge_path; >- int number_of_visible_rows; >- int number_of_rows; >- int number_of_on_screen_rows; >- int number_of_iterations; >- >- if (widget->priv->shrink_animation_timer != NULL && >- gdm_timer_is_started (widget->priv->shrink_animation_timer)) { >- gdm_timer_stop (widget->priv->shrink_animation_timer); >- } >+ GdkScreen *screen; >+ GdkRectangle area; >+ int monitor; > >- number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); >- number_of_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->list_store), NULL); >+ screen = gtk_widget_get_screen (GTK_WIDGET (widget)); > >- if (number_of_visible_rows <= 1) { >- on_shrink_animation_stop (widget); >- return; >- } >+ monitor = gdk_screen_get_monitor_at_window (screen, >+ GTK_WIDGET (widget)->window); >+ gdk_screen_get_monitor_geometry (screen, monitor, &area); > >- edge_path = gtk_tree_path_new_first (); >- widget->priv->top_edge_row = gtk_tree_row_reference_new (GTK_TREE_MODEL (widget->priv->model_sorter), >- edge_path); >- gtk_tree_path_free (edge_path); >- >- edge_path = gtk_tree_path_new_from_indices (number_of_visible_rows - 1, -1); >- >- widget->priv->bottom_edge_row = gtk_tree_row_reference_new (GTK_TREE_MODEL (widget->priv->model_sorter), >- edge_path); >- gtk_tree_path_free (edge_path); >- g_assert (widget->priv->top_edge_row != NULL && widget->priv->bottom_edge_row != NULL); >- >- gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE); >- >- number_of_on_screen_rows = get_number_of_on_screen_rows (widget); >- number_of_iterations = number_of_visible_rows - number_of_on_screen_rows; >- number_of_iterations = MAX (0, number_of_iterations); >- >- run_shrink_animation (widget, number_of_iterations); >- >- if (widget->priv->shrink_animation_timer == NULL) { >- widget->priv->shrink_animation_timer = gdm_timer_new (); >- >- g_signal_connect_swapped (G_OBJECT (widget->priv->shrink_animation_timer), >- "tick", G_CALLBACK (on_shrink_animation_tick), >- widget); >- g_signal_connect_swapped (G_OBJECT (widget->priv->shrink_animation_timer), >- "stop", G_CALLBACK (on_shrink_animation_stop), >- widget); >- } >- >- gdm_timer_start (widget->priv->shrink_animation_timer, 1.0); >+ return area.height; > } > > static void > start_grow_animation (GdmChooserWidget *widget) > { >- int number_of_visible_rows; >- int number_of_rows; >- >- if (widget->priv->grow_animation_timer != NULL && >- gdm_timer_is_started (widget->priv->grow_animation_timer)) { >- gdm_timer_stop (widget->priv->grow_animation_timer); >- } >+ int number_of_visible_rows; >+ int number_of_rows; > >- number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); >- number_of_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->list_store), NULL); >+ number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL); >+ number_of_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->list_store), NULL); > >- if (number_of_visible_rows >= number_of_rows) { >- on_grow_animation_stop (widget); >+ if (number_of_visible_rows >= number_of_rows) { >+ on_grow_animation_complete (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), widget); > return; >- } >- >- gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE); >- >- if (widget->priv->grow_animation_timer == NULL) { >- widget->priv->grow_animation_timer = gdm_timer_new (); >- >- g_signal_connect_swapped (G_OBJECT (widget->priv->grow_animation_timer), >- "tick", G_CALLBACK (on_grow_animation_tick), >- widget); >- g_signal_connect_swapped (G_OBJECT (widget->priv->grow_animation_timer), >- "stop", G_CALLBACK (on_grow_animation_stop), >- widget); >- } >- gdm_timer_start (widget->priv->grow_animation_timer, 1.0); >-} >- >-static void >-set_inactive_items_visible (GdmChooserWidget *widget, >- gboolean should_show) >-{ >- GtkTreeModel *model; >- char *active_item_id; >- GtkTreeIter active_item_iter; >- GtkTreeIter iter; >- >- model = GTK_TREE_MODEL (widget->priv->list_store); >- >- if (!gtk_tree_model_get_iter_first (model, &iter)) { >- return; > } > >- active_item_id = get_active_item_id (widget, &active_item_iter); >- >- do { >- gboolean is_active; >- >- is_active = FALSE; >- if (active_item_id != NULL) { >- char *id; >- >- gtk_tree_model_get (model, &iter, >- CHOOSER_ID_COLUMN, &id, -1); >- >- if (strcmp (active_item_id, id) == 0) { >- is_active = TRUE; >- g_free (active_item_id); >- active_item_id = NULL; >- } >- g_free (id); >- } >- >- if (!is_active) { >- gtk_list_store_set (widget->priv->list_store, >- &iter, >- CHOOSER_ITEM_IS_VISIBLE_COLUMN, should_show, >- -1); >- } else { >- gtk_list_store_set (widget->priv->list_store, >- &iter, >- CHOOSER_ITEM_IS_VISIBLE_COLUMN, TRUE, >- -1); >- } >- } while (gtk_tree_model_iter_next (model, &iter)); >- >- g_free (active_item_id); >+ set_inactive_items_visible (widget, TRUE); >+ gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget), >+ get_height_of_screen (widget), >+ NULL, NULL, >+ (GdmScrollableWidgetSlideDoneFunc) >+ on_grow_animation_complete, widget); > } > > static void >@@ -795,10 +602,6 @@ > static void > gdm_chooser_widget_grow (GdmChooserWidget *widget) > { >- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget->priv->scrolled_window), >- GTK_SHADOW_ETCHED_IN); >- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget->priv->scrolled_window), >- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); > gtk_alignment_set (GTK_ALIGNMENT (widget->priv->frame_alignment), > 0.0, 0.0, 1.0, 1.0); > >@@ -852,12 +655,6 @@ > gtk_alignment_set (GTK_ALIGNMENT (widget->priv->frame_alignment), > 0.0, 0.0, 1.0, 0.0); > >- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget->priv->scrolled_window), >- GTK_POLICY_NEVER, GTK_POLICY_NEVER); >- >- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget->priv->scrolled_window), >- GTK_SHADOW_ETCHED_OUT); >- > clear_selection (widget); > > widget->priv->state = GDM_CHOOSER_WIDGET_STATE_SHRINKING; >@@ -1097,120 +894,6 @@ > } > > static void >-gdm_chooser_widget_size_request (GtkWidget *widget, >- GtkRequisition *requisition) >-{ >- GdmChooserWidget *chooser; >- >- chooser = GDM_CHOOSER_WIDGET (widget); >- >- GTK_WIDGET_CLASS (gdm_chooser_widget_parent_class)->size_request (widget, requisition); >- >- /* XXX: this hack makes the scrolled window behave the way we want in >- * the login window. The login window is special because it always >- * tries to hug the widgets as tightly as possible. Normally, this >- * "tight hug" makes the scrolled_window get squeezed into nothing (if >- * POLICY_AUTOMATIC) If we use POLICY_NEVER then the scrolled window >- * gets the right size but can't have a scrollbar (which sort of >- * defeats the point I guess) >- */ >- requisition->height -= chooser->priv->scrolled_window->requisition.height; >- chooser->priv->scrolled_window->requisition.height = chooser->priv->items_view->requisition.height; >- chooser->priv->scrolled_window->requisition.height += chooser->priv->scrolled_window->style->ythickness * 2; >- chooser->priv->scrolled_window->requisition.height += GTK_CONTAINER (chooser->priv->scrolled_window)->border_width * 2; >- requisition->height += chooser->priv->scrolled_window->requisition.height; >-} >- >-#ifdef BUILD_ALLOCATION_HACK >-static gint >-compare_allocation_height (GdmChooserWidget *widget_a, >- GdmChooserWidget *widget_b) >-{ >- return GTK_WIDGET (widget_a)->allocation.height - GTK_WIDGET (widget_b)->allocation.height; >-} >- >-static void >-renegotiate_allocation (GtkContainer *container, >- GdmChooserWidgetClass *klass) >-{ >- GList *children; >- GList *choosers; >- GList *tmp; >- int total_allocation; >- int number_of_choosers; >- >- if (klass->size_negotiation_handler == 0) { >- return; >- } >- klass->size_negotiation_handler = 0; >- g_signal_handlers_disconnect_by_func (container, renegotiate_allocation, klass); >- >- children = gtk_container_get_children (container); >- >- total_allocation = 0; >- number_of_choosers = 0; >- choosers = NULL; >- for (tmp = children; tmp != NULL; tmp = tmp->next) { >- GdmChooserWidget *widget; >- >- if (!GDM_IS_CHOOSER_WIDGET (tmp->data)) { >- continue; >- } >- >- widget = GDM_CHOOSER_WIDGET (tmp->data); >- >- total_allocation += GTK_WIDGET (widget)->allocation.height; >- choosers = g_list_insert_sorted (choosers, widget, (GCompareFunc) compare_allocation_height); >- number_of_choosers++; >- } >- total_allocation = MIN (total_allocation, GTK_WIDGET (container)->allocation.height); >- >- for (tmp = choosers; tmp != NULL; tmp = tmp->next) { >- GdmChooserWidget *widget; >- GtkAllocation allocation; >- >- g_assert (GDM_IS_CHOOSER_WIDGET (tmp->data)); >- >- widget = GDM_CHOOSER_WIDGET (tmp->data); >- >- allocation = GTK_WIDGET (widget)->allocation; >- >- GTK_WIDGET (widget)->allocation.height = MIN (GTK_WIDGET (widget)->requisition.height, >- total_allocation / number_of_choosers); >- >- total_allocation -= allocation.height; >- >- number_of_choosers--; >- } >- g_list_free (children); >-} >- >-static void >-gdm_chooser_widget_size_allocate (GtkWidget *widget, >- GtkAllocation *allocation) >-{ >- GdmChooserWidgetClass *klass; >- >- klass = GDM_CHOOSER_WIDGET_GET_CLASS (widget); >- >- GTK_WIDGET_CLASS (gdm_chooser_widget_parent_class)->size_allocate (widget, allocation); >- >- /* XXX: Vbox isn't too smart about divving up allocations when there isn't enough room to go around. >- * Since we may have more than one chooser widget in a vbox, we redistribute space between the choosers >- * (if one chooser gets lots of space and another gets no space, give some up) >- */ >- if (allocation->height == 1 && klass->size_negotiation_handler == 0) { >- GtkWidget *parent; >- >- parent = gtk_widget_get_parent (widget); >- klass->size_negotiation_handler = g_signal_connect (parent, "size-allocate", >- G_CALLBACK (renegotiate_allocation), >- klass); >- } >-} >-#endif >- >-static void > gdm_chooser_widget_hide (GtkWidget *widget) > { > skip_resize_animation (GDM_CHOOSER_WIDGET (widget)); >@@ -1236,10 +919,6 @@ > object_class->dispose = gdm_chooser_widget_dispose; > object_class->finalize = gdm_chooser_widget_finalize; > widget_class->focus_in_event = gdm_chooser_widget_focus_in; >- widget_class->size_request = gdm_chooser_widget_size_request; >-#ifdef BUILD_ALLOCATION_HACK >- widget_class->size_allocate = gdm_chooser_widget_size_allocate; >-#endif > widget_class->hide = gdm_chooser_widget_hide; > widget_class->show = gdm_chooser_widget_show; > >@@ -1707,15 +1386,10 @@ > > add_frame (widget); > >- widget->priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL); >- >- gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (widget->priv->scrolled_window), >- NULL); >- gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (widget->priv->scrolled_window), >- NULL); >- gtk_widget_show (widget->priv->scrolled_window); >+ widget->priv->scrollable_widget = gdm_scrollable_widget_new (); >+ gtk_widget_show (widget->priv->scrollable_widget); > gtk_container_add (GTK_CONTAINER (widget->priv->frame_alignment), >- widget->priv->scrolled_window); >+ widget->priv->scrollable_widget); > > widget->priv->items_view = gtk_tree_view_new (); > gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget->priv->items_view), >@@ -1738,7 +1412,7 @@ > widget); > > gtk_widget_show (widget->priv->items_view); >- gtk_container_add (GTK_CONTAINER (widget->priv->scrolled_window), >+ gtk_container_add (GTK_CONTAINER (widget->priv->scrollable_widget), > widget->priv->items_view); > > selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->items_view)); >@@ -1859,16 +1533,6 @@ > g_hash_table_destroy (widget->priv->rows_with_timers); > widget->priv->rows_with_timers = NULL; > >- if (widget->priv->shrink_animation_timer != NULL) { >- g_object_unref (widget->priv->shrink_animation_timer); >- widget->priv->shrink_animation_timer = NULL; >- } >- >- if (widget->priv->grow_animation_timer != NULL) { >- g_object_unref (widget->priv->grow_animation_timer); >- widget->priv->grow_animation_timer = NULL; >- } >- > G_OBJECT_CLASS (gdm_chooser_widget_parent_class)->finalize (object); > } > > >Added: trunk/gui/simple-greeter/gdm-scrollable-widget.c >============================================================================== >--- (empty file) >+++ trunk/gui/simple-greeter/gdm-scrollable-widget.c Thu Apr 3 22:09:04 2008 >@@ -0,0 +1,659 @@ >+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- >+ * >+ * Copyright (C) 2008 Red Hat, Inc. >+ * >+ * 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. >+ * >+ * Written by: Ray Strode <rstrode@redhat.com> >+ * >+ * Parts taken from gtkscrolledwindow.c in the GTK+ toolkit. >+ */ >+ >+#include "config.h" >+ >+#include <stdlib.h> >+#include <stdio.h> >+#include <unistd.h> >+#include <string.h> >+#include <errno.h> >+ >+#include <glib.h> >+#include <glib/gi18n.h> >+#include <gdk/gdkkeysyms.h> >+#include <gtk/gtk.h> >+ >+#include "gdm-scrollable-widget.h" >+#include "gdm-timer.h" >+ >+#define GDM_SCROLLABLE_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SCROLLABLE_WIDGET, GdmScrollableWidgetPrivate)) >+ >+enum >+{ >+ SCROLL_CHILD, >+ MOVE_FOCUS_OUT, >+ NUMBER_OF_SIGNALS >+}; >+ >+typedef struct GdmScrollableWidgetAnimation GdmScrollableWidgetAnimation; >+ >+struct GdmScrollableWidgetPrivate >+{ >+ GtkWidget *scrollbar; >+ >+ GdmScrollableWidgetAnimation *animation; >+ GtkWidget *invisible_event_sink; >+}; >+ >+struct GdmScrollableWidgetAnimation >+{ >+ GtkWidget *widget; >+ GdmTimer *timer; >+ int start_height; >+ int desired_height; >+ GdmScrollableWidgetSlideStepFunc step_func; >+ gpointer step_func_user_data; >+ GdmScrollableWidgetSlideDoneFunc done_func; >+ gpointer done_func_user_data; >+}; >+ >+static void gdm_scrollable_widget_class_init (GdmScrollableWidgetClass *klass); >+static void gdm_scrollable_widget_init (GdmScrollableWidget *clock_widget); >+static void gdm_scrollable_widget_finalize (GObject *object); >+ >+static guint signals[NUMBER_OF_SIGNALS] = { 0 }; >+ >+G_DEFINE_TYPE (GdmScrollableWidget, gdm_scrollable_widget, GTK_TYPE_BIN) >+ >+static GdmScrollableWidgetAnimation * >+gdm_scrollable_widget_animation_new (GtkWidget *widget, >+ int start_height, >+ int desired_height, >+ GdmScrollableWidgetSlideStepFunc step_func, >+ gpointer step_func_user_data, >+ GdmScrollableWidgetSlideDoneFunc done_func, >+ gpointer done_func_user_data) >+{ >+ GdmScrollableWidgetAnimation *animation; >+ >+ animation = g_slice_new (GdmScrollableWidgetAnimation); >+ >+ animation->widget = widget; >+ animation->timer = gdm_timer_new (); >+ animation->start_height = start_height; >+ animation->desired_height = desired_height; >+ animation->step_func = step_func; >+ animation->step_func_user_data = step_func_user_data; >+ animation->done_func = done_func; >+ animation->done_func_user_data = done_func_user_data; >+ >+ return animation; >+} >+ >+static void >+gdm_scrollable_widget_animation_free (GdmScrollableWidgetAnimation *animation) >+{ >+ g_object_unref (animation->timer); >+ g_slice_free (GdmScrollableWidgetAnimation, animation); >+} >+ >+void >+on_animation_tick (GdmScrollableWidgetAnimation *animation, >+ double progress) >+{ >+ int progress_in_pixels; >+ int width; >+ int height; >+ >+ progress_in_pixels = progress * (animation->start_height - animation->desired_height); >+ >+ height = animation->start_height - progress_in_pixels; >+ >+ gtk_widget_get_size_request (animation->widget, &width, NULL); >+ gtk_widget_set_size_request (animation->widget, width, height); >+ >+ if (animation->step_func != NULL) { >+ animation->step_func (GDM_SCROLLABLE_WIDGET (animation->widget), >+ progress, >+ animation->step_func_user_data); >+ } >+} >+ >+static gboolean >+gdm_scrollable_redirect_input_to_event_sink (GdmScrollableWidget *scrollable_widget) >+{ >+ GdkGrabStatus status; >+ >+ status = gdk_pointer_grab (scrollable_widget->priv->invisible_event_sink->window, >+ FALSE, 0, NULL, NULL, GDK_CURRENT_TIME); >+ if (status != GDK_GRAB_SUCCESS) { >+ return FALSE; >+ } >+ >+ status = gdk_keyboard_grab (scrollable_widget->priv->invisible_event_sink->window, >+ FALSE, GDK_CURRENT_TIME); >+ if (status != GDK_GRAB_SUCCESS) { >+ gdk_pointer_ungrab (GDK_CURRENT_TIME); >+ return FALSE; >+ } >+ >+ return TRUE; >+} >+ >+static void >+gdm_scrollable_unredirect_input (GdmScrollableWidget *scrollable_widget) >+{ >+ gdk_keyboard_ungrab (GDK_CURRENT_TIME); >+ gdk_pointer_ungrab (GDK_CURRENT_TIME); >+} >+ >+void >+on_animation_stop (GdmScrollableWidgetAnimation *animation) >+{ >+ GdmScrollableWidget *widget; >+ int width; >+ >+ widget = GDM_SCROLLABLE_WIDGET (animation->widget); >+ >+ if (animation->done_func != NULL) { >+ animation->done_func (widget, animation->done_func_user_data); >+ } >+ >+ gdm_scrollable_widget_animation_free (widget->priv->animation); >+ widget->priv->animation = NULL; >+ >+ gtk_widget_get_size_request (GTK_WIDGET (widget), &width, NULL); >+ gtk_widget_set_size_request (GTK_WIDGET (widget), width, -1); >+ gtk_widget_queue_resize (GTK_WIDGET (widget)); >+ >+ gdm_scrollable_unredirect_input (widget); >+} >+ >+static void >+gdm_scrollable_widget_animation_start (GdmScrollableWidgetAnimation *animation) >+{ >+ g_signal_connect_swapped (G_OBJECT (animation->timer), "tick", >+ G_CALLBACK (on_animation_tick), >+ animation); >+ g_signal_connect_swapped (G_OBJECT (animation->timer), "stop", >+ G_CALLBACK (on_animation_stop), >+ animation); >+ gdm_timer_start (animation->timer, .50); >+} >+ >+static gboolean >+gdm_scrollable_widget_needs_scrollbar (GdmScrollableWidget *widget) >+{ >+ GtkAdjustment *adjustment; >+ >+ if (widget->priv->scrollbar == NULL) { >+ return FALSE; >+ } >+ >+ if (widget->priv->animation != NULL) { >+ return FALSE; >+ } >+ >+ adjustment = gtk_range_get_adjustment (GTK_RANGE (widget->priv->scrollbar)); >+ >+ return adjustment->upper - adjustment->lower > adjustment->page_size; >+} >+ >+static void >+gdm_scrollable_widget_size_request (GtkWidget *widget, >+ GtkRequisition *requisition) >+{ >+ GdmScrollableWidget *scrollable_widget; >+ GtkRequisition child_requisition; >+ >+ scrollable_widget = GDM_SCROLLABLE_WIDGET (widget); >+ >+ requisition->width = 2 * GTK_CONTAINER (widget)->border_width; >+ requisition->height = 2 * GTK_CONTAINER (widget)->border_width; >+ >+ requisition->width += 2 * widget->style->xthickness; >+ requisition->height += 2 * widget->style->ythickness; >+ >+ if (GTK_BIN (widget)->child && GTK_WIDGET_VISIBLE (GTK_BIN (widget)->child)) { >+ gtk_widget_size_request (GTK_BIN (widget)->child, >+ &child_requisition); >+ requisition->height += child_requisition.height; >+ } >+ >+ if (gdm_scrollable_widget_needs_scrollbar (scrollable_widget)) { >+ GtkRequisition scrollbar_requisition; >+ >+ gtk_widget_show (scrollable_widget->priv->scrollbar); >+ >+ gtk_widget_size_request (scrollable_widget->priv->scrollbar, >+ &scrollbar_requisition); >+ >+ requisition->height = MAX (requisition->height, >+ scrollbar_requisition.height); >+ requisition->width += scrollbar_requisition.width; >+ } else { >+ gtk_widget_hide (scrollable_widget->priv->scrollbar); >+ } >+} >+ >+static void >+gdm_scrollable_widget_size_allocate (GtkWidget *widget, >+ GtkAllocation *allocation) >+{ >+ GdmScrollableWidget *scrollable_widget; >+ GtkAllocation scrollbar_allocation; >+ GtkAllocation child_allocation; >+ gboolean has_child; >+ gboolean needs_scrollbar; >+ gboolean is_flipped; >+ >+ scrollable_widget = GDM_SCROLLABLE_WIDGET (widget); >+ >+ widget->allocation = *allocation; >+ >+ has_child = GTK_BIN (widget)->child && GTK_WIDGET_VISIBLE (GTK_BIN (widget)->child); >+ needs_scrollbar = gdm_scrollable_widget_needs_scrollbar (scrollable_widget); >+ is_flipped = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; >+ >+ if (needs_scrollbar) { >+ GtkRequisition scrollbar_requisition; >+ >+ gtk_widget_get_child_requisition (scrollable_widget->priv->scrollbar, >+ &scrollbar_requisition); >+ >+ scrollbar_allocation.width = scrollbar_requisition.width; >+ >+ if (!is_flipped) { >+ scrollbar_allocation.x = allocation->x + allocation->width; >+ scrollbar_allocation.x -= GTK_CONTAINER (widget)->border_width; >+ scrollbar_allocation.x -= scrollbar_allocation.width; >+ } else { >+ scrollbar_allocation.x = allocation->x; >+ scrollbar_allocation.x += GTK_CONTAINER (widget)->border_width; >+ } >+ >+ scrollbar_allocation.height = allocation->height; >+ scrollbar_allocation.height -= 2 * GTK_CONTAINER (widget)->border_width; >+ >+ scrollbar_allocation.y = allocation->y; >+ scrollbar_allocation.y += GTK_CONTAINER (widget)->border_width; >+ >+ gtk_widget_size_allocate (scrollable_widget->priv->scrollbar, >+ &scrollbar_allocation); >+ } >+ >+ if (has_child) { >+ GtkRequisition child_requisition; >+ >+ gtk_widget_get_child_requisition (GTK_BIN (widget)->child, >+ &child_requisition); >+ >+ child_allocation.width = allocation->width; >+ child_allocation.width -= 2 * GTK_CONTAINER (widget)->border_width; >+ child_allocation.width -= 2 * widget->style->xthickness; >+ >+ if (needs_scrollbar) { >+ child_allocation.width -= scrollbar_allocation.width; >+ } >+ >+ if (!is_flipped) { >+ child_allocation.x = allocation->x; >+ child_allocation.x += GTK_CONTAINER (widget)->border_width; >+ child_allocation.x += widget->style->xthickness; >+ } else { >+ child_allocation.x = allocation->x + allocation->width; >+ child_allocation.x -= GTK_CONTAINER (widget)->border_width; >+ child_allocation.x -= child_allocation.width; >+ child_allocation.x -= widget->style->xthickness; >+ } >+ >+ child_allocation.height = allocation->height; >+ child_allocation.height -= 2 * GTK_CONTAINER (widget)->border_width; >+ child_allocation.height -= 2 * widget->style->ythickness; >+ >+ child_allocation.y = allocation->y; >+ child_allocation.y += GTK_CONTAINER (widget)->border_width; >+ child_allocation.y += widget->style->ythickness; >+ >+ gtk_widget_size_allocate (GTK_BIN (widget)->child, >+ &child_allocation); >+ } >+} >+ >+static void >+gdm_scrollable_widget_add (GtkContainer *container, >+ GtkWidget *child) >+{ >+ GtkAdjustment *adjustment; >+ >+ GTK_CONTAINER_CLASS (gdm_scrollable_widget_parent_class)->add (container, child); >+ >+ adjustment = gtk_range_get_adjustment (GTK_RANGE (GDM_SCROLLABLE_WIDGET (container)->priv->scrollbar)); >+ >+ g_signal_connect_swapped (adjustment, "changed", >+ G_CALLBACK (gtk_widget_queue_resize), >+ container); >+ >+ gtk_widget_set_scroll_adjustments (child, NULL, adjustment); >+} >+ >+static void >+gdm_scrollable_widget_remove (GtkContainer *container, >+ GtkWidget *child) >+{ >+ gtk_widget_set_scroll_adjustments (child, NULL, NULL); >+ >+ GTK_CONTAINER_CLASS (gdm_scrollable_widget_parent_class)->remove (container, child); >+} >+ >+static void >+gdm_scrollable_widget_forall (GtkContainer *container, >+ gboolean include_internals, >+ GtkCallback callback, >+ gpointer callback_data) >+{ >+ >+ GdmScrollableWidget *scrollable_widget; >+ >+ scrollable_widget = GDM_SCROLLABLE_WIDGET (container); >+ >+ GTK_CONTAINER_CLASS (gdm_scrollable_widget_parent_class)->forall (container, >+ include_internals, >+ callback, >+ callback_data); >+ >+ if (!include_internals) { >+ return; >+ } >+ >+ if (scrollable_widget->priv->scrollbar != NULL) { >+ callback (scrollable_widget->priv->scrollbar, callback_data); >+ } >+} >+ >+static void >+gdm_scrollable_widget_destroy (GtkObject *object) >+{ >+ GdmScrollableWidget *scrollable_widget; >+ >+ scrollable_widget = GDM_SCROLLABLE_WIDGET (object); >+ >+ gtk_widget_unparent (scrollable_widget->priv->scrollbar); >+ gtk_widget_destroy (scrollable_widget->priv->scrollbar); >+ >+ GTK_OBJECT_CLASS (gdm_scrollable_widget_parent_class)->destroy (object); >+} >+ >+static void >+gdm_scrollable_widget_finalize (GObject *object) >+{ >+ GdmScrollableWidget *scrollable_widget; >+ >+ scrollable_widget = GDM_SCROLLABLE_WIDGET (object); >+ >+ G_OBJECT_CLASS (gdm_scrollable_widget_parent_class)->finalize (object); >+} >+ >+static gboolean >+gdm_scrollable_widget_expose_event (GtkWidget *widget, >+ GdkEventExpose *event) >+{ >+ GdmScrollableWidget *scrollable_widget; >+ int x; >+ int y; >+ int width; >+ int height; >+ gboolean is_flipped; >+ >+ scrollable_widget = GDM_SCROLLABLE_WIDGET (widget); >+ >+ if (!GTK_WIDGET_DRAWABLE (widget)) { >+ return FALSE; >+ } >+ >+ is_flipped = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; >+ >+ x = widget->allocation.x; >+ x += 2 * GTK_CONTAINER (widget)->border_width; >+ >+ width = widget->allocation.width; >+ width -= 2 * GTK_CONTAINER (widget)->border_width; >+ >+ if (gdm_scrollable_widget_needs_scrollbar (scrollable_widget)) { >+ width -= scrollable_widget->priv->scrollbar->allocation.width; >+ >+ if (is_flipped) { >+ x += scrollable_widget->priv->scrollbar->allocation.width; >+ } >+ } >+ >+ y = widget->allocation.y; >+ y += 2 * GTK_CONTAINER (widget)->border_width; >+ >+ height = widget->allocation.height; >+ height -= 2 * GTK_CONTAINER (widget)->border_width; >+ >+ gtk_paint_shadow (widget->style, widget->window, >+ GTK_WIDGET_STATE (widget), GTK_SHADOW_IN, >+ &event->area, widget, "scrolled_window", >+ x, y, width, height); >+ >+ return GTK_WIDGET_CLASS (gdm_scrollable_widget_parent_class)->expose_event (widget, event); >+} >+ >+static gboolean >+gdm_scrollable_widget_scroll_event (GtkWidget *widget, >+ GdkEventScroll *event) >+{ >+ if (event->direction != GDK_SCROLL_UP && event->direction != GDK_SCROLL_DOWN) { >+ return FALSE; >+ } >+ >+ if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (widget))) { >+ return FALSE; >+ } >+ >+ return gtk_widget_event (GDM_SCROLLABLE_WIDGET (widget)->priv->scrollbar, >+ (GdkEvent *) event); >+} >+ >+static void >+add_scroll_binding (GtkBindingSet *binding_set, >+ guint keyval, >+ GdkModifierType mask, >+ GtkScrollType scroll) >+{ >+ guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left; >+ >+ gtk_binding_entry_add_signal (binding_set, keyval, mask, >+ "scroll-child", 1, >+ GTK_TYPE_SCROLL_TYPE, scroll); >+ gtk_binding_entry_add_signal (binding_set, keypad_keyval, mask, >+ "scroll-child", 1, >+ GTK_TYPE_SCROLL_TYPE, scroll); >+} >+ >+static void >+add_tab_bindings (GtkBindingSet *binding_set, >+ GdkModifierType modifiers, >+ GtkDirectionType direction) >+{ >+ gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers, >+ "move-focus-out", 1, >+ GTK_TYPE_DIRECTION_TYPE, direction); >+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers, >+ "move-focus-out", 1, >+ GTK_TYPE_DIRECTION_TYPE, direction); >+} >+ >+static void >+gdm_scrollable_widget_class_install_bindings (GdmScrollableWidgetClass *klass) >+{ >+ GtkBindingSet *binding_set; >+ >+ binding_set = gtk_binding_set_by_class (klass); >+ >+ add_scroll_binding (binding_set, GDK_Up, GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD); >+ add_scroll_binding (binding_set, GDK_Down, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD); >+ >+ add_scroll_binding (binding_set, GDK_Page_Up, 0, GTK_SCROLL_PAGE_BACKWARD); >+ add_scroll_binding (binding_set, GDK_Page_Down, 0, GTK_SCROLL_PAGE_FORWARD); >+ >+ add_scroll_binding (binding_set, GDK_Home, 0, GTK_SCROLL_START); >+ add_scroll_binding (binding_set, GDK_End, 0, GTK_SCROLL_END); >+ >+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD); >+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD); >+} >+ >+static void >+gdm_scrollable_widget_class_init (GdmScrollableWidgetClass *klass) >+{ >+ GObjectClass *object_class; >+ GtkObjectClass *gtk_object_class; >+ GtkWidgetClass *widget_class; >+ GtkContainerClass *container_class; >+ GdmScrollableWidgetClass *scrollable_widget_class; >+ >+ object_class = G_OBJECT_CLASS (klass); >+ gtk_object_class = GTK_OBJECT_CLASS (klass); >+ widget_class = GTK_WIDGET_CLASS (klass); >+ container_class = GTK_CONTAINER_CLASS (klass); >+ scrollable_widget_class = GDM_SCROLLABLE_WIDGET_CLASS (klass); >+ >+ object_class->finalize = gdm_scrollable_widget_finalize; >+ >+ gtk_object_class->destroy = gdm_scrollable_widget_destroy; >+ >+ widget_class->size_request = gdm_scrollable_widget_size_request; >+ widget_class->size_allocate = gdm_scrollable_widget_size_allocate; >+ widget_class->expose_event = gdm_scrollable_widget_expose_event; >+ widget_class->scroll_event = gdm_scrollable_widget_scroll_event; >+ >+ container_class->add = gdm_scrollable_widget_add; >+ container_class->remove = gdm_scrollable_widget_remove; >+ container_class->forall = gdm_scrollable_widget_forall; >+ >+ signals[SCROLL_CHILD] = >+ g_signal_new ("scroll-child", >+ G_TYPE_FROM_CLASS (object_class), >+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, >+ G_STRUCT_OFFSET (GtkScrolledWindowClass, scroll_child), >+ NULL, NULL, >+ g_cclosure_marshal_VOID__ENUM, >+ G_TYPE_BOOLEAN, 1, >+ GTK_TYPE_SCROLL_TYPE); >+ signals[MOVE_FOCUS_OUT] = >+ g_signal_new ("move-focus-out", >+ G_TYPE_FROM_CLASS (object_class), >+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, >+ G_STRUCT_OFFSET (GtkScrolledWindowClass, move_focus_out), >+ NULL, NULL, >+ g_cclosure_marshal_VOID__ENUM, >+ G_TYPE_NONE, 1, >+ GTK_TYPE_DIRECTION_TYPE); >+ gdm_scrollable_widget_class_install_bindings (klass); >+ >+ g_type_class_add_private (klass, sizeof (GdmScrollableWidgetPrivate)); >+} >+ >+static void >+gdm_scrollable_widget_add_scrollbar (GdmScrollableWidget *widget) >+{ >+ gtk_widget_push_composite_child (); >+ widget->priv->scrollbar = gtk_vscrollbar_new (NULL); >+ gtk_widget_set_composite_name (widget->priv->scrollbar, "scrollbar"); >+ gtk_widget_pop_composite_child (); >+ gtk_widget_set_parent (widget->priv->scrollbar, GTK_WIDGET (widget)); >+ g_object_ref (widget->priv->scrollbar); >+} >+ >+static void >+gdm_scrollable_widget_add_invisible_event_sink (GdmScrollableWidget *widget) >+{ >+ widget->priv->invisible_event_sink = >+ gtk_invisible_new_for_screen (gtk_widget_get_screen (GTK_WIDGET (widget))); >+ gtk_widget_show (widget->priv->invisible_event_sink); >+} >+ >+static void >+gdm_scrollable_widget_init (GdmScrollableWidget *widget) >+{ >+ widget->priv = GDM_SCROLLABLE_WIDGET_GET_PRIVATE (widget); >+ >+ gdm_scrollable_widget_add_scrollbar (widget); >+ gdm_scrollable_widget_add_invisible_event_sink (widget); >+} >+ >+GtkWidget * >+gdm_scrollable_widget_new (void) >+{ >+ GObject *object; >+ >+ object = g_object_new (GDM_TYPE_SCROLLABLE_WIDGET, NULL); >+ >+ return GTK_WIDGET (object); >+} >+ >+static gboolean >+gdm_scrollable_widget_animations_are_disabled (GdmScrollableWidget *scrollable_widget) >+{ >+ GtkSettings *settings; >+ gboolean animations_are_enabled; >+ >+ settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (scrollable_widget))); >+ g_object_get (settings, "gtk-enable-animations", &animations_are_enabled, NULL); >+ >+ return animations_are_enabled == FALSE; >+} >+ >+void >+gdm_scrollable_widget_slide_to_height (GdmScrollableWidget *scrollable_widget, >+ int height, >+ GdmScrollableWidgetSlideStepFunc step_func, >+ gpointer step_user_data, >+ GdmScrollableWidgetSlideDoneFunc done_func, >+ gpointer done_user_data) >+{ >+ GtkWidget *widget; >+ gboolean input_redirected; >+ >+ g_return_if_fail (GDM_IS_SCROLLABLE_WIDGET (scrollable_widget)); >+ widget = GTK_WIDGET (scrollable_widget); >+ >+ g_return_if_fail (scrollable_widget->priv->animation == NULL); >+ >+ input_redirected = gdm_scrollable_redirect_input_to_event_sink (scrollable_widget); >+ >+ if (!input_redirected || gdm_scrollable_widget_animations_are_disabled (scrollable_widget)) { >+ if (step_func != NULL) { >+ step_func (scrollable_widget, 0.0, step_user_data); >+ } >+ >+ if (done_func != NULL) { >+ done_func (scrollable_widget, done_user_data); >+ } >+ >+ return; >+ } >+ >+ scrollable_widget->priv->animation = >+ gdm_scrollable_widget_animation_new (widget, >+ widget->allocation.height, >+ height, step_func, step_user_data, >+ done_func, done_user_data); >+ >+ gdm_scrollable_widget_animation_start (scrollable_widget->priv->animation); >+} > >Added: trunk/gui/simple-greeter/gdm-scrollable-widget.h >============================================================================== >--- (empty file) >+++ trunk/gui/simple-greeter/gdm-scrollable-widget.h Thu Apr 3 22:09:04 2008 >@@ -0,0 +1,70 @@ >+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- >+ * >+ * Copyright (C) 2008 Red Hat, Inc. >+ * >+ * 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. >+ * >+ * Written by: Ray Strode <rstrode@redhat.com> >+ */ >+ >+#ifndef __GDM_SCROLLABLE_WIDGET_H >+#define __GDM_SCROLLABLE_WIDGET_H >+ >+#include <glib-object.h> >+ >+#include <gtk/gtk.h> >+ >+G_BEGIN_DECLS >+ >+#define GDM_TYPE_SCROLLABLE_WIDGET (gdm_scrollable_widget_get_type ()) >+#define GDM_SCROLLABLE_WIDGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_SCROLLABLE_WIDGET, GdmScrollableWidget)) >+#define GDM_SCROLLABLE_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_SCROLLABLE_WIDGET, GdmScrollableWidgetClass)) >+#define GDM_IS_SCROLLABLE_WIDGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_SCROLLABLE_WIDGET)) >+#define GDM_IS_SCROLLABLE_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_SCROLLABLE_WIDGET)) >+#define GDM_SCROLLABLE_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_SCROLLABLE_WIDGET, GdmScrollableWidgetClass)) >+ >+typedef struct GdmScrollableWidgetClass GdmScrollableWidgetClass; >+typedef struct GdmScrollableWidget GdmScrollableWidget; >+typedef struct GdmScrollableWidgetPrivate GdmScrollableWidgetPrivate; >+typedef void (* GdmScrollableWidgetSlideStepFunc) (GdmScrollableWidget *scrollable_widget, >+ double progress, >+ gpointer *user_data); >+typedef void (* GdmScrollableWidgetSlideDoneFunc) (GdmScrollableWidget *scrollable_widget, >+ gpointer *user_data); >+ >+struct GdmScrollableWidget >+{ >+ GtkBin parent; >+ GdmScrollableWidgetPrivate *priv; >+}; >+ >+struct GdmScrollableWidgetClass >+{ >+ GtkBinClass parent_class; >+ >+ void (* scroll_child) (GdmScrollableWidget *widget, GtkScrollType type); >+ void (* move_focus_out) (GdmScrollableWidget *widget, GtkDirectionType type); >+ >+}; >+ >+GType gdm_scrollable_widget_get_type (void); >+GtkWidget * gdm_scrollable_widget_new (void); >+void gdm_scrollable_widget_slide_to_height (GdmScrollableWidget *widget, >+ int height, >+ GdmScrollableWidgetSlideStepFunc step_func, >+ gpointer step_user_data, >+ GdmScrollableWidgetSlideDoneFunc done_func, >+ gpointer data); >+#endif /* __GDM_SCROLLABLE_WIDGET_H */ >_______________________________________________ >SVN-commits-list mailing list (read only) >http://mail.gnome.org/mailman/listinfo/svn-commits-list > >Want to limit the commits to a few modules? Go to above URL, log in to edit your options and select the modules ('topics') you want. >Module maintainer? It is possible to set the reply-to to your development mailing list. Email svnmaster@gnome.org if interested.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
Attachments on
bug 377784
: 207836