From ab44eb6f7808eaf9fddbf6a248cd227122593d5b Mon Sep 17 00:00:00 2001 From: Xiao-Long Chen Date: Thu, 11 Oct 2012 14:55:48 -0400 Subject: libview: Enable GDK_SMOOTH_SCROLL events for view This enables the smooth/kinetic scrolling support found in GTK+ 3.3.18 with the document view, and handles them for the Ctrl+scroll, Shift+scroll, and non-continuous best-fit mode scrolling cases. https://bugzilla.gnome.org/show_bug.cgi?id=674098 origin commit link: https://git.gnome.org/browse/evince/commit/?id=34d0d5d --- libview/ev-view-private.h | 2 ++ libview/ev-view.c | 71 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index eef79f92..f85af71d 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -150,6 +150,8 @@ struct _EvView { gint scroll_x; gint scroll_y; + /* Delta sum for emulating normal scrolling */ + gdouble total_delta; PendingScroll pending_scroll; gboolean pending_resize; EvPoint pending_point; diff --git a/libview/ev-view.c b/libview/ev-view.c index 3a5fefdd..b7a5335e 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -3287,24 +3287,32 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) EvView *view = EV_VIEW (widget); guint state; - if (event->direction == GDK_SCROLL_SMOOTH) - return FALSE; - state = event->state & gtk_accelerator_get_default_mod_mask (); if (state == GDK_CONTROL_MASK) { ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE); view->zoom_center_x = event->x; view->zoom_center_y = event->y; - if (event->direction == GDK_SCROLL_UP || - event->direction == GDK_SCROLL_LEFT) { - if (ev_view_can_zoom_in (view)) { - ev_view_zoom_in (view); - } - } else { - if (ev_view_can_zoom_out (view)) { + switch (event->direction) { + case GDK_SCROLL_DOWN: + case GDK_SCROLL_RIGHT: + if (ev_view_can_zoom_out (view)) ev_view_zoom_out (view); - } + break; + case GDK_SCROLL_UP: + case GDK_SCROLL_LEFT: + if (ev_view_can_zoom_in (view)) + ev_view_zoom_in (view); + break; + case GDK_SCROLL_SMOOTH: { + gdouble delta = event->delta_x + event->delta_y; + gdouble factor = pow (delta < 0 ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR, fabs (delta)); + + if ((factor < 1.0 && ev_view_can_zoom_out (view)) || + (factor >= 1.0 && ev_view_can_zoom_in (view))) + ev_view_zoom (view, factor); + } + break; } return TRUE; @@ -3322,6 +3330,13 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) event->direction = GDK_SCROLL_RIGHT; else if (event->direction == GDK_SCROLL_RIGHT) event->direction = GDK_SCROLL_DOWN; + else if (event->direction == GDK_SCROLL_SMOOTH) { + /* Swap the deltas for perpendicular direction */ + gdouble tmp_delta = event->delta_x; + + event->delta_x = event->delta_y; + event->delta_y = tmp_delta; + } event->state &= ~GDK_SHIFT_MASK; state &= ~GDK_SHIFT_MASK; @@ -3329,16 +3344,29 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) if (state == 0 && view->sizing_mode == EV_SIZING_BEST_FIT && !view->continuous) { switch (event->direction) { - case GDK_SCROLL_DOWN: - case GDK_SCROLL_RIGHT: - ev_view_next_page (view); - break; - case GDK_SCROLL_UP: - case GDK_SCROLL_LEFT: - ev_view_previous_page (view); - break; - case GDK_SCROLL_SMOOTH: - g_assert_not_reached (); + case GDK_SCROLL_DOWN: + case GDK_SCROLL_RIGHT: + ev_view_next_page (view); + break; + case GDK_SCROLL_UP: + case GDK_SCROLL_LEFT: + ev_view_previous_page (view); + break; + case GDK_SCROLL_SMOOTH: { + gdouble decrement; + + /* Emulate normal scrolling by summing the deltas */ + view->total_delta += event->delta_x + event->delta_y; + + decrement = view->total_delta < 0 ? -1.0 : 1.0; + for (; fabs (view->total_delta) >= 1.0; view->total_delta -= decrement) { + if (decrement < 0) + ev_view_previous_page (view); + else + ev_view_next_page (view); + } + } + break; } return TRUE; @@ -5042,6 +5070,7 @@ ev_view_init (EvView *view) GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK | + GDK_SMOOTH_SCROLL_MASK | GDK_KEY_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | -- cgit v1.2.1