From a6850a001a5c7ac7e202b379f08b6dee250aece7 Mon Sep 17 00:00:00 2001 From: Chow Loong Jin Date: Sat, 14 Apr 2012 15:56:08 +0800 Subject: [PATCH] Enable GDK_SMOOTH_SCROLL events for document 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. Additionally, the ev_view_[can_]zoom_{in,out} functions have been refactored slightly to reduce code duplication and allow for zooming by a factor other than ZOOM_IN_FACTOR and ZOOM_OUT_FACTOR by adding two new functions, needed for smooth zooming via Ctrl+scroll: - gboolean ev_view_can_zoom (EvView *view, gdouble factor) - void ev_view_zoom (EvView *view, gdouble factor) --- configure.ac | 2 +- libview/ev-view-private.h | 3 ++ libview/ev-view.c | 68 ++++++++++++++++++++++++++++++++++++--------- libview/ev-view.h | 4 +++ 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 66958fa..ae5a9e1 100644 --- a/configure.ac +++ b/configure.ac @@ -119,7 +119,7 @@ dnl Specify required versions of dependencies CAIRO_REQUIRED=1.10.0 GLIB_REQUIRED=2.25.11 KEYRING_REQUIRED=2.22.0 -GTK_REQUIRED=3.0.2 +GTK_REQUIRED=3.3.18 NAUTILUS_REQUIRED=2.91.4 AC_SUBST([GLIB_REQUIRED]) diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index 47c397c..562bf76 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -144,6 +144,9 @@ struct _EvView { gint scroll_x; gint scroll_y; + /* Delta sums for emulating normal scrolling */ + gdouble total_delta_x; + gdouble total_delta_y; PendingScroll pending_scroll; gboolean pending_resize; EvPoint pending_point; diff --git a/libview/ev-view.c b/libview/ev-view.c index 06017b5..fc425ec 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -3295,8 +3295,14 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) if (state == GDK_CONTROL_MASK) { ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE); - if (event->direction == GDK_SCROLL_UP || - event->direction == GDK_SCROLL_LEFT) { + if (event->direction == 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 (ev_view_can_zoom (view, factor)) { + ev_view_zoom (view, factor); + } + } else if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT) { if (ev_view_can_zoom_in (view)) { ev_view_zoom_in (view); } @@ -3321,12 +3327,19 @@ 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; } if (state == 0 && view->sizing_mode == EV_SIZING_BEST_FIT && !view->continuous) { + gdouble decrement; switch (event->direction) { case GDK_SCROLL_DOWN: case GDK_SCROLL_RIGHT: @@ -3336,6 +3349,25 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) case GDK_SCROLL_LEFT: ev_view_previous_page (view); break; + case GDK_SCROLL_SMOOTH: + /* Emulate normal scrolling by summing the deltas */ + view->total_delta_x += event->delta_x; + view->total_delta_y += event->delta_y; + + decrement = view->total_delta_x < 0 ? -1.0 : 1.0; + for (; fabs (view->total_delta_x) >= 1.0; view->total_delta_x -= decrement) + if (decrement < 0) + ev_view_previous_page (view); + else + ev_view_next_page (view); + + decrement = view->total_delta_y < 0 ? -1.0 : 1.0; + for (; fabs (view->total_delta_y) >= 1.0; view->total_delta_y -= decrement) + if (decrement < 0) + ev_view_previous_page (view); + else + ev_view_next_page (view); + break; } return TRUE; @@ -4913,6 +4945,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 | @@ -5441,41 +5474,50 @@ ev_view_reload (EvView *view) } /*** Zoom and sizing mode ***/ +gboolean +ev_view_can_zoom (EvView *view, gdouble factor) +{ + gdouble scale = view->scale * factor; + gdouble min_scale = ev_document_model_get_min_scale (view->model); + gdouble max_scale = ev_document_model_get_max_scale (view->model); + + return min_scale <= scale && scale <= max_scale; +} gboolean ev_view_can_zoom_in (EvView *view) { - return view->scale * ZOOM_IN_FACTOR <= ev_document_model_get_max_scale (view->model); + return ev_view_can_zoom (view, ZOOM_IN_FACTOR); } gboolean ev_view_can_zoom_out (EvView *view) { - return view->scale * ZOOM_OUT_FACTOR >= ev_document_model_get_min_scale (view->model); + return ev_view_can_zoom (view, ZOOM_OUT_FACTOR); } void -ev_view_zoom_in (EvView *view) +ev_view_zoom (EvView *view, gdouble factor) { gdouble scale; g_return_if_fail (view->sizing_mode == EV_SIZING_FREE); view->pending_scroll = SCROLL_TO_CENTER; - scale = ev_document_model_get_scale (view->model) * ZOOM_IN_FACTOR; + scale = ev_document_model_get_scale (view->model) * factor; ev_document_model_set_scale (view->model, scale); } void -ev_view_zoom_out (EvView *view) +ev_view_zoom_in (EvView *view) { - gdouble scale; - - g_return_if_fail (view->sizing_mode == EV_SIZING_FREE); + ev_view_zoom (view, ZOOM_IN_FACTOR); +} - view->pending_scroll = SCROLL_TO_CENTER; - scale = ev_document_model_get_scale (view->model) * ZOOM_OUT_FACTOR; - ev_document_model_set_scale (view->model, scale); +void +ev_view_zoom_out (EvView *view) +{ + ev_view_zoom (view, ZOOM_OUT_FACTOR); } static double diff --git a/libview/ev-view.h b/libview/ev-view.h index 06f5b30..e551127 100644 --- a/libview/ev-view.h +++ b/libview/ev-view.h @@ -63,6 +63,10 @@ void ev_view_select_all (EvView *view); gboolean ev_view_get_has_selection (EvView *view); /* Page size */ +gboolean ev_view_can_zoom (EvView *view, + gdouble factor); +void ev_view_zoom (EvView *view, + gdouble factor); gboolean ev_view_can_zoom_in (EvView *view); void ev_view_zoom_in (EvView *view); gboolean ev_view_can_zoom_out (EvView *view); -- 1.7.9.5