diff --git a/src/lib/evas/gesture/efl_canvas_gesture_private.h b/src/lib/evas/gesture/efl_canvas_gesture_private.h index e24dea8307..973a6d224e 100644 --- a/src/lib/evas/gesture/efl_canvas_gesture_private.h +++ b/src/lib/evas/gesture/efl_canvas_gesture_private.h @@ -1,149 +1,152 @@ #ifndef EFL_GESTURE_PRIVATE_H_ #define EFL_GESTURE_PRIVATE_H_ #include "evas_common_private.h" #include "evas_private.h" #include "efl_canvas_gesture_events.eo.h" #include +/* milliseconds */ +#define TAP_TOUCH_TIME_THRESHOLD (0.1 * 1000) + const Efl_Event_Description * _efl_gesture_type_get(const Eo *obj); void efl_gesture_manager_gesture_clean_up(Eo *obj, Eo *target, const Efl_Event_Description *type); typedef struct _Efl_Canvas_Gesture_Manager_Data Efl_Canvas_Gesture_Manager_Data; typedef struct _Efl_Canvas_Gesture_Recognizer_Data Efl_Canvas_Gesture_Recognizer_Data; typedef struct _Efl_Canvas_Gesture_Recognizer_Tap_Data Efl_Canvas_Gesture_Recognizer_Tap_Data; typedef struct _Efl_Canvas_Gesture_Recognizer_Long_Tap_Data Efl_Canvas_Gesture_Recognizer_Long_Tap_Data; typedef struct _Efl_Canvas_Gesture_Recognizer_Double_Tap_Data Efl_Canvas_Gesture_Recognizer_Double_Tap_Data; 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_Zoom_Data Efl_Canvas_Gesture_Recognizer_Zoom_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_Touch_Data { Efl_Canvas_Gesture_Touch_State state; 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; struct _Efl_Canvas_Gesture_Recognizer_Data { Eo *manager; // keeps a reference of the manager Eo *gesture; int finger_size; Eina_Bool continues; }; struct _Efl_Canvas_Gesture_Recognizer_Tap_Data { Eo *target; Eo *gesture; Ecore_Timer *timeout; }; struct _Efl_Canvas_Gesture_Recognizer_Long_Tap_Data { Eina_List *target_timeout; Eo *target; Efl_Canvas_Gesture *gesture; Ecore_Timer *timeout; double start_timeout; Eina_Bool is_timeout; }; struct _Efl_Canvas_Gesture_Recognizer_Double_Tap_Data { Eina_List *target_timeout; Eo *target; Eo *gesture; Ecore_Timer *timeout; double start_timeout; Eina_Bool is_timeout; int tap_count; }; struct _Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data { Eina_List *target_timeout; Eo *target; Eo *gesture; Ecore_Timer *timeout; double start_timeout; Eina_Bool is_timeout; int tap_count; }; struct _Efl_Canvas_Gesture_Recognizer_Momentum_Data { Eina_Position2D st_line; Eina_Position2D end_line; unsigned int t_st; unsigned int t_end; int xdir; int ydir; Eina_Bool touched; }; struct _Efl_Canvas_Gesture_Recognizer_Flick_Data { Eina_Position2D st_line; unsigned int t_st; unsigned int t_end; int line_length; double line_angle; Eina_Bool touched; }; struct _Efl_Canvas_Gesture_Recognizer_Zoom_Data { Efl_Gesture_Touch_Point_Data zoom_st; Efl_Gesture_Touch_Point_Data zoom_st1; 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 */ double zoom_distance_tolerance; double zoom_finger_factor; double zoom_step; double next_step; Eina_Bool calc_temp; }; struct _Efl_Canvas_Gesture_Data { const Efl_Event_Description *type; Efl_Canvas_Gesture_State state; Eina_Position2D hotspot; unsigned int timestamp; }; struct _Efl_Canvas_Gesture_Momentum_Data { Eina_Vector2 momentum; }; struct _Efl_Canvas_Gesture_Flick_Data { Eina_Vector2 momentum; double angle; }; struct _Efl_Canvas_Gesture_Zoom_Data { double radius; double zoom; }; #endif diff --git a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_double_tap.c b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_double_tap.c index c676e0e515..cee5d88fa0 100644 --- a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_double_tap.c +++ b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_double_tap.c @@ -1,191 +1,215 @@ #include "efl_canvas_gesture_private.h" #define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS #define TAP_TIME_OUT 0.33 EOLIAN static Efl_Canvas_Gesture * _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_add(Eo *obj, Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd EINA_UNUSED, Efl_Object *target EINA_UNUSED) { return efl_add(EFL_CANVAS_GESTURE_DOUBLE_TAP_CLASS, obj); } EOLIAN static void _efl_canvas_gesture_recognizer_double_tap_efl_object_destructor(Eo *obj, Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd) { if (pd->timeout) ecore_timer_del(pd->timeout); efl_destructor(efl_super(obj, MY_CLASS)); } static Eina_Bool _tap_timeout_cb(void *data) { Efl_Canvas_Gesture_Recognizer_Data *rd; Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd; rd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS); pd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS); efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_CANCELED); efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_DOUBLE_TAP, pd->gesture); efl_gesture_manager_gesture_clean_up(rd->manager, pd->target, EFL_EVENT_GESTURE_DOUBLE_TAP); pd->timeout = NULL; pd->tap_count = 0; return ECORE_CALLBACK_CANCEL; } EOLIAN static Efl_Canvas_Gesture_Recognizer_Result _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_recognize(Eo *obj, Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd, Efl_Canvas_Gesture *gesture, Efl_Object *watched, Efl_Canvas_Gesture_Touch *event) { double length; double timeout = TAP_TIME_OUT; Eina_Position2D pos; Eina_Vector2 dist; Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS); pd->target = watched; pd->gesture = gesture; if (!pd->start_timeout) { double time; Eina_Value *val = efl_gesture_recognizer_config_get(obj, "glayer_doublee_tap_timeout"); if (val) { eina_value_get(val, &time); pd->start_timeout = timeout = time; } } else timeout = pd->start_timeout; switch (efl_gesture_touch_state_get(event)) { case EFL_GESTURE_TOUCH_STATE_BEGIN: { pos = efl_gesture_touch_start_point_get(event); efl_gesture_hotspot_set(gesture, pos); if (pd->timeout) ecore_timer_reset(pd->timeout); else pd->timeout = ecore_timer_add(timeout, _tap_timeout_cb, obj); result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; break; } case EFL_GESTURE_TOUCH_STATE_UPDATE: { + /* multi-touch */ + if (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN) + { + /* a second finger was pressed at the same time-ish as the first: combine into same event */ + if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD) + { + result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE; + break; + } + } result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE; if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE && !efl_gesture_touch_multi_touch_get(event)) { dist = efl_gesture_touch_distance(event, 0); length = fabs(dist.x) + fabs(dist.y); if (length > rd->finger_size) { if (pd->timeout) { ecore_timer_del(pd->timeout); pd->timeout = NULL; } result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; pd->tap_count = 0; } } break; } case EFL_GESTURE_TOUCH_STATE_END: { if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE && !efl_gesture_touch_multi_touch_get(event)) { + if (efl_gesture_touch_prev_data_get(event)) + { + Efl_Pointer_Action prev_act = efl_gesture_touch_prev_data_get(event)->action; + /* multi-touch */ + if ((prev_act == EFL_POINTER_ACTION_UP) || (prev_act == EFL_POINTER_ACTION_CANCEL)) + { + /* a second finger was pressed at the same time-ish as the first: combine into same event */ + if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD) + { + result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE; + break; + } + } + } dist = efl_gesture_touch_distance(event, 0); length = fabs(dist.x) + fabs(dist.y); if (length <= rd->finger_size) { pd->tap_count++; if (pd->tap_count == 1) { if (pd->timeout) ecore_timer_reset(pd->timeout); result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; } else { if (pd->timeout) { ecore_timer_del(pd->timeout); pd->timeout = NULL; } if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END) result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH; else result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; pd->tap_count = 0; } } else { if (pd->timeout) { ecore_timer_del(pd->timeout); pd->timeout = NULL; } result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; pd->tap_count = 0; } } break; } default: break; } return result; } EOLIAN static double _efl_canvas_gesture_recognizer_double_tap_timeout_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd) { return pd->start_timeout; } EOLIAN static void _efl_canvas_gesture_recognizer_double_tap_timeout_set(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd, double time) { pd->start_timeout = time; } #include "efl_canvas_gesture_recognizer_double_tap.eo.c" diff --git a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_tap.c b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_tap.c index 582c2f47b0..0deb30f607 100644 --- a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_tap.c +++ b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_tap.c @@ -1,95 +1,109 @@ #include "efl_canvas_gesture_private.h" #define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_TAP_CLASS //FIXME: It doesnt have matched config value. // may using dobule tap timeout value? #define EFL_GESTURE_RECOGNIZER_TYPE_TAP_TIME_OUT 0.33 EOLIAN static Efl_Canvas_Gesture * _efl_canvas_gesture_recognizer_tap_efl_canvas_gesture_recognizer_add(Eo *obj, Efl_Canvas_Gesture_Recognizer_Tap_Data *pd EINA_UNUSED, Efl_Object *target EINA_UNUSED) { return efl_add(EFL_CANVAS_GESTURE_TAP_CLASS, obj); } static Eina_Bool _tap_timeout_cb(void *data) { Efl_Canvas_Gesture_Recognizer_Tap_Data *pd = data; pd->timeout = NULL; efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_CANCELED); efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_TAP, pd->gesture); return ECORE_CALLBACK_CANCEL; } EOLIAN static Efl_Canvas_Gesture_Recognizer_Result _efl_canvas_gesture_recognizer_tap_efl_canvas_gesture_recognizer_recognize(Eo *obj, Efl_Canvas_Gesture_Recognizer_Tap_Data *pd, Efl_Canvas_Gesture *gesture, Efl_Object *watched, Efl_Canvas_Gesture_Touch *event) { double length; Eina_Position2D pos; Eina_Vector2 dist; Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS); pd->target = watched; pd->gesture = gesture; switch (efl_gesture_touch_state_get(event)) { case EFL_GESTURE_TOUCH_STATE_BEGIN: { +new_tap: pos = efl_gesture_touch_start_point_get(event); efl_gesture_hotspot_set(gesture, pos); if (pd->timeout) ecore_timer_del(pd->timeout); pd->timeout = ecore_timer_add(EFL_GESTURE_RECOGNIZER_TYPE_TAP_TIME_OUT, _tap_timeout_cb, pd); result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; break; } case EFL_GESTURE_TOUCH_STATE_UPDATE: + /* multi-touch */ + if (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN) + { + /* a second finger was pressed at the same time-ish as the first: combine into same event */ + if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD) + { + result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE; + break; + } + /* another distinct touch occurred, treat this as a new touch */ + goto new_tap; + } + EINA_FALLTHROUGH; case EFL_GESTURE_TOUCH_STATE_END: { if (pd->timeout) { ecore_timer_del(pd->timeout); pd->timeout = NULL; } if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE && !efl_gesture_touch_multi_touch_get(event)) { dist = efl_gesture_touch_distance(event, 0); length = fabs(dist.x) + fabs(dist.y); if (length <= rd->finger_size) { if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END) result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH; else result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; } } break; } default: break; } return result; } #include "efl_canvas_gesture_recognizer_tap.eo.c" diff --git a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_triple_tap.c b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_triple_tap.c index 99d651aa6a..009742c1b6 100644 --- a/src/lib/evas/gesture/efl_canvas_gesture_recognizer_triple_tap.c +++ b/src/lib/evas/gesture/efl_canvas_gesture_recognizer_triple_tap.c @@ -1,191 +1,215 @@ #include "efl_canvas_gesture_private.h" #define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS #define TAP_TIME_OUT 0.33 EOLIAN static Efl_Canvas_Gesture * _efl_canvas_gesture_recognizer_triple_tap_efl_canvas_gesture_recognizer_add(Eo *obj, Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *pd EINA_UNUSED, Efl_Object *target EINA_UNUSED) { return efl_add(EFL_CANVAS_GESTURE_TRIPLE_TAP_CLASS, obj); } EOLIAN static void _efl_canvas_gesture_recognizer_triple_tap_efl_object_destructor(Eo *obj, Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *pd) { if (pd->timeout) ecore_timer_del(pd->timeout); efl_destructor(efl_super(obj, MY_CLASS)); } static Eina_Bool _tap_timeout_cb(void *data) { Efl_Canvas_Gesture_Recognizer_Data *rd; Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *pd; rd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS); pd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS); efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_CANCELED); efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_TRIPLE_TAP, pd->gesture); efl_gesture_manager_gesture_clean_up(rd->manager, pd->target, EFL_EVENT_GESTURE_TRIPLE_TAP); pd->timeout = NULL; pd->tap_count = 0; return ECORE_CALLBACK_CANCEL; } EOLIAN static Efl_Canvas_Gesture_Recognizer_Result _efl_canvas_gesture_recognizer_triple_tap_efl_canvas_gesture_recognizer_recognize(Eo *obj, Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *pd, Efl_Canvas_Gesture *gesture, Efl_Object *watched, Efl_Canvas_Gesture_Touch *event) { double length; double timeout = TAP_TIME_OUT; Eina_Position2D pos; Eina_Vector2 dist; Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS); pd->target = watched; pd->gesture = gesture; if (!pd->start_timeout) { double time; Eina_Value *val = efl_gesture_recognizer_config_get(obj, "glayer_doublee_tap_timeout"); if (val) { eina_value_get(val, &time); pd->start_timeout = timeout = time; } } else timeout = pd->start_timeout; switch (efl_gesture_touch_state_get(event)) { case EFL_GESTURE_TOUCH_STATE_BEGIN: { pos = efl_gesture_touch_start_point_get(event); efl_gesture_hotspot_set(gesture, pos); if (pd->timeout) ecore_timer_reset(pd->timeout); else pd->timeout = ecore_timer_add(timeout, _tap_timeout_cb, obj); result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; break; } case EFL_GESTURE_TOUCH_STATE_UPDATE: { + /* multi-touch */ + if (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN) + { + /* a second finger was pressed at the same time-ish as the first: combine into same event */ + if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD) + { + result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE; + break; + } + } result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE; if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE && !efl_gesture_touch_multi_touch_get(event)) { dist = efl_gesture_touch_distance(event, 0); length = fabs(dist.x) + fabs(dist.y); if (length > rd->finger_size) { if (pd->timeout) { ecore_timer_del(pd->timeout); pd->timeout = NULL; } result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; pd->tap_count = 0; } } break; } case EFL_GESTURE_TOUCH_STATE_END: { if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE && !efl_gesture_touch_multi_touch_get(event)) { + if (efl_gesture_touch_prev_data_get(event)) + { + Efl_Pointer_Action prev_act = efl_gesture_touch_prev_data_get(event)->action; + /* multi-touch */ + if ((prev_act == EFL_POINTER_ACTION_UP) || (prev_act == EFL_POINTER_ACTION_CANCEL)) + { + /* a second finger was pressed at the same time-ish as the first: combine into same event */ + if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD) + { + result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE; + break; + } + } + } dist = efl_gesture_touch_distance(event, 0); length = fabs(dist.x) + fabs(dist.y); if (length <= rd->finger_size) { pd->tap_count++; if (pd->tap_count < 3) { if (pd->timeout) ecore_timer_reset(pd->timeout); result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; } else { if (pd->timeout) { ecore_timer_del(pd->timeout); pd->timeout = NULL; } if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END) result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH; else result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER; pd->tap_count = 0; } } else { if (pd->timeout) { ecore_timer_del(pd->timeout); pd->timeout = NULL; } result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; pd->tap_count = 0; } } break; } default: break; } return result; } EOLIAN static double _efl_canvas_gesture_recognizer_triple_tap_timeout_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *pd) { return pd->start_timeout; } EOLIAN static void _efl_canvas_gesture_recognizer_triple_tap_timeout_set(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *pd, double time) { pd->start_timeout = time; } #include "efl_canvas_gesture_recognizer_triple_tap.eo.c"