From fdfcae968b4a57b57ea553b4475a4a2770f22a00 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Thu, 12 Apr 2018 21:28:49 +0200 Subject: [PATCH] elm_widget: Introduce elm_focus_legacy Code located here is meant for a legacy tree and legacy widgets. This is checked on the entry of the function --- src/Makefile_Elementary.am | 1 + src/lib/elementary/efl_ui_win.c | 29 ++- src/lib/elementary/elm_focus_legacy.c | 291 ++++++++++++++++++++++++++ src/lib/elementary/elm_main.c | 182 ---------------- src/lib/elementary/elm_priv.h | 2 +- src/lib/elementary/elm_widget.h | 10 +- 6 files changed, 317 insertions(+), 198 deletions(-) create mode 100644 src/lib/elementary/elm_focus_legacy.c diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index ac528db73c..0273aada14 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -836,6 +836,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_selection.c \ lib/elementary/efl_datetime_manager.c \ lib/elementary/efl_ui_dnd.c \ + lib/elementary/elm_focus_legacy.c \ static_libs/buildsystem/buildsystem.h \ static_libs/buildsystem/buildsystem_autotools.c \ lib/elementary/efl_ui_pager.c \ diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c index ea579835f2..1fa781997e 100644 --- a/src/lib/elementary/efl_ui_win.c +++ b/src/lib/elementary/efl_ui_win.c @@ -1744,18 +1744,27 @@ _key_action_move(Evas_Object *obj, const char *params) focus_dir = EFL_UI_FOCUS_DIRECTION_DOWN; else return EINA_FALSE; - o = efl_ui_focus_manager_move(obj, focus_dir); - if (!o) - { - if (focus_dir == EFL_UI_FOCUS_DIRECTION_NEXT || focus_dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS) - { - Efl_Ui_Focus_Object *root; + // The handling for legacy is different due to elm_object_next set + if (elm_widget_is_legacy(obj)) + elm_object_focus_next(obj, focus_dir); + else + { + Efl_Ui_Widget *o; + + o = efl_ui_focus_manager_move(obj, focus_dir); + if (!o) + { + if (focus_dir == EFL_UI_FOCUS_DIRECTION_NEXT || focus_dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS) + { + Efl_Ui_Focus_Object *root; + + root = efl_ui_focus_manager_root_get(obj); + efl_ui_focus_manager_setup_on_first_touch(obj, focus_dir, root); + } + } + } - root = efl_ui_focus_manager_root_get(obj); - efl_ui_focus_manager_setup_on_first_touch(obj, focus_dir, root); - } - } return EINA_TRUE; } diff --git a/src/lib/elementary/elm_focus_legacy.c b/src/lib/elementary/elm_focus_legacy.c new file mode 100644 index 0000000000..f39a777b25 --- /dev/null +++ b/src/lib/elementary/elm_focus_legacy.c @@ -0,0 +1,291 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include +#include "elm_priv.h" + +//we need those for legacy compatible code +#include "elm_genlist.eo.h" +#include "elm_gengrid.eo.h" + +#define API_ENTRY()\ + EINA_SAFETY_ON_NULL_RETURN(obj); \ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd); \ + EINA_SAFETY_ON_FALSE_RETURN(elm_widget_is_legacy(obj)); + +#define API_ENTRY_VAL(val)\ + EINA_SAFETY_ON_NULL_RETURN_VAL(obj, val); \ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, val); \ + EINA_SAFETY_ON_FALSE_RETURN_VAL(elm_widget_is_legacy(obj), val); + +#define MAPPING() \ + MAP(PREVIOUS, prev) \ + MAP(NEXT, next) \ + MAP(UP, up) \ + MAP(DOWN, down) \ + MAP(LEFT, left) \ + MAP(RIGHT, right) + + + +static Eina_List* +_custom_chain_get(const Efl_Ui_Widget *node) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(node, pd, NULL); + + return pd->legacy_focus.custom_chain; +} + +static void +_custom_chain_set(Efl_Ui_Widget *node, Eina_List *lst) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(node, pd); + + pd->legacy_focus.custom_chain = eina_list_free(pd->legacy_focus.custom_chain); + pd->legacy_focus.custom_chain = lst; +} + +Evas_Object* +legacy_elm_widget_next_targer(Efl_Ui_Widget *obj, Elm_Focus_Direction dir) +{ + API_ENTRY_VAL(NULL) + Efl_Ui_Widget *target = NULL; + + #define MAP(direction, field) if (dir == EFL_UI_FOCUS_DIRECTION_ ##direction && pd->legacy_focus.field) target = pd->legacy_focus.field; + + if (!target) + { + MAPPING() + } + #undef MAP + + return target; +} + +EAPI void +elm_object_focus_next_object_set(Evas_Object *obj, + Evas_Object *next EINA_UNUSED, + Elm_Focus_Direction dir EINA_UNUSED) +{ + API_ENTRY() + + + #define MAP(direction, field) if (dir == EFL_UI_FOCUS_DIRECTION_ ##direction) pd->legacy_focus.field = next; + MAPPING() + #undef MAP + ELM_WIDGET_DATA_GET_OR_RETURN(next, next_pd); + dir = efl_ui_focus_util_direction_complement(EFL_UI_FOCUS_UTIL_CLASS, dir); + #define MAP(direction, field) if (dir == EFL_UI_FOCUS_DIRECTION_ ##direction) next_pd->legacy_focus.field = obj; + MAPPING() + #undef MAP +} + +EAPI void +elm_object_focus_custom_chain_set(Evas_Object *obj, + Eina_List *objs EINA_UNUSED) +{ + API_ENTRY() + _custom_chain_set(obj, objs); +} + +EAPI void +elm_object_focus_custom_chain_unset(Evas_Object *obj) +{ + API_ENTRY() + + _custom_chain_set(obj, NULL); +} + +EAPI const Eina_List * +elm_object_focus_custom_chain_get(const Evas_Object *obj) +{ + API_ENTRY_VAL(NULL) + + return _custom_chain_get(obj); +} + +EAPI void +elm_object_focus_custom_chain_append(Evas_Object *obj, + Evas_Object *child EINA_UNUSED, + Evas_Object *relative_child EINA_UNUSED) +{ + API_ENTRY() + + pd->legacy_focus.custom_chain = eina_list_append_relative(pd->legacy_focus.custom_chain, child, relative_child); +} + +EAPI void +elm_object_focus_custom_chain_prepend(Evas_Object *obj, + Evas_Object *child EINA_UNUSED, + Evas_Object *relative_child EINA_UNUSED) +{ + API_ENTRY() + + pd->legacy_focus.custom_chain = eina_list_prepend_relative(pd->legacy_focus.custom_chain, child, relative_child); +} + +EINA_DEPRECATED EAPI void +elm_object_focus_cycle(Evas_Object *obj, + Elm_Focus_Direction dir) +{ + elm_object_focus_next(obj, dir); +} + +EAPI void +elm_object_focus_next(Evas_Object *obj, + Elm_Focus_Direction dir) +{ + Eina_Bool legacy_focus_move = EINA_FALSE; + Efl_Ui_Widget *o = NULL, *top; + Efl_Ui_Focus_Object *regular, *logical; + Efl_Ui_Focus_Manager *manager_top; + API_ENTRY() + + top = elm_object_top_widget_get(obj); + manager_top = efl_ui_focus_util_active_manager(EFL_UI_FOCUS_UTIL_CLASS, obj); + regular = efl_ui_focus_manager_request_move(manager_top, dir, NULL, EINA_FALSE); + logical = efl_ui_focus_manager_focus_get(manager_top); + + Efl_Ui_Focus_Object *legacy_target = legacy_elm_widget_next_targer(logical, dir); + if (legacy_target) + { + o = legacy_target; + efl_ui_focus_util_focus(EFL_UI_FOCUS_UTIL_CLASS, legacy_target); + if (elm_object_focused_object_get(top) == legacy_target) + { + legacy_focus_move = EINA_TRUE; + } + } + + if (!legacy_focus_move) + o = efl_ui_focus_manager_move(top, dir); + if (!o) + { + if (dir == EFL_UI_FOCUS_DIRECTION_NEXT || dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS) + { + Efl_Ui_Focus_Object *root; + + root = efl_ui_focus_manager_root_get(obj); + efl_ui_focus_manager_setup_on_first_touch(obj, dir, root); + } + } +} + +EAPI Evas_Object * +elm_object_focus_next_object_get(const Evas_Object *obj, + Elm_Focus_Direction dir) +{ + Efl_Ui_Widget *top = elm_object_top_widget_get(obj); + API_ENTRY_VAL(NULL) + + #define MAP(direction, field) if (dir == EFL_UI_FOCUS_DIRECTION_ ##direction && pd->legacy_focus.field) return pd->legacy_focus.field; + MAPPING() + #undef MAP + + return efl_ui_focus_manager_request_move(efl_ui_focus_util_active_manager(EFL_UI_FOCUS_UTIL_CLASS, top), dir, NULL, EINA_FALSE); +} + +EAPI Elm_Object_Item * +elm_object_focus_next_item_get(const Evas_Object *obj, + Elm_Focus_Direction dir EINA_UNUSED) +{ + API_ENTRY_VAL(NULL) + /* FOCUS-FIXME */ + return NULL; +} + +EAPI void +elm_object_focus_next_item_set(Evas_Object *obj, + Elm_Object_Item *next_item EINA_UNUSED, + Elm_Focus_Direction dir EINA_UNUSED) +{ + API_ENTRY() + /* FOCUS-FIXME */ +} + +EAPI Evas_Object * +elm_object_focused_object_get(const Evas_Object *obj) +{ + API_ENTRY_VAL(NULL) + Efl_Ui_Focus_Manager *man = elm_object_top_widget_get(obj); + + while(efl_ui_focus_manager_redirect_get(man)) + { + man = efl_ui_focus_manager_redirect_get(man); + + // legacy compatible code, earlier those containers have not exposed theire items + if (efl_isa(man, ELM_GENGRID_CLASS) || + efl_isa(man, ELM_TOOLBAR_CLASS) || + efl_isa(man, ELM_GENLIST_CLASS)) return man; + } + + return efl_ui_focus_manager_focus_get(man); +} + +EAPI Eina_Bool +elm_object_focus_get(const Evas_Object *obj) +{ + Efl_Ui_Focus_Manager *m; + Efl_Ui_Focus_Object *focused_child; + API_ENTRY_VAL(EINA_FALSE) + + if (!elm_widget_is(obj)) + return evas_object_focus_get(obj); + + m = efl_ui_focus_object_focus_manager_get(obj); + + //no manager means not registered + if (!m) return EINA_FALSE; + + //assertion: our redirect manager m is in the redirect chain + m = efl_ui_focus_object_focus_manager_get(obj); + + //if obj is the redriect manager its kind of focused + if (efl_ui_focus_manager_redirect_get(m) == obj) return EINA_TRUE; + + //if there is a redirect manager + if (!!efl_ui_focus_manager_redirect_get(m)) return EINA_FALSE; + + //now take the focused object and walk down the parents, if this is + focused_child = efl_ui_focus_manager_focus_get(m); + + while(focused_child) + { + if (focused_child == obj) return EINA_TRUE; + + focused_child = efl_ui_focus_object_focus_parent_get(focused_child); + } + + return efl_ui_focus_object_focus_get(obj); +} + +EAPI void +elm_object_focus_set(Evas_Object *obj, + Eina_Bool focus) +{ + // ugly, but, special case for inlined windows + if (efl_isa(obj, EFL_UI_WIN_CLASS)) + { + Evas_Object *inlined = elm_win_inlined_image_object_get(obj); + if (inlined) + { + evas_object_focus_set(inlined, focus); + return; + } + } + else if (elm_widget_is(obj)) + { + if (focus) + efl_ui_focus_util_focus(EFL_UI_FOCUS_UTIL_CLASS, obj); + else + { + if (efl_ui_focus_manager_focus_get(efl_ui_focus_object_focus_manager_get(obj)) == obj) + efl_ui_focus_manager_pop_history_stack(efl_ui_focus_object_focus_manager_get(obj)); + } + } + else + { + evas_object_focus_set(obj, focus); + } +} diff --git a/src/lib/elementary/elm_main.c b/src/lib/elementary/elm_main.c index a324d12e82..8e643cfd22 100644 --- a/src/lib/elementary/elm_main.c +++ b/src/lib/elementary/elm_main.c @@ -1516,75 +1516,6 @@ elm_cache_all_flush(void) } } -EAPI Eina_Bool -elm_object_focus_get(const Evas_Object *obj) -{ - Efl_Ui_Focus_Manager *m; - Efl_Ui_Focus_Object *focused_child; - EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); - - if (!elm_widget_is(obj)) - return evas_object_focus_get(obj); - - m = efl_ui_focus_object_focus_manager_get(obj); - - //no manager means not registered - if (!m) return EINA_FALSE; - - //assertion: our redirect manager m is in the redirect chain - m = efl_ui_focus_object_focus_manager_get(obj); - - //if obj is the redriect manager its kind of focused - if (efl_ui_focus_manager_redirect_get(m) == obj) return EINA_TRUE; - - //if there is a redirect manager - if (!!efl_ui_focus_manager_redirect_get(m)) return EINA_FALSE; - - //now take the focused object and walk down the parents, if this is - focused_child = efl_ui_focus_manager_focus_get(m); - - while(focused_child) - { - if (focused_child == obj) return EINA_TRUE; - - focused_child = efl_ui_focus_object_focus_parent_get(focused_child); - } - - return efl_ui_focus_object_focus_get(obj); -} - -EAPI void -elm_object_focus_set(Evas_Object *obj, - Eina_Bool focus) -{ - EINA_SAFETY_ON_NULL_RETURN(obj); - - // ugly, but, special case for inlined windows - if (efl_isa(obj, EFL_UI_WIN_CLASS)) - { - Evas_Object *inlined = elm_win_inlined_image_object_get(obj); - if (inlined) - { - evas_object_focus_set(inlined, focus); - return; - } - } - else if (elm_widget_is(obj)) - { - if (focus) - efl_ui_focus_util_focus(EFL_UI_FOCUS_UTIL_CLASS, obj); - else - { - if (efl_ui_focus_manager_focus_get(efl_ui_focus_object_focus_manager_get(obj)) == obj) - efl_ui_focus_manager_pop_history_stack(efl_ui_focus_object_focus_manager_get(obj)); - } - } - else - { - evas_object_focus_set(obj, focus); - } -} - EAPI void elm_object_focus_allow_set(Evas_Object *obj, Eina_Bool enable) @@ -1600,119 +1531,6 @@ elm_object_focus_allow_get(const Evas_Object *obj) return (elm_widget_can_focus_get(obj)) || (elm_widget_child_can_focus_get(obj)); } -EAPI void -elm_object_focus_custom_chain_set(Evas_Object *obj, - Eina_List *objs EINA_UNUSED) -{ - EINA_SAFETY_ON_NULL_RETURN(obj); - ERR("Focus-chain not supported"); -} - -EAPI void -elm_object_focus_custom_chain_unset(Evas_Object *obj) -{ - EINA_SAFETY_ON_NULL_RETURN(obj); - ERR("Focus-chain not supported"); -} - -EAPI const Eina_List * -elm_object_focus_custom_chain_get(const Evas_Object *obj) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); - ERR("Focus-chain not supported"); - return NULL; -} - -EAPI void -elm_object_focus_custom_chain_append(Evas_Object *obj, - Evas_Object *child EINA_UNUSED, - Evas_Object *relative_child EINA_UNUSED) -{ - EINA_SAFETY_ON_NULL_RETURN(obj); - ERR("Focus-chain not supported"); -} - -EAPI void -elm_object_focus_custom_chain_prepend(Evas_Object *obj, - Evas_Object *child EINA_UNUSED, - Evas_Object *relative_child EINA_UNUSED) -{ - EINA_SAFETY_ON_NULL_RETURN(obj); - ERR("Focus-chain not supported"); -} - -EINA_DEPRECATED EAPI void -elm_object_focus_cycle(Evas_Object *obj, - Elm_Focus_Direction dir) -{ - elm_object_focus_next(obj, dir); -} - -EAPI void -elm_object_focus_next(Evas_Object *obj, - Elm_Focus_Direction dir) -{ - Efl_Ui_Widget *top = elm_object_top_widget_get(obj); - EINA_SAFETY_ON_NULL_RETURN(obj); - - efl_ui_focus_manager_move(top, dir); -} - -EAPI Evas_Object * -elm_object_focus_next_object_get(const Evas_Object *obj, - Elm_Focus_Direction dir) -{ - Efl_Ui_Widget *top = elm_object_top_widget_get(obj); - EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); - - return efl_ui_focus_manager_request_move(efl_ui_focus_util_active_manager(EFL_UI_FOCUS_UTIL_CLASS, top), dir, NULL, EINA_FALSE); -} - -EAPI void -elm_object_focus_next_object_set(Evas_Object *obj, - Evas_Object *next EINA_UNUSED, - Elm_Focus_Direction dir EINA_UNUSED) -{ - EINA_SAFETY_ON_NULL_RETURN(obj); - ERR("setting explicit objects not allowed not supported"); -} - -EAPI Elm_Object_Item * -elm_object_focus_next_item_get(const Evas_Object *obj, - Elm_Focus_Direction dir EINA_UNUSED) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); - /* FOCUS-FIXME */ - return NULL; -} - -EAPI void -elm_object_focus_next_item_set(Evas_Object *obj, - Elm_Object_Item *next_item EINA_UNUSED, - Elm_Focus_Direction dir EINA_UNUSED) -{ - EINA_SAFETY_ON_NULL_RETURN(obj); - /* FOCUS-FIXME */ -} - -EAPI Evas_Object * -elm_object_focused_object_get(const Evas_Object *obj) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL); - Efl_Ui_Focus_Manager *man = elm_object_top_widget_get(obj); - - while(efl_ui_focus_manager_redirect_get(man)) - { - man = efl_ui_focus_manager_redirect_get(man); - - // legacy compatible code, earlier those containers have not exposed theire items - if (efl_isa(man, ELM_GENGRID_CLASS) || - efl_isa(man, ELM_TOOLBAR_CLASS) || - efl_isa(man, ELM_GENLIST_CLASS)) return man; - } - - return efl_ui_focus_manager_focus_get(man); -} EAPI void elm_object_tree_focus_allow_set(Evas_Object *obj, diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h index 66814bcacd..eaa260138c 100644 --- a/src/lib/elementary/elm_priv.h +++ b/src/lib/elementary/elm_priv.h @@ -706,7 +706,7 @@ void _elm_win_wl_cursor_set(Evas_Object *obj, const char *cursor void _efl_ui_focus_manager_redirect_events_del(Efl_Ui_Focus_Manager *manager, Eo *obj); void _efl_ui_focus_manager_redirect_events_add(Efl_Ui_Focus_Manager *manager, Eo *obj); - +Evas_Object* legacy_elm_widget_next_targer(Efl_Ui_Widget *obj, Elm_Focus_Direction dir); void _efl_access_shutdown(void); /* Combobox: no proper support for Efl.Part API yet. */ diff --git a/src/lib/elementary/elm_widget.h b/src/lib/elementary/elm_widget.h index 00b38892cc..19d86fa2b4 100644 --- a/src/lib/elementary/elm_widget.h +++ b/src/lib/elementary/elm_widget.h @@ -389,10 +389,6 @@ typedef struct _Elm_Widget_Smart_Data Evas_Object *hover_obj; Evas_Object *bg; Eina_List *tooltips, *cursors; - Evas_Object *focus_previous, *focus_next; - Evas_Object *focus_up, *focus_down, *focus_right, *focus_left; - Elm_Object_Item *item_focus_previous, *item_focus_next; - Elm_Object_Item *item_focus_up, *item_focus_down, *item_focus_right, *item_focus_left; /* "show region" coordinates. all widgets got those because this * info may be set and queried recursively through the widget @@ -441,7 +437,11 @@ typedef struct _Elm_Widget_Smart_Data Efl_Ui_Focus_Manager *manager; Efl_Ui_Focus_Object *provider; } manager; - + struct { + Eina_List *custom_chain; + Evas_Object *prev, *next, *up, *down, *right, *left; + Elm_Object_Item *item_prev, *item_next, *item_up, *item_down, *item_right, *item_left; + } legacy_focus; Eina_Bool scroll_x_locked : 1; Eina_Bool scroll_y_locked : 1;