elm_gesture_layer: Add new config value to handle tap finger size.
[platform/upstream/elementary.git] / src / lib / elm_gesture_layer.c
index f43f65a..e50e0d4 100644 (file)
@@ -1,7 +1,14 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
 #include <Elementary.h>
 #include "elm_priv.h"
 
-static const char GESTURE_LAYER_SMART_NAME[] = "elm_gesture_layer";
+#define MY_CLASS ELM_GESTURE_LAYER_CLASS
+
+#define MY_CLASS_NAME "Elm_Gesture_Layer"
+#define MY_CLASS_NAME_LEGACY "elm_gesture_layer"
 
 /* Some defaults */
 #define ELM_MOUSE_DEVICE             0
@@ -36,10 +43,10 @@ _glayer_buf_dup(void *buf, size_t size)
 
 #define SET_TEST_BIT(P)                               \
   do {                                                \
-       P->test = P->fn[ELM_GESTURE_STATE_START].cb || \
-         P->fn[ELM_GESTURE_STATE_MOVE].cb ||          \
-         P->fn[ELM_GESTURE_STATE_END].cb ||           \
-         P->fn[ELM_GESTURE_STATE_ABORT].cb;           \
+       P->test = P->cbs[ELM_GESTURE_STATE_START] || \
+         P->cbs[ELM_GESTURE_STATE_MOVE] ||          \
+         P->cbs[ELM_GESTURE_STATE_END] ||           \
+         P->cbs[ELM_GESTURE_STATE_ABORT];           \
     } while (0)
 
 #define IS_TESTED_GESTURE(gesture) \
@@ -49,13 +56,13 @@ _glayer_buf_dup(void *buf, size_t size)
   ((sd->gesture[T]) ? sd->gesture[T]->test : EINA_FALSE)
 
 #define ELM_GESTURE_LAYER_DATA_GET(o, sd) \
-  Elm_Gesture_Layer_Smart_Data * sd = evas_object_smart_data_get(o)
+  Elm_Gesture_Layer_Data * sd = eo_data_scope_get(o, MY_CLASS)
 
 #define ELM_GESTURE_LAYER_DATA_GET_OR_RETURN(o, ptr) \
   ELM_GESTURE_LAYER_DATA_GET(o, ptr);                \
   if (!ptr)                                          \
     {                                                \
-       CRITICAL("No widget data for object %p (%s)", \
+       CRI("No widget data for object %p (%s)", \
                 o, evas_object_type_get(o));         \
        return;                                       \
     }
@@ -64,20 +71,15 @@ _glayer_buf_dup(void *buf, size_t size)
   ELM_GESTURE_LAYER_DATA_GET(o, ptr);                         \
   if (!ptr)                                                   \
     {                                                         \
-       CRITICAL("No widget data for object %p (%s)",          \
+       CRI("No widget data for object %p (%s)",          \
                 o, evas_object_type_get(o));                  \
        return val;                                            \
     }
 
 #define ELM_GESTURE_LAYER_CHECK(obj)                                      \
-  if (!obj || !elm_widget_type_check((obj),                               \
-                                     GESTURE_LAYER_SMART_NAME, __func__)) \
+  if (!obj || !eo_isa(obj, MY_CLASS)) \
     return
 
-EVAS_SMART_SUBCLASS_NEW
-  (GESTURE_LAYER_SMART_NAME, _elm_gesture_layer, Elm_Widget_Smart_Class,
-  Elm_Widget_Smart_Class, elm_widget_smart_class_get, NULL);
-
 /**
  * @internal
  *
@@ -115,6 +117,7 @@ typedef struct _Pointer_Event Pointer_Event;
  */
 struct _Func_Data
 {
+   EINA_INLIST;
    void                *user_data; /**< Holds user data to CB (like sd) */
    Elm_Gesture_Event_Cb cb;
 };
@@ -141,7 +144,7 @@ struct _Gesture_Info
 {
    Evas_Object      *obj;
    void             *data; /**< Holds gesture intemidiate processing data */
-   Func_Data         fn[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info for states */
+   Eina_Inlist      *cbs[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info (Func_Data) for states */
    Elm_Gesture_Type  g_type; /**< gesture type */
    Elm_Gesture_State state; /**< gesture state */
    void             *info; /**< Data for the state callback */
@@ -210,6 +213,8 @@ static void _event_process(void *data,
                            void *event_info,
                            Evas_Callback_Type event_type);
 
+static void _callbacks_unregister(Evas_Object *obj);
+
 /* Should be the same order as _Elm_Gesture_Type */
 static Tests_Array_Funcs _glayer_tests_array[] = {
    { NULL, NULL, NULL },     /** Because someone made an awful mistake. */
@@ -352,13 +357,9 @@ struct _Rotate_Type /* Fields used by _rotation_test() */
 };
 typedef struct _Rotate_Type                  Rotate_Type;
 
-typedef struct _Elm_Gesture_Layer_Smart_Data Elm_Gesture_Layer_Smart_Data;
-struct _Elm_Gesture_Layer_Smart_Data
+typedef struct _Elm_Gesture_Layer_Data Elm_Gesture_Layer_Data;
+struct _Elm_Gesture_Layer_Data
 {
-   Elm_Widget_Smart_Data base;    /* base widget smart data as
-                                   * first member obligatory, as
-                                   * we're inheriting from it */
-
    Evas_Object          *target; /* Target Widget */
    Event_History        *event_history_list;
 
@@ -372,6 +373,7 @@ struct _Elm_Gesture_Layer_Smart_Data
    unsigned int          flick_time_limit_ms;
    double                long_tap_start_timeout;
    Eina_Bool             glayer_continues_enable;
+   double                double_tap_timeout;
 
    double                zoom_step;
    double                rotate_step;
@@ -382,6 +384,7 @@ struct _Elm_Gesture_Layer_Smart_Data
    Eina_List            *touched; /* Information  of touched devices */
 
    /* Taps Gestures */
+   Evas_Coord           tap_finger_size;    /* Default from Config */
    Ecore_Timer          *gest_taps_timeout; /* When this expires, dbl
                                              * click/taps ABORTed  */
 
@@ -531,7 +534,7 @@ _event_flag_get(void *event_info,
  * @ingroup Elm_Gesture_Layer
  */
 static void
-_event_consume(Elm_Gesture_Layer_Smart_Data *sd,
+_event_consume(Elm_Gesture_Layer_Data *sd,
                void *event_info,
                Evas_Callback_Type event_type,
                Evas_Event_Flags ev_flags)
@@ -603,14 +606,16 @@ static Evas_Event_Flags
 _state_report(Gesture_Info *gesture,
               void *info)
 {
+   Evas_Event_Flags flags = EVAS_EVENT_FLAG_NONE;
    /* We report current state (START, MOVE, END, ABORT), once */
    if ((gesture->state != ELM_GESTURE_STATE_UNDEFINED) &&
-       (gesture->fn[gesture->state].cb)) /* Fill state-info struct and
-                                          * send ptr to user
-                                          * callback */
+       (gesture->cbs[gesture->state])) /* Fill state-info struct and
+                                        * send ptr to user
+                                        * callback */
      {
-        return gesture->fn[gesture->state].cb(
-                 gesture->fn[gesture->state].user_data, info);
+        Func_Data *cb_info;
+        EINA_INLIST_FOREACH(gesture->cbs[gesture->state], cb_info)
+           flags |= cb_info->cb(cb_info->user_data, info);
      }
 
    return EVAS_EVENT_FLAG_NONE;
@@ -676,7 +681,7 @@ _state_set(Gesture_Info *g,
  * @ingroup Elm_Gesture_Layer
  */
 static void
-_states_reset(Elm_Gesture_Layer_Smart_Data *sd)
+_states_reset(Elm_Gesture_Layer_Data *sd)
 {
    int i;
    Gesture_Info *p;
@@ -706,7 +711,7 @@ _states_reset(Elm_Gesture_Layer_Smart_Data *sd)
  * @ingroup Elm_Gesture_Layer
  */
 static Eina_Bool
-_pointer_event_make(void *data __UNUSED__,
+_pointer_event_make(void *data EINA_UNUSED,
                     void *event_info,
                     Evas_Callback_Type event_type,
                     Pointer_Event *pe)
@@ -833,6 +838,8 @@ _event_history_add(Evas_Object *obj,
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
 
    ev = malloc(sizeof(Event_History));
+   if (!ev) return EINA_FALSE;
+
    ev->event = _event_info_copy(event, event_type);  /* Freed on
                                                       * _event_history_clear */
    ev->event_type = event_type;
@@ -853,8 +860,8 @@ _event_history_add(Evas_Object *obj,
  */
 static void
 _mouse_down_cb(void *data,
-               Evas *e __UNUSED__,
-               Evas_Object *obj __UNUSED__,
+               Evas *e EINA_UNUSED,
+               Evas_Object *obj EINA_UNUSED,
                void *event_info)
 {
    if (((Evas_Event_Mouse_Down *)event_info)->button != 1)
@@ -865,8 +872,8 @@ _mouse_down_cb(void *data,
 
 static void
 _mouse_move_cb(void *data,
-               Evas *e __UNUSED__,
-               Evas_Object *obj __UNUSED__,
+               Evas *e EINA_UNUSED,
+               Evas_Object *obj EINA_UNUSED,
                void *event_info)
 {
    _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_MOVE);
@@ -874,8 +881,8 @@ _mouse_move_cb(void *data,
 
 static void
 _key_down_cb(void *data,
-             Evas *e __UNUSED__,
-             Evas_Object *obj __UNUSED__,
+             Evas *e EINA_UNUSED,
+             Evas_Object *obj EINA_UNUSED,
              void *event_info)
 {
    _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_DOWN);
@@ -883,8 +890,8 @@ _key_down_cb(void *data,
 
 static void
 _key_up_cb(void *data,
-           Evas *e __UNUSED__,
-           Evas_Object *obj __UNUSED__,
+           Evas *e EINA_UNUSED,
+           Evas_Object *obj EINA_UNUSED,
            void *event_info)
 {
    _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_UP);
@@ -892,8 +899,8 @@ _key_up_cb(void *data,
 
 static void
 _mouse_up_cb(void *data,
-             Evas *e __UNUSED__,
-             Evas_Object *obj __UNUSED__,
+             Evas *e EINA_UNUSED,
+             Evas_Object *obj EINA_UNUSED,
              void *event_info)
 {
    if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
@@ -904,8 +911,8 @@ _mouse_up_cb(void *data,
 
 static void
 _mouse_wheel_cb(void *data,
-                Evas *e __UNUSED__,
-                Evas_Object *obj __UNUSED__,
+                Evas *e EINA_UNUSED,
+                Evas_Object *obj EINA_UNUSED,
                 void *event_info)
 {
    _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_WHEEL);
@@ -913,8 +920,8 @@ _mouse_wheel_cb(void *data,
 
 static void
 _multi_down_cb(void *data,
-               Evas *e __UNUSED__,
-               Evas_Object *obj __UNUSED__,
+               Evas *e EINA_UNUSED,
+               Evas_Object *obj EINA_UNUSED,
                void *event_info)
 {
    /* Skip the mouse duplicates. */
@@ -925,8 +932,8 @@ _multi_down_cb(void *data,
 
 static void
 _multi_move_cb(void *data,
-               Evas *e __UNUSED__,
-               Evas_Object *obj __UNUSED__,
+               Evas *e EINA_UNUSED,
+               Evas_Object *obj EINA_UNUSED,
                void *event_info)
 {
    /* Skip the mouse duplicates. */
@@ -937,8 +944,8 @@ _multi_move_cb(void *data,
 
 static void
 _multi_up_cb(void *data,
-             Evas *e __UNUSED__,
-             Evas_Object *obj __UNUSED__,
+             Evas *e EINA_UNUSED,
+             Evas_Object *obj EINA_UNUSED,
              void *event_info)
 {
    /* Skip the mouse duplicates. */
@@ -947,6 +954,17 @@ _multi_up_cb(void *data,
    _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_UP);
 }
 
+static void
+_target_del_cb(void *data,
+               Evas *e EINA_UNUSED,
+               Evas_Object *obj EINA_UNUSED,
+               void *event_info EINA_UNUSED)
+{
+   _callbacks_unregister(data);
+   ELM_GESTURE_LAYER_DATA_GET(data, sd);
+   sd->target = NULL;
+}
+
 /**
  * @internal
  *
@@ -985,6 +1003,9 @@ _callbacks_register(Evas_Object *obj)
      (sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
    evas_object_event_callback_add
      (sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb, obj);
+
+   evas_object_event_callback_add
+     (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
 }
 
 /**
@@ -1003,29 +1024,32 @@ _callbacks_unregister(Evas_Object *obj)
 
    if (!sd->target) return;
 
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb);
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb);
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, obj);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj);
 
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj);
 
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_MULTI_DOWN, _multi_down_cb);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_MULTI_DOWN, _multi_down_cb, obj);
 
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_MULTI_MOVE, _multi_move_cb);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_MULTI_MOVE, _multi_move_cb, obj);
 
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_MULTI_UP, _multi_up_cb);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_MULTI_UP, _multi_up_cb, obj);
+
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb, obj);
 
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb);
-   evas_object_event_callback_del
-     (sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb);
+   evas_object_event_callback_del_full
+     (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
 }
 
 /**
@@ -1144,8 +1168,9 @@ _event_history_clear(Evas_Object *obj)
                }
              else
                {  /* Report ABORT to all gestures that still not finished */
-                 _state_set(p, ELM_GESTURE_STATE_ABORT, sd->gesture[i]->info,
-                            EINA_FALSE);
+                  if (sd->target)
+                    _state_set(p, ELM_GESTURE_STATE_ABORT,
+                          sd->gesture[i]->info, EINA_FALSE);
                }
           }
      }
@@ -1313,7 +1338,7 @@ _continues_gestures_restart(void *data,
  */
 static void
 _event_process(void *data,
-               Evas_Object *obj __UNUSED__,
+               Evas_Object *obj EINA_UNUSED,
                void *event_info,
                Evas_Callback_Type event_type)
 {
@@ -1366,9 +1391,12 @@ static Eina_Bool
 _inside(Evas_Coord xx1,
         Evas_Coord yy1,
         Evas_Coord xx2,
-        Evas_Coord yy2)
+        Evas_Coord yy2,
+        Evas_Coord w)
 {
-   int w = elm_config_finger_size_get() >> 1; /* Finger size devided by 2 */
+   w >>= 1; /* Use half the distance, from center to all directions */
+   if (!w)  /* use system default instead */
+     w = elm_config_finger_size_get() >> 1; /* Finger size divided by 2 */
 
    if (xx1 < (xx2 - w))
      return EINA_FALSE;
@@ -1398,17 +1426,13 @@ _tap_gestures_test_reset(Gesture_Info *gesture)
    EINA_SAFETY_ON_NULL_RETURN(gesture);
    ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
 
-   if (sd->gest_taps_timeout)
-     {
-        ecore_timer_del(sd->gest_taps_timeout);
-        sd->gest_taps_timeout = NULL;
-     }
+   ELM_SAFE_FREE(sd->gest_taps_timeout, ecore_timer_del);
 
    if (!gesture->data)
      return;
 
-   EINA_LIST_FREE (((Taps_Type *)gesture->data)->l, data)
-     EINA_LIST_FREE (data, pe)
+   EINA_LIST_FREE(((Taps_Type *)gesture->data)->l, data)
+     EINA_LIST_FREE(data, pe)
        free(pe);
 
    memset(gesture->data, 0, sizeof(Taps_Type));
@@ -1421,7 +1445,6 @@ _tap_gestures_test_reset(Gesture_Info *gesture)
 static void
 _n_long_tap_test_reset(Gesture_Info *gesture)
 {
-   Eina_List *l;
    Pointer_Event *p;
    Long_Tap_Type *st;
 
@@ -1430,15 +1453,11 @@ _n_long_tap_test_reset(Gesture_Info *gesture)
 
    st = gesture->data;
 
-   EINA_LIST_FOREACH (st->touched, l, p)
+   EINA_LIST_FREE(st->touched, p)
      free(p);
+   st->touched = NULL;
 
-   eina_list_free(st->touched);
-   if (st->timeout)
-     {
-        ecore_timer_del(st->timeout);
-        st->timeout = NULL;
-     }
+   ELM_SAFE_FREE(st->timeout, ecore_timer_del);
    memset(gesture->data, 0, sizeof(Long_Tap_Type));
 }
 
@@ -1464,21 +1483,16 @@ _line_data_reset(Line_Data *st)
 static void
 _line_test_reset(Gesture_Info *gesture)
 {
-   Eina_List *l;
    Line_Type *st;
-   Eina_List *list;
    Line_Data *t_line;
 
    EINA_SAFETY_ON_NULL_RETURN(gesture);
    if (!gesture->data) return;
 
    st = gesture->data;
-   list = st->list;
 
-   EINA_LIST_FOREACH (list, l, t_line)
+   EINA_LIST_FREE(st->list, t_line)
      free(t_line);
-
-   eina_list_free(list);
    st->list = NULL;
 }
 
@@ -1519,25 +1533,24 @@ _rotate_test_reset(Gesture_Info *gesture)
    st->rotate_angular_tolerance = sd->rotate_angular_tolerance;
 }
 
-static int
-_match_fingers_compare(const void *data1,
-                       const void *data2)
+static Eina_List *
+_match_fingers_compare(Eina_List *list,
+                       Pointer_Event *pe1,
+                       Evas_Coord w)
 {
-   /* Compare coords of first item in list to cur coords */
-   const Pointer_Event *pe1 = eina_list_data_get(data1);
-   const Pointer_Event *pe2 = data2;
+    /* Compare coords of first item in list to cur coords */
+   Eina_List *pe_list;
+   Eina_List *l;
 
-   if (_inside(pe1->x, pe1->y, pe2->x, pe2->y))
-     return 0;
-   else if (pe1->x < pe2->x)
-     return -1;
-   else
+   EINA_LIST_FOREACH(list, l, pe_list)
      {
-        if (pe1->x == pe2->x)
-          return pe1->y - pe2->y;
-        else
-          return 1;
+        Pointer_Event *pe2 = eina_list_data_get(pe_list);
+
+        if (_inside(pe1->x, pe1->y, pe2->x, pe2->y, w))
+          return pe_list;
      }
+
+  return NULL;
 }
 
 static int
@@ -1548,11 +1561,6 @@ _pe_device_compare(const void *data1,
    const Pointer_Event *pe1 = eina_list_data_get(data1);
    const Pointer_Event *pe2 = data2;
 
-   /* Only match if last was a down event */
-   if ((pe1->event_type != EVAS_CALLBACK_MULTI_DOWN) &&
-       (pe1->event_type != EVAS_CALLBACK_MOUSE_DOWN))
-     return 1;
-
    if (pe1->device == pe2->device)
      return 0;
    else if (pe1->device < pe2->device)
@@ -1565,7 +1573,7 @@ static Eina_List *
 _pointer_event_record(Taps_Type *st,
                       Eina_List *pe_list,
                       Pointer_Event *pe,
-                      Elm_Gesture_Layer_Smart_Data *sd,
+                      Elm_Gesture_Layer_Data *sd,
                       void *event_info,
                       Evas_Callback_Type event_type)
 {
@@ -1598,6 +1606,51 @@ _pointer_event_record(Taps_Type *st,
 /**
  * @internal
  *
+ * This function computes minimum rect to bound taps at idx index
+ *
+ * @param taps [in] List of lists containing taps info.
+ * @param idx [in] index of events taken from lists.
+ * @param r [out] rect object to save info
+ * @return EINA_TRUE if managed to compute rect.
+ *
+ * @ingroup Elm_Gesture_Layer
+ */
+static Eina_Bool
+_taps_rect_get(Eina_List *taps, int idx, Evas_Coord_Rectangle *r)
+{  /* Build a rect bounding all taps at index idx */
+   Eina_List *l;
+   Evas_Coord bx = 0, by = 0;
+   Eina_List *pe_list;
+   Eina_Bool was_init = EINA_FALSE;
+
+   EINA_LIST_FOREACH(taps, l, pe_list)
+     {
+        Pointer_Event *pe = eina_list_nth(pe_list, idx);
+        if (!pe) continue;  /* Not suppose to happen */
+
+        if (was_init)
+          {
+             if (pe->x < r->x) r->x = pe->x;
+             if (pe->y < r->y) r->y = pe->y;
+             if (pe->x > bx) bx = pe->x;
+             if (pe->y > by) by = pe->y;
+          }
+        else
+          {
+             r->x = bx = pe->x;
+             r->y = by = pe->y;
+             was_init = EINA_TRUE;
+          }
+     }
+
+   r->w = bx - r->x;
+   r->h = by - r->y;
+   return was_init;
+}
+
+/**
+ * @internal
+ *
  * This function checks if the tap gesture is done.
  *
  * @param data gesture info pointer
@@ -1606,17 +1659,25 @@ _pointer_event_record(Taps_Type *st,
  * @ingroup Elm_Gesture_Layer
  */
 static Eina_Bool
-_tap_gesture_check_finish(Gesture_Info *gesture)
+_tap_gesture_check_finish(Gesture_Info *gesture, Evas_Coord tap_finger_size)
 {
    /* Here we check if taps-gesture was completed successfuly */
-   /* Count how many taps were recieved on each device then   */
+   /* Count how many taps were received on each device then   */
    /* determine if it matches n_taps_needed defined on START  */
+   unsigned int i;
    Taps_Type *st = gesture->data;
    Eina_List *l;
    Eina_List *pe_list;
+   Evas_Coord_Rectangle base;
+   Evas_Coord_Rectangle tmp;
+   if (!tap_finger_size)  /* Use system default if not set by user */
+     //TIZEN_ONLY(20180321): gesture layer needs their own tap area size to handle sensitivity.
+     //tap_finger_size = elm_config_finger_size_get();
+     tap_finger_size = _elm_config->glayer_tap_finger_size;
+     //
 
    if (!st->l) return EINA_FALSE;
-   EINA_LIST_FOREACH (st->l, l, pe_list)
+   EINA_LIST_FOREACH(st->l, l, pe_list)
      {
         /* No match taps number on device, ABORT */
         if (eina_list_count(pe_list) != st->n_taps_needed)
@@ -1625,6 +1686,29 @@ _tap_gesture_check_finish(Gesture_Info *gesture)
           }
      }
 
+   /* Now bound each tap touches in a rect, compare diff within tolerance */
+   /* Get rect based on first DOWN events for all devices */
+   if (!_taps_rect_get(st->l, 0, &base))
+     return EINA_FALSE;  /* Should not happen */
+
+   for (i = 1; i < st->n_taps_needed; i++)
+     {  /* Compare all other rects to base, tolerance is finger size */
+        if (_taps_rect_get(st->l, i, &tmp))
+          {
+             if (abs(tmp.x - base.x) > tap_finger_size)
+               return EINA_FALSE;
+
+             if (abs(tmp.y - base.y) > tap_finger_size)
+               return EINA_FALSE;
+
+             if (abs((tmp.x + tmp.w) - (base.x + base.w)) > tap_finger_size)
+               return EINA_FALSE;
+
+             if (abs((tmp.y + tmp.h) - (base.y + base.h)) > tap_finger_size)
+               return EINA_FALSE;
+          }
+     }
+
    return EINA_TRUE;
 }
 
@@ -1638,14 +1722,14 @@ _tap_gesture_check_finish(Gesture_Info *gesture)
  * @ingroup Elm_Gesture_Layer
  */
 static void
-_tap_gesture_finish(void *data)
+_tap_gesture_finish(void *data, Evas_Coord tap_finger_size)
 {
    /* This function will test each tap gesture when timer expires */
    Elm_Gesture_State s = ELM_GESTURE_STATE_ABORT;
    Gesture_Info *gesture = data;
    Taps_Type *st = gesture->data;
 
-   if (_tap_gesture_check_finish(gesture))
+   if (_tap_gesture_check_finish(gesture, tap_finger_size))
      {
         s = ELM_GESTURE_STATE_END;
      }
@@ -1671,13 +1755,16 @@ _multi_tap_timeout(void *data)
    ELM_GESTURE_LAYER_DATA_GET(data, sd);
 
    if (IS_TESTED(ELM_GESTURE_N_TAPS))
-     _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TAPS]);
+     _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TAPS],
+           sd->tap_finger_size);
 
    if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
-     _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]);
+     _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_DOUBLE_TAPS],
+           sd->tap_finger_size);
 
    if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
-     _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]);
+     _tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TRIPLE_TAPS],
+           sd->tap_finger_size);
 
    _clear_if_finished(data);
    sd->gest_taps_timeout = NULL;
@@ -1699,6 +1786,9 @@ static Eina_Bool
 _long_tap_timeout(void *data)
 {
    Gesture_Info *gesture = data;
+   Long_Tap_Type *st = gesture->data;
+
+   st->info.timestamp = ecore_time_get() * 1000;
 
    _state_set(gesture, ELM_GESTURE_STATE_MOVE,
               gesture->data, EINA_TRUE);
@@ -1731,7 +1821,7 @@ _tap_gesture_test(Evas_Object *obj,
    Taps_Type *st;
    Gesture_Info *gesture;
    Eina_List *pe_list = NULL;
-   Pointer_Event *pe_down = NULL;
+   Pointer_Event *pe_last = NULL;
    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
 
    /* Here we fill Tap struct */
@@ -1746,26 +1836,28 @@ _tap_gesture_test(Evas_Object *obj,
    switch (g_type)
      {
       case ELM_GESTURE_N_TAPS:
-        taps = 1;
-        break;
+         taps = 1;
+         break;
 
       case ELM_GESTURE_N_DOUBLE_TAPS:
-        taps = 2;
-        break;
+         taps = 2;
+         break;
 
       case ELM_GESTURE_N_TRIPLE_TAPS:
-        taps = 3;
-        break;
+         taps = 3;
+         break;
 
       default:
-        taps = 0;
-        break;
+         taps = 0;
+         break;
      }
 
    st = gesture->data;
    if (!st) /* Allocated once on first time */
      {
         st = calloc(1, sizeof(Taps_Type));
+        if (!st) return;
+
         gesture->data = st;
         _tap_gestures_test_reset(gesture);
      }
@@ -1774,90 +1866,161 @@ _tap_gesture_test(Evas_Object *obj,
      {
       case EVAS_CALLBACK_MULTI_DOWN:
       case EVAS_CALLBACK_MOUSE_DOWN:
-        /* Check if got tap on same cord was tapped before */
-        pe_list = eina_list_search_unsorted(st->l, _match_fingers_compare, pe);
-
-        if ((!pe_list) &&
-            /* This device was touched in other cord before completion */
-            eina_list_search_unsorted(st->l, _pe_device_compare, pe))
-          {
-             ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
-                                  &st->info, EINA_FALSE);
-             _event_consume(sd, event_info, event_type, ev_flag);
+         /* Each device taps (DOWN, UP event) registered in same list    */
+         /* Find list for this device or start a new list if not found   */
+         pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
+         if (pe_list)
+           {  /* This device touched before, verify that this tap is on  */
+              /* top of a previous tap (including a tap of other device) */
+              if (!_match_fingers_compare(st->l, pe, sd->tap_finger_size))
+                {  /* New DOWN event is not on top of any prev touch     */
+                   ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
+                         &st->info, EINA_FALSE);
+                   _event_consume(sd, event_info, event_type, ev_flag);
 
-             return;
-          }
+                   return;
+                }
+           }
 
-        pe_list = _pointer_event_record
+         /* All tests are good, register this tap in device list */
+         pe_list = _pointer_event_record
             (st, pe_list, pe, sd, event_info, event_type);
-        if ((!sd->gest_taps_timeout) && 
-            (_elm_config->glayer_double_tap_timeout > 0.0))
-          sd->gest_taps_timeout =
-          ecore_timer_add(_elm_config->glayer_double_tap_timeout,
-                          _multi_tap_timeout, gesture->obj);
-        else if (sd->gest_taps_timeout)
-          ecore_timer_reset(sd->gest_taps_timeout);
 
-        /* This is the first mouse down we got */
-        if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
-          {
-             ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
-                                  &st->info, EINA_FALSE);
-             _event_consume(sd, event_info, event_type, ev_flag);
+         if (!sd->gest_taps_timeout)
+           {
+              if (sd->double_tap_timeout > 0.0)
+                {
+                   sd->gest_taps_timeout =
+                      ecore_timer_add(sd->double_tap_timeout,
+                            _multi_tap_timeout, gesture->obj);
+                }
+           }
+         else  /* We re-allocate gest_taps_timeout between taps */
+           ecore_timer_reset(sd->gest_taps_timeout);
 
-             st->n_taps_needed = taps * 2;  /* count DOWN and UP */
+         if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
+           {  /* This is the first mouse down we got */
+              ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
+                    &st->info, EINA_FALSE);
+              _event_consume(sd, event_info, event_type, ev_flag);
 
-             return;
-          }
-        else if (eina_list_count(pe_list) > st->n_taps_needed)
-          /* If we arleady got too many touches for this gesture. */
-          ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
-                               &st->info, EINA_FALSE);
+              st->n_taps_needed = taps * 2;  /* count DOWN and UP */
 
-        break;
+              return;
+           }
+         else if (eina_list_count(pe_list) > st->n_taps_needed)
+           {  /* If we arleady got too many touches for this gesture. */
+              _state_set(gesture, ELM_GESTURE_STATE_ABORT,
+                    &st->info, EINA_FALSE);
+           }
+
+         if (gesture->state == ELM_GESTURE_STATE_MOVE)
+           {  /* Report MOVE if all devices have same DOWN/UP count */
+              /* Should be in MOVE state from last UP event */
+              Eina_List *l;
+              Eina_Bool move = EINA_TRUE;
+              unsigned int n = 0;
+
+              EINA_LIST_FOREACH(st->l, l, pe_list)
+                {
+                   if (n == 0)
+                     {
+                        n = eina_list_count(pe_list);
+                     }
+                   else if (n != eina_list_count(pe_list))
+                     {
+                        move = EINA_FALSE;
+                     }
+                }
+
+              if (move && (n > 0))
+                {
+                   _state_set(gesture, ELM_GESTURE_STATE_MOVE,
+                         &st->info, EINA_TRUE);
+                }
+           }
+
+         break;
 
       case EVAS_CALLBACK_MULTI_UP:
       case EVAS_CALLBACK_MOUSE_UP:
-        pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
-        if (!pe_list) return;
+         pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
+         if (!pe_list) return;
+
+         _pointer_event_record(st, pe_list, pe, sd, event_info, event_type);
+
+         if (((gesture->g_type == ELM_GESTURE_N_TAPS) &&
+                  !IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS) &&
+                  !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) ||
+               ((gesture->g_type == ELM_GESTURE_N_DOUBLE_TAPS) &&
+                !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)))
+           {  /* Test for finish immidiatly, not waiting for timeout */
+              if (_tap_gesture_check_finish(gesture, sd->tap_finger_size))
+                {
+                   _tap_gesture_finish(gesture, sd->tap_finger_size);
+                   return;
+                }
+           }
 
-        pe_list = _pointer_event_record
-            (st, pe_list, pe, sd, event_info, event_type);
+         if ((gesture->state == ELM_GESTURE_STATE_START) ||
+               (gesture->state == ELM_GESTURE_STATE_MOVE))
+           {  /* Tap gesture started, no finger on surface. Report MOVE */
+              Eina_List *l;
+              Eina_Bool move = EINA_TRUE;
+              unsigned int n = 0;
 
-        if (((gesture->g_type == ELM_GESTURE_N_TAPS) &&
-             !IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS) &&
-             !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) ||
-            ((gesture->g_type == ELM_GESTURE_N_DOUBLE_TAPS) &&
-             !IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)))
-          {
-             if (_tap_gesture_check_finish(gesture))
-               {
-                  _tap_gesture_finish(gesture);
-                  return;
-               }
-          }
+              /* Report move only if all devices have same DOWN/UP count */
+              EINA_LIST_FOREACH(st->l, l, pe_list)
+                {
+                   if (n == 0)
+                     {
+                        n = eina_list_count(pe_list);
+                     }
+                   else if (n != eina_list_count(pe_list))
+                     {
+                        move = EINA_FALSE;
+                     }
+                }
 
-        break;
+              if ((move && (n > 0)) && (n < st->n_taps_needed))
+                {  /* Set number of fingers and report MOVE */
+                   /* We don't report MOVE when (n >= st->n_taps_needed)
+                      because will be END or ABORT at this stage */
+                   st->info.n = eina_list_count(st->l);
+                   _state_set(gesture, ELM_GESTURE_STATE_MOVE,
+                         &st->info, EINA_TRUE);
+                }
+           }
+
+         break;
 
       case EVAS_CALLBACK_MULTI_MOVE:
       case EVAS_CALLBACK_MOUSE_MOVE:
-        /* Get first event in first list, this has to be a Mouse Down event  */
-        /* and verify that user didn't move out of this area before next tap */
-        pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
-        if (pe_list)
-          {
-             pe_down = eina_list_data_get(pe_list);
-             if (!_inside(pe_down->x, pe_down->y, pe->x, pe->y))
-               {
-                  ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
-                                       &st->info, EINA_FALSE);
-                  _event_consume(sd, event_info, event_type, ev_flag);
-               }
-          }
-        break;
+         /* Verify that user didn't move out of tap area before next tap */
+         /* BUT: we need to skip some MOVE events coming before DOWN     */
+         /* when user taps next tap. So fetch LAST recorded event for    */
+         /* device (DOWN or UP event), ignore all MOVEs if last was UP   */
+         pe_last = eina_list_data_get(eina_list_last(
+                  eina_list_search_unsorted(st->l, _pe_device_compare, pe)));
+
+         if (pe_last)
+           {  /* pe_last is the last event recorded for this device */
+              if ((pe_last->event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
+                    (pe_last->event_type == EVAS_CALLBACK_MULTI_DOWN))
+                {  /* Test only MOVE events that come after DOWN event */
+                   if (!_inside(pe_last->x, pe_last->y, pe->x, pe->y,
+                            sd->tap_finger_size))
+                     {
+                        ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
+                              &st->info, EINA_FALSE);
+                        _event_consume(sd, event_info, event_type, ev_flag);
+                     }
+                }
+           }
+         break;
 
       default:
-        return;
+         return;
      }
 }
 
@@ -1884,7 +2047,7 @@ _compute_taps_center(Long_Tap_Type *st,
    if (!eina_list_count(st->touched))
      return;
 
-   EINA_LIST_FOREACH (st->touched, l, p)
+   EINA_LIST_FOREACH(st->touched, l, p)
      {  /* Accumulate all then take avarage */
        if (p->device == pe->device) /* This will take care of values
                                      * coming from MOVE event */
@@ -1941,6 +2104,8 @@ _n_long_tap_test(Evas_Object *obj,
    if (!st) /* Allocated once on first time */
      {
         st = calloc(1, sizeof(Long_Tap_Type));
+        if (!st) return;
+
         gesture->data = st;
         _n_long_tap_test_reset(gesture);
      }
@@ -1952,12 +2117,17 @@ _n_long_tap_test(Evas_Object *obj,
         st->touched = _touched_device_add(st->touched, pe);
         st->info.n = eina_list_count(st->touched);
 
+        _event_consume(sd, event_info, event_type, ev_flag);
+        _compute_taps_center(st, &st->info.x, &st->info.y, pe);
+        st->center_x = st->info.x;  /* Update coords for */
+        st->center_y = st->info.y;  /* reporting START  */
+        st->info.timestamp = pe->timestamp;
+
         /* This is the first mouse down we got */
         if (eina_list_count(st->touched) == 1)
           {
              _state_set(gesture, ELM_GESTURE_STATE_START,
                    gesture->data, EINA_FALSE);
-             st->info.timestamp = pe->timestamp;
 
              /* To test long tap */
              /* When this timer expires, gesture STARTED */
@@ -1971,17 +2141,13 @@ _n_long_tap_test(Evas_Object *obj,
                 ecore_timer_reset(st->timeout);
           }
 
-
-        _event_consume(sd, event_info, event_type, ev_flag);
-        _compute_taps_center(st, &st->info.x, &st->info.y, pe);
-        st->center_x = st->info.x;
-        st->center_y = st->info.y;
         break;
 
       case EVAS_CALLBACK_MULTI_UP:
       case EVAS_CALLBACK_MOUSE_UP:
         st->touched = _touched_device_remove(st->touched, pe);
         _compute_taps_center(st, &st->center_x, &st->center_y, pe);
+        st->info.timestamp = pe->timestamp;
         if (st->info.n)
           {
              if (gesture->state == ELM_GESTURE_STATE_MOVE)
@@ -1991,11 +2157,7 @@ _n_long_tap_test(Evas_Object *obj,
                ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
                                     &st->info, EINA_FALSE);
 
-             if (st->timeout)
-               {
-                  ecore_timer_del(st->timeout);
-                  st->timeout = NULL;
-               }
+             ELM_SAFE_FREE(st->timeout, ecore_timer_del);
              _event_consume(sd, event_info, event_type, ev_flag);
           }
 
@@ -2012,14 +2174,12 @@ _n_long_tap_test(Evas_Object *obj,
              Evas_Coord y = 0;
 
              _compute_taps_center(st, &x, &y, pe);
+             st->info.timestamp = pe->timestamp;
              /* ABORT if user moved fingers out of tap area */
-             if (!_inside(x, y, st->center_x, st->center_y))
+             if (!_inside(x, y, st->center_x, st->center_y,
+                      sd->tap_finger_size))
                {
-                  if (st->timeout)
-                    {
-                       ecore_timer_del(st->timeout);
-                       st->timeout = NULL;
-                    }
+                  ELM_SAFE_FREE(st->timeout, ecore_timer_del);
 
                   /* Report MOVE if gesture started */
                   ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
@@ -2042,10 +2202,10 @@ _n_long_tap_test(Evas_Object *obj,
  * This momentum value will be sent to widget when gesture is completed.
  *
  * @param momentum pointer to buffer where we record momentum value.
- * @param x1 x coord where user started gesture.
- * @param y1 y coord where user started gesture.
- * @param x2 x coord where user completed gesture.
- * @param y2 y coord where user completed gesture.
+ * @param xx1 x coord where user started gesture.
+ * @param yy1 y coord where user started gesture.
+ * @param xx2 x coord where user completed gesture.
+ * @param yy2 y coord where user completed gesture.
  * @param t1x timestamp for X, when user started gesture.
  * @param t1y timestamp for Y, when user started gesture.
  * @param t2  timestamp when user completed gesture.
@@ -2095,12 +2255,12 @@ _momentum_set(Elm_Gesture_Momentum_Info *momentum,
  *
  * This function is used for computing rotation angle (DEG).
  *
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
  *
- * @return angle of the line between (x1,y1), (x2,y2) in Deg.
+ * @return angle of the line between (xx1,yy1), (xx2,yy2) in Deg.
  * Angles now are given in DEG, not RAD.
  * ZERO angle at 12-oclock, growing clockwise.
  *
@@ -2114,8 +2274,8 @@ _angle_get(Evas_Coord xx1,
 {
    double a, xx, yy, rt = (-1);
 
-   xx = fabs(xx2 - xx1);
-   yy = fabs(yy2 - yy1);
+   xx = abs(xx2 - xx1);
+   yy = abs(yy2 - yy1);
 
    if (((int)xx) && ((int)yy))
      {
@@ -2163,10 +2323,10 @@ _angle_get(Evas_Coord xx1,
  * This function is used for computing the magnitude and direction
  * of vector between two points.
  *
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
  * @param l length computed (output)
  * @param a angle computed (output)
  *
@@ -2244,6 +2404,8 @@ _momentum_test(Evas_Object *obj,
    if (!st) /* Allocated once on first time */
      {
         st = calloc(1, sizeof(Momentum_Type));
+        if (!st) return;
+
         gesture->data = st;
         _momentum_test_reset(gesture);
      }
@@ -2253,7 +2415,7 @@ _momentum_test(Evas_Object *obj,
 
    /* First make avarage of all touched devices to determine center point */
    pe_local = *pe; /* Copy pe event info to local */
-   EINA_LIST_FOREACH (sd->touched, l, p)
+   EINA_LIST_FOREACH(sd->touched, l, p)
      if (p->device != pe_local.device)
        {
           pe_local.x += p->x;
@@ -2382,8 +2544,8 @@ _momentum_test(Evas_Object *obj,
         st->line_end.y = pe_local.y;
         st->t_end = pe_local.timestamp;
 
-        if ((fabs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) ||
-            (fabs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM))
+        if ((abs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) ||
+            (abs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM))
           state_to_report = ELM_GESTURE_STATE_END;
         else
           state_to_report = ELM_GESTURE_STATE_ABORT;
@@ -2529,6 +2691,8 @@ _n_line_test(Evas_Object *obj,
    if (!st)
      {
         st = calloc(1, sizeof(Line_Type));
+        if (!st) return;
+
         gesture->data = st;
      }
 
@@ -2635,7 +2799,7 @@ _n_line_test(Evas_Object *obj,
    Line_Data *t_line;
    double base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
    Eina_Bool lines_parallel = EINA_TRUE;
-   EINA_LIST_FOREACH (list, l, t_line)
+   EINA_LIST_FOREACH(list, l, t_line)
      {
         if (base_angle < 0)
           base_angle = t_line->line_angle;
@@ -2831,14 +2995,14 @@ _on_rotation_broke_tolerance(Rotate_Type *st)
  * This function is used for computing the gap between fingers.
  * It returns the length and center point between fingers.
  *
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
- * @param x  Gets center point x cord (output)
- * @param y  Gets center point y cord (output)
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
+ * @param x  Get center point x cord (output)
+ * @param y  Get center point y cord (output)
  *
- * @return length of the line between (x1,y1), (x2,y2) in pixels.
+ * @return length of the line between (xx1,yy1), (xx2,yy2) in pixels.
  *
  * @ingroup Elm_Gesture_Layer
  */
@@ -2851,8 +3015,8 @@ _finger_gap_length_get(Evas_Coord xx1,
                        Evas_Coord *y)
 {
    double a, b, xx, yy, gap;
-   xx = fabs(xx2 - xx1);
-   yy = fabs(yy2 - yy1);
+   xx = abs(xx2 - xx1);
+   yy = abs(yy2 - yy1);
    gap = sqrt((xx * xx) + (yy * yy));
 
    /* START - Compute zoom center point */
@@ -2957,10 +3121,10 @@ _zoom_momentum_get(Zoom_Type *st,
  * This function is used for computing zoom value.
  *
  * @param st Pointer to zoom data based on user input.
- * @param x1 first finger x location.
- * @param y1 first finger y location.
- * @param x2 second finger x location.
- * @param y2 second finger y location.
+ * @param xx1 first finger x location.
+ * @param yy1 first finger y location.
+ * @param xx2 second finger x location.
+ * @param yy2 second finger y location.
  * @param factor zoom-factor, used to determine how fast zoom works.
  *
  * @return zoom value, when 1.0 means no zoom, 0.5 half size...
@@ -3049,6 +3213,8 @@ _zoom_with_wheel_test(Evas_Object *obj,
    if (!st) /* Allocated once on first time, used for zoom intermediate data */
      {
         st = calloc(1, sizeof(Zoom_Type));
+        if (!st) return;
+
         gesture_zoom->data = st;
         _zoom_test_reset(gesture_zoom);
      }
@@ -3058,9 +3224,9 @@ _zoom_with_wheel_test(Evas_Object *obj,
       case EVAS_CALLBACK_KEY_UP:
       {
          Evas_Event_Key_Up *p = event_info;
-         if ((!strcmp(p->keyname, "Control_L")) ||
+         if ((!strcmp(p->key, "Control_L")) ||
              /* Test if we ended a zoom gesture when releasing CTRL */
-             (!strcmp(p->keyname, "Control_R")))
+             (!strcmp(p->key, "Control_R")))
            {
               if ((st->zoom_wheel) &&
                   ((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
@@ -3193,6 +3359,8 @@ _zoom_test(Evas_Object *obj,
    if (!st) /* Allocated once on first time, used for zoom data */
      {
         st = calloc(1, sizeof(Zoom_Type));
+        if (!st) return;
+
         gesture_zoom->data = st;
         _zoom_test_reset(gesture_zoom);
      }
@@ -3207,7 +3375,7 @@ _zoom_test(Evas_Object *obj,
         if ((!sd->glayer_continues_enable) &&
             (!st->zoom_st.timestamp))
           return;
-
+        // fallthrough is intentional
       case EVAS_CALLBACK_MOUSE_DOWN:
       case EVAS_CALLBACK_MULTI_DOWN:
       { /* Here we take care of zoom-start and zoom move */
@@ -3229,7 +3397,7 @@ _zoom_test(Evas_Object *obj,
         if (!st->zoom_st.timestamp) /* Now scan touched-devices list
                                      * and find other finger */
           {
-             EINA_LIST_FOREACH (sd->touched, l, p)
+             EINA_LIST_FOREACH(sd->touched, l, p)
                { /* Device of other finger <> pe device */
                  if (p->device != pe->device)
                    break;
@@ -3419,6 +3587,10 @@ _rotate_test(Evas_Object *obj,
              Evas_Callback_Type event_type,
              Elm_Gesture_Type g_type)
 {
+   Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
+   Gesture_Info *gesture;
+   Rotate_Type *st = NULL;
+
    if (!_elm_config->glayer_rotate_finger_enable)
      return;
 
@@ -3429,20 +3601,19 @@ _rotate_test(Evas_Object *obj,
 
    if (!sd->gesture[g_type]) return;
 
-   Gesture_Info *gesture = sd->gesture[g_type];
-   Rotate_Type *st;
-   if (gesture)
+   gesture = sd->gesture[g_type];
+   if (!gesture) return ;
+
+   st = gesture->data;
+   if (!st) /* Allocated once on first time */
      {
-        st = gesture->data;
-        if (!st) /* Allocated once on first time */
-          {
-             st = calloc(1, sizeof(Rotate_Type));
-             gesture->data = st;
-             _rotate_test_reset(gesture);
-          }
+       st = calloc(1, sizeof(Rotate_Type));
+       if (!st) return;
+
+       gesture->data = st;
+       _rotate_test_reset(gesture);
      }
 
-   Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
    switch (event_type)
      {
       case EVAS_CALLBACK_MOUSE_MOVE:
@@ -3451,7 +3622,7 @@ _rotate_test(Evas_Object *obj,
         if ((!sd->glayer_continues_enable) &&
             (!st->rotate_st.timestamp))
           return;
-
+        // fallthrough is intentional
       case EVAS_CALLBACK_MOUSE_DOWN:
       case EVAS_CALLBACK_MULTI_DOWN:
       { /* Here we take care of rotate-start and rotate move */
@@ -3472,7 +3643,7 @@ _rotate_test(Evas_Object *obj,
         if (!st->rotate_st.timestamp) /* Now scan touched-devices list
                                        * and find other finger */
           {
-             EINA_LIST_FOREACH (sd->touched, l, p)
+             EINA_LIST_FOREACH(sd->touched, l, p)
                { /* Device of other finger <> pe device */
                  if (p->device != pe->device)
                    break;
@@ -3570,8 +3741,8 @@ _rotate_test(Evas_Object *obj,
      }
 }
 
-static Eina_Bool
-_elm_gesture_layer_smart_disable(Evas_Object *obj)
+EOLIAN static Eina_Bool
+_elm_gesture_layer_elm_widget_disable(Eo *obj, Elm_Gesture_Layer_Data *_pd EINA_UNUSED)
 {
    if (elm_widget_disabled_get(obj))
      _callbacks_unregister(obj);
@@ -3581,14 +3752,12 @@ _elm_gesture_layer_smart_disable(Evas_Object *obj)
    return EINA_TRUE;
 }
 
-static void
-_elm_gesture_layer_smart_add(Evas_Object *obj)
+EOLIAN static void
+_elm_gesture_layer_evas_object_smart_add(Eo *obj, Elm_Gesture_Layer_Data *priv)
 {
-   EVAS_SMART_DATA_ALLOC(obj, Elm_Gesture_Layer_Smart_Data);
-
-   _elm_gesture_layer_parent_sc->base.add(obj);
+   eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
+   elm_widget_sub_object_parent_add(obj);
 
-   priv->target = NULL;
    priv->line_min_length =
      _elm_config->glayer_line_min_length * elm_config_finger_size_get();
    priv->zoom_distance_tolerance = _elm_config->glayer_zoom_distance_tolerance
@@ -3609,169 +3778,404 @@ _elm_gesture_layer_smart_add(Evas_Object *obj)
    /* FIXME: Hack to get around old configs - if too small, enlarge. */
    if (_elm_config->glayer_double_tap_timeout < 0.00001)
      _elm_config->glayer_double_tap_timeout = 0.25;
+   priv->double_tap_timeout = _elm_config->glayer_double_tap_timeout;
 
    memset(priv->gesture, 0, sizeof(priv->gesture));
 }
 
-static void
-_elm_gesture_layer_smart_del(Evas_Object *obj)
+static void _cbs_clean(Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type);
+
+EOLIAN static void
+_elm_gesture_layer_evas_object_smart_del(Eo *obj, Elm_Gesture_Layer_Data *sd)
 {
    Pointer_Event *data;
    int i;
 
-   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
-
-   _event_history_clear(obj);
-   eina_list_free(sd->pending);
-
-   EINA_LIST_FREE (sd->touched, data)
-     free(data);
-
-   if (!elm_widget_disabled_get(obj))
-     _callbacks_unregister(obj);
+   /* Clear all gestures intermediate data, stop any timers */
+   {
+      /* FIXME: +1 because of the mistake in the enum. */
+      Gesture_Info **gitr = sd->gesture + 1;
+      Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
+      for (; fitr->reset; fitr++, gitr++)
+        {
+           if (IS_TESTED_GESTURE(*gitr))
+             fitr->reset(*gitr);
+        }
+   }
 
-   /* Free all gestures internal data structures */
+   /* First Free all gestures internal data structures */
    for (i = 0; i < ELM_GESTURE_LAST; i++)
      if (sd->gesture[i])
        {
           if (sd->gesture[i]->data)
             free(sd->gesture[i]->data);
 
+          _cbs_clean(sd, i, ELM_GESTURE_STATE_START);
+          _cbs_clean(sd, i, ELM_GESTURE_STATE_MOVE);
+          _cbs_clean(sd, i, ELM_GESTURE_STATE_END);
+          _cbs_clean(sd, i, ELM_GESTURE_STATE_ABORT);
           free(sd->gesture[i]);
+          sd->gesture[i] = NULL; /* Referenced by _event_history_clear */
        }
+   ecore_timer_del(sd->gest_taps_timeout);
+
+   /* Then take care of clearing events */
+   _event_history_clear(obj);
+   sd->pending = eina_list_free(sd->pending);
+
+   EINA_LIST_FREE(sd->touched, data)
+     free(data);
+
+   if (!elm_widget_disabled_get(obj))
+     _callbacks_unregister(obj);
+
+   eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
+}
 
-   _elm_gesture_layer_parent_sc->base.del(obj); /* handles freeing sd */
+EAPI Evas_Object *
+elm_gesture_layer_add(Evas_Object *parent)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+   Evas_Object *obj = eo_add(MY_CLASS, parent);
+   return obj;
+}
+
+EOLIAN static Eo *
+_elm_gesture_layer_eo_base_constructor(Eo *obj, Elm_Gesture_Layer_Data *_pd EINA_UNUSED)
+{
+   obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+   eo_do(obj, evas_obj_type_set(MY_CLASS_NAME_LEGACY));
+
+   return obj;
+}
+
+EOLIAN static Eina_Bool
+_elm_gesture_layer_hold_events_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
+{
+   return !sd->repeat_events;
+}
+
+EOLIAN static void
+_elm_gesture_layer_hold_events_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, Eina_Bool hold_events)
+{
+   sd->repeat_events = !(!!hold_events);
+}
+
+EOLIAN static double
+_elm_gesture_layer_zoom_step_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
+{
+   return sd->zoom_step;
+}
+
+EOLIAN static void
+_elm_gesture_layer_zoom_step_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, double step)
+{
+   if (step < 0) return;
+
+   sd->zoom_step = step;
+}
+
+EOLIAN static double
+_elm_gesture_layer_rotate_step_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
+{
+   return sd->rotate_step;
+}
+
+EOLIAN static void
+_elm_gesture_layer_rotate_step_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, double step)
+{
+   if (step < 0) return;
+
+   sd->rotate_step = step;
+}
+
+EOLIAN static Eina_Bool
+_elm_gesture_layer_attach(Eo *obj, Elm_Gesture_Layer_Data *sd, Evas_Object *target)
+{
+   if (!target) return EINA_FALSE;
+
+   /* if was attached before, unregister callbacks first */
+   if (sd->target)
+     _callbacks_unregister(obj);
+
+   sd->target = target;
+
+   _callbacks_register(obj);
+   return EINA_TRUE;
 }
 
 static void
-_elm_gesture_layer_smart_set_user(Elm_Widget_Smart_Class *sc)
+_cbs_clean(Elm_Gesture_Layer_Data *sd,
+          Elm_Gesture_Type idx,
+          Elm_Gesture_State cb_type)
 {
-   sc->base.add = _elm_gesture_layer_smart_add;
-   sc->base.del = _elm_gesture_layer_smart_del;
+   if (!sd->gesture[idx]) return;
 
-   sc->disable = _elm_gesture_layer_smart_disable;
+   Func_Data *cb_info;
+   EINA_INLIST_FREE(sd->gesture[idx]->cbs[cb_type], cb_info)
+     {
+        sd->gesture[idx]->cbs[cb_type] = eina_inlist_remove(
+              sd->gesture[idx]->cbs[cb_type], EINA_INLIST_GET(cb_info));
+        free(cb_info);
+     }
+   SET_TEST_BIT(sd->gesture[idx]);
 }
 
-EAPI Evas_Object *
-elm_gesture_layer_add(Evas_Object *parent)
+EOLIAN static void
+_elm_gesture_layer_cb_set(Eo *obj, Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
 {
-   Evas *e;
-   Evas_Object *obj;
+   /* Clear gesture intermediate data, stop any timers */
+   if (IS_TESTED_GESTURE(sd->gesture[idx]))
+     _glayer_tests_array[idx].reset(sd->gesture[idx]);
 
-   EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
+   _cbs_clean(sd, idx, cb_type); // for ABI compat.
+   eo_do(obj, elm_obj_gesture_layer_cb_add(idx, cb_type, cb, data));
+}
+
+EOLIAN static void
+_elm_gesture_layer_cb_add(Eo *obj, Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
+{
+   if (!cb) return;
 
-   e = evas_object_evas_get(parent);
-   if (!e) return NULL;
+   Gesture_Info *p;
 
-   obj = evas_object_smart_add(e, _elm_gesture_layer_smart_class_new());
+   if (!sd->gesture[idx])
+     sd->gesture[idx] = calloc(1, sizeof(Gesture_Info));
+   if (!sd->gesture[idx]) return;
 
-   if (!elm_widget_sub_object_add(parent, obj))
-     ERR("could not add %p as sub object of %p", obj, parent);
+   Func_Data *cb_info = calloc(1, sizeof(*cb_info));
+   if (!cb_info) return;
+   cb_info->cb = cb;
+   cb_info->user_data = data;
 
-   return obj;
+   p = sd->gesture[idx];
+   p->obj = obj;
+   p->g_type = idx;
+   p->cbs[cb_type] = eina_inlist_append(p->cbs[cb_type],
+         EINA_INLIST_GET(cb_info));
+   p->state = ELM_GESTURE_STATE_UNDEFINED;
+   SET_TEST_BIT(p);
 }
 
-EAPI Eina_Bool
-elm_gesture_layer_hold_events_get(const Evas_Object *obj)
+EOLIAN static void
+_elm_gesture_layer_cb_del(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
 {
-   ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
-   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   if (!sd->gesture[idx]) return;
 
-   return !sd->repeat_events;
+   Eina_Inlist *itr;
+   Func_Data *cb_info;
+   EINA_INLIST_FOREACH_SAFE(sd->gesture[idx]->cbs[cb_type], itr, cb_info)
+     {
+        if (cb_info->cb == cb && cb_info->user_data == data)
+          {
+             /* Clear gesture intermediate data, stop any timers */
+             if (IS_TESTED_GESTURE(sd->gesture[idx]))
+                _glayer_tests_array[idx].reset(sd->gesture[idx]);
+
+             sd->gesture[idx]->cbs[cb_type] = eina_inlist_remove(
+                   sd->gesture[idx]->cbs[cb_type], EINA_INLIST_GET(cb_info));
+             free(cb_info);
+             SET_TEST_BIT(sd->gesture[idx]);
+             return;
+          }
+     }
 }
 
 EAPI void
-elm_gesture_layer_hold_events_set(Evas_Object *obj,
-                                  Eina_Bool hold_events)
+elm_gesture_layer_line_min_length_set(Evas_Object *obj, int line_min_length)
 {
    ELM_GESTURE_LAYER_CHECK(obj);
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
-
-   sd->repeat_events = !(!!hold_events);
+   sd->line_min_length = line_min_length;
 }
 
-EAPI double
-elm_gesture_layer_zoom_step_get(const Evas_Object *obj)
+EAPI int
+elm_gesture_layer_line_min_length_get(const Evas_Object *obj)
 {
    ELM_GESTURE_LAYER_CHECK(obj) 0;
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->line_min_length;
+}
 
-   return sd->zoom_step;
+EAPI void
+elm_gesture_layer_zoom_distance_tolerance_set(Evas_Object *obj, Evas_Coord zoom_distance_tolerance)
+{
+   ELM_GESTURE_LAYER_CHECK(obj);
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->zoom_distance_tolerance = zoom_distance_tolerance;
+}
+
+EAPI Evas_Coord
+elm_gesture_layer_zoom_distance_tolerance_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->zoom_distance_tolerance;
 }
 
 EAPI void
-elm_gesture_layer_zoom_step_set(Evas_Object *obj,
-                                double step)
+elm_gesture_layer_line_distance_tolerance_set(Evas_Object *obj, Evas_Coord line_distance_tolerance)
 {
    ELM_GESTURE_LAYER_CHECK(obj);
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->line_distance_tolerance = line_distance_tolerance;
+}
 
-   if (step < 0) return;
+EAPI Evas_Coord
+elm_gesture_layer_line_distance_tolerance_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->line_distance_tolerance;
+}
 
-   sd->zoom_step = step;
+EAPI void
+elm_gesture_layer_line_angular_tolerance_set(Evas_Object *obj, double line_angular_tolerance)
+{
+   ELM_GESTURE_LAYER_CHECK(obj);
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->line_angular_tolerance = line_angular_tolerance;
 }
 
 EAPI double
-elm_gesture_layer_rotate_step_get(const Evas_Object *obj)
+elm_gesture_layer_line_angular_tolerance_get(const Evas_Object *obj)
 {
-   ELM_GESTURE_LAYER_CHECK(obj) 0;
+   ELM_GESTURE_LAYER_CHECK(obj) 0.0;
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->line_angular_tolerance;
+}
 
-   return sd->rotate_step;
+EAPI void
+elm_gesture_layer_zoom_wheel_factor_set(Evas_Object *obj, double zoom_wheel_factor)
+{
+   ELM_GESTURE_LAYER_CHECK(obj);
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->zoom_wheel_factor = zoom_wheel_factor;
+}
+
+EAPI double
+elm_gesture_layer_zoom_wheel_factor_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0.0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->zoom_wheel_factor;
 }
 
 EAPI void
-elm_gesture_layer_rotate_step_set(Evas_Object *obj,
-                                  double step)
+elm_gesture_layer_zoom_finger_factor_set(Evas_Object *obj, double zoom_finger_factor)
 {
    ELM_GESTURE_LAYER_CHECK(obj);
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->zoom_finger_factor = zoom_finger_factor;
+}
 
-   if (step < 0) return;
+EAPI double
+elm_gesture_layer_zoom_finger_factor_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0.0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->zoom_finger_factor;
+}
 
-   sd->rotate_step = step;
+EAPI void
+elm_gesture_layer_rotate_angular_tolerance_set(Evas_Object *obj, double rotate_angular_tolerance)
+{
+   ELM_GESTURE_LAYER_CHECK(obj);
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->rotate_angular_tolerance = rotate_angular_tolerance;
 }
 
-EAPI Eina_Bool
-elm_gesture_layer_attach(Evas_Object *obj,
-                         Evas_Object *target)
+EAPI double
+elm_gesture_layer_rotate_angular_tolerance_get(const Evas_Object *obj)
 {
-   ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
+   ELM_GESTURE_LAYER_CHECK(obj) 0.0;
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->rotate_angular_tolerance;
+}
 
-   if (!target) return EINA_FALSE;
+EAPI void
+elm_gesture_layer_flick_time_limit_ms_set(Evas_Object *obj, unsigned int flick_time_limit_ms)
+{
+   ELM_GESTURE_LAYER_CHECK(obj);
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->flick_time_limit_ms = flick_time_limit_ms;
+}
 
-   /* if was attached before, unregister callbacks first */
-   if (sd->target)
-     _callbacks_unregister(obj);
+EAPI unsigned int
+elm_gesture_layer_flick_time_limit_ms_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->flick_time_limit_ms;
+}
 
-   sd->target = target;
+EAPI void
+elm_gesture_layer_long_tap_start_timeout_set(Evas_Object *obj, double long_tap_start_timeout)
+{
+   ELM_GESTURE_LAYER_CHECK(obj);
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->long_tap_start_timeout = long_tap_start_timeout;
+}
 
-   _callbacks_register(obj);
-   return EINA_TRUE;
+EAPI double
+elm_gesture_layer_long_tap_start_timeout_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0.0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->long_tap_start_timeout;
 }
 
 EAPI void
-elm_gesture_layer_cb_set(Evas_Object *obj,
-                         Elm_Gesture_Type idx,
-                         Elm_Gesture_State cb_type,
-                         Elm_Gesture_Event_Cb cb,
-                         void *data)
+elm_gesture_layer_continues_enable_set(Evas_Object *obj, Eina_Bool continues_enable)
 {
-   Gesture_Info *p;
+   ELM_GESTURE_LAYER_CHECK(obj);
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->glayer_continues_enable = continues_enable;
+}
+
+EAPI Eina_Bool
+elm_gesture_layer_continues_enable_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0.0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->glayer_continues_enable;
+}
 
+EAPI void
+elm_gesture_layer_double_tap_timeout_set(Evas_Object *obj, double double_tap_timeout)
+{
    ELM_GESTURE_LAYER_CHECK(obj);
    ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   sd->double_tap_timeout = double_tap_timeout;
+}
 
-   if (!sd->gesture[idx])
-     sd->gesture[idx] = calloc(1, sizeof(Gesture_Info));
-   if (!sd->gesture[idx]) return;
+EAPI double
+elm_gesture_layer_double_tap_timeout_get(const Evas_Object *obj)
+{
+   ELM_GESTURE_LAYER_CHECK(obj) 0.0;
+   ELM_GESTURE_LAYER_DATA_GET(obj, sd);
+   return sd->double_tap_timeout;
+}
 
-   p = sd->gesture[idx];
-   p->obj = obj;
-   p->g_type = idx;
-   p->fn[cb_type].cb = cb;
-   p->fn[cb_type].user_data = data;
-   p->state = ELM_GESTURE_STATE_UNDEFINED;
-   SET_TEST_BIT(p);
+EOLIAN static void
+_elm_gesture_layer_tap_finger_size_set(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd, Evas_Coord sz)
+{
+   if (sz < 0)
+      sz = 0;  /* Should not be negative, will reset to system value */
+
+   sd->tap_finger_size = sz;
+}
+
+EOLIAN static Evas_Coord
+_elm_gesture_layer_tap_finger_size_get(Eo *obj EINA_UNUSED, Elm_Gesture_Layer_Data *sd)
+{
+   return sd->tap_finger_size;
+}
+
+static void
+_elm_gesture_layer_class_constructor(Eo_Class *klass)
+{
+   evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
 }
+
+#include "elm_gesture_layer.eo.c"