From 42768626e77556ca28a627e18db87ff7e3d4a61e Mon Sep 17 00:00:00 2001 From: Clement Lefebvre Date: Tue, 14 Mar 2017 13:47:19 +0000 Subject: ev-view: Add pinch/zoom gesture to handle document zooming This is delegated on a GtkGestureZoom. When triggered, the document will be zoomed based on the distance changes between both fingers. When the gesture is not active, regular event handling (text selection, clicking, etc...) will happen. Upstream commit from garnacho on 28 Mar 2014: https://github.com/GNOME/evince/commit/36c7f21 --- libview/ev-view-private.h | 4 +++ libview/ev-view.c | 68 ++++++++++++++++++++++++++++++++++++++++------- libview/ev-view.h | 2 ++ 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index 8957dad8..6e41d2ad 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -202,6 +202,10 @@ struct _EvView { /* Accessibility */ AtkObject *accessible; + + /* Gestures */ + GtkGesture *zoom_gesture; + gdouble prev_zoom_gesture_scale; }; struct _EvViewClass { diff --git a/libview/ev-view.c b/libview/ev-view.c index 86eef350..77851234 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -3609,7 +3609,10 @@ ev_view_button_press_event (GtkWidget *widget, if (!view->document) return FALSE; - + + if (gtk_gesture_is_recognized (view->zoom_gesture)) + return TRUE; + if (!gtk_widget_has_focus (widget)) { gtk_widget_grab_focus (widget); } @@ -3922,6 +3925,9 @@ ev_view_motion_notify_event (GtkWidget *widget, if (!view->document) return FALSE; + if (gtk_gesture_is_recognized (view->zoom_gesture)) + return TRUE; + bin_window = gtk_widget_get_window (widget); if (event->is_hint || event->window != bin_window) { @@ -4082,6 +4088,9 @@ ev_view_button_release_event (GtkWidget *widget, view->image_dnd_info.in_drag = FALSE; + if (gtk_gesture_is_recognized (view->zoom_gesture)) + return TRUE; + if (view->scroll_info.autoscrolling) { ev_view_autoscroll_stop (view); view->pressed_button = -1; @@ -4567,6 +4576,8 @@ ev_view_finalize (GObject *object) g_object_unref (view->image_dnd_info.image); view->image_dnd_info.image = NULL; + g_object_unref (view->zoom_gesture); + G_OBJECT_CLASS (ev_view_parent_class)->finalize (object); } @@ -4889,6 +4900,33 @@ on_notify_scale_factor (EvView *view, view_update_range_and_current_page (view); } +static void +zoom_gesture_begin_cb (GtkGesture *gesture, + GdkEventSequence *sequence, + EvView *view) +{ + view->prev_zoom_gesture_scale = 1; +} + +static void +zoom_gesture_scale_changed_cb (GtkGestureZoom *gesture, + gdouble scale, + EvView *view) +{ + gdouble factor; + + view->drag_info.in_drag = FALSE; + view->image_dnd_info.in_drag = FALSE; + + factor = scale - view->prev_zoom_gesture_scale + 1; + view->prev_zoom_gesture_scale = scale; + ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE); + + if ((factor < 1.0 && ev_view_can_zoom_out (view)) || + (factor >= 1.0 && ev_view_can_zoom_in (view))) + ev_view_zoom (view, factor); +} + static void ev_view_init (EvView *view) { @@ -4904,6 +4942,7 @@ ev_view_init (EvView *view) gtk_style_context_add_class (context, "view"); gtk_widget_set_events (GTK_WIDGET (view), + GDK_TOUCH_MASK | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | @@ -4938,6 +4977,15 @@ ev_view_init (EvView *view) g_signal_connect (view, "notify::scale-factor", G_CALLBACK (on_notify_scale_factor), NULL); + + view->zoom_gesture = gtk_gesture_zoom_new (GTK_WIDGET (view)); + gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (view->zoom_gesture), + GTK_PHASE_CAPTURE); + + g_signal_connect (view->zoom_gesture, "begin", + G_CALLBACK (zoom_gesture_begin_cb), view); + g_signal_connect (view->zoom_gesture, "scale-changed", + G_CALLBACK (zoom_gesture_scale_changed_cb), view); } /*** Callbacks ***/ @@ -5447,27 +5495,27 @@ ev_view_can_zoom_out (EvView *view) } 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 85c942df..31a9bf41 100644 --- a/libview/ev-view.h +++ b/libview/ev-view.h @@ -68,6 +68,8 @@ gboolean ev_view_can_zoom_in (EvView *view); void ev_view_zoom_in (EvView *view); gboolean ev_view_can_zoom_out (EvView *view); void ev_view_zoom_out (EvView *view); +void ev_view_zoom (EvView *view, + gdouble factor); /* Find */ void ev_view_find_next (EvView *view); -- cgit v1.2.1