efl/gesture: move Point_Data to eo and add methods to fetch it for recognizers
authorMike Blumenkrantz <zmike@samsung.com>
Mon, 13 Jan 2020 20:04:38 +0000 (15:04 -0500)
committerJongmin Lee <jm105.lee@samsung.com>
Thu, 30 Jan 2020 21:01:32 +0000 (06:01 +0900)
this lets gesture framework track two touch points in order to distinguish between
successive presses and e.g., treat a simultaneous two finger tap as a single tap
gesture rather than two

it also simplifies some internal code and removes most hash lookups

Reviewed-by: woochan lee <wc0917.lee@samsung.com>
Differential Revision: https://phab.enlightenment.org/D11085

src/lib/evas/gesture/efl_canvas_gesture_private.h
src/lib/evas/gesture/efl_canvas_gesture_recognizer_zoom.c
src/lib/evas/gesture/efl_canvas_gesture_touch.c
src/lib/evas/gesture/efl_canvas_gesture_touch.eo
src/lib/evas/gesture/efl_canvas_gesture_types.eot

index fb24d0f..e24dea8 100644 (file)
@@ -25,22 +25,13 @@ typedef struct _Efl_Canvas_Gesture_Momentum_Data               Efl_Canvas_Gestur
 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 _Pointer_Data
-{
-   struct
-     {
-        Eina_Position2D pos;
-        unsigned int timestamp;
-     } start, prev, cur;
-   int id;
-   Efl_Pointer_Action action;
-} Pointer_Data;
-
 typedef struct _Efl_Canvas_Gesture_Touch_Data
 {
    Efl_Canvas_Gesture_Touch_State state;
-   Eina_Hash              *touch_points;
+   Eina_Array             *touch_points;
    int                     touch_down;
+   Efl_Gesture_Touch_Point_Data *cur_touch;
+   Efl_Gesture_Touch_Point_Data *prev_touch;
    Eina_Bool               multi_touch;
    Eo                     *target;
 } Efl_Canvas_Gesture_Touch_Data;
@@ -115,11 +106,11 @@ struct _Efl_Canvas_Gesture_Recognizer_Flick_Data
 
 struct _Efl_Canvas_Gesture_Recognizer_Zoom_Data
 {
-   Pointer_Data                    zoom_st;
-   Pointer_Data                    zoom_st1;
+   Efl_Gesture_Touch_Point_Data                    zoom_st;
+   Efl_Gesture_Touch_Point_Data                    zoom_st1;
 
-   Pointer_Data                    zoom_mv;
-   Pointer_Data                    zoom_mv1;
+   Efl_Gesture_Touch_Point_Data                    zoom_mv;
+   Efl_Gesture_Touch_Point_Data                    zoom_mv1;
 
    Evas_Coord                      zoom_base; /* Holds gap between fingers on
                                                                           * zoom-start  */
index 0603098..d88a9c0 100644 (file)
@@ -126,8 +126,6 @@ _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo *
                                                                             Efl_Object *watched,
                                                                             Efl_Canvas_Gesture_Touch *event)
 {
-   int id1 = 0;
-   int id2 = 1;
    Eina_Value *val;
    unsigned char zoom_finger_enable;
    unsigned char glayer_continues_enable;
@@ -186,14 +184,14 @@ _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo *
               if (!efl_gesture_touch_multi_touch_get(event))
                 return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
 
-              Pointer_Data *p1 = eina_hash_find(td->touch_points, &id1);
-              Pointer_Data *p2 = eina_hash_find(td->touch_points, &id2);
+              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);
 
-              memcpy(&pd->zoom_st, p2, sizeof(Pointer_Data));
-              memcpy(&pd->zoom_st1, p1, sizeof(Pointer_Data));
+              memcpy(&pd->zoom_st, p2, sizeof(Efl_Gesture_Touch_Point_Data));
+              memcpy(&pd->zoom_st1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
 
-              memcpy(&pd->zoom_mv, p2, sizeof(Pointer_Data));
-              memcpy(&pd->zoom_mv1, p1, sizeof(Pointer_Data));
+              memcpy(&pd->zoom_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
+              memcpy(&pd->zoom_mv1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
 
               int x, y;  //Hot spot
               zd->zoom = 1.0;
@@ -212,11 +210,11 @@ _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo *
               return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
            }
 
-         Pointer_Data *p2 = eina_hash_find(td->touch_points, &id2);
+         const Efl_Gesture_Touch_Point_Data *p2 = efl_gesture_touch_data_get(event, 1);
          if (p2->id == pd->zoom_mv.id)
-           memcpy(&pd->zoom_mv, p2, sizeof(Pointer_Data));
+           memcpy(&pd->zoom_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
          else if (p2->id == pd->zoom_mv1.id)
-           memcpy(&pd->zoom_mv1, p2, sizeof(Pointer_Data));
+           memcpy(&pd->zoom_mv1, p2, sizeof(Efl_Gesture_Touch_Point_Data));
 
          zd->zoom = _zoom_compute(pd, zd, pd->zoom_mv.cur.pos.x,
                                   pd->zoom_mv.cur.pos.y, pd->zoom_mv1.cur.pos.x,
index 6ddb3be..3ed9dfe 100644 (file)
@@ -6,33 +6,30 @@
 //that are directed to a particular object from the
 //first finger down to the last finger up
 
-static void
-_hash_free_cb(Pointer_Data *point)
-{
-   free(point);
-}
-
 static inline void
 _touch_points_reset(Efl_Canvas_Gesture_Touch_Data *pd)
 {
-   eina_hash_free(pd->touch_points);
-   pd->touch_points = eina_hash_int32_new(EINA_FREE_CB(_hash_free_cb));
+   while (eina_array_count(pd->touch_points))
+     free(eina_array_pop(pd->touch_points));
    pd->touch_down = 0;
+   pd->prev_touch = pd->cur_touch = NULL;
    pd->state = EFL_GESTURE_TOUCH_STATE_UNKNOWN;
 }
 
 EOLIAN static Efl_Object *
 _efl_canvas_gesture_touch_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_Touch_Data *pd)
 {
-   obj = efl_constructor(efl_super(obj, MY_CLASS));
-   _touch_points_reset(pd);
-   return obj;
+   pd->touch_points = eina_array_new(2);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pd->touch_points, NULL);
+   return efl_constructor(efl_super(obj, MY_CLASS));
 }
 
 EOLIAN static void
 _efl_canvas_gesture_touch_efl_object_destructor(Eo *obj, Efl_Canvas_Gesture_Touch_Data *pd)
 {
-   eina_hash_free(pd->touch_points);
+   while (eina_array_count(pd->touch_points))
+     free(eina_array_pop(pd->touch_points));
+   eina_array_free(pd->touch_points);
    efl_destructor(efl_super(obj, MY_CLASS));
 }
 
@@ -51,14 +48,16 @@ _efl_canvas_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_T
    Efl_Pointer_Action action = pointer_data->action;
    Eina_Vector2 pos = pointer_data->cur;
 
-   Pointer_Data *point = eina_hash_find(pd->touch_points, &id);
    Eina_Position2D _pos = { pos.x, pos.y };
+   Efl_Gesture_Touch_Point_Data *point = NULL;
+
+   if (eina_array_count(pd->touch_points) >= (unsigned int)id + 1)
+     point = eina_array_data_get(pd->touch_points, id);
 
    if (action == EFL_POINTER_ACTION_DOWN)
      {
         pd->touch_down++;
-        //TODO: Need to handle 2 or more case.
-        if (pd->touch_down == 2)
+        if (pd->touch_down >= 2)
           pd->multi_touch = EINA_TRUE;
      }
    else if ((action == EFL_POINTER_ACTION_UP) ||
@@ -86,18 +85,17 @@ _efl_canvas_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_T
              //Discard any other event
              return;
           }
-        point = calloc(1, sizeof(Pointer_Data));
+        point = calloc(1, sizeof(Efl_Gesture_Touch_Point_Data));
         if (!point) return;
         point->start.pos = point->prev.pos = point->cur.pos = _pos;
         point->start.timestamp = point->prev.timestamp = point->cur.timestamp = timestamp;
         point->id = id;
 
-        //Add to the hash
-        eina_hash_add(pd->touch_points, &id, point);
-        //FIXME: finger_list was broken
-        if (id)
-          pd->multi_touch = EINA_TRUE;
+        eina_array_push(pd->touch_points, point);
      }
+   if (pd->cur_touch != point)
+     pd->prev_touch = pd->cur_touch;
+   pd->cur_touch = point;
    point->action = action;
 
    if (!id && (action == EFL_POINTER_ACTION_DOWN))
@@ -124,11 +122,28 @@ _efl_canvas_gesture_touch_multi_touch_get(const Eo *obj EINA_UNUSED, Efl_Canvas_
    return pd->multi_touch;
 }
 
+EOLIAN static const Efl_Gesture_Touch_Point_Data *
+_efl_canvas_gesture_touch_cur_data_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
+{
+    return pd->cur_touch;
+}
+
+EOLIAN static const Efl_Gesture_Touch_Point_Data *
+_efl_canvas_gesture_touch_prev_data_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
+{
+    return pd->prev_touch;
+}
+
+EOLIAN static const Efl_Gesture_Touch_Point_Data *
+_efl_canvas_gesture_touch_data_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, unsigned int id)
+{
+    return eina_array_count(pd->touch_points) >= id + 1 ? eina_array_data_get(pd->touch_points, id) : NULL;
+}
+
 EOLIAN static Eina_Position2D
-_efl_canvas_gesture_touch_start_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
+_efl_canvas_gesture_touch_start_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd EINA_UNUSED)
 {
-   int tool = 0;
-   Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+   const Efl_Gesture_Touch_Point_Data *point = efl_gesture_touch_data_get(obj, 0);
    Eina_Position2D vec = { 0, 0 };
 
    if (!point)
@@ -140,8 +155,7 @@ _efl_canvas_gesture_touch_start_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_
 EOLIAN static Eina_Position2D
 _efl_canvas_gesture_touch_cur_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
 {
-   int tool = 0;
-   Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+   const Efl_Gesture_Touch_Point_Data *point = pd->cur_touch;
    Eina_Position2D vec = { 0, 0 };
 
    if (!point)
@@ -153,8 +167,7 @@ _efl_canvas_gesture_touch_cur_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Ge
 EOLIAN static unsigned int
 _efl_canvas_gesture_touch_cur_timestamp_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
 {
-   int tool = 0;
-   Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+   const Efl_Gesture_Touch_Point_Data *point = pd->cur_touch;
 
    if (!point)
      return 0;
@@ -165,11 +178,10 @@ _efl_canvas_gesture_touch_cur_timestamp_get(const Eo *obj EINA_UNUSED, Efl_Canva
 EOLIAN static Eina_Vector2
 _efl_canvas_gesture_touch_delta(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, int tool)
 {
-   Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+   Efl_Gesture_Touch_Point_Data *point = eina_array_count(pd->touch_points) >= (unsigned)tool + 1 ? eina_array_data_get(pd->touch_points, tool) : NULL;
    Eina_Vector2 vec = { 0, 0 };
 
-   if (!point)
-     return vec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(point, vec);
 
    Eina_Vector2 v1 = { point->cur.pos.x, point->cur.pos.y };
    Eina_Vector2 v2 = { point->prev.pos.x, point->prev.pos.y };
@@ -181,11 +193,10 @@ _efl_canvas_gesture_touch_delta(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_To
 EOLIAN static Eina_Vector2
 _efl_canvas_gesture_touch_distance(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, int tool)
 {
-   Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+   Efl_Gesture_Touch_Point_Data *point = eina_array_count(pd->touch_points) >= (unsigned)tool + 1 ? eina_array_data_get(pd->touch_points, tool) : NULL;
    Eina_Vector2 vec = { 0, 0 };
 
-   if (!point)
-     return vec;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(point, vec);
 
    Eina_Vector2 v1 = { point->cur.pos.x, point->cur.pos.y };
    Eina_Vector2 v2 = { point->start.pos.x, point->start.pos.y };
index 0425aa7..a12d26d 100644 (file)
@@ -66,6 +66,29 @@ class @beta Efl.Canvas.Gesture_Touch extends Efl.Object
             return : Efl.Canvas.Gesture_Touch_State; [[touch event state]]
          }
       }
+      @property cur_data {
+         [[This property holds the data struct of the most recent touch point.]]
+         get {}
+         values {
+            data: const(Efl.Canvas.Gesture_Touch_Point_Data) @by_ref; [[The current data.]]
+         }
+      }
+      @property prev_data {
+         [[This property holds the data struct of the second-most recent touch point.
+           If there is only one touch point active, it will return NULL.
+         ]]
+         get {}
+         values {
+            data: const(Efl.Canvas.Gesture_Touch_Point_Data) @by_ref; [[The previous touch point's data.]]
+         }
+      }
+      data_get @const {
+         [[This fetches the data for a specified touch point.]]
+         params {
+            @in id: uint; [[The id of the touch point to return.]]
+         }
+         return: const(Efl.Canvas.Gesture_Touch_Point_Data) @by_ref; [[The specified data if it exists.]]
+      }
       /* FIXME: finger_list was broken by design - TODO */
    }
    implements {
index 8cde6e1..600518b 100644 (file)
@@ -1,3 +1,6 @@
+import eina_types;
+import efl_input_types;
+
 enum @beta Efl.Canvas.Gesture_Touch_State
 {
    [[ This enum type describes the state of a touch event. ]]
@@ -44,3 +47,18 @@ enum @beta Efl.Canvas.Gesture_Recognizer_Type
    flick,
    zoom,
 }
+
+struct @beta @c_name(Efl_Gesture_Touch_Point_Info) Efl.Canvas.Gesture_Touch_Point_Info {
+   [[This struct represents the underlying data of a touch point.]]
+   pos: Eina.Position2D; [[The canvas position of the touch point data.]]
+   timestamp: uint; [[The timestamp of the touch point data.]]
+}
+
+struct @beta @c_name(Efl_Gesture_Touch_Point_Data) Efl.Canvas.Gesture_Touch_Point_Data {
+    [[This struct represents the state of a touch point.]]
+    id: int; [[Touch id of the point.]]
+    action: Efl.Pointer.Action; [[The last event with this point.]]
+    start: Efl.Canvas.Gesture_Touch_Point_Info; [[The start data for the touch point.]]
+    prev: Efl.Canvas.Gesture_Touch_Point_Info; [[The previous data for the touch point.]]
+    cur: Efl.Canvas.Gesture_Touch_Point_Info; [[The current data for the touch point.]]
+}