efl/gesture: redo (and make stupider) hash usage in gesture manager

this rewrites the gesture event dispatcher to use a hash of hashes for
tracking which events are being watched on a given object to avoid:
* dispatching n gesture events per object to each callback, where n is the
  number of gesture callbacks for any given type
* removing all gesture callbacks when only one callback is removed

this is not smart code. it should be improved at some time, but that time
is not now.

Differential Revision: https://phab.enlightenment.org/D11144
This commit is contained in:
Mike Blumenkrantz 2020-01-21 14:51:16 -05:00 committed by Marcel Hollerbach
parent 38641ecd9b
commit e41434d96d
1 changed files with 107 additions and 83 deletions

View File

@ -14,7 +14,7 @@ typedef struct _Object_Gesture
typedef struct _Efl_Canvas_Gesture_Manager_Data
{
//Keeps track of all the gesture request for a particular target
Eina_Hash *m_gesture_contex; // (*target, *event_desc)
Eina_Hash *m_gesture_contex; // (*target, Eina_Hash(type, int))
//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
@ -59,7 +59,7 @@ _efl_canvas_gesture_manager_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_M
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->m_recognizers = eina_hash_pointer_new(EINA_FREE_CB(_hash_unref_cb));
pd->m_gesture_contex = eina_hash_pointer_new(NULL);
pd->m_gesture_contex = eina_hash_pointer_new(EINA_FREE_CB(eina_hash_free));
pd->m_object_events = eina_hash_pointer_new(EINA_FREE_CB(_hash_unref_cb));
pd->m_object_gestures = NULL;
pd->m_gestures_to_delete = NULL;
@ -136,7 +136,18 @@ _efl_canvas_gesture_manager_callback_add_hook(void *data, Eo *target, const Efl_
if (recognizer)
{
//Add it to the gesture context.
eina_hash_list_append(pd->m_gesture_contex, &target, type);
Eina_Hash *thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
int count = 0;
/* already present */
if (thisisreallystupid)
count = (intptr_t)eina_hash_find(thisisreallystupid, &type);
else
{
thisisreallystupid = eina_hash_pointer_new(NULL);
eina_hash_set(pd->m_gesture_contex, &target, thisisreallystupid);
}
count++;
eina_hash_set(thisisreallystupid, &type, (intptr_t*)(long)count);
}
}
@ -148,7 +159,18 @@ _efl_canvas_gesture_manager_callback_del_hook(void *data, Eo *target, const Efl_
Efl_Canvas_Gesture_Recognizer *recognizer = eina_hash_find(pd->m_recognizers, &type);
if (recognizer)
{
eina_hash_list_remove(pd->m_gesture_contex, &target, type);
Eina_Hash *thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
int count;
if (!thisisreallystupid) return;
count = (intptr_t)eina_hash_find(thisisreallystupid, &type);
if (!count) return;
count--;
eina_hash_set(thisisreallystupid, &type, (intptr_t*)(long)count);
if (count) return;
eina_hash_del_by_key(thisisreallystupid, &type);
if (eina_hash_population(thisisreallystupid)) return;
eina_hash_del_by_key(pd->m_gesture_contex, &target);
_cleanup_cached_gestures(pd, target, type);
}
}
@ -157,19 +179,21 @@ void
_efl_canvas_gesture_manager_filter_event(void *data, Eo *target, void *event)
{
Efl_Canvas_Gesture_Manager_Data *pd = data;
Eina_List *l, *gesture_context;
const Efl_Event_Description *gesture_type;
Eina_Hash *thisisreallystupid;
Eina_Iterator *it;
Eina_Hash_Tuple *tup;
Efl_Canvas_Gesture_Recognizer *recognizer;
Efl_Canvas_Gesture *gesture;
Efl_Canvas_Gesture_Recognizer_Result recog_result;
Efl_Canvas_Gesture_Recognizer_Result recog_state;
Efl_Canvas_Gesture_Touch *touch_event;
gesture_context = eina_hash_find(pd->m_gesture_contex, &target);
if (gesture_context)
{
EINA_LIST_FOREACH(gesture_context, l, gesture_type)
thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
if (!thisisreallystupid) return;
it = eina_hash_iterator_tuple_new(thisisreallystupid);
EINA_ITERATOR_FOREACH(it, tup)
{
const Efl_Event_Description *gesture_type = *(void**)tup->key;
//Check there is already created event exist or not.
touch_event = eina_hash_find(pd->m_object_events, &gesture_type);
@ -248,7 +272,7 @@ post_event:
pd->m_gestures_to_delete = NULL;
}
}
}
eina_iterator_free(it);
}
EOLIAN static void