diff options
-rw-r--r-- | libempathy-gtk/empathy-individual-view.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/libempathy-gtk/empathy-individual-view.c b/libempathy-gtk/empathy-individual-view.c index 2ad0fc0e0..5f604058a 100644 --- a/libempathy-gtk/empathy-individual-view.c +++ b/libempathy-gtk/empathy-individual-view.c @@ -81,6 +81,12 @@ typedef struct guint expand_groups_idle_handler; /* owned string (group name) -> bool (whether to expand/contract) */ GHashTable *expand_groups; + + /* Auto scroll */ + guint auto_scroll_timeout_id; + /* Distance between mouse pointer and the nearby border. Negative when + scrolling updards.*/ + gint distance; } EmpathyIndividualViewPriv; typedef struct @@ -549,6 +555,34 @@ individual_view_drag_motion_cb (DragMotionData *data) return FALSE; } +/* Minimum distance between the mouse pointer and a horizontal border when we + start auto scrolling. */ +#define AUTO_SCROLL_MARGIN_SIZE 20 +/* How far to scroll per one tick. */ +#define AUTO_SCROLL_PITCH 10 + +static gboolean +individual_view_auto_scroll_cb (EmpathyIndividualView *self) +{ + EmpathyIndividualViewPriv *priv = GET_PRIV (self); + GtkAdjustment *adj; + gdouble new_value; + + adj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (self)); + + if (priv->distance < 0) + new_value = gtk_adjustment_get_value (adj) - AUTO_SCROLL_PITCH; + else + new_value = gtk_adjustment_get_value (adj) + AUTO_SCROLL_PITCH; + + new_value = CLAMP (new_value, gtk_adjustment_get_lower (adj), + gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj)); + + gtk_adjustment_set_value (adj, new_value); + + return TRUE; +} + static gboolean individual_view_drag_motion (GtkWidget *widget, GdkDragContext *context, @@ -566,10 +600,32 @@ individual_view_drag_motion (GtkWidget *widget, gboolean is_different = FALSE; gboolean cleanup = TRUE; gboolean retval = TRUE; + GtkAllocation allocation; priv = GET_PRIV (EMPATHY_INDIVIDUAL_VIEW (widget)); model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + if (priv->auto_scroll_timeout_id != 0) + { + g_source_remove (priv->auto_scroll_timeout_id); + priv->auto_scroll_timeout_id = 0; + } + + gtk_widget_get_allocation (widget, &allocation); + + if (y < AUTO_SCROLL_MARGIN_SIZE || + y > (allocation.height - AUTO_SCROLL_MARGIN_SIZE)) + { + if (y < AUTO_SCROLL_MARGIN_SIZE) + priv->distance = MIN (-y, -1); + else + priv->distance = MAX (allocation.height - y, 1); + + priv->auto_scroll_timeout_id = g_timeout_add (10 * ABS (priv->distance), + (GSourceFunc) individual_view_auto_scroll_cb, widget); + } + is_row = gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y, &path, NULL, NULL, NULL); |