#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_Double_Tap_Data *pd; 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(efl_provider_find(data, EFL_CANVAS_GESTURE_MANAGER_CLASS), pd->target, EFL_EVENT_GESTURE_DOUBLE_TAP, data); 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, start_timeout = pd->start_timeout; double timeout = TAP_TIME_OUT; Eina_Position2D pos; Eina_Vector2 dist; Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL; pd->target = watched; pd->gesture = gesture; if (!EINA_DBL_NONZERO(start_timeout)) { double time; Eina_Value *val = _recognizer_config_get(obj, "glayer_double_tap_timeout"); if (val) { eina_value_get(val, &time); pd->start_timeout = timeout = time; } } else timeout = 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 > pd->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 <= pd->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"