Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/shell
diff options
context:
space:
mode:
authorNickolay V. Shmyrev <nshmyrev@yandex.ru>2007-12-24 21:46:31 (GMT)
committer Nickolay V. Shmyrev <nshmyrev@src.gnome.org>2007-12-24 21:46:31 (GMT)
commit4afda26e15369c1ff2dbbdb132438f3cfaccb529 (patch)
tree6137a63836ad42c138aff46cab519edad6422f6e /shell
parent2740d28b0dd8752bf5dbfd10099f7fd274be4d34 (diff)
Kinetic scrolling implemented as requested in bug #461271. Thanks to David
2007-12-25 Nickolay V. Shmyrev <nshmyrev@yandex.ru> * shell/ev-view-private.h: * shell/ev-view.c: (ev_view_drag_update_momentum), (ev_view_scroll_drag_release), (ev_view_motion_notify_event), (ev_view_button_release_event), (ev_view_destroy): Kinetic scrolling implemented as requested in bug #461271. Thanks to David Turner <cillian64@googlemail.com>. svn path=/trunk/; revision=2783
Diffstat (limited to 'shell')
-rw-r--r--shell/ev-view-private.h6
-rw-r--r--shell/ev-view.c96
2 files changed, 98 insertions, 4 deletions
diff --git a/shell/ev-view-private.h b/shell/ev-view-private.h
index 22bd7a0..a2a2812 100644
--- a/shell/ev-view-private.h
+++ b/shell/ev-view-private.h
@@ -28,12 +28,18 @@
#include "ev-form-field.h"
#include "ev-selection.h"
+#define DRAG_HISTORY 10
+
/* Information for middle clicking and moving around the doc */
typedef struct {
gboolean in_drag;
GdkPoint start;
gdouble hadj;
gdouble vadj;
+ guint drag_timeout_id;
+ guint release_timeout_id;
+ GdkPoint buffer[DRAG_HISTORY];
+ GdkPoint momentum;
} DragInfo;
/* Autoscrolling */
diff --git a/shell/ev-view.c b/shell/ev-view.c
index c4baa7c..9782d0b 100644
--- a/shell/ev-view.c
+++ b/shell/ev-view.c
@@ -2893,6 +2893,66 @@ selection_scroll_timeout_cb (EvView *view)
}
static gboolean
+ev_view_drag_update_momentum (EvView *view)
+{
+ int i;
+ if (!view->drag_info.in_drag)
+ return FALSE;
+
+ for (i = DRAG_HISTORY - 1; i > 0; i--) {
+ view->drag_info.buffer[i].x = view->drag_info.buffer[i-1].x;
+ view->drag_info.buffer[i].y = view->drag_info.buffer[i-1].y;
+ }
+
+ /* Momentum is a moving average of 10ms granularity over
+ * the last 100ms with each 10ms stored in buffer.
+ */
+
+ view->drag_info.momentum.x = (view->drag_info.buffer[DRAG_HISTORY - 1].x - view->drag_info.buffer[0].x);
+ view->drag_info.momentum.y = (view->drag_info.buffer[DRAG_HISTORY - 1].y - view->drag_info.buffer[0].y);
+
+ return TRUE;
+}
+
+static gboolean
+ev_view_scroll_drag_release (EvView *view)
+{
+ gdouble dhadj_value, dvadj_value;
+ gdouble oldhadjustment, oldvadjustment;
+
+ view->drag_info.momentum.x /= 1.2;
+ view->drag_info.momentum.y /= 1.2; /* Alter these constants to change "friction" */
+
+ dhadj_value = view->hadjustment->page_size *
+ (gdouble)view->drag_info.momentum.x / GTK_WIDGET (view)->allocation.width;
+ dvadj_value = view->vadjustment->page_size *
+ (gdouble)view->drag_info.momentum.y / GTK_WIDGET (view)->allocation.height;
+
+ oldhadjustment = gtk_adjustment_get_value (view->hadjustment);
+ oldvadjustment = gtk_adjustment_get_value (view->vadjustment);
+
+ if (((oldhadjustment + dhadj_value) > (view->hadjustment->upper - view->hadjustment->page_size)) ||
+ ((oldhadjustment + dhadj_value) < 0))
+ view->drag_info.momentum.x *= -0.5; /* 0.5 rather than 1 means the edges absorb some momentum */
+ if (((oldvadjustment + dvadj_value) > (view->vadjustment->upper - view->vadjustment->page_size)) ||
+ ((oldvadjustment + dvadj_value) < 0))
+ view->drag_info.momentum.y *= -0.5;
+
+ gtk_adjustment_set_value (view->hadjustment,
+ MIN (oldhadjustment + dhadj_value,
+ view->hadjustment->upper - view->hadjustment->page_size));
+ gtk_adjustment_set_value (view->vadjustment,
+ MIN (oldvadjustment + dvadj_value,
+ view->vadjustment->upper - view->vadjustment->page_size));
+
+ if (((view->drag_info.momentum.x < 1) && (view->drag_info.momentum.x > -1)) &&
+ ((view->drag_info.momentum.y < 1) && (view->drag_info.momentum.y > -1)))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static gboolean
ev_view_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event)
{
@@ -2983,6 +3043,7 @@ ev_view_motion_notify_event (GtkWidget *widget,
} else if (view->pressed_button == 2) {
if (!view->drag_info.in_drag) {
gboolean start;
+ int i;
start = gtk_drag_check_threshold (widget,
view->drag_info.start.x,
@@ -2990,12 +3051,25 @@ ev_view_motion_notify_event (GtkWidget *widget,
event->x_root,
event->y_root);
view->drag_info.in_drag = start;
+ view->drag_info.drag_timeout_id = g_timeout_add (10,
+ (GSourceFunc)ev_view_drag_update_momentum, view);
+ /* Set 100 to choose how long it takes to build up momentum */
+ /* Clear out previous momentum info: */
+ for (i = 0; i < DRAG_HISTORY; i++) {
+ view->drag_info.buffer[i].x = event->x;
+ view->drag_info.buffer[i].y = event->y;
+ }
+ view->drag_info.momentum.x = 0;
+ view->drag_info.momentum.y = 0;
}
if (view->drag_info.in_drag) {
int dx, dy;
gdouble dhadj_value, dvadj_value;
+ view->drag_info.buffer[0].x = event->x;
+ view->drag_info.buffer[0].y = event->y;
+
dx = event->x_root - view->drag_info.start.x;
dy = event->y_root - view->drag_info.start.y;
@@ -3033,6 +3107,9 @@ ev_view_button_release_event (GtkWidget *widget,
view->drag_info.in_drag = FALSE;
view->image_dnd_info.in_drag = FALSE;
+
+ view->drag_info.release_timeout_id = g_timeout_add (20,
+ (GSourceFunc)ev_view_scroll_drag_release, view);
if (view->pressed_button == 2) {
ev_view_handle_cursor_over_xy (view, event->x, event->y);
@@ -3048,10 +3125,6 @@ ev_view_button_release_event (GtkWidget *widget,
g_source_remove (view->selection_scroll_id);
view->selection_scroll_id = 0;
}
- if (view->scroll_info.timeout_id) {
- g_source_remove (view->scroll_info.timeout_id);
- view->scroll_info.timeout_id = 0;
- }
if (view->selection_update_id) {
g_source_remove (view->selection_update_id);
view->selection_update_id = 0;
@@ -3764,6 +3837,21 @@ ev_view_destroy (GtkObject *object)
view->loading_text = NULL;
}
+ if (view->scroll_info.timeout_id) {
+ g_source_remove (view->scroll_info.timeout_id);
+ view->scroll_info.timeout_id = 0;
+ }
+
+ if (view->drag_info.drag_timeout_id) {
+ g_source_remove (view->drag_info.drag_timeout_id);
+ view->drag_info.drag_timeout_id = 0;
+ }
+
+ if (view->drag_info.release_timeout_id) {
+ g_source_remove (view->drag_info.release_timeout_id);
+ view->drag_info.release_timeout_id = 0;
+ }
+
ev_view_presentation_transition_stop (view);
ev_view_set_scroll_adjustments (GTK_LAYOUT (view), NULL, NULL);