bu5hm4n pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=b364293b0c2238c74a8450c4d27787ebe027b483
commit b364293b0c2238c74a8450c4d27787ebe027b483 Author: Marcel Hollerbach <mar...@osg.samsung.com> Date: Sat Nov 11 18:26:53 2017 +0100 genlist: implement item focus this implements item-content focus for genlist. feel free to notify me if there are any crashes or something simular. ref T6181 --- src/lib/elementary/elm_genlist.c | 105 ++++++++++++++++++++++++++++---- src/lib/elementary/elm_genlist.eo | 13 ++-- src/lib/elementary/elm_genlist_item.eo | 5 +- src/lib/elementary/elm_widget_genlist.h | 3 + 4 files changed, 108 insertions(+), 18 deletions(-) diff --git a/src/lib/elementary/elm_genlist.c b/src/lib/elementary/elm_genlist.c index 6c77edff13..25aa0b1bd5 100644 --- a/src/lib/elementary/elm_genlist.c +++ b/src/lib/elementary/elm_genlist.c @@ -8,6 +8,7 @@ #define EFL_ACCESS_SELECTION_PROTECTED #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED #define ELM_WIDGET_ITEM_PROTECTED +#define EFL_UI_FOCUS_COMPOSITION_PROTECTED #include <Elementary.h> #include <Elementary_Cursor.h> @@ -15,6 +16,8 @@ #include "elm_priv.h" #include "elm_widget_genlist.h" #include "elm_interface_scrollable.h" +#include "efl_ui_focus_parent_provider_gen.eo.h" +#include "efl_ui_focus_composition_adapter.eo.h" #include "elm_genlist_item.eo.h" #include "elm_genlist_pan.eo.h" #include "elm_genlist.eo.h" @@ -403,6 +406,8 @@ _item_content_realize(Elm_Gen_Item *it, Eina_List *source; const char *key; + ELM_GENLIST_DATA_GET_FROM_ITEM(it, sd); + if (!parts) { EINA_LIST_FREE(*contents, content) @@ -437,6 +442,7 @@ _item_content_realize(Elm_Gen_Item *it, if (content != old) { + eina_hash_add(sd->content_item_map, &content, it->base->eo_obj); // FIXME: Genlist item doesn't update its size when the size of // content is changed, so deferred calculation for content should // be performed before realization. @@ -472,6 +478,7 @@ out: { *contents = eina_list_remove(*contents, old); evas_object_del(old); + eina_hash_del_by_key(sd->content_item_map, &old); } } } @@ -1684,6 +1691,7 @@ _item_cache_find(Elm_Gen_Item *it) static Eina_List * _content_cache_add(Elm_Gen_Item *it, Eina_List **cache) { + ELM_GENLIST_DATA_GET_FROM_ITEM(it, pd); Evas_Object *content = NULL; EINA_LIST_FREE(it->contents, content) { @@ -1691,6 +1699,7 @@ _content_cache_add(Elm_Gen_Item *it, Eina_List **cache) elm_widget_disabled_set(content, EINA_FALSE); *cache = eina_list_append(*cache, content); + eina_hash_del_by_key(pd->content_item_map, &content); } return *cache; @@ -5786,16 +5795,50 @@ elm_genlist_add(Evas_Object *parent) return elm_legacy_add(MY_CLASS, parent); } +static void +_genlist_element_focused(void *data, const Efl_Event *ev) +{ + ELM_GENLIST_DATA_GET(data, pd); + Elm_Widget *focused = efl_ui_focus_manager_focus_get(ev->object); + Elm_Widget_Item *item; + + if (!focused) return; + + if (efl_isa(focused, EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS)) + item = efl_parent_get(focused); + else + item = efl_ui_focus_parent_provider_find_logical_parent(pd->provider, focused); + + if (efl_isa(item, ELM_GENLIST_ITEM_CLASS)) + { + _elm_genlist_item_focused(item); + _all_items_deselect(pd); + elm_genlist_item_selected_set(item, EINA_TRUE); + elm_genlist_item_bring_in(item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE); + } +} + EOLIAN static Eo * _elm_genlist_efl_object_constructor(Eo *obj, Elm_Genlist_Data *sd) { obj = efl_constructor(efl_super(obj, MY_CLASS)); + + sd->content_item_map = eina_hash_pointer_new(NULL); + sd->provider = efl_add(EFL_UI_FOCUS_PARENT_PROVIDER_GEN_CLASS, obj, + efl_ui_focus_parent_provider_gen_container_set(efl_added, obj), + efl_ui_focus_parent_provider_gen_content_item_map_set(efl_added, sd->content_item_map)); + + efl_ui_focus_composition_custom_manager_set(obj, obj); + efl_ui_focus_composition_logical_mode_set(obj, EINA_TRUE); + sd->obj = obj; efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); efl_access_role_set(obj, EFL_ACCESS_ROLE_LIST); + efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED, _genlist_element_focused, obj); + return obj; } @@ -5924,17 +5967,7 @@ _item_select(Elm_Gen_Item *it) if (!(sd->focus_on_selection_enabled || _elm_config->item_select_on_focus_disable)) { - Evas_Object *swallow_obj; - Eina_List *l; - EINA_LIST_FOREACH(it->contents, l, swallow_obj) - { - if (elm_widget_is(swallow_obj) && elm_object_focus_get(swallow_obj)) - { - elm_object_focus_set(obj, EINA_FALSE); - elm_object_focus_set(obj, EINA_TRUE); - break; - } - } + efl_ui_focus_manager_focus_set(obj, it->base->eo_obj); } evas_object_unref(obj); @@ -6191,6 +6224,8 @@ _elm_genlist_item_new(Elm_Genlist_Data *sd, it->item->expanded_depth = depth; sd->item_count++; + efl_ui_focus_composition_dirty(sd->obj); + return it; } @@ -8702,6 +8737,54 @@ _elm_genlist_efl_access_selection_child_deselect(Eo *obj EINA_UNUSED, Elm_Genlis return EINA_FALSE; } +EOLIAN static Efl_Object* +_elm_genlist_efl_object_provider_find(Eo *obj, Elm_Genlist_Data *pd, const Efl_Object *klass) +{ + if (klass == EFL_UI_FOCUS_PARENT_PROVIDER_INTERFACE) + return pd->provider; + return efl_provider_find(efl_super(obj, ELM_GENLIST_CLASS), klass); +} + +EOLIAN static void +_elm_genlist_efl_ui_focus_composition_prepare(Eo *obj, Elm_Genlist_Data *pd) +{ + Elm_Gen_Item *item; + Eina_List *order = NULL; + + EINA_INLIST_FOREACH(pd->items, item) + { + if (item->base->disabled) + continue; + + order = eina_list_append(order, item->base->eo_obj); + } + + efl_ui_focus_composition_elements_set(obj, order); +} + +EOLIAN static void +_elm_genlist_item_efl_ui_focus_object_prepare_logical(Eo *obj, Elm_Gen_Item *pd) +{ + Eina_List *n; + Elm_Widget *wid; + + _item_realize(pd, pd->item->order_num_in, EINA_FALSE); + + EINA_LIST_FOREACH(pd->contents, n, wid) + { + if (efl_isa(wid, ELM_WIDGET_CLASS)) + _elm_widget_full_eval(wid); + } + + efl_ui_focus_object_prepare_logical(efl_super(obj, ELM_GENLIST_ITEM_CLASS)); +} + +EOLIAN static Eina_Bool +_elm_genlist_elm_widget_focus_state_apply(Eo *obj, Elm_Genlist_Data *pd EINA_UNUSED, Elm_Widget_Focus_State current_state, Elm_Widget_Focus_State *configured_state, Elm_Widget *redirect EINA_UNUSED) +{ + return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj); +} + /* Standard widget overrides */ ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_genlist, Elm_Genlist_Data) diff --git a/src/lib/elementary/elm_genlist.eo b/src/lib/elementary/elm_genlist.eo index 52cb44908c..c0460b12ef 100644 --- a/src/lib/elementary/elm_genlist.eo +++ b/src/lib/elementary/elm_genlist.eo @@ -2,7 +2,7 @@ import elm_general; import elm_list; import elm_genlist_item; -class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, Efl.Ui.Clickable, +class Elm.Genlist (Efl.Ui.Layout, Efl.Ui.Focus.Composition, Elm.Interface_Scrollable, Efl.Ui.Clickable, Elm.Interface.Atspi_Widget_Action, Efl.Access.Selection, Efl.Ui.Selectable) { @@ -301,7 +301,7 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, Efl.Ui.Clickable, This returns a list of the realized items in the genlist. The list contains genlist item pointers. The list must be - freed by the caller when done with \@ref eina_list_free. The + freed by the caller when done with \@ref eina_list_free. The item pointers in the list are only valid so long as those items are not deleted or the genlist is not deleted. ]] @@ -331,7 +331,7 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, Efl.Ui.Clickable, [[Get the last item in the genlist This returns the last item in the list. - + If filter is set to genlist, it returns last filtered item in the list. ]] @@ -532,6 +532,7 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, Efl.Ui.Clickable, Efl.Gfx.position { set; } Efl.Gfx.size { set; } Efl.Canvas.Group.group_member_add; + Efl.Object.provider_find; Elm.Widget.theme_apply; Elm.Widget.widget_sub_object_add; Elm.Widget.on_access_update; @@ -554,6 +555,8 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, Efl.Ui.Clickable, Efl.Access.Selection.is_child_selected; Efl.Access.Selection.all_children_select; Efl.Access.Selection.clear; + Efl.Ui.Focus.Composition.prepare; + Elm.Widget.focus_state_apply; } events { item,focused; [[Called when genlist item got focus]] @@ -568,11 +571,11 @@ class Elm.Genlist (Efl.Ui.Layout, Elm.Interface_Scrollable, Efl.Ui.Clickable, edge,bottom; [[Called when bottom edge is reached]] edge,left; [[Called when left edge is reached]] edge,right; [[Called when right edge is reached]] - moved; [[Called when genlist item moved]] + moved; [[Called when genlist item moved]] moved,before; [[Called when genlist item moved before]] moved,after; [[Called when genlist item moved after]] swipe; [[Called when swipe is detected]] - multi,pinch,in; [[Called when multitouch pinch in detected]] + multi,pinch,in; [[Called when multitouch pinch in detected]] multi,pinch,out; [[Called when multitouch pinch out detected]] multi,swipe,down; [[Called when multitouch swipe down detected]] multi,swipe,up; [[Called when multitouch swipe up detected]] diff --git a/src/lib/elementary/elm_genlist_item.eo b/src/lib/elementary/elm_genlist_item.eo index 87bc3bcff8..64fb0982a6 100644 --- a/src/lib/elementary/elm_genlist_item.eo +++ b/src/lib/elementary/elm_genlist_item.eo @@ -38,7 +38,7 @@ enum Elm.Genlist.Item.Scrollto_Type bottom = (1 << 3) [[To the bottom of viewport.]] } -class Elm.Genlist.Item(Elm.Widget.Item) +class Elm.Genlist.Item(Elm.Widget.Item.Static_Focus) { [[Elementary genlist item class]] legacy_prefix: elm_genlist_item; @@ -223,7 +223,7 @@ class Elm.Genlist.Item(Elm.Widget.Item) @property select_mode { get { [[Get the genlist item's select mode. - + It's ELM_OBJECT_SELECT_MODE_MAX on failure. ]] } @@ -461,5 +461,6 @@ class Elm.Genlist.Item(Elm.Widget.Item) Elm.Widget.Item.cursor_unset; Efl.Access.name { get; } Efl.Access.state_set { get; } + Efl.Ui.Focus.Object.prepare_logical; } } diff --git a/src/lib/elementary/elm_widget_genlist.h b/src/lib/elementary/elm_widget_genlist.h index 5e81cbe8ac..69c0cb530a 100644 --- a/src/lib/elementary/elm_widget_genlist.h +++ b/src/lib/elementary/elm_widget_genlist.h @@ -149,6 +149,9 @@ struct _Elm_Genlist_Data Ecore_Idle_Enterer *queue_filter_enterer; Eina_Hash *size_caches; + Eina_Hash *content_item_map; + Eo *provider; + Eina_Bool filter; Eina_Bool focus_on_selection_enabled : 1; Eina_Bool tree_effect_enabled : 1; --