[clutter] gesture-action: add _get_motion_delta()/_get_velocity()



commit 436ebb2716b24743b3873aa7b330073c48793b86
Author: Emanuele Aina <emanuele aina collabora com>
Date:   Sat Aug 25 16:04:24 2012 +0200

    gesture-action: add _get_motion_delta()/_get_velocity()
    
    Add some accessors to simplify common tasks for GestureAction users:
    
    â clutter_gesture_action_get_motion_delta() to get the delta
      on the X and Y axis in stage coordinates since the last motion
      event, and the scalar distance travelled;
    
    â clutter_gesture_action_get_velocity() to get an estimate of the
      speed of the last motion event along the X and Y axis and as a
      scalar value in pixels per millisecond.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=681648

 clutter/clutter-gesture-action.c           |  121 +++++++++++++++++++++++++++-
 clutter/clutter-gesture-action.h           |   10 +++
 clutter/clutter.symbols                    |    2 +
 doc/reference/clutter/clutter-sections.txt |    2 +
 4 files changed, 131 insertions(+), 4 deletions(-)
---
diff --git a/clutter/clutter-gesture-action.c b/clutter/clutter-gesture-action.c
index ace980b..5994107 100644
--- a/clutter/clutter-gesture-action.c
+++ b/clutter/clutter-gesture-action.c
@@ -62,7 +62,10 @@
 #include "clutter-marshal.h"
 #include "clutter-private.h"
 
+#include <math.h>
+
 #define MAX_GESTURE_POINTS (10)
+#define FLOAT_EPSILON   (1e-15)
 
 typedef struct
 {
@@ -70,7 +73,10 @@ typedef struct
   ClutterEventSequence *sequence;
 
   gfloat press_x, press_y;
+  gint64 last_motion_time;
   gfloat last_motion_x, last_motion_y;
+  gint64 last_delta_time;
+  gfloat last_delta_x, last_delta_y;
   gfloat release_x, release_y;
 } GesturePoint;
 
@@ -118,6 +124,10 @@ gesture_register_point (ClutterGestureAction *action, ClutterEvent *event)
   clutter_event_get_coords (event, &point->press_x, &point->press_y);
   point->last_motion_x = point->press_x;
   point->last_motion_y = point->press_y;
+  point->last_motion_time = clutter_event_get_time (event);
+
+  point->last_delta_x = point->last_delta_y = 0;
+  point->last_delta_time = 0;
 
   if (clutter_event_type (event) != CLUTTER_BUTTON_PRESS)
     point->sequence = clutter_event_get_event_sequence (event);
@@ -192,6 +202,8 @@ stage_captured_event_cb (ClutterActor       *stage,
   gint position;
   gboolean return_value;
   GesturePoint *point;
+  gfloat motion_x, motion_y;
+  gint64 time;
 
   if ((point = gesture_find_point (action, event, &position)) == NULL)
     return CLUTTER_EVENT_PROPAGATE;
@@ -218,8 +230,8 @@ stage_captured_event_cb (ClutterActor       *stage,
 
     case CLUTTER_TOUCH_UPDATE:
       clutter_event_get_coords (event,
-                                &point->last_motion_x,
-                                &point->last_motion_y);
+                                &motion_x,
+                                &motion_y);
 
       if (priv->points->len < priv->requested_nb_points)
         return CLUTTER_EVENT_PROPAGATE;
@@ -233,8 +245,8 @@ stage_captured_event_cb (ClutterActor       *stage,
                         "dnd-drag-threshold", &drag_threshold,
                         NULL);
 
-          if ((ABS (point->press_y - point->last_motion_y) >= drag_threshold) ||
-              (ABS (point->press_x - point->last_motion_x) >= drag_threshold))
+          if ((ABS (point->press_y - motion_y) >= drag_threshold) ||
+              (ABS (point->press_x - motion_x) >= drag_threshold))
             {
               priv->in_gesture = TRUE;
 
@@ -250,6 +262,15 @@ stage_captured_event_cb (ClutterActor       *stage,
             return CLUTTER_EVENT_PROPAGATE;
         }
 
+      point->last_delta_x = motion_x - point->last_motion_x;
+      point->last_delta_y = motion_y - point->last_motion_y;
+      point->last_motion_x = motion_x;
+      point->last_motion_y = motion_y;
+
+      time = clutter_event_get_time (event);
+      point->last_delta_time = time - point->last_motion_time;
+      point->last_motion_time = time;
+
       g_signal_emit (action, gesture_signals[GESTURE_PROGRESS], 0, actor,
                      &return_value);
       if (!return_value)
@@ -267,6 +288,12 @@ stage_captured_event_cb (ClutterActor       *stage,
         if (priv->in_gesture &&
             ((priv->points->len - 1) < priv->requested_nb_points))
           {
+            /* Treat the release event as the continuation of the last motion,
+             * in case the user keeps the pointer still for a while before
+             * releasing it. */
+            time = clutter_event_get_time (event);
+            point->last_delta_time += time - point->last_motion_time;
+
             priv->in_gesture = FALSE;
             g_signal_emit (action, gesture_signals[GESTURE_END], 0, actor);
           }
@@ -573,6 +600,49 @@ clutter_gesture_action_get_motion_coords (ClutterGestureAction *action,
 }
 
 /**
+ * clutter_gesture_action_get_motion_delta:
+ * @action: a #ClutterGestureAction
+ * @device: currently unused, set to 0
+ * @delta_x: (out) (allow-none): return location for the X axis
+ *   component of the incremental motion delta
+ * @delta_y: (out) (allow-none): return location for the Y axis
+ *   component of the incremental motion delta
+ *
+ * Retrieves the incremental delta since the last motion event
+ * during the dragging.
+ *
+ * Return value: the distance since last motion event
+ *
+ * Since: 1.12
+ */
+gfloat
+clutter_gesture_action_get_motion_delta (ClutterGestureAction *action,
+                                         guint                 device,
+                                         gfloat               *delta_x,
+                                         gfloat               *delta_y)
+{
+  gfloat d_x, d_y;
+
+  g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
+  g_return_val_if_fail (action->priv->points->len > device, 0);
+
+  d_x = g_array_index (action->priv->points,
+                       GesturePoint,
+                       device).last_delta_x;
+  d_y = g_array_index (action->priv->points,
+                       GesturePoint,
+                       device).last_delta_y;
+
+  if (delta_x)
+    *delta_x = d_x;
+
+  if (delta_y)
+    *delta_y = d_y;
+
+  return sqrt ((d_x * d_x) + (d_y * d_y));
+}
+
+/**
  * clutter_gesture_action_get_release_coords:
  * @action: a #ClutterGestureAction
  * @device: currently unused, set to 0
@@ -607,6 +677,49 @@ clutter_gesture_action_get_release_coords (ClutterGestureAction *action,
 }
 
 /**
+ * clutter_gesture_action_get_velocity:
+ * @action: a #ClutterGestureAction
+ * @device: currently unused, set to 0
+ * @velocity_x: (out) (allow-none): return location for the latest motion
+ *   event's X velocity
+ * @velocity_y: (out) (allow-none): return location for the latest motion
+ *   event's Y velocity
+ *
+ * Retrieves the velocity, in stage pixels per microseconds, of the
+ * latest motion event during the dragging
+ *
+ * Since: 1.12
+ */
+gfloat
+clutter_gesture_action_get_velocity (ClutterGestureAction *action,
+                                     guint                 device,
+                                     gfloat               *velocity_x,
+                                     gfloat               *velocity_y)
+{
+  gfloat d_x, d_y, distance, velocity;
+  gint64 d_t;
+
+  g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
+  g_return_val_if_fail (action->priv->points->len > device, 0);
+
+  distance = clutter_gesture_action_get_motion_delta (action, device,
+                                                      &d_x, &d_y);
+
+  d_t = g_array_index (action->priv->points,
+                       GesturePoint,
+                       device).last_delta_time;
+
+  if (velocity_x)
+    *velocity_x = d_t > FLOAT_EPSILON ? d_x / d_t : 0;
+
+  if (velocity_y)
+    *velocity_y = d_t > FLOAT_EPSILON ? d_y / d_t : 0;
+
+  velocity = d_t > FLOAT_EPSILON ? distance / d_t : 0;
+  return velocity;
+}
+
+/**
  * clutter_gesture_action_get_n_touch_points:
  * @action: a #ClutterGestureAction
  *
diff --git a/clutter/clutter-gesture-action.h b/clutter/clutter-gesture-action.h
index 3aade5b..7587bd0 100644
--- a/clutter/clutter-gesture-action.h
+++ b/clutter/clutter-gesture-action.h
@@ -113,10 +113,20 @@ void            clutter_gesture_action_get_motion_coords        (ClutterGestureA
                                                                  guint                 device,
                                                                  gfloat               *motion_x,
                                                                  gfloat               *motion_y);
+CLUTTER_AVAILABLE_IN_1_12
+gfloat          clutter_gesture_action_get_motion_delta         (ClutterGestureAction *action,
+                                                                 guint                 device,
+                                                                 gfloat               *delta_x,
+                                                                 gfloat               *delta_y);
 void            clutter_gesture_action_get_release_coords       (ClutterGestureAction *action,
                                                                  guint                 device,
                                                                  gfloat               *release_x,
                                                                  gfloat               *release_y);
+CLUTTER_AVAILABLE_IN_1_12
+gfloat          clutter_gesture_action_get_velocity             (ClutterGestureAction *action,
+                                                                 guint                 device,
+                                                                 gfloat               *velocity_x,
+                                                                 gfloat               *velocity_y);
 
 G_END_DECLS
 
diff --git a/clutter/clutter.symbols b/clutter/clutter.symbols
index 261ac83..9991579 100644
--- a/clutter/clutter.symbols
+++ b/clutter/clutter.symbols
@@ -734,10 +734,12 @@ clutter_geometry_get_type
 clutter_geometry_intersects
 clutter_geometry_union
 clutter_gesture_action_get_motion_coords
+clutter_gesture_action_get_motion_delta
 clutter_gesture_action_get_n_touch_points
 clutter_gesture_action_get_press_coords
 clutter_gesture_action_get_release_coords
 clutter_gesture_action_get_type
+clutter_gesture_action_get_velocity
 clutter_gesture_action_set_n_touch_points
 clutter_gesture_action_new
 clutter_get_accessibility_enabled
diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt
index 1b2a08d..72b7889 100644
--- a/doc/reference/clutter/clutter-sections.txt
+++ b/doc/reference/clutter/clutter-sections.txt
@@ -2941,7 +2941,9 @@ ClutterGestureActionClass
 clutter_gesture_action_new
 clutter_gesture_action_get_press_coords
 clutter_gesture_action_get_motion_coords
+clutter_gesture_action_get_motion_delta
 clutter_gesture_action_get_release_coords
+clutter_gesture_action_get_velocity
 clutter_gesture_action_get_n_touch_points
 clutter_gesture_action_set_n_touch_points
 <SUBSECTION Standard>



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