summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libview/ev-view-private.h8
-rw-r--r--libview/ev-view.c72
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;