diff options
Diffstat (limited to 'src/lib/elementary/efl_ui_focus_manager_calc.c')
-rw-r--r-- | src/lib/elementary/efl_ui_focus_manager_calc.c | 165 |
1 files changed, 129 insertions, 36 deletions
diff --git a/src/lib/elementary/efl_ui_focus_manager_calc.c b/src/lib/elementary/efl_ui_focus_manager_calc.c index efb67fcabf..5b7589d95f 100644 --- a/src/lib/elementary/efl_ui_focus_manager_calc.c +++ b/src/lib/elementary/efl_ui_focus_manager_calc.c @@ -85,6 +85,7 @@ typedef struct { int freeze; Node *root; + Eina_Bool border_elements_changed; } Efl_Ui_Focus_Manager_Calc_Data; static Eina_Mempool *_node_mempool; @@ -111,11 +112,11 @@ _focus_manager_active_get(Eo *obj) { Eo *root, *manager, *comp_parent, *redirect; - if (efl_isa(obj, EFL_UI_FOCUS_MANAGER_WINDOW_ROOT_INTERFACE) || - (efl_composite_part_is(obj) && efl_isa(efl_parent_get(obj), EFL_UI_FOCUS_MANAGER_WINDOW_ROOT_INTERFACE))) + root = efl_ui_focus_manager_root_get(obj); + + if (efl_isa(root, EFL_UI_FOCUS_MANAGER_WINDOW_ROOT_INTERFACE)) return EINA_TRUE; - root = efl_ui_focus_manager_root_get(obj); manager = efl_ui_focus_object_focus_manager_get(root); if (!manager) return EINA_FALSE; @@ -159,20 +160,25 @@ _manager_in_chain_set(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) efl_class_name_get(pd->root->focusable), root); } + static void border_onedirection_set(Node *node, Efl_Ui_Focus_Direction direction, Eina_List *list) { Node *partner; Eina_List *lnode; Border *border; + Efl_Ui_Focus_Direction complement; EINA_SAFETY_ON_FALSE_RETURN(DIRECTION_IS_2D(direction)); + complement = efl_ui_focus_util_direction_complement(direction); + //this is basically a nop. The complement of 2D will *always* be 2D + EINA_SAFETY_ON_FALSE_RETURN(DIRECTION_IS_2D(complement)); border = &DIRECTION_ACCESS(node, direction); EINA_LIST_FREE(border->one_direction, partner) { - Border *b = &DIRECTION_ACCESS(partner, efl_ui_focus_util_direction_complement(direction)); + Border *b = &DIRECTION_ACCESS(partner, complement); b->cleanup_nodes = eina_list_remove(b->cleanup_nodes, node); } @@ -180,7 +186,7 @@ border_onedirection_set(Node *node, Efl_Ui_Focus_Direction direction, Eina_List EINA_LIST_FOREACH(border->one_direction, lnode, partner) { - Border *comp_border = &DIRECTION_ACCESS(partner,efl_ui_focus_util_direction_complement(direction)); + Border *comp_border = &DIRECTION_ACCESS(partner, complement); comp_border->cleanup_nodes = eina_list_append(comp_border->cleanup_nodes, node); } @@ -191,14 +197,18 @@ border_onedirection_cleanup(Node *node, Efl_Ui_Focus_Direction direction) { Node *partner; Border *border; + Efl_Ui_Focus_Direction complement; EINA_SAFETY_ON_FALSE_RETURN(DIRECTION_IS_2D(direction)); + complement = efl_ui_focus_util_direction_complement(direction); + //this is basically a nop. The complement of 2D will *always* be 2D + EINA_SAFETY_ON_FALSE_RETURN(DIRECTION_IS_2D(complement)); border = &DIRECTION_ACCESS(node, direction); EINA_LIST_FREE(border->cleanup_nodes, partner) { - Border *b = &DIRECTION_ACCESS(partner, efl_ui_focus_util_direction_complement(direction)); + Border *b = &DIRECTION_ACCESS(partner, complement); b->one_direction = eina_list_remove(b->one_direction, node); } } @@ -247,7 +257,6 @@ node_item_free(Node *item) Eina_List *l; Eo *obj = item->manager; FOCUS_DATA(obj); - Eina_Bool dirty_added = EINA_FALSE; /*cleanup graph parts*/ @@ -264,7 +273,7 @@ node_item_free(Node *item) if (partner->type != NODE_TYPE_ONLY_LOGICAL) \ { \ dirty_add(obj, pd, partner); \ - dirty_added = EINA_TRUE; \ + pd->border_elements_changed = EINA_TRUE; \ } \ } @@ -278,7 +287,7 @@ node_item_free(Node *item) } //the unregistering of a item should ever result in atleast a coords_dirty call - if (dirty_added) + if (pd->border_elements_changed) efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, NULL); /*cleanup manager householdings*/ @@ -402,6 +411,8 @@ dirty_flush_node(Efl_Ui_Focus_Manager *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Cal { Efl_Ui_Focus_Direction direction = -1; Efl_Ui_Focus_Graph_Calc_Direction_Result *res = NULL; + Node *partner; + Eina_List *n; if (i == 0) { @@ -424,6 +435,9 @@ dirty_flush_node(Efl_Ui_Focus_Manager *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Cal res = &result.bottom; } + EINA_LIST_FOREACH(res->relation, n, partner) + partner->unused = EINA_FALSE; + border_onedirection_set(node, direction, res->relation); } @@ -470,7 +484,9 @@ dirty_add(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Node *dirty) pd->dirty = eina_list_append(pd->dirty, dirty); dirty->on_list = EINA_TRUE; - efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, NULL); + if (!pd->border_elements_changed) + efl_event_callback_call(obj, EFL_UI_FOCUS_MANAGER_EVENT_COORDS_DIRTY, NULL); + pd->border_elements_changed = EINA_TRUE; } @@ -776,10 +792,10 @@ _efl_ui_focus_manager_calc_update_children(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Man } static inline Node* -_request_subchild_except(Node *n, Node *except) +_request_subchild_except(Node *n, Eo *except) { n = _request_subchild(n); - while (n == except) + while (n && n->focusable == except) { n = _next(n); } @@ -788,7 +804,7 @@ _request_subchild_except(Node *n, Node *except) } 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) +_efl_ui_focus_manager_calc_unregister(Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Efl_Ui_Focus_Object *child) { Node *node; @@ -800,7 +816,7 @@ _efl_ui_focus_manager_calc_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_ if (eina_list_last_data_get(pd->focus_stack) == node) { - if (!efl_invalidated_get(pd->root->focusable)) + if (!efl_invalidated_get(pd->root->focusable) && _focus_manager_active_get(obj)) { Node *n = NULL; @@ -810,7 +826,7 @@ _efl_ui_focus_manager_calc_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_ { n = eina_list_nth(pd->focus_stack, eina_list_count(pd->focus_stack) - 2); if (!n) - n = _request_subchild_except(pd->root, node); + n = _request_subchild_except(pd->root, node->focusable); if (n) efl_ui_focus_manager_focus_set(obj, n->focusable); @@ -869,7 +885,7 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_redirect_set(Eo *obj, Efl_Ui_Foc } else { - n = _request_subchild(pd->root); + n = _request_subchild_except(pd->root, pd->redirect_entry); if (n) efl_ui_focus_manager_focus_set(obj, n->focusable); } @@ -919,6 +935,7 @@ _efl_ui_focus_manager_calc_efl_object_constructor(Eo *obj, Efl_Ui_Focus_Manager_ pd->node_hash = eina_hash_pointer_new(_free_node); pd->graph_ctx.offset_focusable = offsetof(Node, focusable); + pd->border_elements_changed = EINA_TRUE; return obj; } @@ -1105,9 +1122,18 @@ _elements_iterator_new(const Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) EOLIAN static Eina_Iterator* _efl_ui_focus_manager_calc_efl_ui_focus_manager_border_elements_get(const Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd) { + pd->border_elements_changed = EINA_FALSE; return (Eina_Iterator*) _elements_iterator_new(obj, pd); } + +EOLIAN static Eina_Bool +_efl_ui_focus_manager_calc_efl_ui_focus_manager_border_elements_changed_get(const Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd) +{ + return pd->border_elements_changed; +} + + EOLIAN static Eina_Iterator* _efl_ui_focus_manager_calc_efl_ui_focus_manager_viewport_elements_get(const Eo *obj, Efl_Ui_Focus_Manager_Calc_Data *pd, Eina_Rect viewport) { @@ -1789,18 +1815,6 @@ _efl_ui_focus_manager_calc_efl_object_finalize(Eo *obj, Efl_Ui_Focus_Manager_Cal return result; } -static Eina_List* -_convert(Border b) -{ - Eina_List *n, *par = NULL; - Node *node; - - EINA_LIST_FOREACH(b.one_direction, 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_manager_focus_get(const Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Calc_Data *pd) { @@ -1815,6 +1829,63 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_manager_focus_get(const Eo *obj return upper->focusable; } +typedef struct _Eina_Iterator_Focusable Eina_Iterator_Focusable; +struct _Eina_Iterator_Focusable +{ + Eina_Iterator iterator; + + Eina_Iterator *redirect; +}; + +static Eina_Bool +_node_focusable_iterator_next(Eina_Iterator_Focusable *it, void **data) +{ + Node *node = NULL; + Eina_Bool r; + + if (!it->redirect) return EINA_FALSE; + + r = eina_iterator_next(it->redirect, (void **) &node); + if (r && data) *data = node->focusable; + + return r; +} + +static Eina_List * +_node_focusable_iterator_get_container(Eina_Iterator_Focusable *it) +{ + if (!it->redirect) return NULL; + + return eina_iterator_container_get(it->redirect); +} + +static void +_node_focusable_iterator_free(Eina_Iterator_Focusable *it) +{ + eina_iterator_free(it->redirect); + EINA_MAGIC_SET(&it->iterator, 0); + free(it); +} + +static Eina_Iterator * +_node_focusable_iterator_new(Eina_List *nodes) +{ + Eina_Iterator_Focusable *it; + + it = calloc(1, sizeof (Eina_Iterator_Focusable)); + if (!it) return NULL; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + it->redirect = eina_list_iterator_new(nodes); + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_node_focusable_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_node_focusable_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_node_focusable_iterator_free); + + return &it->iterator; +} + 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) { @@ -1834,12 +1905,14 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_fetch(Eo *obj, Efl_Ui_Focus_Mana efl_ui_focus_object_setup_order(n->tree.parent->focusable); efl_ui_focus_object_setup_order(n->focusable); -#define DIR_CLONE(dir) _convert(DIRECTION_ACCESS(n,dir)); + // FIXME: the iterator must actually return the (Node*)->focusable object in it + // Just redirect to default eina list iterator but offset the returned pointer? +#define DIR_ITERATOR(dir) _node_focusable_iterator_new(DIRECTION_ACCESS(n,dir).one_direction); - 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->right = DIR_ITERATOR(EFL_UI_FOCUS_DIRECTION_RIGHT); + res->left = DIR_ITERATOR(EFL_UI_FOCUS_DIRECTION_LEFT); + res->top = DIR_ITERATOR(EFL_UI_FOCUS_DIRECTION_UP); + res->down = DIR_ITERATOR(EFL_UI_FOCUS_DIRECTION_DOWN); res->next = (tmp = _next(n)) ? tmp->focusable : NULL; res->prev = (tmp = _prev(n)) ? tmp->focusable : NULL; res->position_in_history = eina_list_data_idx(pd->focus_stack, n); @@ -1850,7 +1923,7 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_fetch(Eo *obj, Efl_Ui_Focus_Mana if (T(n).parent) res->parent = T(n).parent->focusable; res->redirect = n->redirect_manager; -#undef DIR_CLONE +#undef DIR_ITERATOR return res; } @@ -1951,7 +2024,7 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_pop_history_stack(Eo *obj EINA_U } else { - last = _request_subchild_except(pd->root, node_get(obj, pd, last_focusable)); + last = _request_subchild_except(pd->root, last_focusable); if (last) efl_ui_focus_manager_focus_set(obj, last->focusable); } @@ -2014,7 +2087,27 @@ _efl_ui_focus_manager_calc_efl_ui_focus_manager_dirty_logic_unfreeze(Eo *obj, Ef } } +static void +_efl_ui_focus_manager_calc_update_children_ownership_fallback(Efl_Ui_Focus_Object *parent, Eina_List *children) +{ + (void)parent; + eina_list_free(children); +} + +EOAPI EFL_FUNC_BODYV_FALLBACK(efl_ui_focus_manager_calc_update_children, Eina_Bool, 0, _efl_ui_focus_manager_calc_update_children_ownership_fallback(parent, children);, EFL_FUNC_CALL(parent, children), Efl_Ui_Focus_Object *parent, Eina_List *children); + +static void +_efl_ui_focus_manager_calc_update_order_ownership_fallback(Efl_Ui_Focus_Object *parent, Eina_List *children) +{ + (void)parent; + eina_list_free(children); +} + +EOAPI EFL_VOID_FUNC_BODYV_FALLBACK(efl_ui_focus_manager_calc_update_order, _efl_ui_focus_manager_calc_update_order_ownership_fallback(parent, children);, EFL_FUNC_CALL(parent, children), Efl_Ui_Focus_Object *parent, Eina_List *children); + #define EFL_UI_FOCUS_MANAGER_CALC_EXTRA_OPS \ - EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_ui_focus_manager_calc_efl_object_dbg_info_get) + EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_ui_focus_manager_calc_efl_object_dbg_info_get), \ + EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_calc_update_children, _efl_ui_focus_manager_calc_update_children), \ + EFL_OBJECT_OP_FUNC(efl_ui_focus_manager_calc_update_order, _efl_ui_focus_manager_calc_update_order) #include "efl_ui_focus_manager_calc.eo.c" |