diff --git a/src/lib/evas/Evas_Internal.h b/src/lib/evas/Evas_Internal.h index 782742f5d9..d631cdcde5 100644 --- a/src/lib/evas/Evas_Internal.h +++ b/src/lib/evas/Evas_Internal.h @@ -38,6 +38,8 @@ extern "C" { #include +typedef struct _Evas_Object_Pointer_Data Evas_Object_Pointer_Data; + EOAPI const Eina_List *efl_input_device_children_get(const Eo *obj); EOAPI void efl_input_device_evas_set(Eo *obj, Evas *e); @@ -46,6 +48,9 @@ EOAPI Evas *efl_input_device_evas_get(const Eo *obj); EOAPI void efl_input_device_subclass_set(Eo *obj, Evas_Device_Subclass sub_clas); EOAPI Evas_Device_Subclass efl_input_device_subclass_get(const Eo *obj); +EOAPI void efl_input_device_grab_register(Eo *obj, Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata); +EOAPI void efl_input_device_grab_unregister(Eo *obj, Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata); + typedef struct _Efl_Input_Pointer_Data Efl_Input_Pointer_Data; typedef struct _Efl_Input_Key_Data Efl_Input_Key_Data; typedef struct _Efl_Input_Hold_Data Efl_Input_Hold_Data; diff --git a/src/lib/evas/canvas/efl_input_device.c b/src/lib/evas/canvas/efl_input_device.c index 607ffd5f76..52eae92cbb 100644 --- a/src/lib/evas/canvas/efl_input_device.c +++ b/src/lib/evas/canvas/efl_input_device.c @@ -5,6 +5,8 @@ #include "Evas.h" #define EFL_INTERNAL_UNSTABLE #include "Evas_Internal.h" +#include "evas_common_private.h" +#include "evas_private.h" #define MY_CLASS EFL_INPUT_DEVICE_CLASS @@ -16,6 +18,9 @@ struct _Efl_Input_Device_Data Eo *evas; /* Evas */ Efl_Input_Device *source; /* ref */ Eina_List *children; /* ref'ed by efl_parent, not by this list */ + Eina_Hash *grabs; /* Hash of all the object that might grab this device. + We expect thousand of them to be registered here, + that is why we use a hash. */ unsigned int id; Efl_Input_Device_Type klass; unsigned int subclass; // Evas_Device_Subclass (unused) @@ -71,6 +76,12 @@ _efl_input_device_efl_object_destructor(Eo *obj, Efl_Input_Device_Data *pd) } efl_unref(pd->source); + if (pd->grabs) + { + eina_hash_free(pd->grabs); + pd->grabs = NULL; + } + return efl_destructor(efl_super(obj, MY_CLASS)); } @@ -279,11 +290,42 @@ _efl_input_device_subclass_set(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd, EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_subclass_set, EFL_FUNC_CALL(sub_clas), Evas_Device_Subclass sub_clas); +static void +_grab_del(void *data) +{ + Evas_Object_Pointer_Data *pdata = data; + + evas_object_pointer_grab_del(pdata->obj, pdata); +} + +static void +_efl_input_device_grab_register(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd, + Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata) +{ + if (!pd->grabs) pd->grabs = eina_hash_pointer_new(_grab_del); + eina_hash_add(pd->grabs, &grab, pdata); +} + +EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_register, EFL_FUNC_CALL(grab, pdata), + Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata); + +static void +_efl_input_device_grab_unregister(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd, + Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata) +{ + eina_hash_del(pd->grabs, &grab, pdata); +} + +EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_unregister, EFL_FUNC_CALL(grab, pdata), + Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata); + #define EFL_INPUT_DEVICE_EXTRA_OPS \ EFL_OBJECT_OP_FUNC(efl_input_device_evas_get, _efl_input_device_evas_get), \ EFL_OBJECT_OP_FUNC(efl_input_device_evas_set, _efl_input_device_evas_set), \ EFL_OBJECT_OP_FUNC(efl_input_device_subclass_get, _efl_input_device_subclass_get), \ EFL_OBJECT_OP_FUNC(efl_input_device_subclass_set, _efl_input_device_subclass_set), \ EFL_OBJECT_OP_FUNC(efl_input_device_children_get, _efl_input_device_children_get), \ + EFL_OBJECT_OP_FUNC(efl_input_device_grab_register, _efl_input_device_grab_register), \ + EFL_OBJECT_OP_FUNC(efl_input_device_grab_unregister, _efl_input_device_grab_unregister), #include "efl_input_device.eo.c" diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c index 27ec6e2bfc..d5b20aed22 100644 --- a/src/lib/evas/canvas/evas_object_main.c +++ b/src/lib/evas/canvas/evas_object_main.c @@ -81,9 +81,9 @@ _init_cow(void) return EINA_TRUE; } -static Evas_Object_Pointer_Data * -_evas_object_pointer_data_find(Evas_Object_Protected_Data *obj, - Efl_Input_Device *pointer) +Evas_Object_Pointer_Data * +evas_object_pointer_data_find(Evas_Object_Protected_Data *obj, + Efl_Input_Device *pointer) { Evas_Object_Pointer_Data *pdata; @@ -95,22 +95,6 @@ _evas_object_pointer_data_find(Evas_Object_Protected_Data *obj, return NULL; } -static void -_evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj, Evas_Object_Pointer_Data *pdata); - -static void -_evas_device_del_cb(void *data, const Efl_Event *ev) -{ - Evas_Object_Protected_Data *obj; - Evas_Object_Pointer_Data *pdata; - - obj = efl_data_scope_safe_get(data, MY_CLASS); - EINA_SAFETY_ON_NULL_RETURN(obj); - pdata = _evas_object_pointer_data_find(obj, ev->object); - if (!pdata) return; - _evas_object_pointer_grab_del(obj, pdata); -} - static void _evas_object_proxy_grab_del(Evas_Object_Protected_Data *obj, Evas_Object_Pointer_Data *pdata) @@ -138,9 +122,9 @@ _evas_object_proxy_grab_del(Evas_Object_Protected_Data *obj, } } -static void -_evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj, - Evas_Object_Pointer_Data *pdata) +void +evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj, + Evas_Object_Pointer_Data *pdata) { if ((pdata->mouse_grabbed > 0) && (obj->layer) && (obj->layer->evas)) pdata->evas_pdata->seat->mouse_grabbed -= pdata->mouse_grabbed; @@ -151,11 +135,12 @@ _evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj, if (obj->proxy->is_proxy && obj->proxy->src_events) _evas_object_proxy_grab_del(obj, pdata); } - efl_event_callback_del(pdata->evas_pdata->pointer, EFL_EVENT_DEL, - _evas_device_del_cb, obj->object); - EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) - events->pointer_grabs = eina_inlist_remove(events->pointer_grabs, EINA_INLIST_GET(pdata)); - EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); + if (obj->events->pointer_grabs) + { + EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) + events->pointer_grabs = eina_inlist_remove(events->pointer_grabs, EINA_INLIST_GET(pdata)); + EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); + } free(pdata); } @@ -170,14 +155,13 @@ _evas_object_pointer_data_add(Evas_Pointer_Data *evas_pdata, EINA_SAFETY_ON_NULL_RETURN_VAL(pdata, NULL); pdata->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB; pdata->evas_pdata = evas_pdata; + pdata->obj = obj; EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) events->pointer_grabs = eina_inlist_append(events->pointer_grabs, EINA_INLIST_GET(pdata)); EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); - efl_event_callback_priority_add(evas_pdata->pointer, EFL_EVENT_DEL, - EFL_CALLBACK_PRIORITY_BEFORE, - _evas_device_del_cb, obj->object); + efl_input_device_grab_register(evas_pdata->pointer, obj->object, pdata); return pdata; } @@ -187,7 +171,7 @@ _evas_object_pointer_data_get(Evas_Pointer_Data *evas_pdata, { Evas_Object_Pointer_Data *pdata; - pdata = _evas_object_pointer_data_find(obj, evas_pdata->pointer); + pdata = evas_object_pointer_data_find(obj, evas_pdata->pointer); //The pointer does not exist yet - create one. if (!pdata) @@ -1068,29 +1052,39 @@ _efl_canvas_object_efl_object_invalidate(Eo *eo_obj, Evas_Object_Protected_Data evas_object_hide(eo_obj); if (obj->events) - EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) - { - Evas_Public_Data *edata = NULL; + { + Eina_Inlist *pointer_grabs; - if (!efl_invalidated_get(evas_object_evas_get(eo_obj))) - edata = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS); + EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) + { + Evas_Public_Data *edata = NULL; - EINA_LIST_FREE (events->focused_by_seats, dev) - { - event_id = _evas_event_counter; - efl_event_callback_del(dev, EFL_EVENT_INVALIDATE, - _evas_focus_device_invalidate_cb, obj); - if (edata) eina_hash_del_by_key(edata->focused_objects, &dev); - _evas_focus_dispatch_event(obj, dev, EINA_FALSE); - if ((obj->layer) && (obj->layer->evas)) - _evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas, event_id); - } - EINA_INLIST_FREE(events->pointer_grabs, pdata) - _evas_object_pointer_grab_del(obj, pdata); - EINA_LIST_FREE(events->events_whitelist, dev) - efl_event_callback_del(dev, EFL_EVENT_DEL, _whitelist_events_device_remove_cb, obj); - } - EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); + if (!efl_invalidated_get(evas_object_evas_get(eo_obj))) + edata = efl_data_scope_get(evas_object_evas_get(eo_obj), EVAS_CANVAS_CLASS); + + EINA_LIST_FREE (events->focused_by_seats, dev) + { + event_id = _evas_event_counter; + efl_event_callback_del(dev, EFL_EVENT_INVALIDATE, + _evas_focus_device_invalidate_cb, obj); + if (edata) eina_hash_del_by_key(edata->focused_objects, &dev); + _evas_focus_dispatch_event(obj, dev, EINA_FALSE); + if ((obj->layer) && (obj->layer->evas)) + _evas_post_event_callback_call(obj->layer->evas->evas, obj->layer->evas, event_id); + } + pointer_grabs = events->pointer_grabs; + events->pointer_grabs = NULL; + EINA_LIST_FREE(events->events_whitelist, dev) + efl_event_callback_del(dev, EFL_EVENT_DEL, _whitelist_events_device_remove_cb, obj); + } + EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); + + EINA_INLIST_FREE(pointer_grabs, pdata) + { + pointer_grabs = eina_inlist_remove(pointer_grabs, EINA_INLIST_GET(pdata)); + efl_input_device_grab_unregister(pdata->evas_pdata->pointer, eo_obj, pdata); + } + } event_id = _evas_object_event_new(); evas_object_event_callback_call(eo_obj, obj, EVAS_CALLBACK_DEL, NULL, event_id, NULL); diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 6906195db9..2081c3dc85 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -77,6 +77,7 @@ typedef struct _Evas_Format Evas_Format; typedef struct _Evas_Map_Point Evas_Map_Point; typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array; typedef struct _Evas_Smart_Interfaces_Array Evas_Smart_Interfaces_Array; +typedef enum _Evas_Object_Intercept_Cb_Type Evas_Object_Intercept_Cb_Type; typedef struct _Evas_Post_Callback Evas_Post_Callback; typedef struct _Evas_Coord_Touch_Point Evas_Coord_Touch_Point; typedef struct _Evas_Object_Proxy_Data Evas_Object_Proxy_Data; @@ -1095,6 +1096,7 @@ struct _Evas_Object_Protected_State struct _Evas_Object_Pointer_Data { EINA_INLIST; + Evas_Object_Protected_Data *obj; Evas_Pointer_Data *evas_pdata; Evas_Object_Pointer_Mode pointer_mode; int mouse_grabbed; @@ -1679,6 +1681,10 @@ void evas_object_inform_call_image_preloaded(Evas_Object *obj); void evas_object_inform_call_image_unloaded(Evas_Object *obj); void evas_object_inform_call_image_resize(Evas_Object *obj); void evas_object_intercept_cleanup(Evas_Object *obj); +Evas_Object_Pointer_Data *evas_object_pointer_data_find(Evas_Object_Protected_Data *obj, + Efl_Input_Device *pointer); +void evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj, + Evas_Object_Pointer_Data *pdata); void evas_object_grabs_cleanup(Evas_Object *obj, Evas_Object_Protected_Data *pd); void evas_key_grab_free(Evas_Object *obj, Evas_Object_Protected_Data *pd, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers); void evas_object_smart_member_cache_invalidate(Evas_Object *obj, Eina_Bool pass_events, Eina_Bool freeze_events, Eina_Bool source_invisible);