summaryrefslogtreecommitdiff
path: root/src/lib/elementary/efl_ui_focus_manager_calc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/elementary/efl_ui_focus_manager_calc.c')
-rw-r--r--src/lib/elementary/efl_ui_focus_manager_calc.c165
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"