[clutter/clutter-1.18] GestureActions: Add per-action thresholds



commit 32b3d27bb91fd305e0d095910a75295e455edd8c
Author: Bastien Nocera <hadess hadess net>
Date:   Wed Feb 12 17:41:03 2014 +0100

    GestureActions: Add per-action thresholds
    
    Instead of relying on the dnd drag threshold, add per-action
    horizontal and vertical thresholds. Use them in the swipe action
    as well.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=724242

 clutter/clutter-gesture-action.c |  163 ++++++++++++++++++++++++++++++++++---
 clutter/clutter-gesture-action.h |   10 +++
 clutter/clutter-swipe-action.c   |   24 +++---
 3 files changed, 172 insertions(+), 25 deletions(-)
---
diff --git a/clutter/clutter-gesture-action.c b/clutter/clutter-gesture-action.c
index 3e8b50c..35019a7 100644
--- a/clutter/clutter-gesture-action.c
+++ b/clutter/clutter-gesture-action.c
@@ -124,6 +124,7 @@ struct _ClutterGestureActionPrivate
   gulong stage_capture_id;
 
   ClutterGestureTriggerEdge edge;
+  float distance_x, distance_y;
 
   guint in_gesture : 1;
 };
@@ -134,6 +135,8 @@ enum
 
   PROP_N_TOUCH_POINTS,
   PROP_THRESHOLD_TRIGGER_EDGE,
+  PROP_THRESHOLD_TRIGGER_DISTANCE_X,
+  PROP_THRESHOLD_TRIGGER_DISTANCE_Y,
 
   PROP_LAST
 };
@@ -265,7 +268,7 @@ gesture_update_release_point (GesturePoint *point,
 }
 
 static gint
-gesture_get_threshold (void)
+gesture_get_default_threshold (void)
 {
   gint threshold;
   ClutterSettings *settings = clutter_settings_get_default ();
@@ -274,15 +277,18 @@ gesture_get_threshold (void)
 }
 
 static gboolean
-gesture_point_pass_threshold (GesturePoint *point, ClutterEvent *event)
+gesture_point_pass_threshold (ClutterGestureAction *action,
+                              GesturePoint         *point,
+                              ClutterEvent         *event)
 {
-  gint drag_threshold = gesture_get_threshold ();
+  float threshold_x, threshold_y;
   gfloat motion_x, motion_y;
 
   clutter_event_get_coords (event, &motion_x, &motion_y);
+  clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
 
-  if ((fabsf (point->press_y - motion_y) < drag_threshold) &&
-      (fabsf (point->press_x - motion_x) < drag_threshold))
+  if ((fabsf (point->press_y - motion_y) < threshold_y) &&
+      (fabsf (point->press_x - motion_x) < threshold_x))
     return TRUE;
   return FALSE;
 }
@@ -352,7 +358,8 @@ stage_captured_event_cb (ClutterActor       *stage,
 {
   ClutterGestureActionPrivate *priv = action->priv;
   ClutterActor *actor;
-  gint position, drag_threshold;
+  gint position;
+  float threshold_x, threshold_y;
   gboolean return_value;
   GesturePoint *point;
 
@@ -391,7 +398,7 @@ stage_captured_event_cb (ClutterActor       *stage,
           /* Wait until the drag threshold has been exceeded
            * before starting _TRIGGER_EDGE_AFTER gestures. */
           if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER &&
-              gesture_point_pass_threshold (point, event))
+              gesture_point_pass_threshold (action, point, event))
             {
               gesture_update_motion_point (point, event);
               return CLUTTER_EVENT_PROPAGATE;
@@ -420,10 +427,10 @@ stage_captured_event_cb (ClutterActor       *stage,
 
       /* Check if a _TRIGGER_EDGE_BEFORE gesture needs to be cancelled because
        * the drag threshold has been exceeded. */
-      drag_threshold = gesture_get_threshold ();
+      clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
       if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE &&
-          ((fabsf (point->press_y - point->last_motion_y) > drag_threshold) ||
-           (fabsf (point->press_x - point->last_motion_x) > drag_threshold)))
+          ((fabsf (point->press_y - point->last_motion_y) > threshold_y) ||
+           (fabsf (point->press_x - point->last_motion_x) > threshold_x)))
         {
           cancel_gesture (action);
           return CLUTTER_EVENT_PROPAGATE;
@@ -571,6 +578,14 @@ clutter_gesture_action_set_property (GObject      *gobject,
       clutter_gesture_action_set_threshold_trigger_edge (self, g_value_get_enum (value));
       break;
 
+    case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
+      clutter_gesture_action_set_threshold_trigger_distance (self, g_value_get_float (value), 
self->priv->distance_y);
+      break;
+
+    case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
+      clutter_gesture_action_set_threshold_trigger_distance (self, self->priv->distance_x, g_value_get_float 
(value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
       break;
@@ -595,6 +610,20 @@ clutter_gesture_action_get_property (GObject    *gobject,
       g_value_set_enum (value, self->priv->edge);
       break;
 
+    case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
+      if (self->priv->distance_x > 0.0)
+        g_value_set_float (value, self->priv->distance_x);
+      else
+        g_value_set_float (value, gesture_get_default_threshold ());
+      break;
+
+    case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
+      if (self->priv->distance_y > 0.0)
+        g_value_set_float (value, self->priv->distance_y);
+      else
+        g_value_set_float (value, gesture_get_default_threshold ());
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
       break;
@@ -659,6 +688,44 @@ clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
                        CLUTTER_PARAM_READWRITE |
                        G_PARAM_CONSTRUCT_ONLY);
 
+  /**
+   * ClutterGestureAction:threshold-trigger-distance-x:
+   *
+   * The horizontal trigger distance to be used by the action to either
+   * emit the #ClutterGestureAction::gesture-begin signal or to emit
+   * the #ClutterGestureAction::gesture-cancel signal.
+   *
+   * A negative value will be interpreted as the default drag threshold.
+   *
+   * Since: 1.18
+   */
+  gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X] =
+    g_param_spec_float ("threshold-trigger-distance-x",
+                        P_("Threshold Trigger Horizontal Distance"),
+                        P_("The horizontal trigger distance used by the action"),
+                        -1.0, G_MAXFLOAT, -1.0,
+                        CLUTTER_PARAM_READWRITE |
+                        G_PARAM_CONSTRUCT_ONLY);
+
+  /**
+   * ClutterGestureAction:threshold-trigger-distance-y:
+   *
+   * The vertical trigger distance to be used by the action to either
+   * emit the #ClutterGestureAction::gesture-begin signal or to emit
+   * the #ClutterGestureAction::gesture-cancel signal.
+   *
+   * A negative value will be interpreted as the default drag threshold.
+   *
+   * Since: 1.18
+   */
+  gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y] =
+    g_param_spec_float ("threshold-trigger-distance-y",
+                        P_("Threshold Trigger Vertical Distance"),
+                        P_("The vertical trigger distance used by the action"),
+                        -1.0, G_MAXFLOAT, -1.0,
+                        CLUTTER_PARAM_READWRITE |
+                        G_PARAM_CONSTRUCT_ONLY);
+
   g_object_class_install_properties (gobject_class,
                                      PROP_LAST,
                                      gesture_props);
@@ -1030,16 +1097,17 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
         {
           ClutterActor *actor =
             clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
-          gint i, drag_threshold;
+          gint i;
+          float threshold_x, threshold_y;
 
-          drag_threshold = gesture_get_threshold ();
+          clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y);
 
           for (i = 0; i < priv->points->len; i++)
             {
               GesturePoint *point = &g_array_index (priv->points, GesturePoint, i);
 
-              if ((ABS (point->press_y - point->last_motion_y) >= drag_threshold) ||
-                  (ABS (point->press_x - point->last_motion_x) >= drag_threshold))
+              if ((fabsf (point->press_y - point->last_motion_y) >= threshold_y) ||
+                  (fabsf (point->press_x - point->last_motion_x) >= threshold_x))
                 {
                   begin_gesture (action, actor);
                   break;
@@ -1200,3 +1268,70 @@ clutter_gesture_action_get_threshold_trigger_egde (ClutterGestureAction *action)
 
   return action->priv->edge;
 }
+
+/**
+ * clutter_gesture_action_set_threshold_trigger_distance:
+ * @action: a #ClutterGestureAction
+ * @x: the distance on the horizontal axis
+ * @y: the distance on the vertical axis
+ *
+ * Sets the threshold trigger distance for the gesture drag threshold, if any.
+ *
+ * This function should only be called by sub-classes of
+ * #ClutterGestureAction during their construction phase.
+ *
+ * Since: 1.18
+ */
+void
+clutter_gesture_action_set_threshold_trigger_distance (ClutterGestureAction      *action,
+                                                       float                      x,
+                                                       float                      y)
+{
+  g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
+
+  if (fabsf (x - action->priv->distance_x) > FLOAT_EPSILON)
+    {
+      action->priv->distance_x = x;
+      g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X]);
+    }
+
+  if (fabsf (y - action->priv->distance_y) > FLOAT_EPSILON)
+    {
+      action->priv->distance_y = y;
+      g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y]);
+    }
+}
+
+/**
+ * clutter_gesture_action_get_threshold_trigger_distance:
+ * @action: a #ClutterGestureAction
+ * @x: (out) (allow-none): The return location for the horizontal distance, or %NULL
+ * @y: (out) (allow-none): The return location for the vertical distance, or %NULL
+ *
+ * Retrieves the threshold trigger distance of the gesture @action,
+ * as set using clutter_gesture_action_set_threshold_trigger_distance().
+ *
+ * Since: 1.18
+ */
+void
+clutter_gesture_action_get_threshold_trigger_distance (ClutterGestureAction *action,
+                                                       float                *x,
+                                                       float                *y)
+{
+  g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
+
+  if (x != NULL)
+    {
+      if (action->priv->distance_x > 0.0)
+        *x = action->priv->distance_x;
+      else
+        *x = gesture_get_default_threshold ();
+    }
+  if (y != NULL)
+    {
+      if (action->priv->distance_y > 0.0)
+        *y = action->priv->distance_y;
+      else
+        *y = gesture_get_default_threshold ();
+    }
+}
diff --git a/clutter/clutter-gesture-action.h b/clutter/clutter-gesture-action.h
index 9660c3e..3f4691e 100644
--- a/clutter/clutter-gesture-action.h
+++ b/clutter/clutter-gesture-action.h
@@ -155,6 +155,16 @@ void                            clutter_gesture_action_set_threshold_trigger_edg
 CLUTTER_AVAILABLE_IN_1_18
 ClutterGestureTriggerEdge       clutter_gesture_action_get_threshold_trigger_egde       
(ClutterGestureAction      *action);
 
+CLUTTER_AVAILABLE_IN_1_18
+void                            clutter_gesture_action_set_threshold_trigger_distance   
(ClutterGestureAction      *action,
+                                                                                         float               
       x,
+                                                                                         float               
       y);
+
+CLUTTER_AVAILABLE_IN_1_18
+void                            clutter_gesture_action_get_threshold_trigger_distance   
(ClutterGestureAction *action,
+                                                                                         float               
 *x,
+                                                                                         float               
 *y);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_GESTURE_ACTION_H__ */
diff --git a/clutter/clutter-swipe-action.c b/clutter/clutter-swipe-action.c
index cac6199..452a5a0 100644
--- a/clutter/clutter-swipe-action.c
+++ b/clutter/clutter-swipe-action.c
@@ -54,7 +54,7 @@ struct _ClutterSwipeActionPrivate
   ClutterSwipeDirection h_direction;
   ClutterSwipeDirection v_direction;
 
-  int threshold;
+  float distance_x, distance_y;
 };
 
 enum
@@ -74,13 +74,15 @@ gesture_begin (ClutterGestureAction  *action,
                ClutterActor          *actor)
 {
   ClutterSwipeActionPrivate *priv = CLUTTER_SWIPE_ACTION (action)->priv;
-  ClutterSettings *settings = clutter_settings_get_default ();
 
   /* reset the state at the beginning of a new gesture */
   priv->h_direction = 0;
   priv->v_direction = 0;
 
-  g_object_get (settings, "dnd-drag-threshold", &priv->threshold, NULL);
+  g_object_get (action,
+                "threshold-trigger-distance-x", &priv->distance_x,
+                "threshold-trigger-distance-y", &priv->distance_y,
+                NULL);
 
   return TRUE;
 }
@@ -108,14 +110,14 @@ gesture_progress (ClutterGestureAction *action,
   delta_x = press_x - motion_x;
   delta_y = press_y - motion_y;
 
-  if (delta_x >= priv->threshold)
+  if (delta_x >= priv->distance_x)
     h_direction = CLUTTER_SWIPE_DIRECTION_RIGHT;
-  else if (delta_x < -priv->threshold)
+  else if (delta_x < -priv->distance_x)
     h_direction = CLUTTER_SWIPE_DIRECTION_LEFT;
 
-  if (delta_y >= priv->threshold)
+  if (delta_y >= priv->distance_y)
     v_direction = CLUTTER_SWIPE_DIRECTION_DOWN;
-  else if (delta_y < -priv->threshold)
+  else if (delta_y < -priv->distance_y)
     v_direction = CLUTTER_SWIPE_DIRECTION_UP;
 
   /* cancel gesture on direction reversal */
@@ -152,14 +154,14 @@ gesture_end (ClutterGestureAction *action,
                                              0,
                                              &release_x, &release_y);
 
-  if (release_x - press_x > priv->threshold)
+  if (release_x - press_x > priv->distance_y)
     direction |= CLUTTER_SWIPE_DIRECTION_RIGHT;
-  else if (press_x - release_x > priv->threshold)
+  else if (press_x - release_x > priv->distance_x)
     direction |= CLUTTER_SWIPE_DIRECTION_LEFT;
 
-  if (release_y - press_y > priv->threshold)
+  if (release_y - press_y > priv->distance_y)
     direction |= CLUTTER_SWIPE_DIRECTION_DOWN;
-  else if (press_y - release_y > priv->threshold)
+  else if (press_y - release_y > priv->distance_y)
     direction |= CLUTTER_SWIPE_DIRECTION_UP;
 
   /* XXX:2.0 remove */


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