elementary: due to lifecycle difference between legacy object and unified object, we need to track their lifecycle more explicitely.

It is my understanding that some items view are created with efl_add directly
and manipulate VIEW directly with Eo new API. This clash with the inconsistent
behavior that evas_object_del expect. To work around this, we track object life
by explictely relying on efl_wref_add while holding the pointer to the object.
This commit is contained in:
Cedric BAIL 2018-05-07 15:16:29 -07:00
parent 0239099d01
commit 0fe3b7962d
19 changed files with 96 additions and 57 deletions

View File

@ -851,6 +851,7 @@ _efl_ui_widget_efl_canvas_group_group_del(Eo *obj, Elm_Widget_Smart_Data *sd)
sd->subobjs = eina_list_remove_list
(sd->subobjs, sd->subobjs);
}
// FIXME: is that a legacy or a new object ?
evas_object_del(sobj);
}
sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
@ -4043,8 +4044,6 @@ _elm_widget_item_efl_object_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
evas_object_del(item->view);
eina_stringshare_del(item->style);
eina_stringshare_del(item->access_info);
eina_stringshare_del(item->accessible_name);
@ -4099,12 +4098,17 @@ _elm_widget_item_efl_object_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
EOLIAN static void
_elm_widget_item_efl_object_invalidate(Eo *eo_item, Elm_Widget_Item_Data *item)
{
ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
item->on_deletion = EINA_TRUE;
Evas_Object *view;
//Widget item delete callback
elm_wdg_item_del_pre(item->eo_obj);
view = item->view;
if (item->view) efl_wref_del(item->view, &item->view);
// FIXME: Is view an Efl.Ui or a legacy object ?
evas_object_del(view);
item->view = NULL;
efl_invalidate(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
}

View File

@ -857,7 +857,8 @@ _elm_hoversel_item_add(Eo *obj, Elm_Hoversel_Data *sd, const char *label, const
snprintf(buf, sizeof(buf), "hoversel_vertical_entry/%s",
elm_widget_style_get(obj));
VIEW(item) = bt = elm_button_add(obj);
bt = elm_button_add(obj);
VIEW_SET(item, bt);
efl_ui_mirrored_set(bt, efl_ui_mirrored_get(obj));
elm_object_style_set(bt, buf);
elm_object_text_set(bt, item->label);

View File

@ -752,7 +752,7 @@ _item_new(Elm_Multibuttonentry_Data *sd,
efl_access_object_role_set(eo_item, EFL_ACCESS_ROLE_RADIO_BUTTON);
ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
VIEW(item) = elm_layout_add(obj);
VIEW_SET(item, elm_layout_add(obj));
efl_access_object_access_type_set(VIEW(item), EFL_ACCESS_TYPE_DISABLED);

View File

@ -1280,7 +1280,7 @@ _item_new(Evas_Object *obj,
ELM_NAVIFRAME_ITEM_DATA_GET(eo_item, it);
//item base layout
VIEW(it) = elm_layout_add(obj);
VIEW_SET(it, elm_layout_add(obj));
evas_object_smart_member_add(VIEW(it), obj);
if (!elm_widget_sub_object_add(obj, VIEW(it)))

View File

@ -923,7 +923,7 @@ _item_new(Elm_Popup_Item_Data *it)
{
char style[1024];
VIEW(it) = elm_layout_add(WIDGET(it));
VIEW_SET(it, elm_layout_add(WIDGET(it)));
elm_object_focus_allow_set(VIEW(it), EINA_TRUE);
efl_ui_mirrored_automatic_set(VIEW(it), EINA_FALSE);
elm_object_mirrored_set(VIEW(it), elm_object_mirrored_get(WIDGET(it)));

View File

@ -1771,7 +1771,7 @@ _elm_color_item_efl_object_constructor(Eo *eo_item, Elm_Color_Item_Data *item)
Evas_Object *obj;
obj = efl_parent_get(eo_item);
VIEW(item) = elm_layout_add(obj);
VIEW_SET(item, elm_layout_add(obj));
if (!elm_layout_theme_set
(VIEW(item), "colorselector", "item", elm_widget_style_get(obj)))
CRI("Failed to set layout!");

View File

@ -174,8 +174,7 @@ _item_del_cb(void *data,
_item_location_get(sd, it));
elm_layout_signal_emit(obj, buf, "elm");
VIEW(it) = NULL;
// The object is already being deleted, there is no point in calling efl_del on it.
// The object is already being deleted, there is no point in calling efl_del on it nore setting it to NULL.
elm_layout_sizing_eval(obj);
break;
@ -243,7 +242,7 @@ _elm_dayselector_content_set(Eo *obj, Elm_Dayselector_Data *sd, const char *item
if (!content) return EINA_TRUE; /* item deletion already handled */
evas_object_del(VIEW(it));
VIEW(it) = content;
VIEW_SET(it, content);
}
else
{
@ -261,7 +260,7 @@ _elm_dayselector_content_set(Eo *obj, Elm_Dayselector_Data *sd, const char *item
}
sd->items = eina_list_append(sd->items, it);
VIEW(it) = content;
VIEW_SET(it, content);
}
snprintf(buf, sizeof(buf), "day%d,visible", _item_location_get(sd, it));
@ -329,7 +328,6 @@ _elm_dayselector_content_unset(Eo *obj, Elm_Dayselector_Data *sd, const char *it
snprintf(buf, sizeof(buf), "day%d,default", _item_location_get(sd, it));
elm_layout_signal_emit(obj, buf, "elm");
VIEW(it) = NULL;
efl_del(EO_OBJ(it));
elm_layout_sizing_eval(obj);

View File

@ -673,7 +673,7 @@ _item_new(Evas_Object *obj,
it->label = eina_stringshare_add(label);
it->func = func;
WIDGET_ITEM_DATA_SET(eo_it, data);
VIEW(it) = edje_object_add(evas_object_evas_get(obj));
VIEW_SET(it, edje_object_add(evas_object_evas_get(obj)));
elm_widget_theme_object_set(obj, VIEW(it), "diskselector", "item",
elm_widget_style_get(obj));

View File

@ -71,6 +71,8 @@ struct Elm_Gen_Item
Eina_Bool cursor_engine_only : 1;
Eina_Bool hide : 1; /**< flag used for hiding the items which do not match filter text */
Eina_Bool filtered: 1; /**<flag used to indicate whether or not item has been filtered */
Eina_Bool callbacks : 1;
};
#endif

View File

@ -231,6 +231,7 @@ _item_cache_add(Elm_Gen_Item *it, Eina_List *contents)
evas_object_hide(itc->base_view);
evas_object_move(itc->base_view, -9999, -9999);
it->spacer = NULL;
if (!it->base->view) efl_wref_del(it->base->view, &it->base->view);
VIEW(it) = NULL;
_item_cache_clean(sd);
@ -261,7 +262,7 @@ _item_cache_find(Elm_Gen_Item *it)
if (!itc) continue;
it->spacer = itc->spacer;
VIEW(it) = itc->base_view;
VIEW_SET(it, itc->base_view);
itc->spacer = NULL;
itc->base_view = NULL;
@ -1576,7 +1577,7 @@ _item_realize(Elm_Gen_Item *it)
if (!_item_cache_find(it))
{
VIEW(it) = _view_create(it, it->itc->item_style);
VIEW_SET(it, _view_create(it, it->itc->item_style));
if (it->item->nocache_once)
it->item->nocache_once = EINA_FALSE;
}

View File

@ -1543,7 +1543,8 @@ _item_cache_free(Item_Cache *itc)
if (!itc) return;
evas_object_del(itc->spacer);
evas_object_del(itc->base_view);
efl_wref_del(itc->base_view, &itc->base_view);
efl_del(itc->base_view);
itc->item_class = NULL;
EINA_LIST_FREE(itc->contents, c)
{
@ -1604,7 +1605,7 @@ _item_cache_add(Elm_Gen_Item *it, Eina_List *contents)
return EINA_FALSE;
}
itc->spacer = it->spacer;
itc->base_view = VIEW(it);
efl_wref_add(VIEW(it), &itc->base_view);
itc->item_class = it->itc;
itc->contents = contents;
if (it->item->type & ELM_GENLIST_ITEM_TREE)
@ -1642,6 +1643,7 @@ _item_cache_add(Elm_Gen_Item *it, Eina_List *contents)
* elm_config_scale_get());
it->spacer = NULL;
efl_wref_del(it->base->view, &it->base->view);
VIEW(it) = NULL;
evas_object_hide(itc->base_view);
evas_object_move(itc->base_view, -9999, -9999);
@ -1677,8 +1679,9 @@ _item_cache_find(Elm_Gen_Item *it)
if (!itc) continue;
it->spacer = itc->spacer;
VIEW(it) = itc->base_view;
VIEW_SET(it, itc->base_view);
itc->spacer = NULL;
efl_wref_del(itc->base_view, &itc->base_view);
itc->base_view = NULL;
eina_list_free(itc->contents);
itc->contents = NULL;
@ -1833,7 +1836,7 @@ _item_realize(Elm_Gen_Item *it, const int index, Eina_Bool calc)
if (sd->tree_effect_enabled ||
(!_item_cache_find(it)))
{
VIEW(it) = _view_create(it, it->itc->item_style);
VIEW_SET(it, _view_create(it, it->itc->item_style));
if (it->item->nocache_once)
it->item->nocache_once = EINA_FALSE;
}
@ -4915,15 +4918,19 @@ _item_mouse_up_cb(void *data,
it->down = EINA_FALSE;
ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
evas_object_ref(WIDGET(it));
efl_ref(EO_OBJ(it));
sd->mouse_down = EINA_FALSE;
efl_event_callback_legacy_call(WIDGET(it), ELM_GENLIST_EVENT_RELEASED, EO_OBJ(it));
if (sd->multi_touched)
{
if ((!sd->multi) && (!it->selected) && (it->highlighted))
_item_unhighlight(it);
if (sd->multi_down) return;
if (sd->multi_down) goto early;
_multi_touch_gesture_eval(it);
return;
goto early;
}
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
sd->on_hold = EINA_TRUE;
@ -4949,7 +4956,7 @@ _item_mouse_up_cb(void *data,
sd->longpressed = EINA_FALSE;
sd->on_hold = EINA_FALSE;
sd->wasselected = EINA_FALSE;
return;
goto early;
}
if ((sd->reorder_mode) && (sd->reorder_it))
{
@ -4983,7 +4990,7 @@ _item_mouse_up_cb(void *data,
if (!sd->wasselected) _item_unselect(it);
sd->longpressed = EINA_FALSE;
sd->wasselected = EINA_FALSE;
return;
goto early;
}
if (dragged)
{
@ -5003,7 +5010,7 @@ _item_mouse_up_cb(void *data,
!it->base->still_in ||
_is_no_select(it) ||
(elm_wdg_item_disabled_get(EO_OBJ(it))))
return;
goto early;
evas_object_ref(sd->obj);
@ -5049,14 +5056,19 @@ _item_mouse_up_cb(void *data,
if (_item_select(it)) goto deleted;
}
deleted:
deleted:
evas_object_unref(sd->obj);
early:
evas_object_unref(WIDGET(it));
efl_unref(EO_OBJ(it));
}
static void
_item_mouse_callbacks_add(Elm_Gen_Item *it,
Evas_Object *view)
{
if (it->callbacks) return ;
it->callbacks = EINA_TRUE;
evas_object_event_callback_add
(view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
evas_object_event_callback_add
@ -5077,6 +5089,8 @@ static void
_item_mouse_callbacks_del(Elm_Gen_Item *it,
Evas_Object *view)
{
if (!it->callbacks) return ;
it->callbacks = EINA_FALSE;
evas_object_event_callback_del_full
(view, EVAS_CALLBACK_MOUSE_DOWN, _item_mouse_down_cb, it);
evas_object_event_callback_del_full
@ -5186,7 +5200,7 @@ _item_unrealize(Elm_Gen_Item *it)
if (!_item_cache_add(it, _content_cache_add(it, &cache)))
{
ELM_SAFE_FREE(VIEW(it), evas_object_del);
ELM_SAFE_FREE(VIEW(it), efl_del);
ELM_SAFE_FREE(it->spacer, evas_object_del);
EINA_LIST_FREE(cache, c)
{
@ -5846,7 +5860,7 @@ _internal_elm_genlist_clear(Evas_Object *obj)
// because sd->items can be modified inside elm_widget_item_del()
while (sd->items)
{
it = EINA_INLIST_CONTAINER_GET(sd->items->last, Elm_Gen_Item);
it = EINA_INLIST_CONTAINER_GET(sd->items, Elm_Gen_Item);
efl_del(EO_OBJ(it));
}
@ -5902,6 +5916,7 @@ _item_select(Elm_Gen_Item *it)
Evas_Object *obj = WIDGET(it);
ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd);
Elm_Object_Item *eo_it = EO_OBJ(it);
Eina_Bool r = EINA_FALSE;
if (elm_wdg_item_disabled_get(eo_it)) return EINA_FALSE;
if (_is_no_select(it) || (it->decorate_it_set)) return EINA_FALSE;
@ -5927,9 +5942,8 @@ _item_select(Elm_Gen_Item *it)
eina_list_append(sd->selected, eo_it);
}
evas_object_ref(obj);
efl_ref(eo_it);
elm_object_item_focus_set(eo_it, EINA_TRUE);
if ((it->base)->on_deletion) goto item_deleted;
_elm_genlist_item_content_focus_set(it, ELM_FOCUS_PREVIOUS);
@ -5943,22 +5957,21 @@ _item_select(Elm_Gen_Item *it)
if (_elm_config->atspi_mode)
efl_access_state_changed_signal_emit(eo_it, EFL_ACCESS_STATE_SELECTED, EINA_TRUE);
// delete item if it's requested deletion in the above callbacks.
if ((it->base)->on_deletion) goto item_deleted;
efl_unref(eo_it);
if ((it->base)->on_deletion)
{
r = EINA_TRUE;
goto item_deleted;
}
if (!(sd->focus_on_selection_enabled || _elm_config->item_select_on_focus_disable))
{
efl_ui_focus_manager_focus_set(obj, it->base->eo_obj);
}
evas_object_unref(obj);
return EINA_FALSE;
item_deleted:
efl_unref(eo_it);
item_deleted:
_item_del(it);
efl_del(eo_it);
evas_object_unref(obj);
return EINA_TRUE;
return r;
}
EOLIAN static Evas_Object *

View File

@ -1351,7 +1351,7 @@ _elm_index_item_append(Eo *obj, Elm_Index_Data *sd, const char *letter, Evas_Sma
sd->items = eina_list_append(sd->items, eo_item);
ELM_INDEX_ITEM_DATA_GET(eo_item, it);
VIEW(it) = edje_object_add(evas_object_evas_get(obj));
VIEW_SET(it, edje_object_add(evas_object_evas_get(obj)));
if (_elm_config->atspi_mode)
{
@ -1373,7 +1373,7 @@ _elm_index_item_prepend(Eo *obj, Elm_Index_Data *sd, const char *letter, Evas_Sm
sd->items = eina_list_prepend(sd->items, eo_item);
ELM_INDEX_ITEM_DATA_GET(eo_item, it);
VIEW(it) = edje_object_add(evas_object_evas_get(obj));
VIEW_SET(it, edje_object_add(evas_object_evas_get(obj)));
if (_elm_config->atspi_mode)
{
@ -1408,7 +1408,7 @@ _elm_index_item_insert_after(Eo *obj, Elm_Index_Data *sd, Elm_Object_Item *after
sd->items = eina_list_append_relative(sd->items, eo_item, after);
ELM_INDEX_ITEM_DATA_GET(eo_item, it);
VIEW(it) = edje_object_add(evas_object_evas_get(obj));
VIEW_SET(it, edje_object_add(evas_object_evas_get(obj)));
if (_elm_config->atspi_mode)
{
@ -1432,7 +1432,7 @@ _elm_index_item_insert_before(Eo *obj, Elm_Index_Data *sd, Elm_Object_Item *befo
sd->items = eina_list_prepend_relative(sd->items, eo_item, before);
ELM_INDEX_ITEM_DATA_GET(eo_item, it);
VIEW(it) = edje_object_add(evas_object_evas_get(obj));
VIEW_SET(it, edje_object_add(evas_object_evas_get(obj)));
if (_elm_config->atspi_mode)
{
@ -1476,7 +1476,7 @@ _elm_index_item_sorted_insert(Eo *obj, Elm_Index_Data *sd, const char *letter, E
}
}
ELM_INDEX_ITEM_DATA_GET(eo_item, it);
VIEW(it) = edje_object_add(evas_object_evas_get(obj));
VIEW_SET(it, edje_object_add(evas_object_evas_get(obj)));
if (_elm_config->atspi_mode)
{

View File

@ -2295,7 +2295,7 @@ _item_new(Evas_Object *obj,
it->func = func;
WIDGET_ITEM_DATA_SET(EO_OBJ(it), data);
VIEW(it) = edje_object_add(evas_object_evas_get(obj));
VIEW_SET(it, edje_object_add(evas_object_evas_get(obj)));
edje_object_update_hints_set(VIEW(it), 1);
if (it->icon) efl_parent_set(it->icon, eo_it);

View File

@ -1870,8 +1870,27 @@ elm_object_focus_region_show_mode_get(const Evas_Object *obj)
return elm_widget_focus_region_show_mode_get(obj);
}
static void
_item_noref(void *data EINA_UNUSED, const Efl_Event *ev)
{
if (!efl_parent_get(ev->object)) return ;
efl_del(ev->object);
}
EAPI void
elm_object_item_del(Eo *obj)
{
efl_del(obj);
Elm_Widget_Item_Data *item;
if (efl_ref_count(obj) == 1)
{
// Noref already, die little item !
efl_del(obj);
return ;
}
item = efl_data_scope_safe_get(obj, ELM_WIDGET_ITEM_CLASS);
if (!item) return ;
efl_event_callback_add(obj, EFL_EVENT_NOREF, _item_noref, NULL);
item->on_deletion = EINA_TRUE;
}

View File

@ -580,7 +580,7 @@ _elm_menu_efl_gfx_entity_visible_set(Eo *obj EINA_UNUSED, Elm_Menu_Data *sd, Ein
static void
_item_obj_create(Elm_Menu_Item_Data *item)
{
VIEW(item) = elm_layout_add(WIDGET(item));
VIEW_SET(item, elm_layout_add(WIDGET(item)));
efl_access_object_access_type_set(VIEW(item), EFL_ACCESS_TYPE_SKIPPED);
evas_object_size_hint_weight_set
(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
@ -604,7 +604,7 @@ _item_obj_create(Elm_Menu_Item_Data *item)
static void
_item_separator_obj_create(Elm_Menu_Item_Data *item)
{
VIEW(item) = elm_layout_add(WIDGET(item));
VIEW_SET(item, elm_layout_add(WIDGET(item)));
efl_access_object_access_type_set(VIEW(item), EFL_ACCESS_TYPE_SKIPPED);
evas_object_size_hint_weight_set
(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);

View File

@ -596,7 +596,7 @@ _elm_segment_control_item_efl_object_constructor(Eo *obj, Elm_Segment_Control_It
Evas_Object *parent;
parent = efl_parent_get(obj);
VIEW(it) = edje_object_add(evas_object_evas_get(parent));
VIEW_SET(it, edje_object_add(evas_object_evas_get(parent)));
edje_object_scale_set(VIEW(it),efl_gfx_entity_scale_get(WIDGET(it)) *
elm_config_scale_get());
evas_object_smart_member_add(VIEW(it), parent);

View File

@ -131,7 +131,7 @@ _item_realize(Elm_Slideshow_Item_Data *item)
if ((!VIEW(item)) && (item->itc->func.get))
{
VIEW(item) = item->itc->func.get(elm_object_item_data_get(EO_OBJ(item)), obj);
VIEW_SET(item, item->itc->func.get(elm_object_item_data_get(EO_OBJ(item)), obj));
item->l_built = eina_list_append(NULL, item);
sd->items_built = eina_list_merge(sd->items_built, item->l_built);
//FIXME: item could be shown by obj
@ -161,9 +161,9 @@ _item_realize(Elm_Slideshow_Item_Data *item)
&& (_item_next->itc->func.get))
{
ic++;
VIEW(_item_next) =
VIEW_SET(_item_next,
_item_next->itc->func.get(
elm_object_item_data_get(EO_OBJ(_item_next)), obj);
elm_object_item_data_get(EO_OBJ(_item_next)), obj));
_item_next->l_built =
eina_list_append(NULL, _item_next);
sd->items_built = eina_list_merge
@ -193,9 +193,9 @@ _item_realize(Elm_Slideshow_Item_Data *item)
&& (_item_prev->itc->func.get))
{
ic++;
VIEW(_item_prev) =
VIEW_SET(_item_prev,
_item_prev->itc->func.get(
elm_object_item_data_get(EO_OBJ(_item_prev)), obj);
elm_object_item_data_get(EO_OBJ(_item_prev)), obj));
_item_prev->l_built =
eina_list_append(NULL, _item_prev);
sd->items_built = eina_list_merge

View File

@ -2398,7 +2398,7 @@ _item_new(Evas_Object *obj,
it->object = NULL;
WIDGET_ITEM_DATA_SET(EO_OBJ(it), data);
VIEW(it) = elm_layout_add(obj);
VIEW_SET(it, elm_layout_add(obj));
elm_widget_tree_unfocusable_set(VIEW(it), EINA_TRUE);
evas_object_data_set(VIEW(it), "item", it);
efl_access_object_access_type_set(VIEW(it), EFL_ACCESS_TYPE_DISABLED);

View File

@ -602,6 +602,7 @@ struct _Elm_Widget_Item_Data
EINA_MAGIC;
/* simple accessor macros */
#define VIEW(X) X->base->view
#define VIEW_SET(X, V) efl_wref_add(V, &X->base->view)
#define WIDGET(X) X->base->widget
#define EO_OBJ(X) ((X)?X->base->eo_obj:NULL)
/**< the owner widget that owns this item */