forked from enlightenment/efl
evas: Fix dangling references with input devices
This solves issues with efl_input_dup() which didn't properly give a reference to the caller, resulting in dangling eo ids. Note: This may trigger leaks (instead of invalid refs), but this now actually reflects the meaning of @owned. This should work with bindings and C API users should know to call efl_unref(). This patch is the reason for the previous improvements on eo_debug. @fix
This commit is contained in:
parent
3dc140abfb
commit
96d94e0076
|
@ -114,7 +114,7 @@ struct _Efl_Input_Focus_Data
|
|||
{
|
||||
Eo *eo;
|
||||
Efl_Input_Device *device; //The seat
|
||||
Eo *object; //The focused object - Efl.Canvas.Object or Efl.Canvas.
|
||||
Eo *object_wref; // wref on the focused object - Efl.Canvas.Object or Efl.Canvas.
|
||||
double timestamp;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,8 +31,15 @@ mixin Efl.Input.Event (Efl.Interface, Efl.Object)
|
|||
[[Resets the internal data to 0 or default values.]]
|
||||
}
|
||||
dup @pure_virtual {
|
||||
[[Creates a copy of this event.]]
|
||||
return: Efl.Input.Event @owned; [[Event copy]]
|
||||
[[Creates a copy of this event.
|
||||
|
||||
The returned event object is similar to the given object in most
|
||||
ways except that @.fake will be $true.
|
||||
|
||||
Note: A reference is given to the caller. In order to avoid leaks
|
||||
the C API users should call $efl_unref() after use.
|
||||
]]
|
||||
return: Efl.Input.Event @owned; [[Event copy, marked as @.fake.]]
|
||||
}
|
||||
@property device @pure_virtual {
|
||||
[[Input device that originated this event.]]
|
||||
|
|
|
@ -39,6 +39,7 @@ _del_hook(Eo *evt)
|
|||
static void
|
||||
_efl_input_focus_free(Efl_Input_Focus_Data *pd)
|
||||
{
|
||||
efl_wref_del_safe(&pd->object_wref);
|
||||
efl_unref(pd->device);
|
||||
}
|
||||
|
||||
|
@ -71,13 +72,13 @@ EOLIAN static void
|
|||
_efl_input_focus_object_set(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data *pd,
|
||||
Efl_Object *object)
|
||||
{
|
||||
pd->object = object;
|
||||
pd->object_wref = object;
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Object *
|
||||
_efl_input_focus_object_get(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data *pd)
|
||||
{
|
||||
return pd->object;
|
||||
return pd->object_wref;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
|
@ -111,18 +112,20 @@ _efl_input_focus_efl_input_event_timestamp_get(Eo *obj EINA_UNUSED,
|
|||
}
|
||||
|
||||
EOLIAN static Efl_Input_Focus *
|
||||
_efl_input_focus_efl_input_event_dup(Eo *obj, Efl_Input_Focus_Data *pd)
|
||||
_efl_input_focus_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Focus_Data *pd)
|
||||
{
|
||||
Efl_Input_Focus_Data *ev;
|
||||
Efl_Input_Focus *evt;
|
||||
|
||||
evt = efl_input_instance_get(MY_CLASS, efl_parent_get(obj), (void **) &ev);
|
||||
if (!evt || !ev) return NULL;
|
||||
evt = efl_add(MY_CLASS, NULL);
|
||||
ev = efl_data_scope_get(evt, MY_CLASS);
|
||||
if (!ev) return NULL;
|
||||
|
||||
memcpy(ev, pd, sizeof(*ev));
|
||||
ev->eo = evt;
|
||||
ev->object = pd->object;
|
||||
ev->device = efl_ref(pd->device);
|
||||
ev->timestamp = pd->timestamp;
|
||||
efl_wref_add(ev->object_wref, &ev->object_wref);
|
||||
|
||||
return evt;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,17 +101,19 @@ _efl_input_hold_efl_input_event_reset(Eo *obj, Efl_Input_Hold_Data *pd)
|
|||
}
|
||||
|
||||
EOLIAN static Efl_Input_Event *
|
||||
_efl_input_hold_efl_input_event_dup(Eo *obj, Efl_Input_Hold_Data *pd)
|
||||
_efl_input_hold_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Hold_Data *pd)
|
||||
{
|
||||
Efl_Input_Hold_Data *ev;
|
||||
Efl_Input_Event *evt = efl_add(EFL_INPUT_HOLD_CLASS, efl_parent_get(obj));
|
||||
Efl_Input_Hold *evt;
|
||||
|
||||
evt = efl_add(MY_CLASS, NULL);
|
||||
ev = efl_data_scope_get(evt, MY_CLASS);
|
||||
if (!ev) return NULL;
|
||||
|
||||
memcpy(ev, pd, sizeof(*ev));
|
||||
ev->eo = evt;
|
||||
ev->timestamp = pd->timestamp;
|
||||
ev->data = pd->data;
|
||||
ev->hold = pd->hold;
|
||||
ev->legacy = NULL;
|
||||
ev->evas_done = 0;
|
||||
ev->device = efl_ref(pd->device);
|
||||
|
||||
return evt;
|
||||
|
|
|
@ -188,13 +188,14 @@ _efl_input_key_efl_input_event_reset(Eo *obj EINA_UNUSED, Efl_Input_Key_Data *pd
|
|||
}
|
||||
|
||||
EOLIAN static Efl_Input_Event *
|
||||
_efl_input_key_efl_input_event_dup(Eo *obj, Efl_Input_Key_Data *pd)
|
||||
_efl_input_key_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Key_Data *pd)
|
||||
{
|
||||
Efl_Input_Key_Data *ev;
|
||||
Efl_Input_Key *evt;
|
||||
|
||||
evt = efl_input_instance_get(MY_CLASS, efl_parent_get(obj), (void **) &ev);
|
||||
if (!evt || !ev) return NULL;
|
||||
evt = efl_add(MY_CLASS, NULL);
|
||||
ev = efl_data_scope_get(evt, MY_CLASS);
|
||||
if (!ev) return NULL;
|
||||
|
||||
memcpy(ev, pd, sizeof(*ev));
|
||||
ev->eo = evt;
|
||||
|
|
|
@ -143,13 +143,14 @@ _efl_input_pointer_efl_input_event_reset(Eo *obj, Efl_Input_Pointer_Data *pd)
|
|||
}
|
||||
|
||||
EOLIAN static Efl_Input_Event *
|
||||
_efl_input_pointer_efl_input_event_dup(Eo *obj, Efl_Input_Pointer_Data *pd)
|
||||
_efl_input_pointer_efl_input_event_dup(Eo *obj EINA_UNUSED, Efl_Input_Pointer_Data *pd)
|
||||
{
|
||||
Efl_Input_Pointer_Data *ev;
|
||||
Efl_Input_Pointer *evt;
|
||||
Efl_Input_Focus *evt;
|
||||
|
||||
evt = efl_input_instance_get(MY_CLASS, efl_parent_get(obj), (void **) &ev);
|
||||
if (!evt) return NULL;
|
||||
evt = efl_add(MY_CLASS, NULL);
|
||||
ev = efl_data_scope_get(evt, MY_CLASS);
|
||||
if (!ev) return NULL;
|
||||
|
||||
memcpy(ev, pd, sizeof(*ev));
|
||||
ev->eo = evt;
|
||||
|
@ -157,7 +158,6 @@ _efl_input_pointer_efl_input_event_dup(Eo *obj, Efl_Input_Pointer_Data *pd)
|
|||
ev->evas_done = 0;
|
||||
ev->win_fed = 0;
|
||||
ev->fake = 1;
|
||||
ev->legacy = NULL;
|
||||
ev->device = efl_ref(pd->device);
|
||||
|
||||
return evt;
|
||||
|
|
|
@ -460,7 +460,7 @@ evas_device_seat_id_get(const Evas_Device *dev)
|
|||
void
|
||||
_evas_device_cleanup(Evas *eo_e)
|
||||
{
|
||||
Eina_List *cpy;
|
||||
Eina_List *cpy, *deleted = NULL;
|
||||
Evas_Device *dev;
|
||||
Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
|
||||
|
||||
|
@ -473,19 +473,26 @@ _evas_device_cleanup(Evas *eo_e)
|
|||
}
|
||||
|
||||
/* If the device is deleted, _del_cb will remove the device
|
||||
from the devices list. */
|
||||
* from the devices list. Ensure we delete them only once, and only if this
|
||||
* Evas is the owner, otherwise we would kill external references (eg.
|
||||
* from efl_input_dup()). */
|
||||
again:
|
||||
e->devices_modified = EINA_FALSE;
|
||||
cpy = eina_list_clone(e->devices);
|
||||
EINA_LIST_FREE(cpy, dev)
|
||||
{
|
||||
if (!eina_list_data_find(deleted, dev) && (efl_parent_get(dev) == eo_e))
|
||||
{
|
||||
evas_device_del(dev);
|
||||
deleted = eina_list_append(deleted, dev);
|
||||
if (e->devices_modified)
|
||||
{
|
||||
eina_list_free(cpy);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
eina_list_free(deleted);
|
||||
|
||||
/* Not all devices were deleted. The user probably will unref them later.
|
||||
Since Evas will be deleted, remove the del callback from them and
|
||||
|
@ -493,9 +500,7 @@ again:
|
|||
*/
|
||||
EINA_LIST_FREE(e->devices, dev)
|
||||
{
|
||||
efl_event_callback_call(e->evas,
|
||||
EFL_CANVAS_EVENT_DEVICE_REMOVED,
|
||||
dev);
|
||||
efl_event_callback_call(e->evas, EFL_CANVAS_EVENT_DEVICE_REMOVED, dev);
|
||||
efl_event_callback_del(dev, EFL_EVENT_DEL, _del_cb, e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ _evas_focus_dispatch_event(Evas_Object_Protected_Data *obj, Efl_Input_Device *se
|
|||
if (!evt) return;
|
||||
|
||||
ev_data->device = efl_ref(seat);
|
||||
ev_data->object = obj->object;
|
||||
efl_wref_add(obj->object, &ev_data->object_wref);
|
||||
ev_data->timestamp = time(NULL);
|
||||
|
||||
if (in)
|
||||
|
|
Loading…
Reference in New Issue