forked from enlightenment/efl
evas: Defer render post callbacks added during async render
Summary: To take screenshots, Enlightenment makes a new snapshot object, performs a manual render, and uses the snapshot results. Turns out if this happens while an async render is in progress, the async render's completion triggers a render post callback on the snapshot object even though it's never been involved in a render. We need to defer new render post callbacks until any currently running render completes, then add them during that render's post. Fix T7156 Reviewers: devilhorns, zmike Reviewed By: devilhorns, zmike Subscribers: devilhorns, cedric, #committers, zmike Tags: #efl Maniphest Tasks: T7156 Differential Revision: https://phab.enlightenment.org/D6711
This commit is contained in:
parent
3524d48719
commit
e7bcf0e690
|
@ -107,6 +107,7 @@ typedef struct
|
|||
void *data;
|
||||
Evas_Callback_Type type;
|
||||
Efl_Event_Info_Type efl_event_type;
|
||||
Evas_Callback_Priority priority;
|
||||
} Evas_Event_Cb_Wrapper_Info;
|
||||
|
||||
static int
|
||||
|
@ -563,6 +564,24 @@ evas_event_callback_add(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func,
|
|||
func, data);
|
||||
}
|
||||
|
||||
void
|
||||
_deferred_callbacks_process(Evas *eo_e, Evas_Public_Data *e)
|
||||
{
|
||||
Evas_Event_Cb_Wrapper_Info *cb_info;
|
||||
const Efl_Event_Description *desc;
|
||||
|
||||
while (e->deferred_callbacks)
|
||||
{
|
||||
cb_info = EINA_INLIST_CONTAINER_GET(e->deferred_callbacks,
|
||||
Evas_Event_Cb_Wrapper_Info);
|
||||
e->deferred_callbacks = eina_inlist_remove(e->deferred_callbacks,
|
||||
e->deferred_callbacks);
|
||||
desc = _legacy_evas_callback_table(cb_info->type);
|
||||
efl_event_callback_priority_add(eo_e, desc, cb_info->priority, _eo_evas_cb, cb_info);
|
||||
e->callbacks = eina_inlist_append(e->callbacks, EINA_INLIST_GET(cb_info));
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_event_callback_priority_add(Evas *eo_e, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Event_Cb func, const void *data)
|
||||
{
|
||||
|
@ -581,13 +600,22 @@ evas_event_callback_priority_add(Evas *eo_e, Evas_Callback_Type type, Evas_Callb
|
|||
cb_info = calloc(1, sizeof(*cb_info));
|
||||
cb_info->func.evas_cb = func;
|
||||
cb_info->data = (void *)data;
|
||||
cb_info->priority = priority;
|
||||
cb_info->type = type;
|
||||
cb_info->efl_event_type = _evas_event_efl_event_info_type(type);
|
||||
|
||||
desc = _legacy_evas_callback_table(type);
|
||||
efl_event_callback_priority_add(eo_e, desc, priority, _eo_evas_cb, cb_info);
|
||||
if ((e->rendering || e->inside_post_render) && type == EVAS_CALLBACK_RENDER_POST)
|
||||
{
|
||||
e->deferred_callbacks = eina_inlist_append(e->deferred_callbacks,
|
||||
EINA_INLIST_GET(cb_info));
|
||||
}
|
||||
else
|
||||
{
|
||||
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));
|
||||
e->callbacks = eina_inlist_append(e->callbacks, EINA_INLIST_GET(cb_info));
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
|
@ -604,6 +632,20 @@ evas_event_callback_del(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func)
|
|||
|
||||
if (!e->callbacks) return NULL;
|
||||
|
||||
if (type == EVAS_CALLBACK_RENDER_POST)
|
||||
EINA_INLIST_REVERSE_FOREACH(e->deferred_callbacks, info)
|
||||
{
|
||||
if (info->func.evas_cb == func)
|
||||
{
|
||||
void *tmp = info->data;
|
||||
|
||||
e->deferred_callbacks =
|
||||
eina_inlist_remove(e->deferred_callbacks, EINA_INLIST_GET(info));
|
||||
free(info);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
EINA_INLIST_REVERSE_FOREACH(e->callbacks, info)
|
||||
{
|
||||
if ((info->func.evas_cb == func) && (info->type == type))
|
||||
|
@ -634,6 +676,20 @@ evas_event_callback_del_full(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb
|
|||
|
||||
if (!e->callbacks) return NULL;
|
||||
|
||||
if (type == EVAS_CALLBACK_RENDER_POST)
|
||||
EINA_INLIST_REVERSE_FOREACH(e->deferred_callbacks, info)
|
||||
{
|
||||
if ((info->func.evas_cb == func) && (info->data == data))
|
||||
{
|
||||
void *tmp = info->data;
|
||||
|
||||
e->deferred_callbacks =
|
||||
eina_inlist_remove(e->deferred_callbacks, EINA_INLIST_GET(info));
|
||||
free(info);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
EINA_INLIST_FOREACH(e->callbacks, info)
|
||||
{
|
||||
if ((info->func.evas_cb == func) && (info->type == type) && (info->data == data))
|
||||
|
|
|
@ -3838,6 +3838,7 @@ evas_render_wakeup(Evas *eo_e)
|
|||
post.updated_area = ret_updates;
|
||||
_cb_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
|
||||
evas->inside_post_render = EINA_FALSE;
|
||||
_deferred_callbacks_process(eo_e, evas);
|
||||
|
||||
evas_render_updates_free(ret_updates);
|
||||
|
||||
|
|
|
@ -860,6 +860,7 @@ struct _Evas_Public_Data
|
|||
Eina_List *post_events; // free me on evas_free
|
||||
|
||||
Eina_Inlist *callbacks;
|
||||
Eina_Inlist *deferred_callbacks;
|
||||
|
||||
int delete_grabs;
|
||||
int walking_grabs;
|
||||
|
@ -1914,6 +1915,8 @@ void _efl_canvas_gesture_manager_callback_add_hook(Eo *gesture_manager, Eo *targ
|
|||
void evas_focus_init(void);
|
||||
void evas_focus_shutdown(void);
|
||||
|
||||
void _deferred_callbacks_process(Evas *eo_e, Evas_Public_Data *e);
|
||||
|
||||
extern Eina_Cow *evas_object_proxy_cow;
|
||||
extern Eina_Cow *evas_object_map_cow;
|
||||
extern Eina_Cow *evas_object_state_cow;
|
||||
|
|
Loading…
Reference in New Issue