evas: Fix crash with events on the canvas

Since ecore now uses efl events to feed input events to the
canvas, anyone can now listen to any event on the evas. But
when using the legacy API the event info needs to be the legacy
struct, and not the eo event info otherwise crashes will happen.

While this is a new use of events, I consider it valid and it's
better to fix it rather than disallowing it. Fixed by wrapping
evas events the same way evas object events were handled.

Fixes T5266
This commit is contained in:
Jean-Philippe Andre 2017-03-14 15:30:40 +09:00
parent c15fee9bcc
commit 0b5b5e44a5
1 changed files with 75 additions and 46 deletions

View File

@ -100,19 +100,14 @@ typedef enum {
typedef struct
{
EINA_INLIST;
Evas_Object_Event_Cb func;
void *data;
Evas_Callback_Type type;
Efl_Event_Info_Type efl_event_type;
} _eo_evas_object_cb_info;
typedef struct
{
EINA_INLIST;
Evas_Event_Cb func;
void *data;
Evas_Callback_Type type;
} _eo_evas_cb_info;
union {
Evas_Event_Cb evas_cb;
Evas_Object_Event_Cb object_cb;
} func;
void *data;
Evas_Callback_Type type;
Efl_Event_Info_Type efl_event_type;
} Evas_Event_Cb_Wrapper_Info;
static int
_evas_event_efl_event_info_type(Evas_Callback_Type type)
@ -162,11 +157,11 @@ _eo_evas_object_cb(void *data, const Efl_Event *event)
{
Evas_Event_Flags *event_flags = NULL, evflags = EVAS_EVENT_FLAG_NONE;
Efl_Input_Event *efl_event_info = event->info;
_eo_evas_object_cb_info *info = data;
Evas_Event_Cb_Wrapper_Info *info = data;
void *event_info;
Evas *evas;
if (!info->func) return;
if (!info->func.object_cb) return;
evas = evas_object_evas_get(event->object);
event_info = event->info;
@ -185,19 +180,21 @@ _eo_evas_object_cb(void *data, const Efl_Event *event)
break;
case EFL_EVENT_TYPE_FOCUS:
event_info = NULL;
// NOTE: fallthrough here is explicitly intended!!!
case EFL_EVENT_TYPE_NULL:
info->func.object_cb(info->data, evas, event->object, NULL);
return;
case EFL_EVENT_TYPE_STRUCT:
case EFL_EVENT_TYPE_OBJECT:
info->func(info->data, evas, event->object, event_info);
info->func.object_cb(info->data, evas, event->object, event_info);
return;
default: return;
}
if (!event_info) return;
if (event_flags) evflags = *event_flags;
info->func(info->data, evas, event->object, event_info);
info->func.object_cb(info->data, evas, event->object, event_info);
if (event_flags && (evflags != *event_flags))
efl_input_event_flags_set(efl_event_info, *event_flags);
}
@ -205,20 +202,47 @@ _eo_evas_object_cb(void *data, const Efl_Event *event)
static void
_eo_evas_cb(void *data, const Efl_Event *event)
{
Evas_Event_Cb_Wrapper_Info *info = data;
Efl_Input_Event *efl_event_info = event->info;
Evas *evas = event->object;
void *event_info;
_eo_evas_cb_info *info = data;
//Keep the legacy behaviour for focus events.
if (event->desc == EFL_CANVAS_EVENT_FOCUS_IN ||
event->desc == EFL_CANVAS_EVENT_FOCUS_OUT)
event_info = NULL;
else if (event->desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_IN ||
event->desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_OUT)
event_info = efl_input_focus_object_get(event->info);
else
event_info = event->info;
if (!info->func.evas_cb) return;
if (info->func) info->func(info->data, event->object, event_info);
if (event->desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_IN ||
event->desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_OUT)
{
event_info = efl_input_focus_object_get(efl_event_info);
goto emit;
}
event_info = event->info;
switch (info->efl_event_type)
{
case EFL_EVENT_TYPE_POINTER:
event_info = efl_input_pointer_legacy_info_fill(evas, efl_event_info, info->type, NULL);
break;
case EFL_EVENT_TYPE_KEY:
event_info = efl_input_key_legacy_info_fill(efl_event_info, NULL);
break;
case EFL_EVENT_TYPE_HOLD:
event_info = efl_input_hold_legacy_info_fill(efl_event_info, NULL);
break;
case EFL_EVENT_TYPE_FOCUS:
case EFL_EVENT_TYPE_NULL:
event_info = NULL;
break;
case EFL_EVENT_TYPE_STRUCT:
case EFL_EVENT_TYPE_OBJECT:
break;
}
emit:
info->func.evas_cb(info->data, event->object, event_info);
}
void
@ -270,7 +294,7 @@ _evas_post_event_callback_free(Evas *eo_e)
void
evas_object_event_callback_all_del(Evas_Object *eo_obj)
{
_eo_evas_object_cb_info *info;
Evas_Event_Cb_Wrapper_Info *info;
Eina_Inlist *itr;
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
@ -295,7 +319,7 @@ evas_object_event_callback_cleanup(Evas_Object *eo_obj)
void
evas_event_callback_all_del(Evas *eo_e)
{
_eo_evas_object_cb_info *info;
Evas_Event_Cb_Wrapper_Info *info;
Eina_Inlist *itr;
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
@ -435,17 +459,19 @@ evas_object_event_callback_priority_add(Evas_Object *eo_obj, Evas_Callback_Type
if(!eo_obj) return;
EINA_SAFETY_ON_FALSE_RETURN(efl_isa(eo_obj, EFL_CANVAS_OBJECT_CLASS));
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
Evas_Event_Cb_Wrapper_Info *cb_info;
const Efl_Event_Description *desc;
if (!obj) return;
if (!func) return;
_eo_evas_object_cb_info *cb_info = calloc(1, sizeof(*cb_info));
cb_info->func = func;
cb_info = calloc(1, sizeof(*cb_info));
cb_info->func.object_cb = func;
cb_info->data = (void *)data;
cb_info->type = type;
cb_info->efl_event_type = _evas_event_efl_event_info_type(type);
const Efl_Event_Description *desc = _legacy_evas_callback_table(type);
desc = _legacy_evas_callback_table(type);
efl_event_callback_priority_add(eo_obj, desc, priority, _eo_evas_object_cb, cb_info);
obj->callbacks =
@ -458,7 +484,7 @@ evas_object_event_callback_del(Evas_Object *eo_obj, Evas_Callback_Type type, Eva
if(!eo_obj) return NULL;
EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(eo_obj, EFL_CANVAS_OBJECT_CLASS), NULL);
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
_eo_evas_object_cb_info *info;
Evas_Event_Cb_Wrapper_Info *info;
if (!obj) return NULL;
if (!func) return NULL;
@ -467,7 +493,7 @@ evas_object_event_callback_del(Evas_Object *eo_obj, Evas_Callback_Type type, Eva
EINA_INLIST_REVERSE_FOREACH(obj->callbacks, info)
{
if ((info->func == func) && (info->type == type))
if ((info->func.object_cb == func) && (info->type == type))
{
void *tmp = info->data;
efl_event_callback_del(eo_obj, _legacy_evas_callback_table(type), _eo_evas_object_cb, info);
@ -487,7 +513,7 @@ evas_object_event_callback_del_full(Evas_Object *eo_obj, Evas_Callback_Type type
if(!eo_obj) return NULL;
EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(eo_obj, EFL_CANVAS_OBJECT_CLASS), NULL);
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
_eo_evas_object_cb_info *info;
Evas_Event_Cb_Wrapper_Info *info;
if (!obj) return NULL;
if (!func) return NULL;
@ -496,7 +522,7 @@ evas_object_event_callback_del_full(Evas_Object *eo_obj, Evas_Callback_Type type
EINA_INLIST_FOREACH(obj->callbacks, info)
{
if ((info->func == func) && (info->type == type) && info->data == data)
if ((info->func.object_cb == func) && (info->type == type) && info->data == data)
{
void *tmp = info->data;
efl_event_callback_del(eo_obj, _legacy_evas_callback_table(type), _eo_evas_object_cb, info);
@ -523,15 +549,18 @@ evas_event_callback_priority_add(Evas *eo_e, Evas_Callback_Type type, Evas_Callb
if(!eo_e) return;
EINA_SAFETY_ON_FALSE_RETURN(efl_isa(eo_e, EVAS_CANVAS_CLASS));
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
Evas_Event_Cb_Wrapper_Info *cb_info;
const Efl_Event_Description *desc;
if (!func) return;
_eo_evas_cb_info *cb_info = calloc(1, sizeof(*cb_info));
cb_info->func = func;
cb_info = calloc(1, sizeof(*cb_info));
cb_info->func.evas_cb = func;
cb_info->data = (void *)data;
cb_info->type = type;
cb_info->efl_event_type = _evas_event_efl_event_info_type(type);
const Efl_Event_Description *desc = _legacy_evas_callback_table(type);
desc = _legacy_evas_callback_table(type);
efl_event_callback_priority_add(eo_e, desc, priority, _eo_evas_cb, cb_info);
e->callbacks = eina_inlist_append(e->callbacks, EINA_INLIST_GET(cb_info));
@ -543,7 +572,7 @@ evas_event_callback_del(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func)
if(!eo_e) return NULL;
EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(eo_e, EVAS_CANVAS_CLASS), NULL);
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
_eo_evas_cb_info *info;
Evas_Event_Cb_Wrapper_Info *info;
if (!e) return NULL;
if (!func) return NULL;
@ -552,7 +581,7 @@ evas_event_callback_del(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func)
EINA_INLIST_REVERSE_FOREACH(e->callbacks, info)
{
if ((info->func == func) && (info->type == type))
if ((info->func.evas_cb == func) && (info->type == type))
{
void *tmp = info->data;
efl_event_callback_del(eo_e, _legacy_evas_callback_table(type), _eo_evas_cb, info);
@ -572,7 +601,7 @@ evas_event_callback_del_full(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb
if(!eo_e) return NULL;
EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(eo_e, EVAS_CANVAS_CLASS), NULL);
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
_eo_evas_cb_info *info;
Evas_Event_Cb_Wrapper_Info *info;
if (!e) return NULL;
if (!func) return NULL;
@ -581,7 +610,7 @@ evas_event_callback_del_full(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb
EINA_INLIST_FOREACH(e->callbacks, info)
{
if ((info->func == func) && (info->type == type) && (info->data == data))
if ((info->func.evas_cb == func) && (info->type == type) && (info->data == data))
{
void *tmp = info->data;
efl_event_callback_del(eo_e, _legacy_evas_callback_table(type), _eo_evas_cb, info);