gdm r6100 - in trunk: . gui/simple-greeter
- From: halfline svn gnome org
- To: svn-commits-list gnome org
- Subject: gdm r6100 - in trunk: . gui/simple-greeter
- Date: Thu, 3 Apr 2008 22:09:04 +0100 (BST)
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 */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]