efl_ui_widget: refactor sub_object handling

efl_ui_widget has a property called widget_parent. The setter for this
function is called is exactly once, and this is within the constructor,
to a value which is not even set to the actaul field parent_obj. Which
shows, that in the sitation right now, the setter of the property is a
bit disconnected and lags some real aspects.
As we are heading towards eo-api stabilization we should beat some sense
into this setter, as people using our classes might overwrite the setter
and except calls to it, whenever the widget_parent is changed, and
implementation as in elm_menu show that this might makes sense sometime.

In order to achive this, the sub_object registering code of elm is
adjusted a bit.
sub_object_add/del is now used to differenciate between evas objects and
efl.ui.widget objects as subobject. In case of a widget, the
widget_parent of this object is set, most of the widget specific code is
then executed in the actaul setter. In case of an evas object, the
parent reference is added. In the end both end up in the subobject
children list. The later is also a requirement for widget_parent_set to
be successfull.

ref T7553

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Differential Revision: https://phab.enlightenment.org/D8031
This commit is contained in:
Marcel Hollerbach 2019-02-26 15:38:28 +01:00
parent ccbc27f24d
commit a1addad60e
1 changed files with 91 additions and 101 deletions

View File

@ -1151,10 +1151,6 @@ elm_widget_focus_region_show(Eo *obj)
}
}
EOLIAN static void
_efl_ui_widget_widget_parent_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *parent EINA_UNUSED)
{
}
EAPI Eina_Bool
elm_widget_api_check(int ver)
@ -1378,74 +1374,27 @@ elm_widget_sub_object_parent_add(Evas_Object *sobj)
return elm_widget_sub_object_add(parent, sobj);
}
/*
* @internal
*
* Add sobj to obj's sub object.
*
* What does elementary sub object mean? This is unique in elementary, it
* handles overall elementary policies between parent and sub objects.
* focus, access, deletion, theme, scale, mirror, scrollable child get,
* translate, name find, display mode set, orientation set, tree dump
* AUTOMATICALLY.
*
* @see elm_widget_sub_object_parent_add()
*/
EOLIAN static Eina_Bool
_efl_ui_widget_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
EOLIAN static void
_efl_ui_widget_widget_parent_set(Eo *obj, Elm_Widget_Smart_Data *pd, Efl_Ui_Widget *parent)
{
Eina_Bool mirrored, pmirrored = efl_ui_mirrored_get(obj);
Elm_Widget_Smart_Data *sdc = NULL;
EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
if (_elm_widget_is(sobj))
sdc = efl_data_scope_get(sobj, MY_CLASS);
if (sobj == sd->parent_obj)
Efl_Ui_Widget *old_parent;
//check if we are in the subobject list of parents
if (parent)
{
/* in this case, sobj must be an elm widget, or something
* very wrong is happening */
if (!sdc) return EINA_FALSE;
if (!elm_widget_sub_object_del(sobj, obj)) return EINA_FALSE;
WRN("You passed a parent object of obj = %p as the sub object = %p!",
obj, sobj);
ELM_WIDGET_DATA_GET_OR_RETURN(parent, ppd);
EINA_SAFETY_ON_FALSE_RETURN(eina_list_data_find(ppd->subobjs, obj));
}
if (sdc)
{
if (sdc->parent_obj == obj) goto end;
if (sdc->parent_obj)
{
if (!elm_widget_sub_object_del(sdc->parent_obj, sobj))
return EINA_FALSE;
}
sdc->parent_obj = obj;
old_parent = pd->parent_obj;
pd->parent_obj = parent;
_full_eval(sobj, sdc);
efl_ui_widget_disabled_set(sobj, efl_ui_widget_disabled_get(obj));
// now lets sync up all states
_elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
}
else
{
void *data = evas_object_data_get(sobj, "elm-parent");
if (data)
{
if (data == obj) goto end;
if (!elm_widget_sub_object_del(data, sobj)) return EINA_FALSE;
}
}
sd->subobjs = eina_list_append(sd->subobjs, sobj);
evas_object_data_set(sobj, "elm-parent", obj);
_callbacks_add(sobj, obj);
if (sdc)
if (pd->parent_obj)
{
/* NOTE: In the following two lines, 'sobj' is correct. Do not change it.
* Due to elementary's scale policy, scale and pscale can be different in
* Due to elementary's scale policy, scale and pscale can be different in
* some cases. This happens when sobj's previous parent and new parent have
* different scale value.
* For example, if sobj's previous parent's scale is 5 and new parent's scale
@ -1453,33 +1402,85 @@ _efl_ui_widget_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Ob
* need to reset sobj's scale to 5.
* Note that each widget's scale is 0 by default.
*/
double scale, pscale = efl_gfx_entity_scale_get(sobj);
Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
double scale, pscale = efl_gfx_entity_scale_get(obj);
Elm_Theme *th, *pth = elm_widget_theme_get(obj);
scale = efl_gfx_entity_scale_get(sobj);
th = elm_widget_theme_get(sobj);
mirrored = efl_ui_mirrored_get(sobj);
scale = efl_gfx_entity_scale_get(obj);
th = elm_widget_theme_get(obj);
mirrored = efl_ui_mirrored_get(obj);
if (!sdc->on_create)
if (!pd->on_create)
{
if ((scale != pscale) || (th != pth) || (pmirrored != mirrored))
elm_widget_theme(sobj);
}
if (_is_focused(sobj)) _parents_focus(obj);
elm_widget_display_mode_set(sobj,
evas_object_size_hint_display_mode_get(obj));
if (_elm_config->atspi_mode && !sd->on_create)
{
Efl_Access_Object *aparent;
aparent = efl_provider_find(efl_parent_get(sobj), EFL_ACCESS_OBJECT_MIXIN);
if (aparent)
efl_access_children_changed_added_signal_emit(aparent, sobj);
elm_widget_theme(obj);
}
if (_is_focused(obj)) _parents_focus(parent);
elm_widget_display_mode_set(obj, evas_object_size_hint_display_mode_get(parent));
elm_widget_disabled_set(obj, efl_ui_widget_disabled_get(parent));
_elm_widget_top_win_focused_set(obj, _elm_widget_top_win_focused_get(parent));
}
end:
_full_eval(obj, pd);
if (old_parent && _elm_config->atspi_mode)
{
Efl_Access_Object *aparent;
aparent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
if (aparent)
efl_access_children_changed_del_signal_emit(aparent, obj);
}
if (pd->parent_obj && _elm_config->atspi_mode && efl_finalized_get(parent))
{
Efl_Access_Object *aparent;
aparent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
if (aparent)
efl_access_children_changed_added_signal_emit(aparent, obj);
}
}
static void
_widget_add_sub(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
{
sd->subobjs = eina_list_append(sd->subobjs, sobj);
evas_object_data_set(sobj, "elm-parent", obj);
_callbacks_add(sobj, obj);
}
static void
_widget_del_sub(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
{
sd->subobjs = eina_list_remove(sd->subobjs, sobj);
evas_object_data_del(sobj, "elm-parent");
_callbacks_del(sobj, obj);
}
EOLIAN static Eina_Bool
_efl_ui_widget_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
{
Efl_Ui_Widget *parent;
//first make sure that we unregister the sobj from the parent
if (elm_widget_is(sobj))
parent = efl_ui_widget_parent_get(sobj);
else
parent = evas_object_data_get(sobj, "elm-parent");
if (parent == obj) return EINA_TRUE;
if (parent)
{
if (!efl_ui_widget_sub_object_del(parent, sobj))
return EINA_FALSE;
}
//sobj does not have a parent here
//first add it to our own children list
_widget_add_sub(obj, sd, sobj);
//and if it is a widget, please set the correct parent on the widget itself
//the parent set method will take care of the property syncing etc.
if (elm_widget_is(sobj))
efl_ui_widget_parent_set(sobj, obj);
return EINA_TRUE;
}
@ -1519,25 +1520,13 @@ _efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Ob
elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
}
if (_elm_config->atspi_mode && !sd->on_destroy)
{
Efl_Access_Object *aparent;
aparent = efl_provider_find(efl_parent_get(sobj), EFL_ACCESS_OBJECT_MIXIN);
if (aparent)
efl_access_children_changed_del_signal_emit(aparent, sobj);
}
ELM_WIDGET_DATA_GET(sobj, sdc);
sdc->parent_obj = NULL;
_full_eval(sobj, sdc);
efl_ui_widget_parent_set(sobj, NULL);
}
if (sd->resize_obj == sobj) sd->resize_obj = NULL;
sd->subobjs = eina_list_remove(sd->subobjs, sobj);
_callbacks_del(sobj, obj);
_widget_del_sub(obj, sd, sobj);
return EINA_TRUE;
}
@ -5023,16 +5012,17 @@ elm_widget_tree_dot_dump(const Evas_Object *top,
EOLIAN static Eo *
_efl_ui_widget_efl_object_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
{
Eo *parent = NULL;
sd->on_create = EINA_TRUE;
_efl_ui_focus_event_redirector(obj, obj);
efl_canvas_group_clipped_set(obj, EINA_FALSE);
obj = efl_constructor(efl_super(obj, MY_CLASS));
efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
parent = efl_parent_get(obj);
efl_ui_widget_parent_set(obj, parent);
if (!efl_isa(obj, EFL_UI_WIN_CLASS))
{
efl_ui_widget_sub_object_add(efl_parent_get(obj), obj);
}
sd->on_create = EINA_FALSE;
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_UNKNOWN);