From d4cd85aa55c15fdc088c27aaf46c745c9000b514 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Wed, 5 Jul 2017 12:48:52 +0200 Subject: [PATCH] efl_ui_focus_manager: split this of tinto a class and a interface it turns out to be very handy to have a interface for the moving and border elements, that is unconnected to the way of how widgets are registering themself. This for example enables us to get a simple focus manager that just redirects the call into a internal 2 dimensional data struct --- src/Makefile_Elementary.am | 2 + src/lib/elementary/Elementary.h | 1 + src/lib/elementary/efl_ui_focus_manager.c | 1452 ---------------- src/lib/elementary/efl_ui_focus_manager.eo | 88 +- .../elementary/efl_ui_focus_manager_calc.c | 1459 +++++++++++++++++ .../elementary/efl_ui_focus_manager_calc.eo | 107 ++ .../efl_ui_focus_manager_root_focus.c | 12 +- .../efl_ui_focus_manager_root_focus.eo | 6 +- src/lib/elementary/efl_ui_focus_manager_sub.c | 6 +- .../elementary/efl_ui_focus_manager_sub.eo | 2 +- src/lib/elementary/efl_ui_win.c | 2 +- src/lib/elementary/elc_fileselector.c | 2 +- src/lib/elementary/elm_box.c | 2 +- src/lib/elementary/elm_gengrid.c | 10 +- src/lib/elementary/elm_grid.c | 2 +- src/lib/elementary/elm_hover.c | 2 +- src/lib/elementary/elm_menu.c | 2 +- src/lib/elementary/elm_scroller.c | 2 +- src/lib/elementary/elm_table.c | 2 +- src/lib/elementary/elm_toolbar.c | 10 +- src/lib/elementary/elm_widget.c | 12 +- src/tests/elementary/elm_test_focus.c | 104 +- src/tests/elementary/elm_test_focus_common.c | 2 +- src/tests/elementary/elm_test_focus_sub.c | 40 +- 24 files changed, 1680 insertions(+), 1649 deletions(-) create mode 100644 src/lib/elementary/efl_ui_focus_manager_calc.c create mode 100644 src/lib/elementary/efl_ui_focus_manager_calc.eo diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index be81e9bf54..7cd5b85b9f 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -126,6 +126,7 @@ elm_public_eolian_files = \ lib/elementary/efl_ui_cursor.eo \ lib/elementary/efl_ui_image_factory.eo \ lib/elementary/efl_ui_focus_manager.eo \ + lib/elementary/efl_ui_focus_manager_calc.eo \ lib/elementary/efl_ui_focus_manager_sub.eo \ lib/elementary/efl_ui_focus_manager_root_focus.eo \ lib/elementary/efl_ui_focus_object.eo \ @@ -681,6 +682,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_clock_private.h \ lib/elementary/efl_ui_image_factory.c \ lib/elementary/efl_ui_focus_manager.c \ + lib/elementary/efl_ui_focus_manager_calc.c \ lib/elementary/efl_ui_focus_manager_sub.c \ lib/elementary/efl_ui_focus_object.c \ lib/elementary/efl_ui_focus_manager_root_focus.c \ diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 829a622bcf..766d854028 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -146,6 +146,7 @@ EAPI extern Elm_Version *elm_version; #if defined (EFL_EO_API_SUPPORT) && defined (EFL_BETA_API_SUPPORT) # include "efl_ui_focus_object.eo.h" # include "efl_ui_focus_manager.eo.h" +# include "efl_ui_focus_manager_calc.eo.h" # include "efl_ui_focus_manager_sub.eo.h" # include "efl_ui_focus_manager_root_focus.eo.h" # include "efl_ui_focus_user.eo.h" diff --git a/src/lib/elementary/efl_ui_focus_manager.c b/src/lib/elementary/efl_ui_focus_manager.c index 9ebb7ba94d..09db7da090 100644 --- a/src/lib/elementary/efl_ui_focus_manager.c +++ b/src/lib/elementary/efl_ui_focus_manager.c @@ -5,1456 +5,4 @@ #include #include "elm_priv.h" -#define MY_CLASS EFL_UI_FOCUS_MANAGER_CLASS -#define FOCUS_DATA(obj) Efl_Ui_Focus_Manager_Data *pd = efl_data_scope_get(obj, MY_CLASS); - -#define DIM_EFL_UI_FOCUS_DIRECTION(dim,neg) dim*2+neg -#define NODE_DIRECTIONS_COUNT 4 - -#define DIRECTION_CHECK(dir) (dir >= 0 && dir < EFL_UI_FOCUS_DIRECTION_LAST) - -//#define CALC_DEBUG -#define DEBUG_TUPLE(obj) efl_name_get(obj), efl_class_name_get(obj) - -static int _focus_log_domain = -1; - -#define F_CRI(...) EINA_LOG_DOM_CRIT(_focus_log_domain, __VA_ARGS__) -#define F_ERR(...) EINA_LOG_DOM_ERR(_focus_log_domain, __VA_ARGS__) -#define F_WRN(...) EINA_LOG_DOM_WARN(_focus_log_domain, __VA_ARGS__) -#define F_INF(...) EINA_LOG_DOM_INFO(_focus_log_domain, __VA_ARGS__) -#define F_DBG(...) EINA_LOG_DOM_DBG(_focus_log_domain, __VA_ARGS__) - -typedef struct { - Eina_Bool positive; - Efl_Ui_Focus_Object *anchor; -} Anchor; - -typedef enum { - DIMENSION_X = 0, - DIMENSION_Y = 1, -} Dimension; - -typedef struct _Border Border; -typedef struct _Node Node; - -struct _Border { - Eina_List *partners; -}; - -typedef enum { - NODE_TYPE_NORMAL = 0, - NODE_TYPE_ONLY_LOGICAL = 2, -} Node_Type; - -struct _Node{ - Node_Type type; //type of the node - - Efl_Ui_Focus_Object *focusable; - Efl_Ui_Focus_Manager *manager; - Efl_Ui_Focus_Manager *redirect_manager; - - struct _Tree_Node{ - Node *parent; //the parent of the tree - Eina_List *children; //this saves the original set of elements - Eina_List *safed_order; - }tree; - - struct _Graph_Node { - Border directions[NODE_DIRECTIONS_COUNT]; - } graph; -}; - -#define T(n) (n->tree) -#define G(n) (n->graph) - -typedef struct { - Eina_List *focus_stack; - Eina_Hash *node_hash; - Efl_Ui_Focus_Manager *redirect; - Eina_List *dirty; - - Node *root; -} Efl_Ui_Focus_Manager_Data; - -static Efl_Ui_Focus_Direction -_complement(Efl_Ui_Focus_Direction dir) -{ - #define COMP(a,b) \ - if (dir == a) return b; \ - if (dir == b) return a; - - COMP(EFL_UI_FOCUS_DIRECTION_RIGHT, EFL_UI_FOCUS_DIRECTION_LEFT) - COMP(EFL_UI_FOCUS_DIRECTION_UP, EFL_UI_FOCUS_DIRECTION_DOWN) - COMP(EFL_UI_FOCUS_DIRECTION_PREV, EFL_UI_FOCUS_DIRECTION_NEXT) - - #undef COMP - - return EFL_UI_FOCUS_DIRECTION_LAST; -} - -/* - * Set this new list of partners to the border. - * All old partners will be deleted - */ -static void -border_partners_set(Node *node, Efl_Ui_Focus_Direction direction, Eina_List *list) -{ - Node *partner; - Eina_List *lnode; - Border *border = &G(node).directions[direction]; - - EINA_LIST_FREE(border->partners, partner) - { - Border *comp_border = &G(partner).directions[_complement(direction)]; - - comp_border->partners = eina_list_remove(comp_border->partners, node); - } - - border->partners = list; - - EINA_LIST_FOREACH(border->partners, lnode, partner) - { - Border *comp_border = &G(partner).directions[_complement(direction)]; - - comp_border->partners = eina_list_append(comp_border->partners, node); - } -} - -/** - * Create a new node - */ -static Node* -node_new(Efl_Ui_Focus_Object *focusable, Efl_Ui_Focus_Manager *manager) -{ - Node *node; - - node = calloc(1, sizeof(Node)); - - node->focusable = focusable; - node->manager = manager; - - return node; -} - -/** - * Looks up given focus object from the focus manager. - * - * @returns node found, or NULL if focusable was not found in the manager. - */ -static Node* -node_get(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *focusable) -{ - Node *ret; - - ret = eina_hash_find(pd->node_hash, &focusable); - - if (ret) return ret; - - ERR("Focusable %p (%s) not registered in manager %p", focusable, efl_class_name_get(focusable), obj); - - return NULL; -} - -/** - * Free a node item and unlink this item from all direction - */ -static void -node_item_free(Node *item) -{ - Node *n; - Eina_List *l; - //free the graph items - for(int i = 0;i < NODE_DIRECTIONS_COUNT; i++) - { - border_partners_set(item, i, NULL); - } - - //free the tree items - if (!item->tree.parent && item->tree.children) - { - ERR("Freeing the root with children is going to break the logical tree!"); - } - - if (item->tree.parent && item->tree.children) - { - Node *parent; - - parent = item->tree.parent; - //reparent everything into the next layer - EINA_LIST_FOREACH(item->tree.children, l, n) - { - n->tree.parent = item->tree.parent; - } - parent->tree.children = eina_list_merge(parent->tree.children , item->tree.children); - } - - if (item->tree.parent) - { - Node *parent; - - parent = item->tree.parent; - T(parent).children = eina_list_remove(T(parent).children, item); - } - - //free the safed order - ELM_SAFE_FREE(T(item).safed_order, eina_list_free); - - free(item); -} - - -//CALCULATING STUFF - -static inline int -_distance(Eina_Rectangle node, Eina_Rectangle op, Dimension dim) -{ - int min, max, point; - int v1, v2; - - if (dim == DIMENSION_X) - { - min = op.x; - max = eina_rectangle_max_x(&op); - point = node.x + node.w/2; - } - else - { - min = op.y; - max = eina_rectangle_max_y(&op); - point = node.y + node.h/2; - } - - v1 = min - point; - v2 = max - point; - - if (abs(v1) < abs(v2)) - return v1; - else - return v2; -} - -static inline void -_calculate_node(Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *node, Dimension dim, Eina_List **pos, Eina_List **neg) -{ - Eina_Rectangle rect = EINA_RECTANGLE_INIT; - Efl_Ui_Focus_Object *op; - int dim_min, dim_max; - Eina_Iterator *nodes; - int cur_pos_min = 0, cur_neg_min = 0; - Node *n; - - nodes = eina_hash_iterator_data_new(pd->node_hash); - rect = efl_ui_focus_object_focus_geometry_get(node); - - *pos = NULL; - *neg = NULL; - - if (dim == DIMENSION_X) - { - dim_min = rect.y; - dim_max = rect.y + rect.h; - } - else - { - dim_min = rect.x; - dim_max = rect.x + rect.w; - } - - EINA_ITERATOR_FOREACH(nodes, n) - { - Eina_Rectangle op_rect = EINA_RECTANGLE_INIT; - int min, max; - - op = n->focusable; - if (op == node) continue; - - if (n->type == NODE_TYPE_ONLY_LOGICAL) continue; - - op_rect = efl_ui_focus_object_focus_geometry_get(op); - - if (dim == DIMENSION_X) - { - min = op_rect.y; - max = eina_rectangle_max_y(&op_rect); - } - else - { - min = op_rect.x; - max = eina_rectangle_max_x(&op_rect); - } - - - /* The only way the calculation does make sense is if the two number - * lines are not disconnected. - * If they are connected one point of the 4 lies between the min and max of the other line - */ - if (!((min <= max && max <= dim_min && dim_min <= dim_max) || - (dim_min <= dim_max && dim_max <= min && min <= max)) && - !eina_rectangle_intersection(&op_rect, &rect)) - { - //this thing hits horizontal - int tmp_dis; - - tmp_dis = _distance(rect, op_rect, dim); - - if (tmp_dis < 0) - { - if (tmp_dis == cur_neg_min) - { - //add it - *neg = eina_list_append(*neg, op); - } - else if (tmp_dis > cur_neg_min - || cur_neg_min == 0) //init case - { - //nuke the old and add -#ifdef CALC_DEBUG - printf("CORRECTION FOR %s-%s\n found anchor %s-%s in distance %d\n (%d,%d,%d,%d)\n (%d,%d,%d,%d)\n\n", DEBUG_TUPLE(node), DEBUG_TUPLE(op), - tmp_dis, - op_rect.x, op_rect.y, op_rect.w, op_rect.h, - rect.x, rect.y, rect.w, rect.h); -#endif - *neg = eina_list_free(*neg); - *neg = eina_list_append(NULL, op); - cur_neg_min = tmp_dis; - } - } - else - { - if (tmp_dis == cur_pos_min) - { - //add it - *pos = eina_list_append(*pos, op); - } - else if (tmp_dis < cur_pos_min - || cur_pos_min == 0) //init case - { - //nuke the old and add -#ifdef CALC_DEBUG - printf("CORRECTION FOR %s-%s\n found anchor %s-%s in distance %d\n (%d,%d,%d,%d)\n (%d,%d,%d,%d)\n\n", DEBUG_TUPLE(node), DEBUG_TUPLE(op), - tmp_dis, - op_rect.x, op_rect.y, op_rect.w, op_rect.h, - rect.x, rect.y, rect.w, rect.h); -#endif - *pos = eina_list_free(*pos); - *pos = eina_list_append(NULL, op); - cur_pos_min = tmp_dis; - } - } - - -#if 0 - printf("(%d,%d,%d,%d)%s vs(%d,%d,%d,%d)%s\n", rect.x, rect.y, rect.w, rect.h, elm_widget_part_text_get(node, NULL), op_rect.x, op_rect.y, op_rect.w, op_rect.h, elm_widget_part_text_get(op, NULL)); - printf("(%d,%d,%d,%d)\n", min, max, dim_min, dim_max); - printf("Candidate %d\n", tmp_dis); - if (anchor->anchor == NULL || abs(tmp_dis) < abs(distance)) //init case - { - distance = tmp_dis; - anchor->positive = tmp_dis > 0 ? EINA_FALSE : EINA_TRUE; - anchor->anchor = op; - //Helper for debugging wrong calculations - - } -#endif - } - - } - eina_iterator_free(nodes); - nodes = NULL; -} - -#ifdef CALC_DEBUG -static void -_debug_node(Node *node) -{ - Eina_List *tmp = NULL; - - if (!node) return; - - printf("NODE %s-%s\n", DEBUG_TUPLE(node->focusable)); - -#define DIR_LIST(dir) G(node).directions[dir].partners - -#define DIR_OUT(dir)\ - tmp = DIR_LIST(dir); \ - { \ - Eina_List *list_node; \ - Node *partner; \ - printf("-"#dir"-> ("); \ - EINA_LIST_FOREACH(tmp, list_node, partner) \ - printf("%s-%s,", DEBUG_TUPLE(partner->focusable)); \ - printf(")\n"); \ - } - - DIR_OUT(EFL_UI_FOCUS_DIRECTION_RIGHT) - DIR_OUT(EFL_UI_FOCUS_DIRECTION_LEFT) - DIR_OUT(EFL_UI_FOCUS_DIRECTION_UP) - DIR_OUT(EFL_UI_FOCUS_DIRECTION_DOWN) - -} -#endif - -static void -convert_border_set(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Data *pd, Node *node, Eina_List *focusable_list, Efl_Ui_Focus_Direction dir) -{ - Eina_List *partners = NULL; - Efl_Ui_Focus_Object *fobj; - - EINA_LIST_FREE(focusable_list, fobj) - { - Node *entry; - - entry = node_get(obj, pd, fobj); - if (!entry) - { - CRI("Found a obj in graph without node-entry!"); - return; - } - partners = eina_list_append(partners, entry); - } - - border_partners_set(node, dir, partners); -} - -static void -dirty_flush_node(Efl_Ui_Focus_Manager *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Node *node) -{ - Eina_List *x_partners_pos, *x_partners_neg; - Eina_List *y_partners_pos, *y_partners_neg; - - _calculate_node(pd, node->focusable, DIMENSION_X, &x_partners_pos, &x_partners_neg); - _calculate_node(pd, node->focusable, DIMENSION_Y, &y_partners_pos, &y_partners_neg); - - convert_border_set(obj, pd, node, x_partners_pos, EFL_UI_FOCUS_DIRECTION_RIGHT); - convert_border_set(obj, pd, node, x_partners_neg, EFL_UI_FOCUS_DIRECTION_LEFT); - convert_border_set(obj, pd, node, y_partners_neg, EFL_UI_FOCUS_DIRECTION_UP); - convert_border_set(obj, pd, node, y_partners_pos, EFL_UI_FOCUS_DIRECTION_DOWN); - -#ifdef CALC_DEBUG - _debug_node(node); -#endif -} - -static void -dirty_flush(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Data *pd, Node *node) -{ - if (!eina_list_data_find(pd->dirty, node)) return; - - efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); - - pd->dirty = eina_list_remove(pd->dirty, node); - - dirty_flush_node(obj, pd, node); -} - -static void -dirty_flush_all(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Data *pd) -{ - Node *node; - - efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); - - EINA_LIST_FREE(pd->dirty, node) - { - dirty_flush_node(obj, pd, node); - } -} - -static void -dirty_add(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Node *dirty) -{ - if (dirty->type == NODE_TYPE_ONLY_LOGICAL) - { - ERR("Only not only logical nodes can be marked dirty"); - return; - } - - //if (eina_list_data_find(pd->dirty, dirty)) return; - pd->dirty = eina_list_remove(pd->dirty, dirty); - pd->dirty = eina_list_append(pd->dirty, dirty); - - efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, NULL); -} - - -static void -_node_new_geometery_cb(void *data, const Efl_Event *event) -{ - Node *node; - FOCUS_DATA(data) - - node = node_get(data, pd, event->object); - if (!node) - return; - - dirty_add(data, pd, node); - - return; -} - -EFL_CALLBACKS_ARRAY_DEFINE(focusable_node, - {EFL_GFX_EVENT_RESIZE, _node_new_geometery_cb}, - {EFL_GFX_EVENT_MOVE, _node_new_geometery_cb}, -); - -//============================= - -static Node* -_register(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *child, Node *parent) -{ - Node *node; - if (!!eina_hash_find(pd->node_hash, &child)) - { - ERR("Child %p is already registered in the graph", child); - return NULL; - } - - node = node_new(child, obj); - eina_hash_add(pd->node_hash, &child, node); - - //add the parent - if (parent) - { - T(node).parent = parent; - T(parent).children = eina_list_append(T(parent).children, node); - } - - return node; -} -EOLIAN static Eina_Bool -_efl_ui_focus_manager_register_logical(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect) -{ - Node *node = NULL; - Node *pnode = NULL; - - EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(parent, EINA_FALSE); - - if (redirect) - EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(redirect, MY_CLASS), EINA_FALSE); - - F_DBG("Manager: %p register %p %p %p", obj, child, parent, redirect); - - pnode = node_get(obj, pd, parent); - if (!pnode) return EINA_FALSE; - - node = _register(obj, pd, child, pnode); - if (!node) return EINA_FALSE; - - node->type = NODE_TYPE_ONLY_LOGICAL; - node->redirect_manager = redirect; - - //set again - if (T(pnode).safed_order) - { - Eina_List *tmp; - - tmp = eina_list_clone(T(pnode).safed_order); - efl_ui_focus_manager_update_order(obj, parent, tmp); - } - - return EINA_TRUE; -} - - -EOLIAN static Eina_Bool -_efl_ui_focus_manager_register(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect) -{ - Node *node = NULL; - Node *pnode = NULL; - - EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(parent, EINA_FALSE); - - if (redirect) - EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(redirect, MY_CLASS), EINA_FALSE); - - F_DBG("Manager: %p register %p %p %p", obj, child, parent, redirect); - - pnode = node_get(obj, pd, parent); - if (!pnode) return EINA_FALSE; - - node = _register(obj, pd, child, pnode); - if (!node) return EINA_FALSE; - - //listen to changes - efl_event_callback_array_add(child, focusable_node(), obj); - - node->type = NODE_TYPE_NORMAL; - node->redirect_manager = redirect; - - //mark dirty - dirty_add(obj, pd, node); - - //set again - if (T(pnode).safed_order) - { - Eina_List *tmp; - - tmp = eina_list_clone(T(pnode).safed_order); - efl_ui_focus_manager_update_order(obj, parent, tmp); - } - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_ui_focus_manager_update_redirect(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Manager *redirect) -{ - Node *node = node_get(obj, pd, child); - if (!node) return EINA_FALSE; - - if (redirect) - EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(redirect, MY_CLASS), EINA_FALSE); - - node->redirect_manager = redirect; - - return EINA_TRUE; -} - -EOLIAN static Eina_Bool -_efl_ui_focus_manager_update_parent(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent_obj) -{ - Node *node; - Node *parent; - - EINA_SAFETY_ON_NULL_RETURN_VAL(parent_obj, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE); - - node = node_get(obj, pd, child); - parent = node_get(obj, pd, parent_obj); - - if (!node || !parent) return EINA_FALSE; - - if (T(node).parent) - { - Node *old_parent; - - old_parent = T(node).parent; - - T(old_parent).children = eina_list_remove(T(old_parent).children, node); - } - - T(node).parent = parent; - - if (T(node).parent) - { - T(parent).children = eina_list_append(T(parent).children, node); - } - - return EINA_TRUE; -} - -static Eina_List* -_set_a_without_b(Eina_List *a, Eina_List *b) -{ - Eina_List *a_out = NULL, *node; - void *data; - - a_out = eina_list_clone(a); - - EINA_LIST_FOREACH(b, node, data) - { - a_out = eina_list_remove(a_out, data); - } - - return a_out; -} - -static Eina_Bool -_equal_set(Eina_List *none_nodes, Eina_List *nodes) -{ - Eina_List *n; - Node *node; - - if (eina_list_count(nodes) != eina_list_count(none_nodes)) return EINA_FALSE; - - EINA_LIST_FOREACH(nodes, n, node) - { - if (!eina_list_data_find(none_nodes, node)) - return EINA_FALSE; - } - - return EINA_TRUE; -} - -EOLIAN static void -_efl_ui_focus_manager_update_order(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *parent, Eina_List *order) -{ - Node *pnode; - Efl_Ui_Focus_Object *o; - Eina_List *node_order = NULL, *not_ordered, *trash, *node_order_clean, *n; - - F_DBG("Manager_update_order on %p %p", obj, parent); - - pnode = node_get(obj, pd, parent); - if (!pnode) - return; - - ELM_SAFE_FREE(T(pnode).safed_order, eina_list_free); - T(pnode).safed_order = order; - - //get all nodes from the subset - EINA_LIST_FOREACH(order, n, o) - { - Node *tmp; - - tmp = eina_hash_find(pd->node_hash, &o); - - if (!tmp) continue; - - node_order = eina_list_append(node_order, tmp); - } - - not_ordered = _set_a_without_b(T(pnode).children, node_order); - trash = _set_a_without_b(node_order, T(pnode).children); - node_order_clean = _set_a_without_b(node_order, trash); - - eina_list_free(node_order); - eina_list_free(trash); - - eina_list_free(T(pnode).children); - T(pnode).children = eina_list_merge(node_order_clean, not_ordered); - - return; -} - -EOLIAN static Eina_Bool -_efl_ui_focus_manager_update_children(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *parent, Eina_List *order) -{ - Node *pnode; - Efl_Ui_Focus_Object *o; - Eina_Bool fail = EINA_FALSE; - Eina_List *node_order = NULL; - - pnode = node_get(obj, pd, parent); - if (!pnode) - return EINA_FALSE; - - //get all nodes from the subset - EINA_LIST_FREE(order, o) - { - Node *tmp; - - tmp = node_get(obj, pd, o); - if (!tmp) - fail = EINA_TRUE; - node_order = eina_list_append(node_order, tmp); - } - - if (fail) - { - eina_list_free(node_order); - return EINA_FALSE; - } - - if (!_equal_set(node_order, T(pnode).children)) - { - ERR("Set of children is not equal"); - return EINA_FALSE; - } - - eina_list_free(T(pnode).children); - T(pnode).children = node_order; - - return EINA_TRUE; -} - -EOLIAN static void -_efl_ui_focus_manager_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *child) -{ - Node *node; - - node = eina_hash_find(pd->node_hash, &child); - - if (!node) return; - - F_DBG("Manager: %p unregister %p", obj, child); - - - //remove the object from the stack if it hasn't done that until now - //after this it's not at the top anymore - //elm_widget_focus_set(node->focusable, EINA_FALSE); - //delete again from the list, for the case it was not at the top - pd->focus_stack = eina_list_remove(pd->focus_stack, node); - - //add all neighbors of the node to the dirty list - for(int i = 0; i < 4; i++) - { - Node *partner; - Eina_List *n; - - EINA_LIST_FOREACH(node->graph.directions[i].partners, n, partner) - { - dirty_add(obj, pd, partner); - } - } - - //remove from the dirty parts - pd->dirty = eina_list_remove(pd->dirty, node); - - eina_hash_del_by_key(pd->node_hash, &child); -} - -EOLIAN static void -_efl_ui_focus_manager_redirect_set(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Manager *redirect) -{ - Efl_Ui_Focus_Manager *old_manager; - - if (pd->redirect == redirect) return; - - F_DBG("Manager: %p setting redirect from %p to %p", obj, pd->redirect, redirect); - - if (pd->redirect) - efl_wref_del(pd->redirect, &pd->redirect); - - old_manager = pd->redirect; - pd->redirect = redirect; - - if (pd->redirect) - efl_wref_add(pd->redirect, &pd->redirect); - - efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_REDIRECT_CHANGED , old_manager); -} - -EOLIAN static Efl_Ui_Focus_Manager * -_efl_ui_focus_manager_redirect_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd) -{ - return pd->redirect; -} - -static void -_free_node(void *data) -{ - Node *node = data; - FOCUS_DATA(node->manager); - - efl_event_callback_array_del(node->focusable, focusable_node(), node->manager); - - if (pd->root != data) - { - node_item_free(node); - } -} - -EOLIAN static Efl_Object * -_efl_ui_focus_manager_efl_object_constructor(Eo *obj, Efl_Ui_Focus_Manager_Data *pd) -{ - pd->node_hash = eina_hash_pointer_new(_free_node); - return efl_constructor(efl_super(obj, MY_CLASS)); -} - -EOLIAN static Efl_Object * -_efl_ui_focus_manager_efl_object_provider_find(Eo *obj, Efl_Ui_Focus_Manager_Data *pd EINA_UNUSED, const Efl_Object *klass) -{ - if (klass == MY_CLASS) - return obj; - - return efl_provider_find(efl_super(obj, MY_CLASS), klass); -} - -EOLIAN static void -_efl_ui_focus_manager_efl_object_destructor(Eo *obj, Efl_Ui_Focus_Manager_Data *pd) -{ - eina_list_free(pd->focus_stack); - eina_list_free(pd->dirty); - - eina_hash_free(pd->node_hash); - - efl_ui_focus_manager_redirect_set(obj, NULL); - - if (pd->root) - node_item_free(pd->root); - pd->root = NULL; - - efl_destructor(efl_super(obj, MY_CLASS)); -} - -typedef struct { - Eina_Iterator iterator; - Eina_Iterator *real_iterator; - Efl_Ui_Focus_Manager *object; -} Border_Elements_Iterator; - -static Eina_Bool -_iterator_next(Border_Elements_Iterator *it, void **data) -{ - Node *node; - - EINA_ITERATOR_FOREACH(it->real_iterator, node) - { - for(int i = 0 ;i < NODE_DIRECTIONS_COUNT; i++) - { - if (node->type != NODE_TYPE_ONLY_LOGICAL && - !node->graph.directions[i].partners) - { - *data = node->focusable; - return EINA_TRUE; - } - } - } - return EINA_FALSE; -} - -static Eo * -_iterator_get_container(Border_Elements_Iterator *it) -{ - return it->object; -} - -static void -_iterator_free(Border_Elements_Iterator *it) -{ - eina_iterator_free(it->real_iterator); - free(it); -} - -EOLIAN static Eina_Iterator* -_efl_ui_focus_manager_border_elements_get(Eo *obj, Efl_Ui_Focus_Manager_Data *pd) -{ - Border_Elements_Iterator *it; - - dirty_flush_all(obj, pd); - - it = calloc(1, sizeof(Border_Elements_Iterator)); - - EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); - - it->real_iterator = eina_hash_iterator_data_new(pd->node_hash); - it->iterator.version = EINA_ITERATOR_VERSION; - it->iterator.next = FUNC_ITERATOR_NEXT(_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_iterator_get_container); - it->iterator.free = FUNC_ITERATOR_FREE(_iterator_free); - it->object = obj; - - return (Eina_Iterator*) it; -} - -static Node* -_no_history_element(Eina_Hash *node_hash) -{ - //nothing is selected yet, just try to use the first element in the iterator - Eina_Iterator *iter; - Node *upper; - - iter = eina_hash_iterator_data_new(node_hash); - - EINA_ITERATOR_FOREACH(iter, upper) - { - if (upper->type == NODE_TYPE_NORMAL) - break; - } - - eina_iterator_free(iter); - - if (upper->type != NODE_TYPE_NORMAL) - return NULL; - - return upper; -} - -static void -_get_middle(Evas_Object *obj, Eina_Vector2 *elem) -{ - Eina_Rectangle geom; - - geom = efl_ui_focus_object_focus_geometry_get(obj); - elem->x = geom.x + geom.w/2; - elem->y = geom.y + geom.h/2; -} - -static Node* -_coords_movement(Efl_Ui_Focus_Manager_Data *pd, Node *upper, Efl_Ui_Focus_Direction direction) -{ - Node *candidate; - Eina_List *node_list; - - //we are searching which of the partners is lower to the history - EINA_LIST_REVERSE_FOREACH(pd->focus_stack, node_list, candidate) - { - if (eina_list_data_find(G(upper).directions[direction].partners, candidate)) - { - //this is the next accessable part - return candidate; - } - } - - //if we haven't found anything in the history, use the widget with the smallest distance - { - Eina_List *lst = G(upper).directions[direction].partners; - Eina_List *n; - Node *node, *min = NULL; - Eina_Vector2 elem, other; - float min_distance = 0.0; - - - _get_middle(upper->focusable, &elem); - - EINA_LIST_FOREACH(lst, n, node) - { - _get_middle(node->focusable, &other); - float tmp = eina_vector2_distance_get(&other, &elem); - if (!min || tmp < min_distance) - { - min = node; - min_distance = tmp; - } - } - candidate = min; - } - return candidate; -} - - -static Node* -_prev_item(Node *node) -{ - Node *parent; - Eina_List *lnode; - - parent = T(node).parent; - lnode = eina_list_data_find_list(T(parent).children, node); - lnode = eina_list_prev(lnode); - - if (lnode) - return eina_list_data_get(lnode); - return NULL; -} - -static Node* -_next(Node *node) -{ - Node *n; - - //Case 1 we are having children - //But only enter the children if it does NOT have a redirect manager - if (T(node).children && !node->redirect_manager) - { - return eina_list_data_get(T(node).children); - } - - //case 2 we are the root and we don't have children, return ourself - if (!T(node).parent) - { - return node; - } - - //case 3 we are not at the end of the parents list - n = node; - while(T(n).parent) - { - Node *parent; - Eina_List *lnode; - - parent = T(n).parent; - lnode = eina_list_data_find_list(T(parent).children, n); - lnode = eina_list_next(lnode); - - if (lnode) - { - return eina_list_data_get(lnode); - } - - n = parent; - } - - //this is then the root again - return NULL; -} - -static Node* -_prev(Node *node) -{ - Node *n = NULL; - - //this is the root there is no parent - if (!T(node).parent) - return NULL; - - n =_prev_item(node); - //case 1 there is a item in the parent previous to node, which has children - if (n && T(n).children) - { - do - { - n = eina_list_last_data_get(T(n).children); - } - while (T(n).children); - - return n; - } - - //case 2 there is a item in the parent previous to node, which has no children - if (n) - return n; - - //case 3 there is a no item in the parent previous to this one - return T(node).parent; -} - - -static Node* -_logical_movement(Efl_Ui_Focus_Manager_Data *pd EINA_UNUSED, Node *upper, Efl_Ui_Focus_Direction direction) -{ - Node* (*deliver)(Node *n); - Node *result; - Eina_List *stack = NULL; - - if (direction == EFL_UI_FOCUS_DIRECTION_NEXT) - deliver = _next; - else - deliver = _prev; - - //search as long as we have a none logical parent - result = upper; - do - { - //give up, if we have already been here - if (!!eina_list_data_find(stack, result)) - { - eina_list_free(stack); - ERR("Warning cycle detected\n"); - return NULL; - } - - stack = eina_list_append(stack, result); - result = deliver(result); - } while(result && result->type != NODE_TYPE_NORMAL && !result->redirect_manager); - - eina_list_free(stack); - - return result; -} - -static Efl_Ui_Focus_Object* -_request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Direction direction, Node *upper) -{ - Node *dir = NULL; - - if (!upper) - upper = eina_list_last_data_get(pd->focus_stack); - - if (!upper) - { - upper = _no_history_element(pd->node_hash); - if (upper) - return upper->focusable; - return NULL; - - } - - dirty_flush(obj, pd, upper); - - if (direction == EFL_UI_FOCUS_DIRECTION_PREV - || direction == EFL_UI_FOCUS_DIRECTION_NEXT) - dir = _logical_movement(pd, upper, direction); - else - dir = _coords_movement(pd, upper, direction); - - //return the widget - if (dir) - return dir->focusable; - else - return NULL; -} - -EOLIAN static Efl_Ui_Focus_Object* -_efl_ui_focus_manager_request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Direction direction) -{ - EINA_SAFETY_ON_FALSE_RETURN_VAL(DIRECTION_CHECK(direction), NULL); - - if (pd->redirect) - return efl_ui_focus_manager_request_move(pd->redirect, direction); - else - { - Node *upper = NULL; - - upper = eina_list_last_data_get(pd->focus_stack); - - if (!upper) - { - upper = _no_history_element(pd->node_hash); - if (upper) - return upper->focusable; - return NULL; - } - - return _request_move(obj, pd, direction, upper); - } -} - -EOLIAN static void -_efl_ui_focus_manager_focus(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *focus) -{ - Node *node; - Node *old_focus; - Efl_Ui_Focus_Manager *redirect_manager; - - EINA_SAFETY_ON_NULL_RETURN(focus); - - //if we want to focus the root then just spin to the first normal - if (focus == pd->root->focusable) - { - Node *f = _logical_movement(pd, pd->root, EFL_UI_FOCUS_DIRECTION_NEXT); - - if (f) - focus = f->focusable; - - if (!focus) return; - } - - //check if node is part of this manager object - node = node_get(obj, pd, focus); - if (!node) return; - - F_DBG("Manager: %p focusing object %p %s", obj, focus, efl_class_name_get(focus)); - - if (node->type == NODE_TYPE_ONLY_LOGICAL && !node->redirect_manager && pd->root != node) - { - ERR(" %p is logical, cannot be focused", obj); - return; - } - - if (pd->redirect) - { - //first unset the redirect - efl_ui_focus_manager_redirect_set(obj, NULL); - } - - redirect_manager = node->redirect_manager; - - if (node->type == NODE_TYPE_NORMAL) - { - Eo *focusable; - //check if this is already the focused object - old_focus = eina_list_last_data_get(pd->focus_stack); - - //check if this is already at the top - if (old_focus && old_focus->focusable == focus) return; - - //remove the object from the list and add it again - pd->focus_stack = eina_list_remove(pd->focus_stack, node); - pd->focus_stack = eina_list_append(pd->focus_stack, node); - - //save fields we later need - focusable = node->focusable; - - //populate the new change - if (old_focus) efl_ui_focus_object_focus_set(old_focus->focusable, EINA_FALSE); - efl_ui_focus_object_focus_set(node->focusable, EINA_TRUE); - efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED, focusable); - node = NULL; - } - else if (node->redirect_manager) - { - Efl_Ui_Focus_Object *root; - - root = efl_ui_focus_manager_root_get(node->redirect_manager); - efl_ui_focus_manager_focus(node->redirect_manager, root); - } - - //now check if this is also a listener object - if (redirect_manager) - { - efl_ui_focus_manager_redirect_set(obj, redirect_manager); - } -} - -EOLIAN static Efl_Ui_Focus_Object* -_efl_ui_focus_manager_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Direction direction) -{ - Efl_Ui_Focus_Object *candidate = NULL; - - EINA_SAFETY_ON_FALSE_RETURN_VAL(DIRECTION_CHECK(direction), NULL); - - if (pd->redirect) - { - Efl_Ui_Focus_Object *old_candidate = NULL; - candidate = efl_ui_focus_manager_move(pd->redirect, direction); - old_candidate = efl_ui_focus_manager_focused(pd->redirect); - - if (!candidate) - { - Efl_Ui_Focus_Object *new_candidate = NULL; - Node *n; - - //there is no candidate check if we have something for that direction - new_candidate = NULL; - n = eina_hash_find(pd->node_hash, &old_candidate); - - if (direction == EFL_UI_FOCUS_DIRECTION_NEXT || - direction == EFL_UI_FOCUS_DIRECTION_PREV) - { - if (n) - { - n = T(n).parent; - new_candidate = _request_move(obj, pd, direction, n); - efl_ui_focus_manager_focus(obj, new_candidate); - candidate = new_candidate; - } - } - else - { - - if (n) - new_candidate = _request_move(obj, pd, direction, n); - - if (new_candidate) - { - //redirect does not have smth. but we do have. - efl_ui_focus_manager_focus(obj, new_candidate); - } - candidate = new_candidate; - } - - } - } - else - { - candidate = efl_ui_focus_manager_request_move(obj, direction); - - if (candidate) - efl_ui_focus_manager_focus(obj, candidate); - } - - F_DBG("Manager: %p moved to %p %s in direction %d", obj, candidate, efl_class_name_get(candidate), direction); - - return candidate; -} - -EOLIAN static Eina_Bool -_efl_ui_focus_manager_root_set(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *root) -{ - Node *node; - - if (pd->root) - { - ERR("Root element can only be set once!"); - return EINA_FALSE; - } - - node = _register(obj, pd, root, NULL); - node->type = NODE_TYPE_ONLY_LOGICAL; - - pd->root = node; - - return EINA_TRUE; -} - -EOLIAN static Efl_Ui_Focus_Object* -_efl_ui_focus_manager_root_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd) -{ - if (!pd->root) return NULL; - - return pd->root->focusable; -} - -EOLIAN static Efl_Object* -_efl_ui_focus_manager_efl_object_finalize(Eo *obj, Efl_Ui_Focus_Manager_Data *pd) -{ - Efl_Object *result; - - if (!pd->root) - { - ERR("Constructing failed. No root element set."); - return NULL; - } - - result = efl_finalize(efl_super(obj, MY_CLASS)); - - return result; -} - -static Eina_List* -_convert(Eina_List *node_list) -{ - Eina_List *n, *par = NULL; - Node *node; - - EINA_LIST_FOREACH(node_list, n, node) - par = eina_list_append(par, node->focusable); - - return par; -} - -EOLIAN static Efl_Ui_Focus_Object* -_efl_ui_focus_manager_focused(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd) -{ - Node *upper = NULL; - - upper = eina_list_last_data_get(pd->focus_stack); - - if (!upper) - return NULL; - return upper->focusable; -} - -EOLIAN static Efl_Ui_Focus_Relations* -_efl_ui_focus_manager_fetch(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *child) -{ - Efl_Ui_Focus_Relations *res; - Node *n, *tmp; - - n = node_get(obj, pd, child); - if (!n) - return NULL; - - res = calloc(1, sizeof(Efl_Ui_Focus_Relations)); - - dirty_flush(obj, pd, n); - -#define DIR_CLONE(dir) _convert(G(n).directions[dir].partners); - - res->right = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_RIGHT); - res->left = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_LEFT); - res->top = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_UP); - res->down = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_DOWN); - res->next = (tmp = _next(n)) ? tmp->focusable : NULL; - res->prev = (tmp = _prev(n)) ? tmp->focusable : NULL; - switch(n->type) - { - case NODE_TYPE_ONLY_LOGICAL: - res->type = "logical"; - break; - case NODE_TYPE_NORMAL: - res->type = "normal"; - break; - } - res->parent = T(n).parent->focusable; - res->redirect = n->redirect_manager; -#undef DIR_CLONE - - return res; -} - -EOLIAN static void -_efl_ui_focus_manager_class_constructor(Efl_Class *c EINA_UNUSED) -{ - _focus_log_domain = eina_log_domain_register("elementary-focus", EINA_COLOR_CYAN); -} - -EOLIAN static void -_efl_ui_focus_manager_class_destructor(Efl_Class *c EINA_UNUSED) -{ - eina_log_domain_unregister(_focus_log_domain); - _focus_log_domain = -1; -} - -EOLIAN static Efl_Ui_Focus_Object* -_efl_ui_focus_manager_logical_end(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd) -{ - Node *child = pd->root; - - EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL); - - //we need to return the most lower right element - - while(T(child).children) - child = eina_list_last_data_get(T(child).children); - while (child->type != NODE_TYPE_NORMAL) - child = _prev(child); - - return child ? child->focusable : NULL; -} - #include "efl_ui_focus_manager.eo.c" diff --git a/src/lib/elementary/efl_ui_focus_manager.eo b/src/lib/elementary/efl_ui_focus_manager.eo index 16a939a852..3491f2096f 100644 --- a/src/lib/elementary/efl_ui_focus_manager.eo +++ b/src/lib/elementary/efl_ui_focus_manager.eo @@ -29,7 +29,7 @@ struct Efl.Ui.Focus.Relations { redirect : Efl.Ui.Focus.Manager; [[Redirect manager]] } -class Efl.Ui.Focus.Manager (Efl.Object) { +interface Efl.Ui.Focus.Manager { [[Calculates the directions of Efl.Ui.Focus.Direction Each registered item will get a other registered object into each @@ -59,84 +59,6 @@ class Efl.Ui.Focus.Manager (Efl.Object) { } return : Efl.Ui.Focus.Object; [[Next object to focus]] } - register { - [[Register a new item in the graph. - - $parent can not be $null, it will be used as the parent in the - logical tree. - $redirect will be set as redirect property on that manager, once - $child gets focused. - ]] - params { - child : Efl.Ui.Focus.Object @nonull; [[The object to register]] - parent : Efl.Ui.Focus.Object @nonull; [[The parent to use in - the logical tree]] - redirect : Efl.Ui.Focus.Manager; [[The redirect manager to set - once this child is focused can be NULL for no redirect]] - } - return : bool; [[$true if successful, $false otherwise]] - } - register_logical { - [[Register a new item just for the logical parent. - - The item can never get focus, it just helps to build a tree out - of the items that are getting focus. - ]] - params { - child : Efl.Ui.Focus.Object @nonull; [[The object to register]] - parent : Efl.Ui.Focus.Object @nonull; [[The parent to use in - the logical tree]] - redirect : Efl.Ui.Focus.Manager; [[The redirect manager to set - once this child is focused can be $null for no redirect]] - } - return : bool; [[$true if successful, $false otherwise]] - } - update_redirect { - [[Set a new redirect object for the given child. - - Once $child is focused the redirect manager will be set - in the redirect property. Set redirect to $null if nothing should happen. - ]] - params { - child : Efl.Ui.Focus.Object @nonull; [[The child to update]] - redirect : Efl.Ui.Focus.Manager; [[Once $child got focused this - element will be set as redirect]] - } - return : bool; [[$true if successful, $false otherwise]] - } - update_parent { - [[Set a new logical parent for the given child.]] - params { - child : Efl.Ui.Focus.Object @nonull; [[The child to update]] - parent : Efl.Ui.Focus.Object @nonull; [[The parent which now - will be the logical parent of child]] - } - return : bool; [[$true if successful, $false otherwise]] - } - update_children { - [[Give the list of children a different order.]] - params { - parent : Efl.Ui.Focus.Object @nonull; [[the parent to update]] - children : own(list); [[the list with the new order]] - } - return : bool; [[$true if successful, $false otherwise]] - } - update_order { - [[Give the given order to the parent's child. - - Children from the list which are no real children are ignored. - ]] - params { - parent : Efl.Ui.Focus.Object @nonull; [[the parent to update]] - children : list; [[the order of items]] - } - } - unregister { - [[Unregister the given item from the focus graph.]] - params { - child : Efl.Ui.Focus.Object; [[The child to unregister.]] - } - } focus { [[Make the given object the currently focused object in this manager. @@ -212,14 +134,6 @@ class Efl.Ui.Focus.Manager (Efl.Object) { return : Efl.Ui.Focus.Object; [[Last object]] } } - implements { - class.constructor; - class.destructor; - Efl.Object.constructor; - Efl.Object.finalize; - Efl.Object.provider_find; - Efl.Object.destructor; - } events { redirect,changed : Efl.Ui.Focus.Manager; [[Emitted when the redirect object has changed, the old manager is passed as event info]] diff --git a/src/lib/elementary/efl_ui_focus_manager_calc.c b/src/lib/elementary/efl_ui_focus_manager_calc.c new file mode 100644 index 0000000000..b8c2294629 --- /dev/null +++ b/src/lib/elementary/efl_ui_focus_manager_calc.c @@ -0,0 +1,1459 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include +#include "elm_priv.h" + +#define MY_CLASS EFL_UI_FOCUS_MANAGER_CALC_CLASS +#define FOCUS_DATA(obj) Efl_Ui_Focus_Manager_Calc_Data *pd = efl_data_scope_get(obj, MY_CLASS); + +#define DIM_EFL_UI_FOCUS_DIRECTION(dim,neg) dim*2+neg +#define NODE_DIRECTIONS_COUNT 4 + +#define DIRECTION_CHECK(dir) (dir >= 0 && dir < EFL_UI_FOCUS_DIRECTION_LAST) + +//#define CALC_DEBUG +#define DEBUG_TUPLE(obj) efl_name_get(obj), efl_class_name_get(obj) + +static int _focus_log_domain = -1; + +#define F_CRI(...) EINA_LOG_DOM_CRIT(_focus_log_domain, __VA_ARGS__) +#define F_ERR(...) EINA_LOG_DOM_ERR(_focus_log_domain, __VA_ARGS__) +#define F_WRN(...) EINA_LOG_DOM_WARN(_focus_log_domain, __VA_ARGS__) +#define F_INF(...) EINA_LOG_DOM_INFO(_focus_log_domain, __VA_ARGS__) +#define F_DBG(...) EINA_LOG_DOM_DBG(_focus_log_domain, __VA_ARGS__) + +typedef struct { + Eina_Bool positive; + Efl_Ui_Focus_Object *anchor; +} Anchor; + +typedef enum { + DIMENSION_X = 0, + DIMENSION_Y = 1, +} Dimension; + +typedef struct _Border Border; +typedef struct _Node Node; + +struct _Border { + Eina_List *partners; +}; + +typedef enum { + NODE_TYPE_NORMAL = 0, + NODE_TYPE_ONLY_LOGICAL = 2, +} Node_Type; + +struct _Node{ + Node_Type type; //type of the node + + Efl_Ui_Focus_Object *focusable; + Efl_Ui_Focus_Manager *manager; + Efl_Ui_Focus_Manager *redirect_manager; + + struct _Tree_Node{ + Node *parent; //the parent of the tree + Eina_List *children; //this saves the original set of elements + Eina_List *safed_order; + }tree; + + struct _Graph_Node { + Border directions[NODE_DIRECTIONS_COUNT]; + } graph; +}; + +#define T(n) (n->tree) +#define G(n) (n->graph) + +typedef struct { + Eina_List *focus_stack; + Eina_Hash *node_hash; + Efl_Ui_Focus_Manager *redirect; + Eina_List *dirty; + + Node *root; +} Efl_Ui_Focus_Manager_Calc_Data; + +static Efl_Ui_Focus_Direction +_complement(Efl_Ui_Focus_Direction dir) +{ + #define COMP(a,b) \ + if (dir == a) return b; \ + if (dir == b) return a; + + COMP(EFL_UI_FOCUS_DIRECTION_RIGHT, EFL_UI_FOCUS_DIRECTION_LEFT) + COMP(EFL_UI_FOCUS_DIRECTION_UP, EFL_UI_FOCUS_DIRECTION_DOWN) + COMP(EFL_UI_FOCUS_DIRECTION_PREV, EFL_UI_FOCUS_DIRECTION_NEXT) + + #undef COMP + + return EFL_UI_FOCUS_DIRECTION_LAST; +} + +/* + * Set this new list of partners to the border. + * All old partners will be deleted + */ +static void +border_partners_set(Node *node, Efl_Ui_Focus_Direction direction, Eina_List *list) +{ + Node *partner; + Eina_List *lnode; + Border *border = &G(node).directions[direction]; + + EINA_LIST_FREE(border->partners, partner) + { + Border *comp_border = &G(partner).directions[_complement(direction)]; + + comp_border->partners = eina_list_remove(comp_border->partners, node); + } + + border->partners = list; + + EINA_LIST_FOREACH(border->partners, lnode, partner) + { + Border *comp_border = &G(partner).directions[_complement(direction)]; + + comp_border->partners = eina_list_append(comp_border->partners, node); + } +} + +/** + * Create a new node + */ +static Node* +node_new(Efl_Ui_Focus_Object *focusable, Efl_Ui_Focus_Manager *manager) +{ + Node *node; + + node = calloc(1, sizeof(Node)); + + node->focusable = focusable; + node->manager = manager; + + return node; +} + +/** + * Looks up given focus object from the focus manager. + * + * @returns node found, or NULL if focusable was not found in the manager. + */ +static Node* +node_get(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *focusable) +{ + Node *ret; + + ret = eina_hash_find(pd->node_hash, &focusable); + + if (ret) return ret; + + ERR("Focusable %p (%s) not registered in manager %p", focusable, efl_class_name_get(focusable), obj); + + return NULL; +} + +/** + * Free a node item and unlink this item from all direction + */ +static void +node_item_free(Node *item) +{ + Node *n; + Eina_List *l; + //free the graph items + for(int i = 0;i < NODE_DIRECTIONS_COUNT; i++) + { + border_partners_set(item, i, NULL); + } + + //free the tree items + if (!item->tree.parent && item->tree.children) + { + ERR("Freeing the root with children is going to break the logical tree!"); + } + + if (item->tree.parent && item->tree.children) + { + Node *parent; + + parent = item->tree.parent; + //reparent everything into the next layer + EINA_LIST_FOREACH(item->tree.children, l, n) + { + n->tree.parent = item->tree.parent; + } + parent->tree.children = eina_list_merge(parent->tree.children , item->tree.children); + } + + if (item->tree.parent) + { + Node *parent; + + parent = item->tree.parent; + T(parent).children = eina_list_remove(T(parent).children, item); + } + + //free the safed order + ELM_SAFE_FREE(T(item).safed_order, eina_list_free); + + free(item); +} + + +//CALCULATING STUFF + +static inline int +_distance(Eina_Rectangle node, Eina_Rectangle op, Dimension dim) +{ + int min, max, point; + int v1, v2; + + if (dim == DIMENSION_X) + { + min = op.x; + max = eina_rectangle_max_x(&op); + point = node.x + node.w/2; + } + else + { + min = op.y; + max = eina_rectangle_max_y(&op); + point = node.y + node.h/2; + } + + v1 = min - point; + v2 = max - point; + + if (abs(v1) < abs(v2)) + return v1; + else + return v2; +} + +static inline void +_calculate_node(Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *node, Dimension dim, Eina_List **pos, Eina_List **neg) +{ + Eina_Rectangle rect = EINA_RECTANGLE_INIT; + Efl_Ui_Focus_Object *op; + int dim_min, dim_max; + Eina_Iterator *nodes; + int cur_pos_min = 0, cur_neg_min = 0; + Node *n; + + nodes = eina_hash_iterator_data_new(pd->node_hash); + rect = efl_ui_focus_object_focus_geometry_get(node); + + *pos = NULL; + *neg = NULL; + + if (dim == DIMENSION_X) + { + dim_min = rect.y; + dim_max = rect.y + rect.h; + } + else + { + dim_min = rect.x; + dim_max = rect.x + rect.w; + } + + EINA_ITERATOR_FOREACH(nodes, n) + { + Eina_Rectangle op_rect = EINA_RECTANGLE_INIT; + int min, max; + + op = n->focusable; + if (op == node) continue; + + if (n->type == NODE_TYPE_ONLY_LOGICAL) continue; + + op_rect = efl_ui_focus_object_focus_geometry_get(op); + + if (dim == DIMENSION_X) + { + min = op_rect.y; + max = eina_rectangle_max_y(&op_rect); + } + else + { + min = op_rect.x; + max = eina_rectangle_max_x(&op_rect); + } + + + /* The only way the calculation does make sense is if the two number + * lines are not disconnected. + * If they are connected one point of the 4 lies between the min and max of the other line + */ + if (!((min <= max && max <= dim_min && dim_min <= dim_max) || + (dim_min <= dim_max && dim_max <= min && min <= max)) && + !eina_rectangle_intersection(&op_rect, &rect)) + { + //this thing hits horizontal + int tmp_dis; + + tmp_dis = _distance(rect, op_rect, dim); + + if (tmp_dis < 0) + { + if (tmp_dis == cur_neg_min) + { + //add it + *neg = eina_list_append(*neg, op); + } + else if (tmp_dis > cur_neg_min + || cur_neg_min == 0) //init case + { + //nuke the old and add +#ifdef CALC_DEBUG + printf("CORRECTION FOR %s-%s\n found anchor %s-%s in distance %d\n (%d,%d,%d,%d)\n (%d,%d,%d,%d)\n\n", DEBUG_TUPLE(node), DEBUG_TUPLE(op), + tmp_dis, + op_rect.x, op_rect.y, op_rect.w, op_rect.h, + rect.x, rect.y, rect.w, rect.h); +#endif + *neg = eina_list_free(*neg); + *neg = eina_list_append(NULL, op); + cur_neg_min = tmp_dis; + } + } + else + { + if (tmp_dis == cur_pos_min) + { + //add it + *pos = eina_list_append(*pos, op); + } + else if (tmp_dis < cur_pos_min + || cur_pos_min == 0) //init case + { + //nuke the old and add +#ifdef CALC_DEBUG + printf("CORRECTION FOR %s-%s\n found anchor %s-%s in distance %d\n (%d,%d,%d,%d)\n (%d,%d,%d,%d)\n\n", DEBUG_TUPLE(node), DEBUG_TUPLE(op), + tmp_dis, + op_rect.x, op_rect.y, op_rect.w, op_rect.h, + rect.x, rect.y, rect.w, rect.h); +#endif + *pos = eina_list_free(*pos); + *pos = eina_list_append(NULL, op); + cur_pos_min = tmp_dis; + } + } + + +#if 0 + printf("(%d,%d,%d,%d)%s vs(%d,%d,%d,%d)%s\n", rect.x, rect.y, rect.w, rect.h, elm_widget_part_text_get(node, NULL), op_rect.x, op_rect.y, op_rect.w, op_rect.h, elm_widget_part_text_get(op, NULL)); + printf("(%d,%d,%d,%d)\n", min, max, dim_min, dim_max); + printf("Candidate %d\n", tmp_dis); + if (anchor->anchor == NULL || abs(tmp_dis) < abs(distance)) //init case + { + distance = tmp_dis; + anchor->positive = tmp_dis > 0 ? EINA_FALSE : EINA_TRUE; + anchor->anchor = op; + //Helper for debugging wrong calculations + + } +#endif + } + + } + eina_iterator_free(nodes); + nodes = NULL; +} + +#ifdef CALC_DEBUG +static void +_debug_node(Node *node) +{ + Eina_List *tmp = NULL; + + if (!node) return; + + printf("NODE %s-%s\n", DEBUG_TUPLE(node->focusable)); + +#define DIR_LIST(dir) G(node).directions[dir].partners + +#define DIR_OUT(dir)\ + tmp = DIR_LIST(dir); \ + { \ + Eina_List *list_node; \ + Node *partner; \ + printf("-"#dir"-> ("); \ + EINA_LIST_FOREACH(tmp, list_node, partner) \ + printf("%s-%s,", DEBUG_TUPLE(partner->focusable)); \ + printf(")\n"); \ + } + + DIR_OUT(EFL_UI_FOCUS_DIRECTION_RIGHT) + DIR_OUT(EFL_UI_FOCUS_DIRECTION_LEFT) + DIR_OUT(EFL_UI_FOCUS_DIRECTION_UP) + DIR_OUT(EFL_UI_FOCUS_DIRECTION_DOWN) + +} +#endif + +static void +convert_border_set(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Node *node, Eina_List *focusable_list, Efl_Ui_Focus_Direction dir) +{ + Eina_List *partners = NULL; + Efl_Ui_Focus_Object *fobj; + + EINA_LIST_FREE(focusable_list, fobj) + { + Node *entry; + + entry = node_get(obj, pd, fobj); + if (!entry) + { + CRI("Found a obj in graph without node-entry!"); + return; + } + partners = eina_list_append(partners, entry); + } + + border_partners_set(node, dir, partners); +} + +static void +dirty_flush_node(Efl_Ui_Focus_Manager *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Node *node) +{ + Eina_List *x_partners_pos, *x_partners_neg; + Eina_List *y_partners_pos, *y_partners_neg; + + _calculate_node(pd, node->focusable, DIMENSION_X, &x_partners_pos, &x_partners_neg); + _calculate_node(pd, node->focusable, DIMENSION_Y, &y_partners_pos, &y_partners_neg); + + convert_border_set(obj, pd, node, x_partners_pos, EFL_UI_FOCUS_DIRECTION_RIGHT); + convert_border_set(obj, pd, node, x_partners_neg, EFL_UI_FOCUS_DIRECTION_LEFT); + convert_border_set(obj, pd, node, y_partners_neg, EFL_UI_FOCUS_DIRECTION_UP); + convert_border_set(obj, pd, node, y_partners_pos, EFL_UI_FOCUS_DIRECTION_DOWN); + +#ifdef CALC_DEBUG + _debug_node(node); +#endif +} + +static void +dirty_flush(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Node *node) +{ + if (!eina_list_data_find(pd->dirty, node)) return; + + efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); + + pd->dirty = eina_list_remove(pd->dirty, node); + + dirty_flush_node(obj, pd, node); +} + +static void +dirty_flush_all(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + Node *node; + + efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); + + EINA_LIST_FREE(pd->dirty, node) + { + dirty_flush_node(obj, pd, node); + } +} + +static void +dirty_add(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Node *dirty) +{ + if (dirty->type == NODE_TYPE_ONLY_LOGICAL) + { + ERR("Only not only logical nodes can be marked dirty"); + return; + } + + //if (eina_list_data_find(pd->dirty, dirty)) return; + pd->dirty = eina_list_remove(pd->dirty, dirty); + pd->dirty = eina_list_append(pd->dirty, dirty); + + efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, NULL); +} + + +static void +_node_new_geometery_cb(void *data, const Efl_Event *event) +{ + Node *node; + FOCUS_DATA(data) + + node = node_get(data, pd, event->object); + if (!node) + return; + + dirty_add(data, pd, node); + + return; +} + +EFL_CALLBACKS_ARRAY_DEFINE(focusable_node, + {EFL_GFX_EVENT_RESIZE, _node_new_geometery_cb}, + {EFL_GFX_EVENT_MOVE, _node_new_geometery_cb}, +); + +//============================= + +static Node* +_register(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child, Node *parent) +{ + Node *node; + if (!!eina_hash_find(pd->node_hash, &child)) + { + ERR("Child %p is already registered in the graph", child); + return NULL; + } + + node = node_new(child, obj); + eina_hash_add(pd->node_hash, &child, node); + + //add the parent + if (parent) + { + T(node).parent = parent; + T(parent).children = eina_list_append(T(parent).children, node); + } + + return node; +} +EOLIAN static Eina_Bool +_efl_ui_focus_manager_calc_register_logical(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect) +{ + Node *node = NULL; + Node *pnode = NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, EINA_FALSE); + + if (redirect) + EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(redirect, MY_CLASS), EINA_FALSE); + + F_DBG("Manager: %p register %p %p %p", obj, child, parent, redirect); + + pnode = node_get(obj, pd, parent); + if (!pnode) return EINA_FALSE; + + node = _register(obj, pd, child, pnode); + if (!node) return EINA_FALSE; + + node->type = NODE_TYPE_ONLY_LOGICAL; + node->redirect_manager = redirect; + + //set again + if (T(pnode).safed_order) + { + Eina_List *tmp; + + tmp = eina_list_clone(T(pnode).safed_order); + efl_ui_focus_manager_calc_update_order(obj, parent, tmp); + } + + return EINA_TRUE; +} + + +EOLIAN static Eina_Bool +_efl_ui_focus_manager_calc_register(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect) +{ + Node *node = NULL; + Node *pnode = NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, EINA_FALSE); + + if (redirect) + EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(redirect, MY_CLASS), EINA_FALSE); + + F_DBG("Manager: %p register %p %p %p", obj, child, parent, redirect); + + pnode = node_get(obj, pd, parent); + if (!pnode) return EINA_FALSE; + + node = _register(obj, pd, child, pnode); + if (!node) return EINA_FALSE; + + //listen to changes + efl_event_callback_array_add(child, focusable_node(), obj); + + node->type = NODE_TYPE_NORMAL; + node->redirect_manager = redirect; + + //mark dirty + dirty_add(obj, pd, node); + + //set again + if (T(pnode).safed_order) + { + Eina_List *tmp; + + tmp = eina_list_clone(T(pnode).safed_order); + efl_ui_focus_manager_calc_update_order(obj, parent, tmp); + } + + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_focus_manager_calc_update_redirect(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Manager *redirect) +{ + Node *node = node_get(obj, pd, child); + if (!node) return EINA_FALSE; + + if (redirect) + EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(redirect, MY_CLASS), EINA_FALSE); + + node->redirect_manager = redirect; + + return EINA_TRUE; +} + +EOLIAN static Eina_Bool +_efl_ui_focus_manager_calc_update_parent(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent_obj) +{ + Node *node; + Node *parent; + + EINA_SAFETY_ON_NULL_RETURN_VAL(parent_obj, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(child, EINA_FALSE); + + node = node_get(obj, pd, child); + parent = node_get(obj, pd, parent_obj); + + if (!node || !parent) return EINA_FALSE; + + if (T(node).parent) + { + Node *old_parent; + + old_parent = T(node).parent; + + T(old_parent).children = eina_list_remove(T(old_parent).children, node); + } + + T(node).parent = parent; + + if (T(node).parent) + { + T(parent).children = eina_list_append(T(parent).children, node); + } + + return EINA_TRUE; +} + +static Eina_List* +_set_a_without_b(Eina_List *a, Eina_List *b) +{ + Eina_List *a_out = NULL, *node; + void *data; + + a_out = eina_list_clone(a); + + EINA_LIST_FOREACH(b, node, data) + { + a_out = eina_list_remove(a_out, data); + } + + return a_out; +} + +static Eina_Bool +_equal_set(Eina_List *none_nodes, Eina_List *nodes) +{ + Eina_List *n; + Node *node; + + if (eina_list_count(nodes) != eina_list_count(none_nodes)) return EINA_FALSE; + + EINA_LIST_FOREACH(nodes, n, node) + { + if (!eina_list_data_find(none_nodes, node)) + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EOLIAN static void +_efl_ui_focus_manager_calc_update_order(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *parent, Eina_List *order) +{ + Node *pnode; + Efl_Ui_Focus_Object *o; + Eina_List *node_order = NULL, *not_ordered, *trash, *node_order_clean, *n; + + F_DBG("Manager_update_order on %p %p", obj, parent); + + pnode = node_get(obj, pd, parent); + if (!pnode) + return; + + ELM_SAFE_FREE(T(pnode).safed_order, eina_list_free); + T(pnode).safed_order = order; + + //get all nodes from the subset + EINA_LIST_FOREACH(order, n, o) + { + Node *tmp; + + tmp = eina_hash_find(pd->node_hash, &o); + + if (!tmp) continue; + + node_order = eina_list_append(node_order, tmp); + } + + not_ordered = _set_a_without_b(T(pnode).children, node_order); + trash = _set_a_without_b(node_order, T(pnode).children); + node_order_clean = _set_a_without_b(node_order, trash); + + eina_list_free(node_order); + eina_list_free(trash); + + eina_list_free(T(pnode).children); + T(pnode).children = eina_list_merge(node_order_clean, not_ordered); + + return; +} + +EOLIAN static Eina_Bool +_efl_ui_focus_manager_calc_update_children(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *parent, Eina_List *order) +{ + Node *pnode; + Efl_Ui_Focus_Object *o; + Eina_Bool fail = EINA_FALSE; + Eina_List *node_order = NULL; + + pnode = node_get(obj, pd, parent); + if (!pnode) + return EINA_FALSE; + + //get all nodes from the subset + EINA_LIST_FREE(order, o) + { + Node *tmp; + + tmp = node_get(obj, pd, o); + if (!tmp) + fail = EINA_TRUE; + node_order = eina_list_append(node_order, tmp); + } + + if (fail) + { + eina_list_free(node_order); + return EINA_FALSE; + } + + if (!_equal_set(node_order, T(pnode).children)) + { + ERR("Set of children is not equal"); + return EINA_FALSE; + } + + eina_list_free(T(pnode).children); + T(pnode).children = node_order; + + return EINA_TRUE; +} + +EOLIAN static void +_efl_ui_focus_manager_calc_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child) +{ + Node *node; + + node = eina_hash_find(pd->node_hash, &child); + + if (!node) return; + + F_DBG("Manager: %p unregister %p", obj, child); + + + //remove the object from the stack if it hasn't done that until now + //after this it's not at the top anymore + //elm_widget_focus_set(node->focusable, EINA_FALSE); + //delete again from the list, for the case it was not at the top + pd->focus_stack = eina_list_remove(pd->focus_stack, node); + + //add all neighbors of the node to the dirty list + for(int i = 0; i < 4; i++) + { + Node *partner; + Eina_List *n; + + EINA_LIST_FOREACH(node->graph.directions[i].partners, n, partner) + { + dirty_add(obj, pd, partner); + } + } + + //remove from the dirty parts + pd->dirty = eina_list_remove(pd->dirty, node); + + eina_hash_del_by_key(pd->node_hash, &child); +} + +EOLIAN static void +_efl_ui_focus_manager_calc_efl_ui_focus_manager_redirect_set(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Manager *redirect) +{ + Efl_Ui_Focus_Manager *old_manager; + + if (pd->redirect == redirect) return; + + F_DBG("Manager: %p setting redirect from %p to %p", obj, pd->redirect, redirect); + + if (pd->redirect) + efl_wref_del(pd->redirect, &pd->redirect); + + old_manager = pd->redirect; + pd->redirect = redirect; + + if (pd->redirect) + efl_wref_add(pd->redirect, &pd->redirect); + + efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_REDIRECT_CHANGED , old_manager); +} + +EOLIAN static Efl_Ui_Focus_Manager * +_efl_ui_focus_manager_calc_efl_ui_focus_manager_redirect_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + return pd->redirect; +} + +static void +_free_node(void *data) +{ + Node *node = data; + FOCUS_DATA(node->manager); + + efl_event_callback_array_del(node->focusable, focusable_node(), node->manager); + + if (pd->root != data) + { + node_item_free(node); + } +} + +EOLIAN static Efl_Object * +_efl_ui_focus_manager_calc_efl_object_constructor(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + pd->node_hash = eina_hash_pointer_new(_free_node); + return efl_constructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static Efl_Object * +_efl_ui_focus_manager_calc_efl_object_provider_find(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd EINA_UNUSED, const Efl_Object *klass) +{ + if (klass == MY_CLASS) + return obj; + + return efl_provider_find(efl_super(obj, MY_CLASS), klass); +} + +EOLIAN static void +_efl_ui_focus_manager_calc_efl_object_destructor(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + eina_list_free(pd->focus_stack); + eina_list_free(pd->dirty); + + eina_hash_free(pd->node_hash); + + efl_ui_focus_manager_redirect_set(obj, NULL); + + if (pd->root) + node_item_free(pd->root); + pd->root = NULL; + + efl_destructor(efl_super(obj, MY_CLASS)); +} + +typedef struct { + Eina_Iterator iterator; + Eina_Iterator *real_iterator; + Efl_Ui_Focus_Manager *object; +} Border_Elements_Iterator; + +static Eina_Bool +_iterator_next(Border_Elements_Iterator *it, void **data) +{ + Node *node; + + EINA_ITERATOR_FOREACH(it->real_iterator, node) + { + for(int i = 0 ;i < NODE_DIRECTIONS_COUNT; i++) + { + if (node->type != NODE_TYPE_ONLY_LOGICAL && + !node->graph.directions[i].partners) + { + *data = node->focusable; + return EINA_TRUE; + } + } + } + return EINA_FALSE; +} + +static Eo * +_iterator_get_container(Border_Elements_Iterator *it) +{ + return it->object; +} + +static void +_iterator_free(Border_Elements_Iterator *it) +{ + eina_iterator_free(it->real_iterator); + free(it); +} + +EOLIAN static Eina_Iterator* +_efl_ui_focus_manager_calc_efl_ui_focus_manager_border_elements_get(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + Border_Elements_Iterator *it; + + dirty_flush_all(obj, pd); + + it = calloc(1, sizeof(Border_Elements_Iterator)); + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->real_iterator = eina_hash_iterator_data_new(pd->node_hash); + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_iterator_free); + it->object = obj; + + return (Eina_Iterator*) it; +} + +static Node* +_no_history_element(Eina_Hash *node_hash) +{ + //nothing is selected yet, just try to use the first element in the iterator + Eina_Iterator *iter; + Node *upper; + + iter = eina_hash_iterator_data_new(node_hash); + + EINA_ITERATOR_FOREACH(iter, upper) + { + if (upper->type == NODE_TYPE_NORMAL) + break; + } + + eina_iterator_free(iter); + + if (upper->type != NODE_TYPE_NORMAL) + return NULL; + + return upper; +} + +static void +_get_middle(Evas_Object *obj, Eina_Vector2 *elem) +{ + Eina_Rectangle geom; + + geom = efl_ui_focus_object_focus_geometry_get(obj); + elem->x = geom.x + geom.w/2; + elem->y = geom.y + geom.h/2; +} + +static Node* +_coords_movement(Efl_Ui_Focus_Manager_Calc_Data *pd, Node *upper, Efl_Ui_Focus_Direction direction) +{ + Node *candidate; + Eina_List *node_list; + + //we are searching which of the partners is lower to the history + EINA_LIST_REVERSE_FOREACH(pd->focus_stack, node_list, candidate) + { + if (eina_list_data_find(G(upper).directions[direction].partners, candidate)) + { + //this is the next accessable part + return candidate; + } + } + + //if we haven't found anything in the history, use the widget with the smallest distance + { + Eina_List *lst = G(upper).directions[direction].partners; + Eina_List *n; + Node *node, *min = NULL; + Eina_Vector2 elem, other; + float min_distance = 0.0; + + + _get_middle(upper->focusable, &elem); + + EINA_LIST_FOREACH(lst, n, node) + { + _get_middle(node->focusable, &other); + float tmp = eina_vector2_distance_get(&other, &elem); + if (!min || tmp < min_distance) + { + min = node; + min_distance = tmp; + } + } + candidate = min; + } + return candidate; +} + + +static Node* +_prev_item(Node *node) +{ + Node *parent; + Eina_List *lnode; + + parent = T(node).parent; + lnode = eina_list_data_find_list(T(parent).children, node); + lnode = eina_list_prev(lnode); + + if (lnode) + return eina_list_data_get(lnode); + return NULL; +} + +static Node* +_next(Node *node) +{ + Node *n; + + //Case 1 we are having children + //But only enter the children if it does NOT have a redirect manager + if (T(node).children && !node->redirect_manager) + { + return eina_list_data_get(T(node).children); + } + + //case 2 we are the root and we don't have children, return ourself + if (!T(node).parent) + { + return node; + } + + //case 3 we are not at the end of the parents list + n = node; + while(T(n).parent) + { + Node *parent; + Eina_List *lnode; + + parent = T(n).parent; + lnode = eina_list_data_find_list(T(parent).children, n); + lnode = eina_list_next(lnode); + + if (lnode) + { + return eina_list_data_get(lnode); + } + + n = parent; + } + + //this is then the root again + return NULL; +} + +static Node* +_prev(Node *node) +{ + Node *n = NULL; + + //this is the root there is no parent + if (!T(node).parent) + return NULL; + + n =_prev_item(node); + //case 1 there is a item in the parent previous to node, which has children + if (n && T(n).children) + { + do + { + n = eina_list_last_data_get(T(n).children); + } + while (T(n).children); + + return n; + } + + //case 2 there is a item in the parent previous to node, which has no children + if (n) + return n; + + //case 3 there is a no item in the parent previous to this one + return T(node).parent; +} + + +static Node* +_logical_movement(Efl_Ui_Focus_Manager_Calc_Data *pd EINA_UNUSED, Node *upper, Efl_Ui_Focus_Direction direction) +{ + Node* (*deliver)(Node *n); + Node *result; + Eina_List *stack = NULL; + + if (direction == EFL_UI_FOCUS_DIRECTION_NEXT) + deliver = _next; + else + deliver = _prev; + + //search as long as we have a none logical parent + result = upper; + do + { + //give up, if we have already been here + if (!!eina_list_data_find(stack, result)) + { + eina_list_free(stack); + ERR("Warning cycle detected\n"); + return NULL; + } + + stack = eina_list_append(stack, result); + result = deliver(result); + } while(result && result->type != NODE_TYPE_NORMAL && !result->redirect_manager); + + eina_list_free(stack); + + return result; +} + +static Efl_Ui_Focus_Object* +_request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Direction direction, Node *upper) +{ + Node *dir = NULL; + + if (!upper) + upper = eina_list_last_data_get(pd->focus_stack); + + if (!upper) + { + upper = _no_history_element(pd->node_hash); + if (upper) + return upper->focusable; + return NULL; + + } + + dirty_flush(obj, pd, upper); + + if (direction == EFL_UI_FOCUS_DIRECTION_PREV + || direction == EFL_UI_FOCUS_DIRECTION_NEXT) + dir = _logical_movement(pd, upper, direction); + else + dir = _coords_movement(pd, upper, direction); + + //return the widget + if (dir) + return dir->focusable; + else + return NULL; +} + +EOLIAN static Efl_Ui_Focus_Object* +_efl_ui_focus_manager_calc_efl_ui_focus_manager_request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Direction direction) +{ + EINA_SAFETY_ON_FALSE_RETURN_VAL(DIRECTION_CHECK(direction), NULL); + + if (pd->redirect) + return efl_ui_focus_manager_request_move(pd->redirect, direction); + else + { + Node *upper = NULL; + + upper = eina_list_last_data_get(pd->focus_stack); + + if (!upper) + { + upper = _no_history_element(pd->node_hash); + if (upper) + return upper->focusable; + return NULL; + } + + return _request_move(obj, pd, direction, upper); + } +} + +EOLIAN static void +_efl_ui_focus_manager_calc_efl_ui_focus_manager_focus(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *focus) +{ + Node *node; + Node *old_focus; + Efl_Ui_Focus_Manager *redirect_manager; + + EINA_SAFETY_ON_NULL_RETURN(focus); + + //if we want to focus the root then just spin to the first normal + if (focus == pd->root->focusable) + { + Node *f = _logical_movement(pd, pd->root, EFL_UI_FOCUS_DIRECTION_NEXT); + + if (f) + focus = f->focusable; + + if (!focus) return; + } + + //check if node is part of this manager object + node = node_get(obj, pd, focus); + if (!node) return; + + F_DBG("Manager: %p focusing object %p %s", obj, focus, efl_class_name_get(focus)); + + if (node->type == NODE_TYPE_ONLY_LOGICAL && !node->redirect_manager && pd->root != node) + { + ERR(" %p is logical, cannot be focused", obj); + return; + } + + if (pd->redirect) + { + //first unset the redirect + efl_ui_focus_manager_redirect_set(obj, NULL); + } + + redirect_manager = node->redirect_manager; + + if (node->type == NODE_TYPE_NORMAL) + { + Eo *focusable; + //check if this is already the focused object + old_focus = eina_list_last_data_get(pd->focus_stack); + + //check if this is already at the top + if (old_focus && old_focus->focusable == focus) return; + + //remove the object from the list and add it again + pd->focus_stack = eina_list_remove(pd->focus_stack, node); + pd->focus_stack = eina_list_append(pd->focus_stack, node); + + //save fields we later need + focusable = node->focusable; + + //populate the new change + if (old_focus) efl_ui_focus_object_focus_set(old_focus->focusable, EINA_FALSE); + efl_ui_focus_object_focus_set(node->focusable, EINA_TRUE); + efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_FOCUSED, focusable); + node = NULL; + } + else if (node->redirect_manager) + { + Efl_Ui_Focus_Object *root; + + root = efl_ui_focus_manager_root_get(node->redirect_manager); + efl_ui_focus_manager_focus(node->redirect_manager, root); + } + + //now check if this is also a listener object + if (redirect_manager) + { + efl_ui_focus_manager_redirect_set(obj, redirect_manager); + } +} + +EOLIAN static Efl_Ui_Focus_Object* +_efl_ui_focus_manager_calc_efl_ui_focus_manager_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Direction direction) +{ + Efl_Ui_Focus_Object *candidate = NULL; + + EINA_SAFETY_ON_FALSE_RETURN_VAL(DIRECTION_CHECK(direction), NULL); + + if (pd->redirect) + { + Efl_Ui_Focus_Object *old_candidate = NULL; + candidate = efl_ui_focus_manager_move(pd->redirect, direction); + old_candidate = efl_ui_focus_manager_focused(pd->redirect); + + if (!candidate) + { + Efl_Ui_Focus_Object *new_candidate = NULL; + Node *n; + + //there is no candidate check if we have something for that direction + new_candidate = NULL; + n = eina_hash_find(pd->node_hash, &old_candidate); + + if (direction == EFL_UI_FOCUS_DIRECTION_NEXT || + direction == EFL_UI_FOCUS_DIRECTION_PREV) + { + if (n) + { + n = T(n).parent; + new_candidate = _request_move(obj, pd, direction, n); + efl_ui_focus_manager_focus(obj, new_candidate); + candidate = new_candidate; + } + } + else + { + + if (n) + new_candidate = _request_move(obj, pd, direction, n); + + if (new_candidate) + { + //redirect does not have smth. but we do have. + efl_ui_focus_manager_focus(obj, new_candidate); + } + candidate = new_candidate; + } + + } + } + else + { + candidate = efl_ui_focus_manager_request_move(obj, direction); + + if (candidate) + efl_ui_focus_manager_focus(obj, candidate); + } + + F_DBG("Manager: %p moved to %p %s in direction %d", obj, candidate, efl_class_name_get(candidate), direction); + + return candidate; +} + +EOLIAN static Eina_Bool +_efl_ui_focus_manager_calc_efl_ui_focus_manager_root_set(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *root) +{ + Node *node; + + if (pd->root) + { + ERR("Root element can only be set once!"); + return EINA_FALSE; + } + + node = _register(obj, pd, root, NULL); + node->type = NODE_TYPE_ONLY_LOGICAL; + + pd->root = node; + + return EINA_TRUE; +} + +EOLIAN static Efl_Ui_Focus_Object* +_efl_ui_focus_manager_calc_efl_ui_focus_manager_root_get(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + if (!pd->root) return NULL; + + return pd->root->focusable; +} + +EOLIAN static Efl_Object* +_efl_ui_focus_manager_calc_efl_object_finalize(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + Efl_Object *result; + + if (!pd->root) + { + ERR("Constructing failed. No root element set."); + return NULL; + } + + result = efl_finalize(efl_super(obj, MY_CLASS)); + + return result; +} + +static Eina_List* +_convert(Eina_List *node_list) +{ + Eina_List *n, *par = NULL; + Node *node; + + EINA_LIST_FOREACH(node_list, n, node) + par = eina_list_append(par, node->focusable); + + return par; +} + +EOLIAN static Efl_Ui_Focus_Object* +_efl_ui_focus_manager_calc_efl_ui_focus_manager_focused(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + Node *upper = NULL; + + upper = eina_list_last_data_get(pd->focus_stack); + + if (!upper) + return NULL; + return upper->focusable; +} + +EOLIAN static Efl_Ui_Focus_Relations* +_efl_ui_focus_manager_calc_efl_ui_focus_manager_fetch(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child) +{ + Efl_Ui_Focus_Relations *res; + Node *n, *tmp; + + n = node_get(obj, pd, child); + if (!n) + return NULL; + + res = calloc(1, sizeof(Efl_Ui_Focus_Relations)); + + dirty_flush(obj, pd, n); + +#define DIR_CLONE(dir) _convert(G(n).directions[dir].partners); + + res->right = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_RIGHT); + res->left = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_LEFT); + res->top = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_UP); + res->down = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_DOWN); + res->next = (tmp = _next(n)) ? tmp->focusable : NULL; + res->prev = (tmp = _prev(n)) ? tmp->focusable : NULL; + switch(n->type) + { + case NODE_TYPE_ONLY_LOGICAL: + res->type = "logical"; + break; + case NODE_TYPE_NORMAL: + res->type = "normal"; + break; + } + res->parent = T(n).parent->focusable; + res->redirect = n->redirect_manager; +#undef DIR_CLONE + + return res; +} + +EOLIAN static void +_efl_ui_focus_manager_calc_class_constructor(Efl_Class *c EINA_UNUSED) +{ + _focus_log_domain = eina_log_domain_register("elementary-focus", EINA_COLOR_CYAN); +} + +EOLIAN static void +_efl_ui_focus_manager_calc_class_destructor(Efl_Class *c EINA_UNUSED) +{ + eina_log_domain_unregister(_focus_log_domain); + _focus_log_domain = -1; +} + +EOLIAN static Efl_Ui_Focus_Object* +_efl_ui_focus_manager_calc_efl_ui_focus_manager_logical_end(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + Node *child = pd->root; + + EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL); + + //we need to return the most lower right element + + while(T(child).children) + child = eina_list_last_data_get(T(child).children); + while (child->type != NODE_TYPE_NORMAL) + child = _prev(child); + + return child ? child->focusable : NULL; +} +#include "efl_ui_focus_manager_calc.eo.c" diff --git a/src/lib/elementary/efl_ui_focus_manager_calc.eo b/src/lib/elementary/efl_ui_focus_manager_calc.eo new file mode 100644 index 0000000000..5817506590 --- /dev/null +++ b/src/lib/elementary/efl_ui_focus_manager_calc.eo @@ -0,0 +1,107 @@ +class Efl.Ui.Focus.Manager.Calc (Efl.Object, Efl.Ui.Focus.Manager) { + [[Calculates the directions of Efl.Ui.Focus.Direction + + Each registered item will get a other registered object into each + direction, you can get those items for the currently focused item if + you call request move. + + @since 1.20 + ]] + methods { + register { + [[Register a new item in the graph. + + $parent can not be $null, it will be used as the parent in the + logical tree. + $redirect will be set as redirect property on that manager, once + $child gets focused. + ]] + params { + child : Efl.Ui.Focus.Object @nonull; [[The object to register]] + parent : Efl.Ui.Focus.Object @nonull; [[The parent to use in + the logical tree]] + redirect : Efl.Ui.Focus.Manager; [[The redirect manager to set + once this child is focused can be NULL for no redirect]] + } + return : bool; [[$true if successful, $false otherwise]] + } + register_logical { + [[Register a new item just for the logical parent. + + The item can never get focus, it just helps to build a tree out + of the items that are getting focus. + ]] + params { + child : Efl.Ui.Focus.Object @nonull; [[The object to register]] + parent : Efl.Ui.Focus.Object @nonull; [[The parent to use in + the logical tree]] + redirect : Efl.Ui.Focus.Manager; [[The redirect manager to set + once this child is focused can be $null for no redirect]] + } + return : bool; [[$true if successful, $false otherwise]] + } + update_redirect { + [[Set a new redirect object for the given child. + + Once $child is focused the redirect manager will be set + in the redirect property. Set redirect to $null if nothing should happen. + ]] + params { + child : Efl.Ui.Focus.Object @nonull; [[The child to update]] + redirect : Efl.Ui.Focus.Manager; [[Once $child got focused this + element will be set as redirect]] + } + return : bool; [[$true if successful, $false otherwise]] + } + update_parent { + [[Set a new logical parent for the given child.]] + params { + child : Efl.Ui.Focus.Object @nonull; [[The child to update]] + parent : Efl.Ui.Focus.Object @nonull; [[The parent which now + will be the logical parent of child]] + } + return : bool; [[$true if successful, $false otherwise]] + } + update_children { + [[Give the list of children a different order.]] + params { + parent : Efl.Ui.Focus.Object @nonull; [[the parent to update]] + children : own(list); [[the list with the new order]] + } + return : bool; [[$true if successful, $false otherwise]] + } + update_order { + [[Give the given order to the parent's child. + + Children from the list which are no real children are ignored. + ]] + params { + parent : Efl.Ui.Focus.Object @nonull; [[the parent to update]] + children : list; [[the order of items]] + } + } + unregister { + [[Unregister the given item from the focus graph.]] + params { + child : Efl.Ui.Focus.Object; [[The child to unregister.]] + } + } + } + implements { + class.constructor; + class.destructor; + Efl.Ui.Focus.Manager.move; + Efl.Ui.Focus.Manager.request_move; + Efl.Ui.Focus.Manager.focus; + Efl.Ui.Focus.Manager.focused; + Efl.Ui.Focus.Manager.redirect {set; get;} + Efl.Ui.Focus.Manager.border_elements {get;} + Efl.Ui.Focus.Manager.root {set; get;} + Efl.Ui.Focus.Manager.fetch; + Efl.Ui.Focus.Manager.logical_end; + Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.provider_find; + Efl.Object.destructor; + } +} diff --git a/src/lib/elementary/efl_ui_focus_manager_root_focus.c b/src/lib/elementary/efl_ui_focus_manager_root_focus.c index fcfbd9047c..056e7e0503 100644 --- a/src/lib/elementary/efl_ui_focus_manager_root_focus.c +++ b/src/lib/elementary/efl_ui_focus_manager_root_focus.c @@ -29,20 +29,20 @@ _state_eval(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd) { if (!pd->none_logicals && pd->rect_registered) { - efl_ui_focus_manager_unregister(obj, pd->rect); + efl_ui_focus_manager_calc_unregister(obj, pd->rect); pd->rect_registered = EINA_FALSE; } else if (pd->none_logicals && !pd->rect_registered) { - efl_ui_focus_manager_register(obj, pd->rect, pd->root, NULL); + efl_ui_focus_manager_calc_register(obj, pd->rect, pd->root, NULL); pd->rect_registered = EINA_TRUE; } } EOLIAN static Eina_Bool -_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_register(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect) +_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_register(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect) { - if (efl_ui_focus_manager_register(efl_super(obj, MY_CLASS), child, parent, redirect)) + if (efl_ui_focus_manager_calc_register(efl_super(obj, MY_CLASS), child, parent, redirect)) { pd->none_logicals = eina_list_append(pd->none_logicals, child); return EINA_TRUE; @@ -53,9 +53,9 @@ _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_register(Eo *obj, Efl_Ui_F } EOLIAN static void -_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_unregister(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child) +_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_unregister(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child) { - efl_ui_focus_manager_unregister(efl_super(obj, MY_CLASS), child); + efl_ui_focus_manager_calc_unregister(efl_super(obj, MY_CLASS), child); pd->none_logicals = eina_list_remove(pd->none_logicals, child); diff --git a/src/lib/elementary/efl_ui_focus_manager_root_focus.eo b/src/lib/elementary/efl_ui_focus_manager_root_focus.eo index 3a3dd46ff8..0865b42cec 100644 --- a/src/lib/elementary/efl_ui_focus_manager_root_focus.eo +++ b/src/lib/elementary/efl_ui_focus_manager_root_focus.eo @@ -1,8 +1,8 @@ -class Efl.Ui.Focus.Manager.Root_Focus(Efl.Ui.Focus.Manager) { +class Efl.Ui.Focus.Manager.Root_Focus(Efl.Ui.Focus.Manager.Calc) { [[ This class ensures that the root is at least focusable, if nothing else is focusable]] implements { - Efl.Ui.Focus.Manager.register; - Efl.Ui.Focus.Manager.unregister; + Efl.Ui.Focus.Manager.Calc.register; + Efl.Ui.Focus.Manager.Calc.unregister; Efl.Ui.Focus.Manager.focus; Efl.Ui.Focus.Manager.focused; Efl.Ui.Focus.Manager.fetch; diff --git a/src/lib/elementary/efl_ui_focus_manager_sub.c b/src/lib/elementary/efl_ui_focus_manager_sub.c index c7a167892f..7826b22041 100644 --- a/src/lib/elementary/efl_ui_focus_manager_sub.c +++ b/src/lib/elementary/efl_ui_focus_manager_sub.c @@ -51,14 +51,14 @@ _focus_changed(void *data, const Efl_Event *event) static void _register(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager *par_m, Efl_Ui_Focus_Object *node, Efl_Ui_Focus_Object *logical) { - efl_ui_focus_manager_register(par_m, node, logical, obj); + efl_ui_focus_manager_calc_register(par_m, node, logical, obj); efl_event_callback_add(node, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED, _focus_changed, obj); } static void _unregister(Efl_Ui_Focus_Manager *obj, Efl_Ui_Focus_Manager *par_m, Efl_Ui_Focus_Object *node) { - efl_ui_focus_manager_unregister(par_m, node); + efl_ui_focus_manager_calc_unregister(par_m, node); efl_event_callback_del(node, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED, _focus_changed, obj); } @@ -170,7 +170,7 @@ _logical_manager_change(void *data EINA_UNUSED, const Efl_Event *ev) EINA_LIST_FOREACH(pd->current_border, n, b) { if (b == ev->object) continue; - efl_ui_focus_manager_update_parent(manager, b, ev->info); + efl_ui_focus_manager_calc_update_parent(manager, b, ev->info); } } diff --git a/src/lib/elementary/efl_ui_focus_manager_sub.eo b/src/lib/elementary/efl_ui_focus_manager_sub.eo index 3c1903bc37..148a399c68 100644 --- a/src/lib/elementary/efl_ui_focus_manager_sub.eo +++ b/src/lib/elementary/efl_ui_focus_manager_sub.eo @@ -1,4 +1,4 @@ -class Efl.Ui.Focus.Manager.Sub (Efl.Ui.Focus.Manager, Efl.Object) +class Efl.Ui.Focus.Manager.Sub (Efl.Ui.Focus.Manager.Calc, Efl.Object) { [[A class that automatically registeres its border elements in the parent manager diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c index 96f27cc535..9947f46635 100644 --- a/src/lib/elementary/efl_ui_win.c +++ b/src/lib/elementary/efl_ui_win.c @@ -5338,7 +5338,7 @@ _efl_ui_win_elm_widget_focus_manager_factory(Eo *obj EINA_UNUSED, Efl_Ui_Win_Dat { Efl_Ui_Focus_Manager *manager; - manager = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, obj, + manager = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj, efl_ui_focus_manager_root_set(efl_added, root) ); diff --git a/src/lib/elementary/elc_fileselector.c b/src/lib/elementary/elc_fileselector.c index 7ecadc659a..efa644b8f0 100644 --- a/src/lib/elementary/elc_fileselector.c +++ b/src/lib/elementary/elc_fileselector.c @@ -113,7 +113,7 @@ _focus_chain_update(Eo *obj, Elm_Fileselector_Data *pd) #undef A - efl_ui_focus_manager_update_order(efl_ui_focus_user_manager_get(obj), obj, tmp); + efl_ui_focus_manager_calc_update_order(efl_ui_focus_user_manager_get(obj), obj, tmp); } static void diff --git a/src/lib/elementary/elm_box.c b/src/lib/elementary/elm_box.c index 9f8cc47838..cda4c9eac4 100644 --- a/src/lib/elementary/elm_box.c +++ b/src/lib/elementary/elm_box.c @@ -28,7 +28,7 @@ _focus_order_flush(Eo *obj, Elm_Box_Data *pd EINA_UNUSED) Elm_Widget_Smart_Data *wpd = efl_data_scope_get(obj, ELM_WIDGET_CLASS); Eina_List *order = evas_object_box_children_get(wpd->resize_obj); - efl_ui_focus_manager_update_order(wpd->focus.manager, obj, order); + efl_ui_focus_manager_calc_update_order(wpd->focus.manager, obj, order); } static void * diff --git a/src/lib/elementary/elm_gengrid.c b/src/lib/elementary/elm_gengrid.c index 3808a60969..15ff80535b 100644 --- a/src/lib/elementary/elm_gengrid.c +++ b/src/lib/elementary/elm_gengrid.c @@ -2693,7 +2693,7 @@ _anim_end(Elm_Gengrid_Data *sd) { sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1)); sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it2)); - + if (it1_prev) { tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it1_prev)); @@ -2702,7 +2702,7 @@ _anim_end(Elm_Gengrid_Data *sd) } else sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it2)); - + if (it2_prev) { tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it2_prev)); @@ -2726,16 +2726,16 @@ _anim_end(Elm_Gengrid_Data *sd) { sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it1)); sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(sd->reorder.it2)); - + if (it1_prev) - { + { tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it1_prev)); sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(sd->reorder.it2), tmp); } else sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(sd->reorder.it2)); - + if (it2_prev) { tmp = eina_inlist_find(sd->items, EINA_INLIST_GET(it2_prev)); diff --git a/src/lib/elementary/elm_grid.c b/src/lib/elementary/elm_grid.c index fcccfb06c4..a1886f6008 100644 --- a/src/lib/elementary/elm_grid.c +++ b/src/lib/elementary/elm_grid.c @@ -19,7 +19,7 @@ _focus_order_flush(Eo *obj) Elm_Widget_Smart_Data *wpd = efl_data_scope_get(obj, ELM_WIDGET_CLASS); Eina_List *order = evas_object_grid_children_get(wpd->resize_obj); - efl_ui_focus_manager_update_order(wpd->focus.manager, obj, order); + efl_ui_focus_manager_calc_update_order(wpd->focus.manager, obj, order); } diff --git a/src/lib/elementary/elm_hover.c b/src/lib/elementary/elm_hover.c index 322f33f9df..ccec32ecee 100644 --- a/src/lib/elementary/elm_hover.c +++ b/src/lib/elementary/elm_hover.c @@ -703,7 +703,7 @@ _elm_hover_elm_widget_focus_manager_factory(Eo *obj EINA_UNUSED, Elm_Hover_Data { Efl_Ui_Focus_Manager *manager; - manager = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, obj, + manager = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj, efl_ui_focus_manager_root_set(efl_added, root) ); diff --git a/src/lib/elementary/elm_menu.c b/src/lib/elementary/elm_menu.c index a4baf34b8f..069f71dc5b 100644 --- a/src/lib/elementary/elm_menu.c +++ b/src/lib/elementary/elm_menu.c @@ -806,7 +806,7 @@ _elm_menu_elm_widget_focus_manager_factory(Eo *obj EINA_UNUSED, Elm_Menu_Data *p { Efl_Ui_Focus_Manager *manager; - manager = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, obj, + manager = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, obj, efl_ui_focus_manager_root_set(efl_added, root) ); diff --git a/src/lib/elementary/elm_scroller.c b/src/lib/elementary/elm_scroller.c index d0225616aa..ac85d6c66e 100644 --- a/src/lib/elementary/elm_scroller.c +++ b/src/lib/elementary/elm_scroller.c @@ -1453,7 +1453,7 @@ _elm_scroller_elm_widget_focus_register(Eo *obj, Elm_Scroller_Data *pd EINA_UNUS { //undepended from logical or not we always reigster as full with ourself as redirect *logical_flag = EINA_TRUE; - return efl_ui_focus_manager_register_logical(manager, obj, logical, obj); + return efl_ui_focus_manager_calc_register_logical(manager, obj, logical, obj); } diff --git a/src/lib/elementary/elm_table.c b/src/lib/elementary/elm_table.c index c3720e11a9..7c54b94e1a 100644 --- a/src/lib/elementary/elm_table.c +++ b/src/lib/elementary/elm_table.c @@ -20,7 +20,7 @@ _focus_order_flush(Eo *obj) Elm_Widget_Smart_Data *wpd = efl_data_scope_get(obj, ELM_WIDGET_CLASS); Eina_List *order = evas_object_table_children_get(wpd->resize_obj); - efl_ui_focus_manager_update_order(wpd->focus.manager, obj, order); + efl_ui_focus_manager_calc_update_order(wpd->focus.manager, obj, order); } EOLIAN static Eina_Bool diff --git a/src/lib/elementary/elm_toolbar.c b/src/lib/elementary/elm_toolbar.c index f01d888be7..ef75fc165f 100644 --- a/src/lib/elementary/elm_toolbar.c +++ b/src/lib/elementary/elm_toolbar.c @@ -87,12 +87,12 @@ _item_focus_eval(Elm_Toolbar_Item_Data *pd) if (want) { - efl_ui_focus_manager_register(manager, EO_OBJ(pd), widget, NULL); + efl_ui_focus_manager_calc_register(manager, EO_OBJ(pd), widget, NULL); pd->registered = manager; } else { - efl_ui_focus_manager_unregister(manager, EO_OBJ(pd)); + efl_ui_focus_manager_calc_unregister(manager, EO_OBJ(pd)); pd->registered = NULL; } @@ -118,7 +118,7 @@ _item_focus_eval_all(Elm_Toolbar *obj, Elm_Toolbar_Data *pd) order = eina_list_append(order, EO_OBJ(pd->more_item)); } - efl_ui_focus_manager_update_order(wpd->focus.manager, obj, order); + efl_ui_focus_manager_calc_update_order(wpd->focus.manager, obj, order); } static int @@ -2381,7 +2381,7 @@ _elm_toolbar_item_efl_object_destructor(Eo *eo_item, Elm_Toolbar_Item_Data *item if (item->registered) { - efl_ui_focus_manager_unregister(item->registered, eo_item); + efl_ui_focus_manager_calc_unregister(item->registered, eo_item); item->registered = NULL; } @@ -3092,7 +3092,7 @@ EOLIAN static Eina_Bool _elm_toolbar_elm_widget_focus_register(Eo *obj, Elm_Toolbar_Data *pd EINA_UNUSED, Efl_Ui_Focus_Manager *manager, Efl_Ui_Focus_Object *logical, Eina_Bool *logical_flag) { *logical_flag = EINA_TRUE; - return efl_ui_focus_manager_register_logical(manager, obj, logical, NULL); + return efl_ui_focus_manager_calc_register_logical(manager, obj, logical, NULL); } EOLIAN static Eo * diff --git a/src/lib/elementary/elm_widget.c b/src/lib/elementary/elm_widget.c index b0b515cd15..cb14afcc70 100644 --- a/src/lib/elementary/elm_widget.c +++ b/src/lib/elementary/elm_widget.c @@ -246,7 +246,7 @@ _focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd) Efl_Ui_Focus_Manager *new = NULL, *old = NULL; parent = elm_widget_parent_get(obj); - if (efl_isa(parent, EFL_UI_FOCUS_MANAGER_CLASS)) + if (efl_isa(parent, EFL_UI_FOCUS_MANAGER_INTERFACE)) { new = parent; } @@ -280,9 +280,9 @@ _elm_widget_focus_register(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED, { if (!*logical_flag) - return efl_ui_focus_manager_register(manager, obj, logical, NULL); + return efl_ui_focus_manager_calc_register(manager, obj, logical, NULL); else - return efl_ui_focus_manager_register_logical(manager, obj, logical, NULL); + return efl_ui_focus_manager_calc_register_logical(manager, obj, logical, NULL); } @@ -329,7 +329,7 @@ _focus_state_eval(Eo *obj, Elm_Widget_Smart_Data *pd) (pd->focus.manager && should && want_full == pd->focus.logical) ) { - efl_ui_focus_manager_unregister(pd->focus.manager, obj); + efl_ui_focus_manager_calc_unregister(pd->focus.manager, obj); pd->focus.manager = NULL; pd->focus.parent = NULL; } @@ -355,7 +355,7 @@ _focus_state_eval(Eo *obj, Elm_Widget_Smart_Data *pd) } else if (!should && pd->focus.manager) { - efl_ui_focus_manager_unregister(pd->focus.manager, obj); + efl_ui_focus_manager_calc_unregister(pd->focus.manager, obj); pd->focus.manager = NULL; pd->focus.parent = NULL; } @@ -4127,7 +4127,7 @@ _elm_widget_efl_object_dbg_info_get(Eo *eo_obj, Elm_Widget_Smart_Data *_pd EINA_ } //if thats a focus manager, give useful information like the border elements - if (efl_isa(eo_obj, EFL_UI_FOCUS_MANAGER_CLASS)) + if (efl_isa(eo_obj, EFL_UI_FOCUS_MANAGER_INTERFACE)) { Efl_Dbg_Info *border; diff --git a/src/tests/elementary/elm_test_focus.c b/src/tests/elementary/elm_test_focus.c index 3908b40ed2..867419fddd 100644 --- a/src/tests/elementary/elm_test_focus.c +++ b/src/tests/elementary/elm_test_focus.c @@ -6,15 +6,15 @@ START_TEST(focus_unregister_twice) Efl_Ui_Focus_Object *r1 = efl_add(FOCUS_TEST_CLASS, NULL); Efl_Ui_Focus_Object *r2 = efl_add(FOCUS_TEST_CLASS, NULL); - Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, r1) ); - fail_if(!efl_ui_focus_manager_register(m, r2, r1, NULL)); + fail_if(!efl_ui_focus_manager_calc_register(m, r2, r1, NULL)); - efl_ui_focus_manager_unregister(m, r1); - efl_ui_focus_manager_unregister(m, r1); - efl_ui_focus_manager_unregister(m, r1); + efl_ui_focus_manager_calc_unregister(m, r1); + efl_ui_focus_manager_calc_unregister(m, r1); + efl_ui_focus_manager_calc_unregister(m, r1); efl_del(r2); efl_del(r1); @@ -31,12 +31,12 @@ START_TEST(focus_register_twice) Efl_Ui_Focus_Object *r1 = elm_focus_test_object_new("r1", 0, 0, 10, 10); Efl_Ui_Focus_Object *r2 = elm_focus_test_object_new("r2", 0, 10, 10, 10); - Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, r1) ); - fail_if(!efl_ui_focus_manager_register(m, r2, r1, NULL)); - fail_if(efl_ui_focus_manager_register(m, r2, r1, NULL)); + fail_if(!efl_ui_focus_manager_calc_register(m, r2, r1, NULL)); + fail_if(efl_ui_focus_manager_calc_register(m, r2, r1, NULL)); efl_del(r1); efl_del(m); @@ -55,11 +55,11 @@ START_TEST(pos_check) elm_focus_test_setup_cross(&middle, &south, &north, &east, &west); m = elm_focus_test_manager_new(&root); - efl_ui_focus_manager_register(m, middle, root, NULL); - efl_ui_focus_manager_register(m, north, root, NULL); - efl_ui_focus_manager_register(m, south, root, NULL); - efl_ui_focus_manager_register(m, west, root, NULL); - efl_ui_focus_manager_register(m, east, root, NULL); + efl_ui_focus_manager_calc_register(m, middle, root, NULL); + efl_ui_focus_manager_calc_register(m, north, root, NULL); + efl_ui_focus_manager_calc_register(m, south, root, NULL); + efl_ui_focus_manager_calc_register(m, west, root, NULL); + efl_ui_focus_manager_calc_register(m, east, root, NULL); #define CHECK(obj, r,l,u,d) \ efl_ui_focus_manager_focus(m, obj); \ @@ -97,16 +97,16 @@ START_TEST(redirect) TEST_OBJ_NEW(one, 0, 0, 20, 20); TEST_OBJ_NEW(two, 20, 0, 20, 20); - Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + Efl_Ui_Focus_Manager *m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root) ); - Efl_Ui_Focus_Manager *m2 = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + Efl_Ui_Focus_Manager *m2 = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root2) ); - efl_ui_focus_manager_register(m2, one, root2, NULL); - efl_ui_focus_manager_register(m2, two, root2, NULL); + efl_ui_focus_manager_calc_register(m2, one, root2, NULL); + efl_ui_focus_manager_calc_register(m2, two, root2, NULL); efl_ui_focus_manager_redirect_set(m, m2); efl_ui_focus_manager_focus(m2, one); @@ -130,11 +130,11 @@ START_TEST(border_check) elm_focus_test_setup_cross(&middle, &south, &north, &east, &west); m = elm_focus_test_manager_new(&root); - efl_ui_focus_manager_register(m, middle, root, NULL); - efl_ui_focus_manager_register(m, south, root, NULL); - efl_ui_focus_manager_register(m, north, root, NULL); - efl_ui_focus_manager_register(m, east, root, NULL); - efl_ui_focus_manager_register(m, west, root, NULL); + efl_ui_focus_manager_calc_register(m, middle, root, NULL); + efl_ui_focus_manager_calc_register(m, south, root, NULL); + efl_ui_focus_manager_calc_register(m, north, root, NULL); + efl_ui_focus_manager_calc_register(m, east, root, NULL); + efl_ui_focus_manager_calc_register(m, west, root, NULL); iter = efl_ui_focus_manager_border_elements_get(m); @@ -192,16 +192,16 @@ START_TEST(logical_chain) TEST_OBJ_NEW(subchild23, 0, i*20, 20, 20); //register everything - efl_ui_focus_manager_register(m, root, lroot, NULL); - efl_ui_focus_manager_register(m, child1, root, NULL); - efl_ui_focus_manager_register(m, child2, root, NULL); - efl_ui_focus_manager_register_logical(m, child3, root, NULL); - efl_ui_focus_manager_register(m, subchild11, child1, NULL); - efl_ui_focus_manager_register(m, subchild12, child1, NULL); - efl_ui_focus_manager_register(m, subchild13, child1, NULL); - efl_ui_focus_manager_register(m, subchild21, child3, NULL); - efl_ui_focus_manager_register(m, subchild22, child3, NULL); - efl_ui_focus_manager_register(m, subchild23, child3, NULL); + efl_ui_focus_manager_calc_register(m, root, lroot, NULL); + efl_ui_focus_manager_calc_register(m, child1, root, NULL); + efl_ui_focus_manager_calc_register(m, child2, root, NULL); + efl_ui_focus_manager_calc_register_logical(m, child3, root, NULL); + efl_ui_focus_manager_calc_register(m, subchild11, child1, NULL); + efl_ui_focus_manager_calc_register(m, subchild12, child1, NULL); + efl_ui_focus_manager_calc_register(m, subchild13, child1, NULL); + efl_ui_focus_manager_calc_register(m, subchild21, child3, NULL); + efl_ui_focus_manager_calc_register(m, subchild22, child3, NULL); + efl_ui_focus_manager_calc_register(m, subchild23, child3, NULL); efl_ui_focus_manager_focus(m, root); @@ -228,7 +228,7 @@ START_TEST(finalize_check) elm_init(1, NULL); - m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL); + m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL); fail_if(m); elm_shutdown(); @@ -245,15 +245,15 @@ START_TEST(redirect_param) TEST_OBJ_NEW(root2, 0, 20, 20, 20); TEST_OBJ_NEW(child, 0, 20, 20, 20); - m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root) ); - m2 = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + m2 = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root2) ); - efl_ui_focus_manager_register(m, child, root, m2); + efl_ui_focus_manager_calc_register(m, child, root, m2); efl_ui_focus_manager_focus(m, child); ck_assert_ptr_eq(efl_ui_focus_manager_redirect_get(m), m2); @@ -272,23 +272,23 @@ START_TEST(invalid_args_check) TEST_OBJ_NEW(child, 0, 20, 20, 20); TEST_OBJ_NEW(child2, 0, 20, 20, 20); - m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root) ); //no child and no parent - ck_assert_int_eq(efl_ui_focus_manager_register(m, NULL, NULL, NULL), 0); - ck_assert_int_eq(efl_ui_focus_manager_register(m, child, NULL, NULL), 0); - ck_assert_int_eq(efl_ui_focus_manager_register(m, NULL, root, NULL), 0); + ck_assert_int_eq(efl_ui_focus_manager_calc_register(m, NULL, NULL, NULL), 0); + ck_assert_int_eq(efl_ui_focus_manager_calc_register(m, child, NULL, NULL), 0); + ck_assert_int_eq(efl_ui_focus_manager_calc_register(m, NULL, root, NULL), 0); - ck_assert_int_eq(efl_ui_focus_manager_register(m, child, root, NULL), 1); + ck_assert_int_eq(efl_ui_focus_manager_calc_register(m, child, root, NULL), 1); - ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, child, NULL), 0); - ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, NULL, NULL), 0); - ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, child, child2), 0); + ck_assert_int_eq(efl_ui_focus_manager_calc_update_parent(m, child, NULL), 0); + ck_assert_int_eq(efl_ui_focus_manager_calc_update_parent(m, NULL, NULL), 0); + ck_assert_int_eq(efl_ui_focus_manager_calc_update_parent(m, child, child2), 0); - ck_assert_int_eq(efl_ui_focus_manager_register(m, child2, root, NULL), 1); - ck_assert_int_eq(efl_ui_focus_manager_update_parent(m, child, child2), 1); + ck_assert_int_eq(efl_ui_focus_manager_calc_register(m, child2, root, NULL), 1); + ck_assert_int_eq(efl_ui_focus_manager_calc_update_parent(m, child, child2), 1); elm_shutdown(); } @@ -306,27 +306,27 @@ START_TEST(order_check) TEST_OBJ_NEW(child2, 0, 20, 20, 20); TEST_OBJ_NEW(child3, 0, 20, 20, 20); - m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root) ); //no child and no parent - efl_ui_focus_manager_register(m, child1, root, NULL); - efl_ui_focus_manager_register(m, child2, root, NULL); - efl_ui_focus_manager_register(m, child3, root, NULL); + efl_ui_focus_manager_calc_register(m, child1, root, NULL); + efl_ui_focus_manager_calc_register(m, child2, root, NULL); + efl_ui_focus_manager_calc_register(m, child3, root, NULL); //positiv check order = eina_list_append(order, child2); order = eina_list_append(order, child3); order = eina_list_append(order, child1); - ck_assert_int_eq(efl_ui_focus_manager_update_children(m, root, order), 1); + ck_assert_int_eq(efl_ui_focus_manager_calc_update_children(m, root, order), 1); order = NULL; //negativ check order = eina_list_append(order, child1); order = eina_list_append(order, child2); - ck_assert_int_eq(efl_ui_focus_manager_update_children(m, root, order), 0); + ck_assert_int_eq(efl_ui_focus_manager_calc_update_children(m, root, order), 0); elm_shutdown(); } diff --git a/src/tests/elementary/elm_test_focus_common.c b/src/tests/elementary/elm_test_focus_common.c index ea0a640700..128e1c00ac 100644 --- a/src/tests/elementary/elm_test_focus_common.c +++ b/src/tests/elementary/elm_test_focus_common.c @@ -46,7 +46,7 @@ elm_focus_test_manager_new(Efl_Ui_Focus_Object **middle) Efl_Ui_Focus_Manager *m; root = elm_focus_test_object_new("middle", 40, 40, 20, 20); - m = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + m = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root) ); if (middle) diff --git a/src/tests/elementary/elm_test_focus_sub.c b/src/tests/elementary/elm_test_focus_sub.c index 226df536e5..1c52c1bcd9 100644 --- a/src/tests/elementary/elm_test_focus_sub.c +++ b/src/tests/elementary/elm_test_focus_sub.c @@ -37,7 +37,7 @@ _register(Eo *eo, void* data EINA_UNUSED, Efl_Ui_Focus_Object *child, Efl_Ui_Foc registered = eina_list_append(registered, child); printf("REGISTERED %p %s\n", child, efl_name_get(child)); - return efl_ui_focus_manager_register(efl_super(eo, EFL_OBJECT_OVERRIDE_CLASS) , child, parent, manager); + return efl_ui_focus_manager_calc_register(efl_super(eo, EFL_OBJECT_OVERRIDE_CLASS) , child, parent, manager); } static void @@ -46,7 +46,7 @@ _unregister(Eo *eo, void* data EINA_UNUSED, Efl_Ui_Focus_Object *child) unregistered = eina_list_append(unregistered, child); printf("UNREGISTERED %p %s\n", child, efl_name_get(child)); - efl_ui_focus_manager_unregister(efl_super(eo, EFL_OBJECT_OVERRIDE_CLASS) , child); + efl_ui_focus_manager_calc_unregister(efl_super(eo, EFL_OBJECT_OVERRIDE_CLASS) , child); } static Eina_Bool @@ -74,11 +74,11 @@ _setup(Efl_Ui_Focus_Manager **m, Efl_Ui_Focus_Manager_Sub **sub, Efl_Ui_Focus_Ob TEST_OBJ_NEW(root_manager, 0, 20, 20, 20); EFL_OPS_DEFINE(manager_tracker, - EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_register, _register), - EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_unregister, _unregister), + EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_calc_register, _register), + EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_calc_unregister, _unregister), ); - Efl_Ui_Focus_Manager *manager = efl_add(EFL_UI_FOCUS_MANAGER_CLASS, NULL, + Efl_Ui_Focus_Manager *manager = efl_add(EFL_UI_FOCUS_MANAGER_CALC_CLASS, NULL, efl_ui_focus_manager_root_set(efl_added, root_manager) ); //flush now all changes @@ -98,7 +98,7 @@ _setup(Efl_Ui_Focus_Manager **m, Efl_Ui_Focus_Manager_Sub **sub, Efl_Ui_Focus_Ob ); efl_composite_attach(focus_main, subm); - efl_ui_focus_manager_register_logical(manager, focus_main, root_manager, subm); + efl_ui_focus_manager_calc_register_logical(manager, focus_main, root_manager, subm); *sub = focus_main; *m = manager; @@ -125,17 +125,17 @@ START_TEST(correct_register) set1 = eina_list_append(set1, child3); //test register stuff - efl_ui_focus_manager_register(sub, child1, root, NULL); - efl_ui_focus_manager_register(sub, child2, root, NULL); - efl_ui_focus_manager_register(sub, child3, root, NULL); + efl_ui_focus_manager_calc_register(sub, child1, root, NULL); + efl_ui_focus_manager_calc_register(sub, child2, root, NULL); + efl_ui_focus_manager_calc_register(sub, child3, root, NULL); //now force submanager to flush things efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); ck_assert_ptr_eq(unregistered, NULL); fail_if(!_set_equal(registered, set1)); - efl_ui_focus_manager_unregister(sub, child1); - efl_ui_focus_manager_unregister(sub, child2); - efl_ui_focus_manager_unregister(sub, child3); + efl_ui_focus_manager_calc_unregister(sub, child1); + efl_ui_focus_manager_calc_unregister(sub, child2); + efl_ui_focus_manager_calc_unregister(sub, child3); efl_del(child1); efl_del(child2); efl_del(child3); @@ -161,9 +161,9 @@ START_TEST(correct_unregister) set = eina_list_append(set, child3); //test register stuff - efl_ui_focus_manager_register(sub, child1, root, NULL); - efl_ui_focus_manager_register(sub, child2, root, NULL); - efl_ui_focus_manager_register(sub, child3, root, NULL); + efl_ui_focus_manager_calc_register(sub, child1, root, NULL); + efl_ui_focus_manager_calc_register(sub, child2, root, NULL); + efl_ui_focus_manager_calc_register(sub, child3, root, NULL); efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); eina_list_free(unregistered); unregistered = NULL; @@ -171,7 +171,7 @@ START_TEST(correct_unregister) registered = NULL; //test unregister stuff - efl_ui_focus_manager_unregister(sub, child3); + efl_ui_focus_manager_calc_unregister(sub, child3); efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); ck_assert_ptr_eq(registered, NULL); fail_if(!_set_equal(unregistered, set)); @@ -204,8 +204,8 @@ START_TEST(correct_un_register) set_add = eina_list_append(set_add, child2); set_del = eina_list_append(set_del, child3); //test register stuff - efl_ui_focus_manager_register(sub, child1, root, NULL); - efl_ui_focus_manager_register(sub, child3, root, NULL); + efl_ui_focus_manager_calc_register(sub, child1, root, NULL); + efl_ui_focus_manager_calc_register(sub, child3, root, NULL); efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); eina_list_free(unregistered); unregistered = NULL; @@ -213,8 +213,8 @@ START_TEST(correct_un_register) registered = NULL; //test unregister stuff - efl_ui_focus_manager_unregister(sub, child3); - efl_ui_focus_manager_register(sub, child2, root, NULL); + efl_ui_focus_manager_calc_unregister(sub, child3); + efl_ui_focus_manager_calc_register(sub, child2, root, NULL); efl_event_callback_call(manager, EFL_UI_FOCUS_MANAGER_EVENT_FLUSH_PRE, NULL); fail_if(!_set_equal(registered, set_add)); fail_if(!_set_equal(unregistered, set_del));