From c508d14764871f4d052cc28b283dc9f0f1416898 Mon Sep 17 00:00:00 2001 From: Clement Lefebvre Date: Tue, 14 Mar 2017 14:35:04 +0000 Subject: ev-view: Add pan gesture to switch page This only applies on non-continuous mode, and the page fits with no horizontal scrolling. The gesture is actually connected to the parent GtkScrolledWindow (tracked through hierarchy events), so it is able to interact with kinetic scrolling gestures there, and cancel those if the pan gesture is recognized. Upstream commits by garnacho on 6 May and 15 Aug 2014: https://github.com/GNOME/evince/commit/afc50e7e07c135e22137a33cbf9913713692bf49 https://github.com/GNOME/evince/commit/2280b09ec71ee88eeeb7fd8d02adb2985d17a765 --- libview/ev-view-private.h | 8 ++++++ libview/ev-view.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index 6e41d2ad..1d1220f3 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -73,6 +73,12 @@ typedef struct { EvImage *image; } ImageDNDInfo; +typedef enum { + EV_PAN_ACTION_NONE, + EV_PAN_ACTION_NEXT, + EV_PAN_ACTION_PREV +} EvPanAction; + /* Annotation popup windows */ typedef struct { GtkWidget *window; @@ -204,8 +210,10 @@ struct _EvView { AtkObject *accessible; /* Gestures */ + GtkGesture *pan_gesture; GtkGesture *zoom_gesture; gdouble prev_zoom_gesture_scale; + EvPanAction pan_action; }; struct _EvViewClass { diff --git a/libview/ev-view.c b/libview/ev-view.c index 4bd3b23c..c9d97f44 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -4756,6 +4756,77 @@ ev_view_forall (GtkContainer *container, } } +static void +pan_gesture_pan_cb (GtkGesturePan *gesture, + GtkPanDirection direction, + gdouble offset, + EvView *view) +{ + GtkAllocation allocation; + + gtk_widget_get_allocation (GTK_WIDGET (view), &allocation); + + if (view->continuous || + allocation.width < view->requisition.width) { + gtk_gesture_set_state (GTK_GESTURE (gesture), + GTK_EVENT_SEQUENCE_DENIED); + return; + } + +#define PAN_ACTION_DISTANCE 200 + + view->pan_action = EV_PAN_ACTION_NONE; + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); + + if (offset > PAN_ACTION_DISTANCE) { + if (direction == GTK_PAN_DIRECTION_LEFT || + gtk_widget_get_direction (GTK_WIDGET (view)) == GTK_TEXT_DIR_RTL) + view->pan_action = EV_PAN_ACTION_NEXT; + else + view->pan_action = EV_PAN_ACTION_PREV; + } +#undef PAN_ACTION_DISTANCE +} + +static void +pan_gesture_end_cb (GtkGesture *gesture, + GdkEventSequence *sequence, + EvView *view) +{ + if (!gtk_gesture_handles_sequence (gesture, sequence)) + return; + + if (view->pan_action == EV_PAN_ACTION_PREV) + ev_view_previous_page (view); + else if (view->pan_action == EV_PAN_ACTION_NEXT) + ev_view_next_page (view); + + view->pan_action = EV_PAN_ACTION_NONE; +} + +static void +ev_view_hierarchy_changed (GtkWidget *widget, + GtkWidget *previous_toplevel) +{ + GtkWidget *parent = gtk_widget_get_parent (widget); + EvView *view = EV_VIEW (widget); + + if (parent && !view->pan_gesture) { + view->pan_gesture = + gtk_gesture_pan_new (parent, GTK_ORIENTATION_HORIZONTAL); + g_signal_connect (view->pan_gesture, "pan", + G_CALLBACK (pan_gesture_pan_cb), widget); + g_signal_connect (view->pan_gesture, "end", + G_CALLBACK (pan_gesture_end_cb), widget); + + gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (view->pan_gesture), TRUE); + gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (view->pan_gesture), + GTK_PHASE_CAPTURE); + } else if (!parent && view->pan_gesture) { + g_clear_object (&view->pan_gesture); + } +} + static void ev_view_parent_set (GtkWidget *widget, GtkWidget *previous_parent) @@ -4799,6 +4870,7 @@ ev_view_class_init (EvViewClass *class) widget_class->popup_menu = ev_view_popup_menu; widget_class->query_tooltip = ev_view_query_tooltip; widget_class->parent_set = ev_view_parent_set; + widget_class->hierarchy_changed = ev_view_hierarchy_changed; object_class->dispose = ev_view_dispose; -- cgit v1.2.1