From a1addad60e1c9d9a32a6559460f23610932afc21 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Tue, 26 Feb 2019 15:38:28 +0100 Subject: [PATCH] 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 Differential Revision: https://phab.enlightenment.org/D8031 --- src/lib/elementary/efl_ui_widget.c | 192 ++++++++++++++--------------- 1 file changed, 91 insertions(+), 101 deletions(-) diff --git a/src/lib/elementary/efl_ui_widget.c b/src/lib/elementary/efl_ui_widget.c index 25462ceb02..ed959eb479 100644 --- a/src/lib/elementary/efl_ui_widget.c +++ b/src/lib/elementary/efl_ui_widget.c @@ -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);