diff options
-rw-r--r-- | libview/ev-view-private.h | 8 | ||||
-rw-r--r-- | libview/ev-view.c | 72 |
2 files changed, 80 insertions, 0 deletions
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 @@ -4757,6 +4757,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; |