forked from enlightenment/efl
evas: Fix layer usage count and deletion
When using smart objects (quite likely, isn't it?), the internal layer usage count was not perfectly tracked. This was especially true if layer_set() was called on a (top-level) smart object. As a consequence, there could be no objects in the layer but the usage would still be > 0. Thus, the layer was not deleted, not removed from the inlist of layers, and efl_gfx_stack_above_get() could return NULL as the layer above a certain object was empty. Fixes T5201
This commit is contained in:
parent
500401364d
commit
aacd25ef6b
|
@ -1,8 +1,6 @@
|
|||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
static void _evas_layer_free(Evas_Layer *lay);
|
||||
|
||||
void
|
||||
evas_object_inject(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas *e)
|
||||
{
|
||||
|
@ -44,7 +42,6 @@ evas_object_release(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, int cl
|
|||
if (obj->layer->usage <= 0)
|
||||
{
|
||||
evas_layer_del(obj->layer);
|
||||
_evas_layer_free(obj->layer);
|
||||
}
|
||||
}
|
||||
obj->layer = NULL;
|
||||
|
@ -66,12 +63,6 @@ evas_layer_new(Evas *eo_e)
|
|||
return lay;
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_layer_free(Evas_Layer *lay)
|
||||
{
|
||||
free(lay);
|
||||
}
|
||||
|
||||
void
|
||||
_evas_layer_flush_removes(Evas_Layer *lay)
|
||||
{
|
||||
|
@ -90,7 +81,6 @@ _evas_layer_flush_removes(Evas_Layer *lay)
|
|||
if (lay->usage <= 0)
|
||||
{
|
||||
evas_layer_del(lay);
|
||||
_evas_layer_free(lay);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +120,6 @@ evas_layer_clean(Evas *eo_e)
|
|||
{
|
||||
tmp = e->layers;
|
||||
evas_layer_del(tmp);
|
||||
_evas_layer_free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,20 +161,26 @@ evas_layer_del(Evas_Layer *lay)
|
|||
|
||||
e = lay->evas;
|
||||
e->layers = (Evas_Layer *)eina_inlist_remove(EINA_INLIST_GET(e->layers), EINA_INLIST_GET(lay));
|
||||
|
||||
efl_data_unref(e->evas, e);
|
||||
lay->evas = NULL;
|
||||
eina_freeq_ptr_main_add(lay, free, sizeof(*lay));
|
||||
}
|
||||
|
||||
static void
|
||||
_evas_object_layer_set_child(Evas_Object *eo_obj, Evas_Object *par, short l)
|
||||
_evas_object_layer_set_child(Evas_Object_Protected_Data *obj, Evas_Object_Protected_Data *par_obj, short l)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
Evas_Object_Protected_Data *par_obj = efl_data_scope_get(par, EFL_CANVAS_OBJECT_CLASS);
|
||||
|
||||
if (obj->delete_me) return;
|
||||
if (obj->cur->layer == l) return;
|
||||
evas_object_release(eo_obj, obj, 1);
|
||||
if (EINA_UNLIKELY(obj->in_layer))
|
||||
{
|
||||
ERR("Invalid internal state of object %p (child marked as being a "
|
||||
"top-level object)!", obj->object);
|
||||
evas_object_release(obj->object, obj, 1);
|
||||
}
|
||||
else if ((--obj->layer->usage) == 0)
|
||||
{
|
||||
evas_layer_del(obj->layer);
|
||||
}
|
||||
|
||||
EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
|
||||
{
|
||||
state_write->layer = l;
|
||||
|
@ -199,10 +194,10 @@ _evas_object_layer_set_child(Evas_Object *eo_obj, Evas_Object *par, short l)
|
|||
Eina_Inlist *contained;
|
||||
Evas_Object_Protected_Data *member;
|
||||
|
||||
contained = (Eina_Inlist *)evas_object_smart_members_get_direct(eo_obj);
|
||||
contained = (Eina_Inlist *)evas_object_smart_members_get_direct(obj->object);
|
||||
EINA_INLIST_FOREACH(contained, member)
|
||||
{
|
||||
_evas_object_layer_set_child(member->object, eo_obj, l);
|
||||
_evas_object_layer_set_child(member, obj, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -260,7 +255,7 @@ _efl_canvas_object_efl_gfx_stack_layer_set(Eo *eo_obj, Evas_Object_Protected_Dat
|
|||
contained = (Eina_Inlist *)evas_object_smart_members_get_direct(eo_obj);
|
||||
EINA_INLIST_FOREACH(contained, member)
|
||||
{
|
||||
_evas_object_layer_set_child(member->object, eo_obj, l);
|
||||
_evas_object_layer_set_child(member, obj, l);
|
||||
}
|
||||
}
|
||||
evas_object_inform_call_restack(eo_obj);
|
||||
|
|
|
@ -253,16 +253,27 @@ _efl_canvas_group_group_member_add(Eo *smart_obj, Evas_Smart_Data *o, Evas_Objec
|
|||
evas_object_async_block(obj);
|
||||
if (obj->smart.parent) evas_object_smart_member_del(eo_obj);
|
||||
|
||||
o->member_count++;
|
||||
evas_object_release(eo_obj, obj, 1);
|
||||
obj->layer = smart->layer;
|
||||
EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
|
||||
if (obj->layer != smart->layer)
|
||||
{
|
||||
state_write->layer = obj->layer->layer;
|
||||
if (obj->in_layer)
|
||||
evas_object_release(eo_obj, obj, 1);
|
||||
else if ((--obj->layer->usage) == 0)
|
||||
evas_layer_del(obj->layer);
|
||||
}
|
||||
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
|
||||
|
||||
else if (obj->in_layer)
|
||||
{
|
||||
evas_object_release(eo_obj, obj, 1);
|
||||
}
|
||||
obj->layer = smart->layer;
|
||||
obj->layer->usage++;
|
||||
if (obj->layer->layer != obj->cur->layer)
|
||||
{
|
||||
EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
|
||||
state_write->layer = obj->layer->layer;
|
||||
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
|
||||
}
|
||||
|
||||
o->member_count++;
|
||||
obj->smart.parent = smart_obj;
|
||||
obj->smart.parent_data = o;
|
||||
obj->smart.parent_object_data = smart;
|
||||
|
@ -324,13 +335,13 @@ _efl_canvas_group_group_member_del(Eo *smart_obj, Evas_Smart_Data *_pd EINA_UNUS
|
|||
o->member_count--;
|
||||
obj->smart.parent = NULL;
|
||||
evas_object_smart_member_cache_invalidate(eo_obj, EINA_TRUE, EINA_TRUE, EINA_TRUE);
|
||||
obj->layer->usage--;
|
||||
|
||||
EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
|
||||
if (obj->layer->layer != obj->cur->layer)
|
||||
{
|
||||
state_write->layer = obj->layer->layer;
|
||||
EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
|
||||
state_write->layer = obj->layer->layer;
|
||||
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
|
||||
}
|
||||
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
|
||||
|
||||
if (obj->is_smart)
|
||||
{
|
||||
|
@ -344,6 +355,17 @@ _efl_canvas_group_group_member_del(Eo *smart_obj, Evas_Smart_Data *_pd EINA_UNUS
|
|||
}
|
||||
}
|
||||
|
||||
if (EINA_UNLIKELY(obj->in_layer))
|
||||
{
|
||||
ERR("Invalid internal state of object %p (child marked as being a"
|
||||
"top-level object)!", obj->object);
|
||||
evas_object_release(obj->object, obj, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Layer usage shouldn't reach 0 here (as parent is still in layer)
|
||||
obj->layer->usage--;
|
||||
}
|
||||
evas_object_inject(eo_obj, obj, obj->layer->evas->evas);
|
||||
obj->restack = 1;
|
||||
evas_object_change(eo_obj, obj);
|
||||
|
|
Loading…
Reference in New Issue