forked from enlightenment/efl
evas/gesture: Added gesture manager implementaion.
This commit is contained in:
parent
4b997e89e5
commit
9da7a7f0d2
|
@ -270,6 +270,7 @@ lib/evas/gesture/efl_gesture.c \
|
||||||
lib/evas/gesture/efl_gesture_tap.c \
|
lib/evas/gesture/efl_gesture_tap.c \
|
||||||
lib/evas/gesture/efl_gesture_recognizer.c \
|
lib/evas/gesture/efl_gesture_recognizer.c \
|
||||||
lib/evas/gesture/efl_gesture_recognizer_tap.c \
|
lib/evas/gesture/efl_gesture_recognizer_tap.c \
|
||||||
|
lib/evas/gesture/efl_gesture_manager.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXTRA_DIST2 += \
|
EXTRA_DIST2 += \
|
||||||
|
|
|
@ -0,0 +1,350 @@
|
||||||
|
#include "efl_gesture_private.h"
|
||||||
|
|
||||||
|
#define MY_CLASS EFL_GESTURE_MANAGER_CLASS
|
||||||
|
|
||||||
|
typedef struct _Object_Gesture
|
||||||
|
{
|
||||||
|
Eo *object;
|
||||||
|
const Efl_Event_Description *type;
|
||||||
|
Efl_Gesture *gesture;
|
||||||
|
Efl_Gesture_Recognizer *recognizer;
|
||||||
|
}Object_Gesture;
|
||||||
|
|
||||||
|
typedef struct _Efl_Gesture_Manager_Data
|
||||||
|
{
|
||||||
|
// keeps track of all the gesture request for a particular target
|
||||||
|
Eina_Hash *m_gesture_contex; // (*target, *event_desc)
|
||||||
|
// keeps all the event directed to this particular object from touch_begin till touch_end
|
||||||
|
Eina_Hash *m_object_events; // (*target, *efl_gesture_touch)
|
||||||
|
// keeps all the recognizer registered to gesture manager
|
||||||
|
Eina_Hash *m_recognizers; // (*gesture_type, *recognizer)
|
||||||
|
// keeps track of all current object gestures.
|
||||||
|
Eina_List *m_object_gestures; //(List of *object_gesture)
|
||||||
|
// lazy deletion of gestures
|
||||||
|
Eina_List *m_gestures_to_delete;
|
||||||
|
|
||||||
|
Eina_Hash *m_config;
|
||||||
|
} Efl_Gesture_Manager_Data;
|
||||||
|
|
||||||
|
static void _cleanup_cached_gestures(Efl_Gesture_Manager_Data *pd,
|
||||||
|
Eo *target, const Efl_Event_Description *type);
|
||||||
|
static Efl_Gesture*
|
||||||
|
_get_state(Efl_Gesture_Manager_Data *pd, Eo *target,
|
||||||
|
Efl_Gesture_Recognizer *recognizer, const Efl_Event_Description *type);
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cleanup_object(Eina_List *list)
|
||||||
|
{
|
||||||
|
Eina_List *l;
|
||||||
|
Eo *obj;
|
||||||
|
|
||||||
|
if (!list) return;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(list, l, obj)
|
||||||
|
efl_del(obj);
|
||||||
|
|
||||||
|
eina_list_free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hash_free_cb(Eo *obj)
|
||||||
|
{
|
||||||
|
efl_del(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Efl_Object *
|
||||||
|
_efl_gesture_manager_efl_object_constructor(Eo *obj, Efl_Gesture_Manager_Data *pd EINA_UNUSED)
|
||||||
|
{
|
||||||
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
||||||
|
|
||||||
|
pd->m_recognizers = eina_hash_pointer_new(EINA_FREE_CB(_hash_free_cb));
|
||||||
|
pd->m_gesture_contex = eina_hash_pointer_new(NULL);
|
||||||
|
pd->m_object_events = eina_hash_pointer_new(EINA_FREE_CB(_hash_free_cb));
|
||||||
|
pd->m_object_gestures = NULL;
|
||||||
|
pd->m_gestures_to_delete = NULL;
|
||||||
|
|
||||||
|
pd->m_config = eina_hash_string_superfast_new(EINA_FREE_CB(eina_value_free));
|
||||||
|
|
||||||
|
efl_gesture_manager_recognizer_register(obj, efl_add(EFL_GESTURE_RECOGNIZER_TAP_CLASS, obj));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EOLIAN static Eina_Value *
|
||||||
|
_efl_gesture_manager_config_get(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd, const char *name)
|
||||||
|
{
|
||||||
|
return eina_hash_find(pd->m_config, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_gesture_manager_config_set(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd, const char *name, Eina_Value *value)
|
||||||
|
{
|
||||||
|
Eina_Value *v = eina_value_new(eina_value_type_get(value));
|
||||||
|
eina_value_copy(value, v);
|
||||||
|
eina_hash_add(pd->m_config, name, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_gesture_manager_efl_object_destructor(Eo *obj, Efl_Gesture_Manager_Data *pd EINA_UNUSED)
|
||||||
|
{
|
||||||
|
eina_hash_free(pd->m_recognizers);
|
||||||
|
eina_hash_free(pd->m_gesture_contex);
|
||||||
|
eina_hash_free(pd->m_object_events);
|
||||||
|
_cleanup_object(pd->m_gestures_to_delete);
|
||||||
|
efl_destructor(efl_super(obj, MY_CLASS));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_efl_gesture_manager_callback_add_hook(Eo *obj, Eo *target, const Efl_Event_Description *type)
|
||||||
|
{
|
||||||
|
Efl_Gesture_Manager_Data *pd = efl_data_scope_get(obj, MY_CLASS);
|
||||||
|
// if there is a recognizer registered for that event then add it to the gesture context
|
||||||
|
Efl_Gesture_Recognizer *recognizer = eina_hash_find (pd->m_recognizers, &type);
|
||||||
|
if (recognizer)
|
||||||
|
{
|
||||||
|
// add it to the gesture context.
|
||||||
|
eina_hash_list_append(pd->m_gesture_contex, &target, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_efl_gesture_manager_callback_del_hook(Eo *obj, Eo *target, const Efl_Event_Description *type)
|
||||||
|
{
|
||||||
|
Efl_Gesture_Manager_Data *pd = efl_data_scope_get(obj, MY_CLASS);
|
||||||
|
// if there is a recognizer registered for that event then add it to the gesture context
|
||||||
|
Efl_Gesture_Recognizer *recognizer = eina_hash_find (pd->m_recognizers, &type);
|
||||||
|
if (recognizer)
|
||||||
|
{
|
||||||
|
eina_hash_list_remove(pd->m_gesture_contex, &target, type);
|
||||||
|
_cleanup_cached_gestures(pd, target, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_efl_gesture_manager_filter_event(Eo *obj, Eo *target, void *event)
|
||||||
|
{
|
||||||
|
Eina_List *l, *gesture_context;
|
||||||
|
Efl_Gesture_Manager_Data *pd;
|
||||||
|
const Efl_Event_Description *gesture_type;
|
||||||
|
Efl_Gesture_Recognizer *recognizer;
|
||||||
|
Efl_Gesture *gesture;
|
||||||
|
Efl_Gesture_Recognizer_Result recog_result;
|
||||||
|
Efl_Gesture_Recognizer_Result recog_state;
|
||||||
|
Efl_Gesture_Touch *touch_event;
|
||||||
|
Efl_Input_Pointer_Data *pointer_data = efl_data_scope_get(event, EFL_INPUT_POINTER_CLASS);
|
||||||
|
|
||||||
|
pd = efl_data_scope_get(obj, MY_CLASS);
|
||||||
|
gesture_context = eina_hash_find(pd->m_gesture_contex, &target);
|
||||||
|
if (gesture_context)
|
||||||
|
{
|
||||||
|
// get the touch event for this particular widget
|
||||||
|
touch_event = eina_hash_find(pd->m_object_events, &target);
|
||||||
|
if (touch_event)
|
||||||
|
{
|
||||||
|
efl_gesture_touch_point_record(touch_event, pointer_data->tool, pointer_data->cur.x, pointer_data->cur.y,
|
||||||
|
pointer_data->timestamp, pointer_data->action);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
touch_event = efl_add(EFL_GESTURE_TOUCH_CLASS, NULL);
|
||||||
|
efl_gesture_touch_point_record(touch_event, pointer_data->tool, pointer_data->cur.x, pointer_data->cur.y,
|
||||||
|
pointer_data->timestamp, pointer_data->action);
|
||||||
|
eina_hash_add(pd->m_object_events, &target, touch_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_UNKNOWN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(gesture_context, l, gesture_type)
|
||||||
|
{
|
||||||
|
recognizer = eina_hash_find(pd->m_recognizers, &gesture_type);
|
||||||
|
gesture = _get_state(pd, target, recognizer, gesture_type);
|
||||||
|
if (!gesture)
|
||||||
|
continue;
|
||||||
|
recog_result = efl_gesture_recognizer_recognize(recognizer, gesture, target, touch_event);
|
||||||
|
recog_state = recog_result & EFL_GESTURE_RESULT_MASK;
|
||||||
|
if (recog_state == EFL_GESTURE_TRIGGER)
|
||||||
|
{
|
||||||
|
if (efl_gesture_state_get(gesture) == EFL_GESTURE_NONE)
|
||||||
|
efl_gesture_state_set(gesture, EFL_GESTURE_STARTED);
|
||||||
|
else
|
||||||
|
efl_gesture_state_set(gesture, EFL_GESTURE_UPDATED);
|
||||||
|
}
|
||||||
|
else if (recog_state == EFL_GESTURE_FINISH)
|
||||||
|
{
|
||||||
|
efl_gesture_state_set(gesture, EFL_GESTURE_FINISHED);
|
||||||
|
}
|
||||||
|
else if (recog_state == EFL_GESTURE_MAYBE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (recog_state == EFL_GESTURE_CANCEL)
|
||||||
|
{
|
||||||
|
if (efl_gesture_state_get(gesture) != EFL_GESTURE_NONE)
|
||||||
|
{
|
||||||
|
efl_gesture_state_set(gesture, EFL_GESTURE_CANCELED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (recog_state == EFL_GESTURE_IGNORE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
efl_event_callback_call(target, gesture_type, gesture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_END)
|
||||||
|
{
|
||||||
|
EINA_LIST_FOREACH(gesture_context, l, gesture_type)
|
||||||
|
_cleanup_cached_gestures(pd, target, gesture_type);
|
||||||
|
|
||||||
|
eina_hash_del(pd->m_object_events, &target, NULL);
|
||||||
|
// free gesture_to_delete list
|
||||||
|
_cleanup_object(pd->m_gestures_to_delete);
|
||||||
|
pd->m_gestures_to_delete = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static const Efl_Event_Description *
|
||||||
|
_efl_gesture_manager_recognizer_register(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd,
|
||||||
|
Efl_Gesture_Recognizer *recognizer)
|
||||||
|
{
|
||||||
|
Efl_Gesture_Recognizer_Data *rpd;
|
||||||
|
Efl_Gesture *dummy = efl_gesture_recognizer_create(recognizer, 0);
|
||||||
|
|
||||||
|
if (!dummy)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
const Efl_Event_Description *type = efl_gesture_type_get(dummy);
|
||||||
|
|
||||||
|
// Add the recognizer to the m_recognizers
|
||||||
|
eina_hash_add(pd->m_recognizers, &type, recognizer);
|
||||||
|
// update the manager
|
||||||
|
rpd = efl_data_scope_get(recognizer, EFL_GESTURE_RECOGNIZER_CLASS);
|
||||||
|
rpd->manager = obj;
|
||||||
|
|
||||||
|
efl_del(dummy);
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_gesture_manager_recognizer_unregister(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd,
|
||||||
|
Efl_Gesture_Recognizer *recognizer)
|
||||||
|
{
|
||||||
|
Eina_List *l, *l_next;
|
||||||
|
Object_Gesture *object_gesture;
|
||||||
|
const Efl_Event_Description *type;
|
||||||
|
Efl_Gesture *dummy;
|
||||||
|
|
||||||
|
if (!recognizer) return;
|
||||||
|
|
||||||
|
// find the type of the recognizer
|
||||||
|
dummy = efl_gesture_recognizer_create(recognizer, 0);
|
||||||
|
if (!dummy)return;
|
||||||
|
|
||||||
|
type = efl_gesture_type_get(dummy);
|
||||||
|
efl_del(dummy);
|
||||||
|
|
||||||
|
// check if its already registered
|
||||||
|
recognizer = eina_hash_find(pd->m_recognizers, &type);
|
||||||
|
|
||||||
|
if (!recognizer) return;
|
||||||
|
|
||||||
|
// remove that gesture from the list of object gestures
|
||||||
|
EINA_LIST_FOREACH_SAFE(pd->m_object_gestures, l, l_next, object_gesture)
|
||||||
|
{
|
||||||
|
if (object_gesture->type == type)
|
||||||
|
{
|
||||||
|
pd->m_gestures_to_delete = eina_list_append(pd->m_gestures_to_delete, object_gesture->gesture);
|
||||||
|
free(object_gesture);
|
||||||
|
pd->m_object_gestures = eina_list_remove_list(pd->m_object_gestures, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eina_hash_del(pd->m_recognizers, &type, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EOLIAN static void
|
||||||
|
// _efl_gesture_manager_ungrab_all(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd,
|
||||||
|
// Eo *target)
|
||||||
|
// {
|
||||||
|
// const Efl_Event_Description *type;
|
||||||
|
// Eina_List *l;
|
||||||
|
|
||||||
|
// Eina_List *gesture_type_list = eina_hash_find(pd->m_gesture_contex, &target);
|
||||||
|
|
||||||
|
// if (!gesture_type_list) return;
|
||||||
|
|
||||||
|
// EINA_LIST_FOREACH(gesture_type_list, l, type)
|
||||||
|
// {
|
||||||
|
// _cleanup_cached_gestures(obj, pd, target, type);
|
||||||
|
// }
|
||||||
|
// eina_hash_del(pd->m_gesture_contex, &target, NULL);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// get or create a gesture object that will represent the state for a given object, used by the recognizer
|
||||||
|
Efl_Gesture*
|
||||||
|
_get_state(Efl_Gesture_Manager_Data *pd,
|
||||||
|
Eo *target, Efl_Gesture_Recognizer *recognizer, const Efl_Event_Description *type)
|
||||||
|
{
|
||||||
|
Eina_List *l;
|
||||||
|
Object_Gesture *object_gesture;
|
||||||
|
Efl_Gesture *gesture;
|
||||||
|
|
||||||
|
// if the widget is being deleted we should be careful not to
|
||||||
|
// create a new state.
|
||||||
|
if (efl_destructed_is(target))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//TODO find a optimized way of looking for gesture
|
||||||
|
EINA_LIST_FOREACH(pd->m_object_gestures, l, object_gesture)
|
||||||
|
{
|
||||||
|
if (object_gesture->object == target &&
|
||||||
|
object_gesture->recognizer == recognizer &&
|
||||||
|
object_gesture->type == type)
|
||||||
|
{
|
||||||
|
// the gesture is already processed waiting for cleanup
|
||||||
|
if ((efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_FINISHED) ||
|
||||||
|
(efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_CANCELED))
|
||||||
|
return NULL;
|
||||||
|
return object_gesture->gesture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gesture = efl_gesture_recognizer_create(recognizer, target);
|
||||||
|
if (!gesture)
|
||||||
|
return 0;
|
||||||
|
object_gesture = calloc(1, sizeof(Object_Gesture));
|
||||||
|
object_gesture->object = target;
|
||||||
|
object_gesture->recognizer = recognizer;
|
||||||
|
object_gesture->type = type;
|
||||||
|
object_gesture->gesture = gesture;
|
||||||
|
|
||||||
|
pd->m_object_gestures = eina_list_append(pd->m_object_gestures, object_gesture);
|
||||||
|
|
||||||
|
return gesture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cleanup_cached_gestures(Efl_Gesture_Manager_Data *pd,
|
||||||
|
Eo *target, const Efl_Event_Description *type)
|
||||||
|
{
|
||||||
|
Eina_List *l, *l_next;
|
||||||
|
Object_Gesture *object_gesture;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH_SAFE(pd->m_object_gestures, l, l_next, object_gesture)
|
||||||
|
{
|
||||||
|
if ( (object_gesture->type == type) && (target == object_gesture->object))
|
||||||
|
{
|
||||||
|
pd->m_gestures_to_delete = eina_list_append(pd->m_gestures_to_delete, object_gesture->gesture);
|
||||||
|
free(object_gesture);
|
||||||
|
pd->m_object_gestures = eina_list_remove_list(pd->m_object_gestures, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "efl_gesture_manager.eo.c"
|
Loading…
Reference in New Issue