efl/gesture: port 'rotate' gesture from elm to new gesture framework
authorMike Blumenkrantz <zmike@samsung.com>
Wed, 19 Feb 2020 15:24:04 +0000 (10:24 -0500)
committerJongmin Lee <jm105.lee@samsung.com>
Tue, 3 Mar 2020 21:16:58 +0000 (06:16 +0900)
this is a 1:1 port with minimal changes other than what's necessary to
integrate into the new framework

Differential Revision: https://phab.enlightenment.org/D11383

src/bin/elementary/test_gesture_framework.c
src/lib/evas/Efl_Canvas.h
src/lib/evas/Evas_Eo.h
src/lib/evas/gesture/efl_canvas_gesture_events.eo
src/lib/evas/gesture/efl_canvas_gesture_manager.c
src/lib/evas/gesture/efl_canvas_gesture_private.h
src/lib/evas/gesture/efl_canvas_gesture_recognizer_rotate.c [new file with mode: 0644]
src/lib/evas/gesture/efl_canvas_gesture_recognizer_rotate.eo [new file with mode: 0644]
src/lib/evas/gesture/efl_canvas_gesture_rotate.c [new file with mode: 0644]
src/lib/evas/gesture/efl_canvas_gesture_rotate.eo [new file with mode: 0644]
src/lib/evas/gesture/meson.build

index ff40711..4675604 100644 (file)
@@ -224,6 +224,33 @@ finger_flick_abort(void *data , Efl_Canvas_Gesture *tap EINA_UNUSED)
 }
 
 static void
+finger_rotate_start(void *data , Efl_Canvas_Gesture *tap)
+{
+   Eina_Position2D pos = efl_gesture_hotspot_get(tap);
+
+   _color_and_icon_set(data, ROTATE_NAME, 1, MAX_TAP, START_COLOR);
+   printf("Rotate Gesture started x,y=<%d,%d> \n", pos.x, pos.y);
+}
+
+static void
+finger_rotate_end(void *data , Efl_Canvas_Gesture *tap)
+{
+   Eina_Position2D pos = efl_gesture_hotspot_get(tap);
+   double angle = efl_gesture_rotate_angle_get(tap);
+   double radius = efl_gesture_rotate_radius_get(tap);
+
+   _color_and_icon_set(data, ROTATE_NAME, 1, MAX_TAP, END_COLOR);
+   printf("Rotate Gesture ended x,y=<%d,%d> angle=<%g> radius=<%f>\n", pos.x, pos.y, angle, radius);
+}
+
+static void
+finger_rotate_abort(void *data , Efl_Canvas_Gesture *tap EINA_UNUSED)
+{
+   _color_and_icon_set(data, ROTATE_NAME, 1, MAX_TAP, ABORT_COLOR);
+   printf("Rotate Aborted\n");
+}
+
+static void
 finger_zoom_start(void *data , Efl_Canvas_Gesture *tap)
 {
    Eina_Position2D pos = efl_gesture_hotspot_get(tap);
@@ -432,6 +459,26 @@ flick_gesture_cb(void *data , const Efl_Event *ev)
 }
 
 static void
+rotate_gesture_cb(void *data , const Efl_Event *ev)
+{
+   Efl_Canvas_Gesture *g = ev->info;
+   switch(efl_gesture_state_get(g))
+   {
+      case EFL_GESTURE_STATE_STARTED:
+         finger_rotate_start(data, g);
+         break;
+      case EFL_GESTURE_STATE_CANCELED:
+         finger_rotate_abort(data, g);
+         break;
+      case EFL_GESTURE_STATE_FINISHED:
+         finger_rotate_end(data, g);
+         break;
+      default:
+         break;
+   }
+}
+
+static void
 zoom_gesture_cb(void *data , const Efl_Event *ev)
 {
    Efl_Canvas_Gesture *g = ev->info;
@@ -741,6 +788,7 @@ test_gesture_framework(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
    efl_event_callback_add(target, EFL_EVENT_GESTURE_TRIPLE_TAP, triple_tap_gesture_cb, infra);
    efl_event_callback_add(target, EFL_EVENT_GESTURE_MOMENTUM, momentum_gesture_cb, infra);
    efl_event_callback_add(target, EFL_EVENT_GESTURE_FLICK, flick_gesture_cb, infra);
+   efl_event_callback_add(target, EFL_EVENT_GESTURE_ROTATE, rotate_gesture_cb, infra);
    efl_event_callback_add(target, EFL_EVENT_GESTURE_ZOOM, zoom_gesture_cb, infra);
 
    /* Update color state 20 times a second */
index f457acc..55534b1 100644 (file)
@@ -117,10 +117,12 @@ extern "C" {
 #include <gesture/efl_canvas_gesture_recognizer_momentum.eo.h>
 #include <gesture/efl_canvas_gesture_recognizer_tap.eo.h>
 #include <gesture/efl_canvas_gesture_recognizer_triple_tap.eo.h>
+#include <gesture/efl_canvas_gesture_recognizer_rotate.eo.h>
 #include <gesture/efl_canvas_gesture_recognizer_zoom.eo.h>
 #include <gesture/efl_canvas_gesture_recognizer_custom.eo.h>
 #include <gesture/efl_canvas_gesture_tap.eo.h>
 #include <gesture/efl_canvas_gesture_triple_tap.eo.h>
+#include <gesture/efl_canvas_gesture_rotate.eo.h>
 #include <gesture/efl_canvas_gesture_zoom.eo.h>
 #include <gesture/efl_canvas_gesture_custom.eo.h>
 #include <gesture/efl_canvas_gesture_events.eo.h>
index 7d25c38..046f2c5 100644 (file)
@@ -91,6 +91,7 @@ struct _Efl_Canvas_Object_Animation_Event
 #include "gesture/efl_canvas_gesture_triple_tap.eo.h"
 #include "gesture/efl_canvas_gesture_momentum.eo.h"
 #include "gesture/efl_canvas_gesture_flick.eo.h"
+#include "gesture/efl_canvas_gesture_rotate.eo.h"
 #include "gesture/efl_canvas_gesture_zoom.eo.h"
 #include "gesture/efl_canvas_gesture_custom.eo.h"
 #include "gesture/efl_canvas_gesture_recognizer.eo.h"
@@ -100,6 +101,7 @@ struct _Efl_Canvas_Object_Animation_Event
 #include "gesture/efl_canvas_gesture_recognizer_triple_tap.eo.h"
 #include "gesture/efl_canvas_gesture_recognizer_momentum.eo.h"
 #include "gesture/efl_canvas_gesture_recognizer_flick.eo.h"
+#include "gesture/efl_canvas_gesture_recognizer_rotate.eo.h"
 #include "gesture/efl_canvas_gesture_recognizer_zoom.eo.h"
 #include "gesture/efl_canvas_gesture_recognizer_custom.eo.h"
 #include "gesture/efl_canvas_gesture_manager.eo.h"
index 01c50a7..6d95e68 100644 (file)
@@ -38,6 +38,11 @@ interface @beta Efl.Canvas.Gesture_Events
         holding down a mouse button) with the release occurring before slowing down.
       ]]
 
+      gesture,rotate: Efl.Canvas.Gesture_Rotate; [[Emitted when a Rotate gesture has been detected.
+        A Rotate gesture consists of two fingers touching the screen and performing a motion such that
+        one finger rotates around the other.
+        This gesture cannot be performed with a mouse as it requires more than one pointer.
+      ]]
       gesture,zoom: Efl.Canvas.Gesture_Zoom; [[Emitted when a Zoom gesture has been detected.
         A Zoom gesture consists of two fingers touching the screen and separating ("zoom in") or
         getting closer ("zoom out" or "pinch").
index 5f86e41..e33e3f2 100644 (file)
@@ -53,6 +53,8 @@ _gesture_recognizer_event_type_get(const Efl_Canvas_Gesture_Recognizer *recogniz
      return EFL_EVENT_GESTURE_MOMENTUM;
    if (type == EFL_CANVAS_GESTURE_FLICK_CLASS)
      return EFL_EVENT_GESTURE_FLICK;
+   if (type == EFL_CANVAS_GESTURE_ROTATE_CLASS)
+     return EFL_EVENT_GESTURE_ROTATE;
    if (type == EFL_CANVAS_GESTURE_ZOOM_CLASS)
      return EFL_EVENT_GESTURE_ZOOM;
    return EFL_EVENT_GESTURE_CUSTOM;
@@ -85,6 +87,7 @@ _update_finger_sizes(Efl_Canvas_Gesture_Manager_Data *pd, int finger_size)
    Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *ttd;
    Efl_Canvas_Gesture_Recognizer_Long_Press_Data *ltd;
    Efl_Canvas_Gesture_Recognizer_Flick_Data *fd;
+   Efl_Canvas_Gesture_Recognizer_Rotate_Data *rd;
    Efl_Canvas_Gesture_Recognizer_Zoom_Data *zd;
    const Efl_Event_Description *type;
 
@@ -113,6 +116,11 @@ _update_finger_sizes(Efl_Canvas_Gesture_Manager_Data *pd, int finger_size)
    fd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS);
    fd->finger_size = finger_size;
 
+   type = EFL_EVENT_GESTURE_ROTATE;
+   r = eina_hash_find(pd->m_recognizers, &type);
+   rd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_ROTATE_CLASS);
+   rd->finger_size = finger_size;
+
    type = EFL_EVENT_GESTURE_ZOOM;
    r = eina_hash_find(pd->m_recognizers, &type);
    zd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS);
@@ -152,6 +160,7 @@ _efl_canvas_gesture_manager_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_M
    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS, obj));
    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_MOMENTUM_CLASS, obj));
    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS, obj));
+   efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_ROTATE_CLASS, obj));
    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS, obj));
    _update_finger_sizes(pd, EFL_GESTURE_RECOGNIZER_TYPE_TAP_FINGER_SIZE);
 
index fe8de41..7b9b855 100644 (file)
@@ -26,12 +26,14 @@ typedef struct _Efl_Canvas_Gesture_Recognizer_Double_Tap_Data  Efl_Canvas_Gestur
 typedef struct _Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data  Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data;
 typedef struct _Efl_Canvas_Gesture_Recognizer_Momentum_Data    Efl_Canvas_Gesture_Recognizer_Momentum_Data;
 typedef struct _Efl_Canvas_Gesture_Recognizer_Flick_Data       Efl_Canvas_Gesture_Recognizer_Flick_Data;
+typedef struct _Efl_Canvas_Gesture_Recognizer_Rotate_Data        Efl_Canvas_Gesture_Recognizer_Rotate_Data;
 typedef struct _Efl_Canvas_Gesture_Recognizer_Zoom_Data        Efl_Canvas_Gesture_Recognizer_Zoom_Data;
 typedef struct _Efl_Canvas_Gesture_Recognizer_Custom_Data        Efl_Canvas_Gesture_Recognizer_Custom_Data;
 typedef struct _Efl_Canvas_Gesture_Data                        Efl_Canvas_Gesture_Data;
 typedef struct _Efl_Canvas_Gesture_Momentum_Data               Efl_Canvas_Gesture_Momentum_Data;
 typedef struct _Efl_Canvas_Gesture_Flick_Data                  Efl_Canvas_Gesture_Flick_Data;
 typedef struct _Efl_Canvas_Gesture_Zoom_Data                   Efl_Canvas_Gesture_Zoom_Data;
+typedef struct _Efl_Canvas_Gesture_Rotate_Data                   Efl_Canvas_Gesture_Rotate_Data;
 typedef struct _Efl_Canvas_Gesture_Custom_Data                 Efl_Canvas_Gesture_Custom_Data;
 
 typedef struct _Efl_Canvas_Gesture_Touch_Data
@@ -114,6 +116,24 @@ struct _Efl_Canvas_Gesture_Recognizer_Flick_Data
    Eina_Bool                       touched;
 };
 
+struct _Efl_Canvas_Gesture_Recognizer_Rotate_Data
+{
+   Efl_Gesture_Touch_Point_Data                    rotate_st;
+   Efl_Gesture_Touch_Point_Data                    rotate_st1;
+
+   Efl_Gesture_Touch_Point_Data                    rotate_mv;
+   Efl_Gesture_Touch_Point_Data                    rotate_mv1;
+   double                  rotate_step;
+   double     base_angle; /**< Holds start-angle */
+   double                  prev_momentum; /* Snapshot of momentum 0.01
+                                           * sec ago */
+   double                  accum_momentum;
+   double                  rotate_angular_tolerance;
+   double                  next_step;
+   unsigned int            prev_momentum_tm; /* timestamp of prev_momentum */
+   int                            finger_size;
+};
+
 struct _Efl_Canvas_Gesture_Recognizer_Zoom_Data
 {
    Efl_Gesture_Touch_Point_Data                    zoom_st;
@@ -159,6 +179,14 @@ struct _Efl_Canvas_Gesture_Flick_Data
    int id;
 };
 
+struct _Efl_Canvas_Gesture_Rotate_Data
+{
+   //Evas_Coord x, y; /**< Holds rotate center point reported to user      */
+   double     angle; /**< Rotation value: 0.0 means no rotation         */
+   double     momentum; /**< Rotation momentum: rotation done per second (NOT YET SUPPORTED) */
+   Evas_Coord radius; /**< Holds radius between fingers reported to user */
+};
+
 struct _Efl_Canvas_Gesture_Zoom_Data
 {
    double                          radius;
diff --git a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_rotate.c b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_rotate.c
new file mode 100644 (file)
index 0000000..97fa907
--- /dev/null
@@ -0,0 +1,269 @@
+#include "efl_canvas_gesture_private.h"
+
+#define NEGATIVE_ANGLE   (-1.0) /* Magic number */
+
+#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_ROTATE_CLASS
+
+static void
+_reset_recognizer(Efl_Canvas_Gesture_Recognizer_Rotate_Data *pd)
+{
+   memset(&pd->rotate_st, 0, sizeof(Efl_Gesture_Touch_Point_Data));
+   memset(&pd->rotate_st1, 0, sizeof(Efl_Gesture_Touch_Point_Data));
+   memset(&pd->rotate_mv, 0, sizeof(Efl_Gesture_Touch_Point_Data));
+   memset(&pd->rotate_mv1, 0, sizeof(Efl_Gesture_Touch_Point_Data));
+   pd->prev_momentum = 0;
+   pd->base_angle = 0;
+   pd->next_step = pd->accum_momentum = 0;
+}
+
+#define memset do not use memset to reset rotate data, use _reset_recognizer
+
+
+static void
+_rotate_properties_get(Efl_Canvas_Gesture_Recognizer_Rotate_Data *pd,
+                       Efl_Canvas_Gesture_Rotate_Data *gd,
+                       Evas_Coord xx1,
+                       Evas_Coord yy1,
+                       Evas_Coord xx2,
+                       Evas_Coord yy2,
+                       double *angle, Eina_Bool started)
+{
+   /* FIXME: Fix momentum computation, it's wrong */
+   double prev_angle = *angle;
+   int x, y;
+   gd->radius = _finger_gap_length_get(xx1, yy1, xx2, yy2, &x, &y) / 2;
+
+   *angle = _angle_get(xx1, yy1, xx2, yy2);
+
+   if (!started) /* Fingers are moving, compute momentum */
+     {
+        unsigned int tm_start =
+          (pd->rotate_st.cur.timestamp > pd->rotate_st1.cur.timestamp)
+          ?  pd->rotate_st.cur.timestamp : pd->rotate_st1.cur.timestamp;
+        unsigned int tm_end =
+          (pd->rotate_mv.cur.timestamp > pd->rotate_mv1.cur.timestamp)
+          ? pd->rotate_mv.cur.timestamp : pd->rotate_mv1.cur.timestamp;
+
+        unsigned int tm_total = tm_end - tm_start;
+        if (tm_total) /* Momentum computed as:
+                         accumulated rotation angle (deg) divided by time */
+          {
+             double m = 0;
+             if (((prev_angle < 90) && ((*angle) > 270)) ||
+                 /* We circle passing ZERO point */
+                 ((prev_angle > 270) && ((*angle) < 90)))
+               {
+                  prev_angle = (*angle);
+               }
+             else m = prev_angle - (*angle);
+
+             pd->accum_momentum += m;
+
+             if ((tm_end - pd->prev_momentum_tm) < 100)
+               pd->prev_momentum += m;
+             else
+               {
+                  if (fabs(pd->prev_momentum) < 0.002)
+                    pd->accum_momentum = 0.0;  /* reset momentum */
+
+                  pd->prev_momentum = 0.0; /* Start again    */
+               }
+
+             pd->prev_momentum_tm = tm_end;
+             gd->momentum = (pd->accum_momentum * 1000) / tm_total;
+          }
+     }
+   else
+     gd->momentum = 0;
+}
+
+static Eina_Bool
+_on_rotation_broke_tolerance(Efl_Canvas_Gesture_Recognizer_Rotate_Data *pd, Efl_Canvas_Gesture_Rotate_Data *gd)
+{
+   if (pd->base_angle < 0)
+     return EINA_FALSE;  /* Angle has to be computed first */
+
+   if (pd->rotate_angular_tolerance < 0)
+     return EINA_TRUE;
+
+   double low = pd->base_angle - pd->rotate_angular_tolerance;
+   double high = pd->base_angle + pd->rotate_angular_tolerance;
+   double t = gd->angle;
+
+   if (low < 0)
+     {
+        low += 180;
+        high += 180;
+
+        if (t < 180)
+          t += 180;
+        else
+          t -= 180;
+     }
+
+   if (high > 360)
+     {
+        low -= 180;
+        high -= 180;
+
+        if (t < 180)
+          t += 180;
+        else
+          t -= 180;
+     }
+
+   if ((t < low) || (t > high)) /* This marks that rotation action has
+                                 * started */
+     {
+        pd->rotate_angular_tolerance = NEGATIVE_ANGLE;
+        pd->base_angle = gd->angle; /* Avoid jump in angle value */
+        return EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+EOLIAN static const Efl_Class *
+_efl_canvas_gesture_recognizer_rotate_efl_canvas_gesture_recognizer_type_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Rotate_Data *pd EINA_UNUSED)
+{
+   return EFL_CANVAS_GESTURE_ROTATE_CLASS;
+}
+
+EOLIAN static Efl_Canvas_Gesture_Recognizer_Result
+_efl_canvas_gesture_recognizer_rotate_efl_canvas_gesture_recognizer_recognize(Eo *obj,
+                                                                            Efl_Canvas_Gesture_Recognizer_Rotate_Data *pd,
+                                                                            Efl_Canvas_Gesture *gesture,
+                                                                            Efl_Object *watched,
+                                                                            Efl_Canvas_Gesture_Touch *event)
+{
+   Eina_Value *val;
+   unsigned char glayer_continues_enable;
+   Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
+   Efl_Canvas_Gesture_Rotate_Data *gd = efl_data_scope_get(gesture, EFL_CANVAS_GESTURE_ROTATE_CLASS);
+   Efl_Canvas_Gesture_Touch_Data *td = efl_data_scope_get(event, EFL_CANVAS_GESTURE_TOUCH_CLASS);
+   Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
+   const Efl_Gesture_Touch_Point_Data *p1 = efl_gesture_touch_data_get(event, 0);
+   const Efl_Gesture_Touch_Point_Data *p2 = efl_gesture_touch_data_get(event, 1);
+
+   //FIXME: Wheel rotate test first here.
+
+   val = _recognizer_config_get(obj, "glayer_continues_enable");
+   if (val) eina_value_get(val, &glayer_continues_enable);
+   else glayer_continues_enable = 1;
+
+   rd->continues = EINA_TRUE;
+
+   switch (efl_gesture_touch_state_get(event))
+     {
+      case EFL_GESTURE_TOUCH_STATE_UPDATE:
+      {
+         if ((!glayer_continues_enable) && (!pd->rotate_st.cur.timestamp))
+           {
+              return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+           }
+         EINA_FALLTHROUGH;
+      }
+
+      case EFL_GESTURE_TOUCH_STATE_BEGIN:
+      {
+         if (td->touch_down > 2)
+           {
+              _reset_recognizer(pd);
+              if (efl_gesture_state_get(gesture) == EFL_GESTURE_STATE_CANCELED)
+                return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+              return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
+           }
+         if (td->touch_down == 1)
+           {
+              return EFL_GESTURE_RECOGNIZER_RESULT_MAYBE;
+           }
+
+         if (!pd->rotate_st.cur.timestamp)   /* Now scan touched-devices list
+                                            * and find other finger */
+           {
+              if (!_event_multi_touch_get(event))
+                return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+              pd->base_angle = NEGATIVE_ANGLE;
+              val = _recognizer_config_get(obj, "glayer_rotate_angular_tolerance");
+              if (val) eina_value_get(val, &pd->rotate_angular_tolerance);
+              else pd->rotate_angular_tolerance = 2.0;
+
+              memcpy(&pd->rotate_st, p2, sizeof(Efl_Gesture_Touch_Point_Data));
+              memcpy(&pd->rotate_st1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
+
+              memcpy(&pd->rotate_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
+              memcpy(&pd->rotate_mv1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
+
+              _rotate_properties_get(pd, gd,
+                                     pd->rotate_st.cur.pos.x, pd->rotate_st.cur.pos.y,
+                                     pd->rotate_st1.cur.pos.x, pd->rotate_st1.cur.pos.y,
+                                     &pd->base_angle, EINA_TRUE);
+              if ((efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_STARTED) &&
+                  (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_UPDATED))
+                return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
+
+              return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
+           }
+
+         if (p2->id == pd->rotate_mv.id)
+           memcpy(&pd->rotate_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
+         else if (p2->id == pd->rotate_mv1.id)
+           memcpy(&pd->rotate_mv1, p2, sizeof(Efl_Gesture_Touch_Point_Data));
+
+         _rotate_properties_get(pd, gd,
+                                pd->rotate_mv.cur.pos.x, pd->rotate_mv.cur.pos.y,
+                                pd->rotate_mv1.cur.pos.x, pd->rotate_mv1.cur.pos.y,
+                                &gd->angle, EINA_FALSE);
+
+        if (_on_rotation_broke_tolerance(pd, gd)) /* Rotation broke
+                                               * tolerance, report
+                                               * move */
+           {
+              double d = gd->angle - pd->next_step;
+
+              if (d < 0.0) d = (-d);
+
+              if (d >= pd->rotate_step)
+                {
+                   pd->next_step = gd->angle;
+
+                   return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
+                }
+           }
+
+         return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+      }
+
+      case EFL_GESTURE_TOUCH_STATE_END:
+      {
+         /* no gesture was started, so no gesture should be detected */
+         if ((td->touch_down == 0) || (!pd->rotate_st.cur.timestamp))
+           {
+              rd->continues = EINA_FALSE;
+
+              _reset_recognizer(pd);
+              efl_gesture_manager_recognizer_cleanup(efl_provider_find(obj, EFL_CANVAS_GESTURE_MANAGER_CLASS), obj, watched);
+
+              return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+           }
+         _reset_recognizer(pd);
+         if (pd->rotate_angular_tolerance < 0)
+           {
+              return EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
+           }
+
+         if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE)
+           {
+              return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
+           }
+      }
+
+      default:
+
+        break;
+     }
+
+   return result;
+}
+
+#include "efl_canvas_gesture_recognizer_rotate.eo.c"
diff --git a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_rotate.eo b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_rotate.eo
new file mode 100644 (file)
index 0000000..28291b3
--- /dev/null
@@ -0,0 +1,12 @@
+class @beta Efl.Canvas.Gesture_Recognizer_Rotate extends Efl.Canvas.Gesture_Recognizer
+{
+   [[This is the recognizer for Rotate gestures.
+     See @Efl.Canvas.Gesture_Rotate and @Efl.Canvas.Gesture_Recognizer.
+     For internal use only.
+   ]]
+   c_prefix: efl_gesture_recognizer_rotate;
+   implements {
+      Efl.Canvas.Gesture_Recognizer.type { get; }
+      Efl.Canvas.Gesture_Recognizer.recognize;
+   }
+}
diff --git a/src/lib/evas/gesture/efl_canvas_gesture_rotate.c b/src/lib/evas/gesture/efl_canvas_gesture_rotate.c
new file mode 100644 (file)
index 0000000..7735123
--- /dev/null
@@ -0,0 +1,17 @@
+#include "efl_canvas_gesture_private.h"
+
+#define MY_CLASS EFL_CANVAS_GESTURE_ROTATE_CLASS
+
+EOLIAN static unsigned int
+_efl_canvas_gesture_rotate_radius_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Rotate_Data *pd)
+{
+   return pd->radius;
+}
+
+EOLIAN static double
+_efl_canvas_gesture_rotate_angle_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Rotate_Data *pd)
+{
+   return pd->angle;
+}
+
+#include "efl_canvas_gesture_rotate.eo.c"
diff --git a/src/lib/evas/gesture/efl_canvas_gesture_rotate.eo b/src/lib/evas/gesture/efl_canvas_gesture_rotate.eo
new file mode 100644 (file)
index 0000000..8cd35f8
--- /dev/null
@@ -0,0 +1,28 @@
+class @beta Efl.Canvas.Gesture_Rotate extends Efl.Canvas.Gesture
+{
+   [[Rotate gesture class holding state information.
+     See @Efl.Canvas.Gesture to see what this state is and
+     @[Efl.Canvas.Gesture_Events.gesture,rotate] for a description of the Rotate gesture.
+
+     Application developers receive these objects inside a gesture event and do not typically need to create their own.
+   ]]
+   c_prefix: efl_gesture_rotate;
+   methods {
+      @property radius {
+         [[The current radius (i.e. the distance between the two fingers) of the gesture.]]
+         get {
+         }
+         values {
+            radius: uint; [[The radius value in pixels.]]
+         }
+      }
+      @property angle {
+         [[The current angle of rotation for this gesture.]]
+         get {
+         }
+         values {
+            rotate: double; [[The angle of the rotation. $[0.0] means no rotation has occurred.]]
+         }
+      }
+   }
+}
index 7c2fc28..d57cdd0 100644 (file)
@@ -7,6 +7,7 @@ pub_eo_files = [
   'efl_canvas_gesture_long_press.eo',
   'efl_canvas_gesture_momentum.eo',
   'efl_canvas_gesture_flick.eo',
+  'efl_canvas_gesture_rotate.eo',
   'efl_canvas_gesture_zoom.eo',
   'efl_canvas_gesture_custom.eo',
   'efl_canvas_gesture_recognizer.eo',
@@ -16,6 +17,7 @@ pub_eo_files = [
   'efl_canvas_gesture_recognizer_long_press.eo',
   'efl_canvas_gesture_recognizer_momentum.eo',
   'efl_canvas_gesture_recognizer_flick.eo',
+  'efl_canvas_gesture_recognizer_rotate.eo',
   'efl_canvas_gesture_recognizer_zoom.eo',
   'efl_canvas_gesture_recognizer_custom.eo',
   'efl_canvas_gesture_manager.eo',
@@ -71,6 +73,7 @@ evas_src += files([
   'efl_canvas_gesture_long_press.c',
   'efl_canvas_gesture_momentum.c',
   'efl_canvas_gesture_flick.c',
+  'efl_canvas_gesture_rotate.c',
   'efl_canvas_gesture_zoom.c',
   'efl_canvas_gesture_custom.c',
   'efl_canvas_gesture_recognizer.c',
@@ -80,6 +83,7 @@ evas_src += files([
   'efl_canvas_gesture_recognizer_long_press.c',
   'efl_canvas_gesture_recognizer_momentum.c',
   'efl_canvas_gesture_recognizer_flick.c',
+  'efl_canvas_gesture_recognizer_rotate.c',
   'efl_canvas_gesture_recognizer_zoom.c',
   'efl_canvas_gesture_recognizer_custom.c',
   'efl_canvas_gesture_manager.c',