[evince/gestures: 2/2] ev-view: Add pan gesture to switch page



commit 996e57a8abc0f9cca2a1688752cd400bbddf6177
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue May 6 13:57:00 2014 +0200

    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.

 libview/ev-view-private.h |    8 +++++
 libview/ev-view.c         |   75 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+), 0 deletions(-)
---
diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h
index 82cc241..c005632 100644
--- a/libview/ev-view-private.h
+++ b/libview/ev-view-private.h
@@ -72,6 +72,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;
@@ -223,8 +229,10 @@ struct _EvView {
        guint    cursor_blink_time;
 
        /* Gestures */
+       GtkGesture *pan_gesture;
        GtkGesture *zoom_gesture;
        gdouble prev_zoom_scale;
+       EvPanAction pan_action;
 };
 
 struct _EvViewClass {
diff --git a/libview/ev-view.c b/libview/ev-view.c
index acb7a7e..a31b9e8 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -6446,6 +6446,80 @@ ev_view_screen_changed (GtkWidget *widget,
 }
 
 static void
+pan_gesture_pan_cb (GtkGesturePan   *gesture,
+                   GtkPanDirection  direction,
+                   gdouble          offset,
+                   EvView          *view)
+{
+       GtkAllocation allocation;
+       GtkWidget *parent;
+
+       parent = gtk_widget_get_parent (GTK_WIDGET (view));
+       g_assert (GTK_IS_SCROLLED_WINDOW (parent));
+
+       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 && GTK_IS_SCROLLED_WINDOW (parent) && !view->pan_gesture) {
+               view->pan_gesture =
+                       gtk_gesture_pan_new (parent, GTK_PAN_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_attach (view->pan_gesture, GTK_PHASE_CAPTURE);
+       } else if (!parent && view->pan_gesture) {
+               gtk_gesture_detach (view->pan_gesture);
+               g_clear_object (&view->pan_gesture);
+       }
+}
+
+static void
 add_move_binding_keypad (GtkBindingSet  *binding_set,
                         guint           keyval,
                         GdkModifierType modifiers,
@@ -6512,6 +6586,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->screen_changed = ev_view_screen_changed;
+       widget_class->hierarchy_changed = ev_view_hierarchy_changed;
 
        container_class->remove = ev_view_remove;
        container_class->forall = ev_view_forall;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]