forked from enlightenment/efl
efl_ui_focus_manager: handle redirect objects in logical better
This commit is contained in:
parent
200ad8ab50
commit
a5c7006579
|
@ -830,11 +830,16 @@ _no_history_element(Eina_Hash *node_hash)
|
||||||
|
|
||||||
iter = eina_hash_iterator_data_new(node_hash);
|
iter = eina_hash_iterator_data_new(node_hash);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
if (!eina_iterator_next(iter, (void**)&upper))
|
if (!eina_iterator_next(iter, (void**)&upper))
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
}
|
||||||
return upper;
|
while (upper->type != NODE_TYPE_NORMAL);
|
||||||
|
|
||||||
eina_iterator_free(iter);
|
eina_iterator_free(iter);
|
||||||
|
|
||||||
|
return upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node*
|
static Node*
|
||||||
|
@ -884,33 +889,39 @@ _next(Node *node)
|
||||||
Node *n;
|
Node *n;
|
||||||
|
|
||||||
//Case 1 we are having children
|
//Case 1 we are having children
|
||||||
if (T(node).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);
|
return eina_list_data_get(T(node).children);
|
||||||
|
}
|
||||||
|
|
||||||
//case 2 we are the root and we dont have children, return ourself
|
//case 2 we are the root and we dont have children, return ourself
|
||||||
if (!T(node).parent)
|
if (!T(node).parent)
|
||||||
|
{
|
||||||
return node;
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
//case 3 we are not at the end of the parents list
|
//case 3 we are not at the end of the parents list
|
||||||
n = _parent_item(node, EINA_TRUE);
|
|
||||||
if (n)
|
|
||||||
return n;
|
|
||||||
|
|
||||||
//case 4 we are at the end of the parents list
|
|
||||||
n = node;
|
n = node;
|
||||||
while(T(n).parent)
|
while(T(n).parent)
|
||||||
{
|
{
|
||||||
Node *parent_next;
|
Node *parent;
|
||||||
|
Eina_List *lnode;
|
||||||
|
|
||||||
parent_next = _parent_item(n, EINA_TRUE);
|
parent = T(n).parent;
|
||||||
|
lnode = eina_list_data_find_list(T(parent).children, n);
|
||||||
|
lnode = eina_list_next(lnode);
|
||||||
|
|
||||||
if (parent_next)
|
if (lnode)
|
||||||
return parent_next;
|
{
|
||||||
|
return eina_list_data_get(lnode);
|
||||||
n = T(n).parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n = parent;
|
||||||
|
}
|
||||||
|
|
||||||
//this is then the root again
|
//this is then the root again
|
||||||
return n;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node*
|
static Node*
|
||||||
|
@ -920,17 +931,7 @@ _prev(Node *node)
|
||||||
|
|
||||||
//this is the root there is no parent
|
//this is the root there is no parent
|
||||||
if (!T(node).parent)
|
if (!T(node).parent)
|
||||||
{
|
return NULL;
|
||||||
Node *subtree;
|
|
||||||
|
|
||||||
subtree = node;
|
|
||||||
//search the most down right item
|
|
||||||
while(T(subtree).children)
|
|
||||||
{
|
|
||||||
subtree = eina_list_last_data_get(T(subtree).children);
|
|
||||||
}
|
|
||||||
return subtree;
|
|
||||||
}
|
|
||||||
|
|
||||||
n =_parent_item(node, EINA_FALSE);
|
n =_parent_item(node, EINA_FALSE);
|
||||||
//case 1 there is a item in the parent previous to node, which has children
|
//case 1 there is a item in the parent previous to node, which has children
|
||||||
|
@ -972,12 +973,8 @@ _logical_movement(Efl_Ui_Focus_Manager_Data *pd EINA_UNUSED, Node *upper, Efl_Ui
|
||||||
}
|
}
|
||||||
|
|
||||||
stack = eina_list_append(stack, result);
|
stack = eina_list_append(stack, result);
|
||||||
|
|
||||||
result = deliver(result);
|
result = deliver(result);
|
||||||
} while(result && result->type != NODE_TYPE_NORMAL);
|
} while(result && result->type != NODE_TYPE_NORMAL && !result->redirect_manager);
|
||||||
|
|
||||||
if (result->type != NODE_TYPE_NORMAL)
|
|
||||||
abort();
|
|
||||||
|
|
||||||
eina_list_free(stack);
|
eina_list_free(stack);
|
||||||
|
|
||||||
|
@ -989,6 +986,7 @@ _request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_D
|
||||||
{
|
{
|
||||||
Node *dir = NULL;
|
Node *dir = NULL;
|
||||||
|
|
||||||
|
if (!upper)
|
||||||
upper = eina_list_last_data_get(pd->focus_stack);
|
upper = eina_list_last_data_get(pd->focus_stack);
|
||||||
|
|
||||||
if (!upper)
|
if (!upper)
|
||||||
|
@ -1040,6 +1038,23 @@ _efl_ui_focus_manager_request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Dat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Efl_Ui_Focus_Object*
|
||||||
|
_find_normal_node(Node *n)
|
||||||
|
{
|
||||||
|
Eina_List *l;
|
||||||
|
Node *n2;
|
||||||
|
if (n->type == NODE_TYPE_NORMAL) return n->focusable;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(T(n).children , l, n2)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Object *r;
|
||||||
|
|
||||||
|
r = _find_normal_node(n2);
|
||||||
|
if (r) return r;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
EOLIAN static void
|
EOLIAN static void
|
||||||
_efl_ui_focus_manager_focus(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *focus)
|
_efl_ui_focus_manager_focus(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus_Object *focus)
|
||||||
{
|
{
|
||||||
|
@ -1048,13 +1063,19 @@ _efl_ui_focus_manager_focus(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN(focus);
|
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)
|
||||||
|
{
|
||||||
|
focus = _find_normal_node(pd->root);
|
||||||
|
}
|
||||||
|
|
||||||
//check if node is part of this manager object
|
//check if node is part of this manager object
|
||||||
node = node_get(pd, focus);
|
node = node_get(obj, pd, focus);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
|
|
||||||
F_DBG("Manager: %p focusing object %p %s", obj, focus, efl_class_name_get(focus));
|
F_DBG("Manager: %p focusing object %p %s", obj, focus, efl_class_name_get(focus));
|
||||||
|
|
||||||
if (node->type == NODE_TYPE_ONLY_LOGICAL)
|
if (node->type == NODE_TYPE_ONLY_LOGICAL && !node->redirect_manager && pd->root != node)
|
||||||
{
|
{
|
||||||
ERR(" %p is logical, cannot be focused", obj);
|
ERR(" %p is logical, cannot be focused", obj);
|
||||||
return;
|
return;
|
||||||
|
@ -1066,6 +1087,8 @@ _efl_ui_focus_manager_focus(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus
|
||||||
efl_ui_focus_manager_redirect_set(obj, NULL);
|
efl_ui_focus_manager_redirect_set(obj, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->type == NODE_TYPE_NORMAL)
|
||||||
|
{
|
||||||
//check if this is already the focused object
|
//check if this is already the focused object
|
||||||
old_focus = eina_list_last_data_get(pd->focus_stack);
|
old_focus = eina_list_last_data_get(pd->focus_stack);
|
||||||
|
|
||||||
|
@ -1079,6 +1102,14 @@ _efl_ui_focus_manager_focus(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus
|
||||||
//populate the new change
|
//populate the new change
|
||||||
if (old_focus) efl_ui_focus_object_focus_set(old_focus->focusable, EINA_FALSE);
|
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_ui_focus_object_focus_set(node->focusable, EINA_TRUE);
|
||||||
|
}
|
||||||
|
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
|
//now check if this is also a listener object
|
||||||
if (node->redirect_manager)
|
if (node->redirect_manager)
|
||||||
|
@ -1098,8 +1129,6 @@ _efl_ui_focus_manager_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, E
|
||||||
|
|
||||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(DIRECTION_CHECK(direction), NULL);
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(DIRECTION_CHECK(direction), NULL);
|
||||||
|
|
||||||
F_DBG("Manager: %p move to %d", obj, direction);
|
|
||||||
|
|
||||||
if (pd->redirect)
|
if (pd->redirect)
|
||||||
{
|
{
|
||||||
Efl_Ui_Focus_Object *old_candidate = NULL;
|
Efl_Ui_Focus_Object *old_candidate = NULL;
|
||||||
|
@ -1115,6 +1144,16 @@ _efl_ui_focus_manager_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, E
|
||||||
new_candidate = NULL;
|
new_candidate = NULL;
|
||||||
n = eina_hash_find(pd->node_hash, &old_candidate);
|
n = eina_hash_find(pd->node_hash, &old_candidate);
|
||||||
|
|
||||||
|
if (direction == EFL_UI_FOCUS_DIRECTION_NEXT ||
|
||||||
|
direction == EFL_UI_FOCUS_DIRECTION_PREV)
|
||||||
|
{
|
||||||
|
n = T(n).parent;
|
||||||
|
new_candidate = _request_move(obj, pd, direction, n);
|
||||||
|
efl_ui_focus_manager_focus(obj, new_candidate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
if (n)
|
if (n)
|
||||||
new_candidate = _request_move(obj, pd, direction, n);
|
new_candidate = _request_move(obj, pd, direction, n);
|
||||||
|
|
||||||
|
@ -1126,6 +1165,7 @@ _efl_ui_focus_manager_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, E
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
candidate = efl_ui_focus_manager_request_move(obj, direction);
|
candidate = efl_ui_focus_manager_request_move(obj, direction);
|
||||||
|
@ -1134,7 +1174,7 @@ _efl_ui_focus_manager_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, E
|
||||||
efl_ui_focus_manager_focus(obj, candidate);
|
efl_ui_focus_manager_focus(obj, candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
F_DBG("Manager: %p moved to %s %s", obj, DEBUG_TUPLE(candidate));
|
F_DBG("Manager: %p moved to %s %s in direction %d", obj, DEBUG_TUPLE(candidate), direction);
|
||||||
|
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
@ -1224,8 +1264,8 @@ _efl_ui_focus_manager_fetch(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Efl_Ui_Focus
|
||||||
res->left = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_LEFT);
|
res->left = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_LEFT);
|
||||||
res->top = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_UP);
|
res->top = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_UP);
|
||||||
res->down = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_DOWN);
|
res->down = DIR_CLONE(EFL_UI_FOCUS_DIRECTION_DOWN);
|
||||||
res->next = _next(n)->focusable;
|
res->next = (tmp = _next(n)) ? tmp->focusable : NULL;
|
||||||
res->prev = _prev(n)->focusable;
|
res->prev = (tmp = _prev(n)) ? tmp->focusable : NULL;
|
||||||
switch(n->type)
|
switch(n->type)
|
||||||
{
|
{
|
||||||
case NODE_TYPE_ONLY_LOGICAL:
|
case NODE_TYPE_ONLY_LOGICAL:
|
||||||
|
@ -1255,4 +1295,29 @@ _efl_ui_focus_manager_class_destructor(Efl_Class *c EINA_UNUSED)
|
||||||
_focus_log_domain = -1;
|
_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)
|
||||||
|
{
|
||||||
|
//we need to return the most lower right element
|
||||||
|
Node *child = pd->root;
|
||||||
|
Efl_Ui_Focus_Object *last_normal = NULL;
|
||||||
|
while(T(child).children)
|
||||||
|
{
|
||||||
|
Efl_Ui_Focus_Object *tmp_last_normal;
|
||||||
|
|
||||||
|
tmp_last_normal = _find_normal_node(child);
|
||||||
|
if (tmp_last_normal)
|
||||||
|
last_normal = tmp_last_normal;
|
||||||
|
|
||||||
|
child = eina_list_last_data_get(T(child).children);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_normal)
|
||||||
|
return last_normal;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#include "efl_ui_focus_manager.eo.c"
|
#include "efl_ui_focus_manager.eo.c"
|
|
@ -159,6 +159,9 @@ class Efl.Ui.Focus.Manager (Efl.Object) {
|
||||||
|
|
||||||
return : own(ptr(Efl.Ui.Focus.Relations));
|
return : own(ptr(Efl.Ui.Focus.Relations));
|
||||||
}
|
}
|
||||||
|
logical_end {
|
||||||
|
return : Efl.Ui.Focus.Object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
implements {
|
implements {
|
||||||
class.constructor;
|
class.constructor;
|
||||||
|
@ -169,6 +172,7 @@ class Efl.Ui.Focus.Manager (Efl.Object) {
|
||||||
Efl.Object.destructor;
|
Efl.Object.destructor;
|
||||||
}
|
}
|
||||||
events {
|
events {
|
||||||
|
redirect,changed : Efl.Ui.Focus.Manager; [[Emitted when the redirect object has changed, the old manager is passed as event info]]
|
||||||
pre,flush; [[Emitted once the graph calculationg will be performed]]
|
pre,flush; [[Emitted once the graph calculationg will be performed]]
|
||||||
coords,dirty; [[Emitted once the graph is dirty, this means there are potential changes in border_elements you want to know about]]
|
coords,dirty; [[Emitted once the graph is dirty, this means there are potential changes in border_elements you want to know about]]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue