summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPankaj Mittal <m.pankaj@samsung.com>2016-06-21 16:04:31 +0200
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>2016-06-21 19:03:09 +0200
commit1a5321c7cc502c39e81936e7b67590aa8560a495 (patch)
tree020961a514b88f0a7a2ebcfc1cd79547718b3556
parentd72098a81711d603e5c8b89484bf69c9b886caba (diff)
downloadefl-devs/bu5hm4n/focus_secure.tar.gz
focus: next/prev(Tab Order) implementationdevs/bu5hm4n/focus_secure
Summary: This feature is being used when user presses TAB or SHIFT+TAB key for focus movement. The idea is to use existing nodes of graph instead of creating new one, and adding links for creating required ordering. @feature Reviewers: yashu21985, atulfokk, singh.amitesh, cedric Subscribers: alok25, bu5hm4n, cedric, jpeg Differential Revision: https://phab.enlightenment.org/D4026
-rw-r--r--src/lib/elementary/efl_ui_focus_manager.c62
-rw-r--r--src/lib/elementary/efl_ui_win.c15
2 files changed, 71 insertions, 6 deletions
diff --git a/src/lib/elementary/efl_ui_focus_manager.c b/src/lib/elementary/efl_ui_focus_manager.c
index bb65db8395..b3fc1dc1b0 100644
--- a/src/lib/elementary/efl_ui_focus_manager.c
+++ b/src/lib/elementary/efl_ui_focus_manager.c
@@ -27,10 +27,13 @@ struct _Border {
};
typedef struct _Node Node;
+
struct _Node {
Elm_Widget *focusable;
Border directions[NODE_DIRECTIONS_COUNT];
Efl_Ui_Focus_Manager *manager;
+ Node *next;
+ Node *prev;
};
typedef struct {
@@ -40,6 +43,8 @@ typedef struct {
Efl_Ui_Focus_Manager *redirect;
Eina_List *dirty;
+
+ Node *last_node;
} Efl_Ui_Focus_Manager_Data;
static Efl_Ui_Focus_Direction
@@ -124,6 +129,38 @@ node_item_free(Node *item)
//CALCULATING STUFF
+// Append current Object to Focus Chain
+static void
+efl_ui_focus_chain_append(Efl_Ui_Focus_Manager_Data *pd, Node *prev, Node *current)
+{
+ if (!current)
+ {
+ CRI("Appending NULL Object!!");
+ return;
+ }
+ if (prev)
+ {
+ prev->next = current;
+ current->prev = prev;
+ }
+ pd->last_node = current;
+}
+// Remove current Object to Focus Chain
+static void
+efl_ui_focus_chain_remove(Efl_Ui_Focus_Manager_Data *pd, Node *current)
+{
+ if (!current)
+ {
+ CRI("Removing NULL Object!!");
+ return;
+ }
+ if (current->prev)
+ current->prev->next = current->next;
+ if (current->next)
+ current->next->prev = current->prev;
+ else
+ pd->last_node = current->prev;
+}
static inline int
_distance(Eina_Rectangle node, Eina_Rectangle op, Dimension dim)
{
@@ -446,6 +483,9 @@ _efl_ui_focus_manager_register(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Evas_Obje
//mark dirty
dirty_add(pd, node);
+ //update next/prev links
+ efl_ui_focus_chain_append(pd, pd->last_node, node);
+
//listen to events
eo_event_callback_array_add(child, focusable_node(), obj);
@@ -483,7 +523,6 @@ _efl_ui_focus_manager_listener(Eo *obj, Efl_Ui_Focus_Manager_Data *pd, Eo_Base *
return EINA_TRUE;
}
-
EOLIAN static void
_efl_ui_focus_manager_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data *pd, Evas_Object *child)
{
@@ -525,6 +564,11 @@ _efl_ui_focus_manager_unregister(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Data
//remove from known listeners
eina_hash_del_by_key(pd->listener_hash, &child);
}
+ else
+ {
+ //update next/prev links
+ efl_ui_focus_chain_remove(pd, node);
+ }
eina_hash_del_by_key(pd->node_hash, &child);
}
@@ -725,6 +769,20 @@ _efl_ui_focus_manager_request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Dat
_debug_node(upper);
#endif
+ //for Handling Tab and SHIFT + tab movements.
+ if (direction == EFL_UI_FOCUS_DIRECTION_NEXT)
+ {
+ if (upper->next)
+ return upper->next->focusable;
+ return NULL;
+ }
+ else if (direction == EFL_UI_FOCUS_DIRECTION_PREV)
+ {
+ if (upper->prev)
+ return upper->prev->focusable;
+ return NULL;
+ }
+
//we are searcing which of the partners is lower to the history
EINA_LIST_REVERSE_FOREACH(pd->focus_stack, node, candidate)
{
@@ -746,4 +804,4 @@ _efl_ui_focus_manager_request_move(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Dat
}
-#include "efl_ui_focus_manager.eo.c" \ No newline at end of file
+#include "efl_ui_focus_manager.eo.c"
diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c
index c0a7e7eb04..8b9725454f 100644
--- a/src/lib/elementary/efl_ui_win.c
+++ b/src/lib/elementary/efl_ui_win.c
@@ -1625,7 +1625,6 @@ static Eina_Bool
_key_action_move(Evas_Object *obj, const char *params)
{
const char *dir = params;
-
if (!getenv("FOCUS_WORK"))
{
_elm_widget_focus_auto_show(obj);
@@ -1643,7 +1642,6 @@ _key_action_move(Evas_Object *obj, const char *params)
elm_widget_focus_cycle(obj, ELM_FOCUS_DOWN);
else return EINA_FALSE;
-
return EINA_TRUE;
}
else
@@ -3948,9 +3946,16 @@ _focus_movement(void *data, Evas *e, Evas_Object *obj, void *event_info)
r = efl_ui_focus_manager_move(data, EFL_UI_FOCUS_DIRECTION_UP);
else if (!strcmp(down->keyname, "Down"))
r = efl_ui_focus_manager_move(data, EFL_UI_FOCUS_DIRECTION_DOWN);
+ else if (!strcmp(down->keyname, "Tab"))
+ {
+ const Evas_Modifier *m = evas_key_modifier_get(e);
+ if (evas_key_modifier_is_set(m, "Shift"))
+ r = efl_ui_focus_manager_move(data, EFL_UI_FOCUS_DIRECTION_PREV);
+ else
+ r = efl_ui_focus_manager_move(data, EFL_UI_FOCUS_DIRECTION_NEXT);
+ }
}
-
static Eo *
_elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_Win_Type type)
{
@@ -4564,7 +4569,9 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W
evas_object_key_grab(sd->edje, "Left", 0, 0, EINA_TRUE);
evas_object_key_grab(sd->edje, "Up", 0, 0, EINA_TRUE);
evas_object_key_grab(sd->edje, "Down", 0, 0, EINA_TRUE);
-
+ evas_object_key_grab(sd->edje, "Tab", 0, 0, EINA_TRUE);
+ evas_object_key_grab(sd->edje, "Shift_L", 0, 0, EINA_TRUE);
+ evas_object_key_grab(sd->edje, "Shift_R", 0, 0, EINA_TRUE);
evas_object_event_callback_add
(sd->edje, EVAS_CALLBACK_KEY_DOWN, _focus_movement, obj);
}