aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libempathy-gtk/empathy-individual-view.c56
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);