summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <marcel-hollerbach@t-online.de>2016-02-19 20:34:14 +0100
committerMarcel Hollerbach <marcel-hollerbach@t-online.de>2016-02-19 22:54:45 +0100
commit017e7bd48411f483ba0b03eee6159606d2db2bbf (patch)
tree77c7dde738a099005c0db834eac839e2cb6cabcf
parent8673e7a1b89687570b2db2d77f692dd57a41dc01 (diff)
first version of the focus graph each window will get
-rw-r--r--src/lib/Makefile.am6
-rw-r--r--src/lib/elm_focus_manager.eo20
-rw-r--r--src/lib/elm_focusable.eo1
-rw-r--r--src/lib/elm_win.c218
-rw-r--r--src/lib/elm_win.eo6
5 files changed, 239 insertions, 12 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 40fb59746..cc5f5a8bd 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -382,6 +382,8 @@ elm_win_eo.h \
382elm_win_legacy.h \ 382elm_win_legacy.h \
383elm_win_standard.h \ 383elm_win_standard.h \
384elm_win_standard.eo.h \ 384elm_win_standard.eo.h \
385elm_focus_manager.eo.h \
386elm_focusable.eo.h \
385elm_helper.h 387elm_helper.h
386includesubdir = $(includedir)/elementary-@VMAJ@/ 388includesubdir = $(includedir)/elementary-@VMAJ@/
387 389
@@ -634,7 +636,9 @@ elm_gengrid_item.eo \
634elm_list_item.eo \ 636elm_list_item.eo \
635elm_toolbar_item.eo \ 637elm_toolbar_item.eo \
636elm_diskselector_item.eo \ 638elm_diskselector_item.eo \
637elm_popup_item.eo 639elm_popup_item.eo \
640elm_focus_manager.eo \
641elm_focusable.eo
638 642
639elm_eolian_type_files = \ 643elm_eolian_type_files = \
640elm_general.eot 644elm_general.eot
diff --git a/src/lib/elm_focus_manager.eo b/src/lib/elm_focus_manager.eo
index f0b85cded..858255320 100644
--- a/src/lib/elm_focus_manager.eo
+++ b/src/lib/elm_focus_manager.eo
@@ -1,9 +1,11 @@
1interface Elm.Focus_Manager { 1interface Elm.Focus_Manager {
2
2 [[A focusable Object should register itself to the next available Focus_Manager. 3 [[A focusable Object should register itself to the next available Focus_Manager.
3 4
4 The next Focus_Manager which is found up in the widget tree is used. 5 The next Focus_Manager which is found up in the widget tree is used.
5 6
6 Container widgets can also implement this interface to set there own right left top bottom objects, they just have to redirect the call up the widget tree so the next focus_manager registers the object]] 7 Container widgets can also implement this interface to set there own right left top bottom objects, they just have to redirect the call up the widget tree so the next focus_manager registers the object]]
8 legacy_prefix: null;
7 methods { 9 methods {
8 register { 10 register {
9 [[register a focusable object to a focusmanager. 11 [[register a focusable object to a focusmanager.
@@ -13,25 +15,25 @@ interface Elm.Focus_Manager {
13 if the given object is already regsitered the childs will be updated. 15 if the given object is already regsitered the childs will be updated.
14 ]] 16 ]]
15 params { 17 params {
16 object : Elm.Focus*; [[object to add to the graph]] 18 object : Elm.Focusable*; [[object to add to the graph]]
17 right : Elm.Focus*; [[Next focusable object for direction right]] 19 right : Elm.Focusable*; [[Next focusable object for direction right]]
18 left : Elm.Focus*; [[Next focusable object for direction left]] 20 left : Elm.Focusable*; [[Next focusable object for direction left]]
19 top : Elm.Focus*; [[Next focusable object for direction top]] 21 top : Elm.Focusable*; [[Next focusable object for direction top]]
20 bottom : Elm.Focus*; [[Next focusable object for direction bottom]] 22 bottom : Elm.Focusable*; [[Next focusable object for direction bottom]]
21 back : Elm.Focus*; [[Next focusable object for tab presses]] 23 back : Elm.Focusable*; [[Next focusable object for tab presses]]
22 forth : Elm.Focus*; [[Next focusable object for forth presses]] 24 next : Elm.Focusable*; [[Next focusable object for forth presses]]
23 } 25 }
24 } 26 }
25 register_simple { 27 register_simple {
26 [[registers a focusable object to this Focus_Manager without any presetted direction objects.]] 28 [[registers a focusable object to this Focus_Manager without any presetted direction objects.]]
27 params { 29 params {
28 object : Elm.Focus*; 30 object : Elm.Focusable*;
29 } 31 }
30 } 32 }
31 unregister { 33 unregister {
32 [[unregister a before registered widget]] 34 [[unregister a before registered widget]]
33 params { 35 params {
34 object : Elm.Focus*; 36 object : Elm.Focusable*;
35 } 37 }
36 } 38 }
37 } 39 }
diff --git a/src/lib/elm_focusable.eo b/src/lib/elm_focusable.eo
index a31ffc727..d868c6f7a 100644
--- a/src/lib/elm_focusable.eo
+++ b/src/lib/elm_focusable.eo
@@ -1,5 +1,6 @@
1interface Elm.Focusable { 1interface Elm.Focusable {
2 [[Implemented by objects which may be focusable]] 2 [[Implemented by objects which may be focusable]]
3 legacy_prefix: null;
3 methods { 4 methods {
4 focusable { 5 focusable {
5 [[returns true if this object is focusable]] 6 [[returns true if this object is focusable]]
diff --git a/src/lib/elm_win.c b/src/lib/elm_win.c
index 24041a93d..b4e404089 100644
--- a/src/lib/elm_win.c
+++ b/src/lib/elm_win.c
@@ -17,6 +17,9 @@
17#define MY_CLASS_NAME "Elm_Win" 17#define MY_CLASS_NAME "Elm_Win"
18#define MY_CLASS_NAME_LEGACY "elm_win" 18#define MY_CLASS_NAME_LEGACY "elm_win"
19 19
20#include "elm_focusable.eo.h"
21#include "elm_focus_manager.eo.h"
22
20static const Elm_Win_Trap *trap = NULL; 23static const Elm_Win_Trap *trap = NULL;
21 24
22#define TRAP(sd, name, ...) \ 25#define TRAP(sd, name, ...) \
@@ -230,6 +233,7 @@ struct _Elm_Win_Data
230 Eina_Bool noblank : 1; 233 Eina_Bool noblank : 1;
231 Eina_Bool theme_alpha : 1; /**< alpha value fetched by a theme. this has higher priority than application_alpha */ 234 Eina_Bool theme_alpha : 1; /**< alpha value fetched by a theme. this has higher priority than application_alpha */
232 Eina_Bool application_alpha : 1; /**< alpha value set by an elm_win_alpha_set() api. this has lower priority than theme_alpha */ 235 Eina_Bool application_alpha : 1; /**< alpha value set by an elm_win_alpha_set() api. this has lower priority than theme_alpha */
236 Eina_List *focus_objects;
233}; 237};
234 238
235static const char SIG_DELETE_REQUEST[] = "delete,request"; 239static const char SIG_DELETE_REQUEST[] = "delete,request";
@@ -1912,7 +1916,7 @@ _elm_win_evas_object_smart_del(Eo *obj, Elm_Win_Data *sd)
1912 DECREMENT_MODALITY() 1916 DECREMENT_MODALITY()
1913 } 1917 }
1914 1918
1915 if ((sd->modal) && (sd->modal_count > 0)) 1919 if ((sd->modal) && (sd->modal_count > 0))
1916 ERR("Deleted modal win was blocked by another modal win which was created after creation of that win."); 1920 ERR("Deleted modal win was blocked by another modal win which was created after creation of that win.");
1917 1921
1918 evas_object_event_callback_del_full(sd->edje, 1922 evas_object_event_callback_del_full(sd->edje,
@@ -5758,4 +5762,216 @@ _elm_win_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Win_Data *sd EINA_
5758 return name ? strdup(name) : NULL; 5762 return name ? strdup(name) : NULL;
5759} 5763}
5760 5764
5765//following is focus tryouts
5766
5767typedef struct _Focus_Node Focus_Node;
5768
5769typedef enum {
5770 LEFT = 0,
5771 RIGHT = 1,
5772 BOTTOM = 2,
5773 TOP = 3,
5774 NEXT = 4,
5775 PREV = 5,
5776 CONNECT_TYPE_END = 6
5777} Connect_Type;
5778
5779struct _Focus_Node{
5780 Eo *widget;
5781 Focus_Node *refs[CONNECT_TYPE_END];
5782};
5783
5784static Connect_Type
5785complement(Connect_Type type) {
5786 if (type == LEFT) return RIGHT;
5787 if (type == RIGHT) return LEFT;
5788 if (type == TOP) return BOTTOM;
5789 if (type == BOTTOM) return TOP;
5790 if (type == PREV) return NEXT;
5791 if (type == NEXT) return PREV;
5792
5793 return CONNECT_TYPE_END;
5794}
5795
5796static Focus_Node*
5797focus_node_unconnect(Focus_Node *node1, Connect_Type type)
5798{
5799 Focus_Node *node2 = NULL;
5800
5801 if (node1)
5802 {
5803 node2 = node1->refs[type];
5804 node1->refs[type] = NULL;
5805 }
5806 if (node2)
5807 {
5808 node2->refs[complement(type)] = NULL;
5809 return node2;
5810 }
5811
5812 return node2;
5813}
5814
5815static void
5816focus_node_connect(Focus_Node *node1, Focus_Node *node2, Connect_Type type)
5817{
5818 focus_node_unconnect(node1, type);
5819 focus_node_unconnect(node2, complement(type));
5820
5821 if (node1) node1->refs[type] = node2;
5822 if (node2) node2->refs[complement(type)] = node1;
5823}
5824
5825static Eina_Bool
5826_del(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info)
5827{
5828 eo_do(obj, elm_focus_manager_unregister(data));
5829
5830 return EO_CALLBACK_CONTINUE;
5831}
5832
5833static void
5834_dump(Eina_List *list) {
5835 Eina_List *node;
5836 Focus_Node *n;
5837
5838 if (!getenv("ELM_FOCUS_DEBUG")) return;
5839
5840 printf("====================================================>\n");
5841
5842 EINA_LIST_FOREACH(list, node, n)
5843 {
5844 if (!n->widget) continue;
5845
5846 printf("Node %s %p - %p %p %p %p %p %p\n"
5847 ,elm_object_widget_type_get(n->widget)
5848 ,n
5849 ,n->refs[0]
5850 ,n->refs[1]
5851 ,n->refs[2]
5852 ,n->refs[3]
5853 ,n->refs[4]
5854 ,n->refs[5]
5855 );
5856 }
5857}
5858
5859static void
5860_compare(int d, Focus_Node *node, int distances[4], Focus_Node *nodes[4], int dir)
5861{
5862 if (d > distances[dir] && distances[dir] != -1) return;
5863
5864 nodes[dir] = node;
5865 distances[dir] = d;
5866
5867}
5868
5869static void
5870_compute_node(Focus_Node *node, Eina_List *objects)
5871{
5872 int x = 0,y = 0,w = 0,h = 0;
5873 Focus_Node *nodes[4] = { 0 }, *r;
5874 Eina_List *n;
5875 int distances[4] = {-1, -1, -1, -1};
5876
5877 evas_object_geometry_get(node->widget, &x, &y, &w, &h);
5878 EINA_LIST_FOREACH(objects, n, r)
5879 {
5880 int rx = 0,ry = 0,rw = 0,rh = 0;
5881 int rel_x = 0, rel_y = 0; //relativ coords from new widget to old
5882 int d;
5883
5884 if (r == node) continue;
5885
5886 evas_object_geometry_get(r->widget, &rx, &ry, &rw, &rh);
5887 rel_x = rx+rw/2 - x+w/2;
5888 rel_y = ry+rh/2 - y+h/2;
5889 d = sqrt(powerof2(rel_x)+powerof2(rel_y));
5890
5891 if (rel_x > 0)
5892 _compare(d, r, distances, nodes, LEFT);
5893 if (rel_x <= 0)
5894 _compare(d, r, distances, nodes, RIGHT);
5895 if (rel_y > 0)
5896 _compare(d, r, distances, nodes, TOP);
5897 if (rel_y <= 0)
5898 _compare(d, r, distances, nodes, BOTTOM);
5899 }
5900
5901 focus_node_connect(node, nodes[LEFT], LEFT);
5902 focus_node_connect(node, nodes[RIGHT], RIGHT);
5903 focus_node_connect(node, nodes[TOP], TOP);
5904 focus_node_connect(node, nodes[BOTTOM], BOTTOM);
5905}
5906
5907EOLIAN static void
5908_elm_win_elm_focus_manager_register(Eo *obj, Elm_Win_Data *pd, Elm_Focusable *object,
5909 Elm_Focusable *right, Elm_Focusable *left, Elm_Focusable *top, Elm_Focusable *bottom, Elm_Focusable *back, Elm_Focusable *forth)
5910{
5911 Focus_Node *node;
5912
5913 node = calloc(1, sizeof(Focus_Node));
5914
5915 //add the node to the known ones
5916 node->widget = object;
5917 eo_do(node->widget, eo_event_callback_add(EO_BASE_EVENT_DEL, _del, obj));
5918 pd->focus_objects = eina_list_append(pd->focus_objects, node);
5919 _compute_node(node, pd->focus_objects);
5920
5921 _dump(pd->focus_objects);
5922}
5923
5924
5925EOLIAN static void
5926_elm_win_elm_focus_manager_register_simple(Eo *obj, Elm_Win_Data *pd, Elm_Focusable *object)
5927{
5928 eo_do(obj, elm_focus_manager_register(obj, NULL,NULL,NULL,NULL,NULL,NULL));
5929}
5930
5931
5932EOLIAN static void
5933_elm_win_elm_focus_manager_unregister(Eo *obj, Elm_Win_Data *pd, Elm_Focusable *object)
5934{
5935 Focus_Node *n = NULL, *focusable;
5936 Eina_List *node;
5937
5938 EINA_LIST_FOREACH(pd->focus_objects, node, focusable)
5939 {
5940 if (focusable->widget == object)
5941 {
5942 n = focusable;
5943 break;
5944 }
5945 }
5946
5947 //check if this is focusable at all
5948 if (!n) return;
5949
5950 pd->focus_objects = eina_list_remove(pd->focus_objects, n);
5951
5952 //delete all attached events
5953 eo_do(n->widget, eo_event_callback_del(EO_BASE_EVENT_DEL, _del, n));
5954
5955 #define UNCONNECT_RECOMPUTE(n,d) \
5956 do { \
5957 Focus_Node *orphan_node; \
5958 orphan_node = focus_node_unconnect(n, d); \
5959 if (orphan_node) {\
5960 _compute_node(orphan_node, pd->focus_objects); \
5961 } \
5962 } while(0) \
5963
5964 //unconnect all nodes
5965 UNCONNECT_RECOMPUTE(n, RIGHT);
5966 UNCONNECT_RECOMPUTE(n, LEFT);
5967 UNCONNECT_RECOMPUTE(n, BOTTOM);
5968 UNCONNECT_RECOMPUTE(n, TOP);
5969 UNCONNECT_RECOMPUTE(n, NEXT);
5970 UNCONNECT_RECOMPUTE(n, PREV);
5971
5972 free(n);
5973}
5974
5975#include "elm_focus_manager.eo.c"
5976#include "elm_focusable.eo.c"
5761#include "elm_win.eo.c" 5977#include "elm_win.eo.c"
diff --git a/src/lib/elm_win.eo b/src/lib/elm_win.eo
index 0dd7c4ae2..c4295fd7f 100644
--- a/src/lib/elm_win.eo
+++ b/src/lib/elm_win.eo
@@ -155,7 +155,8 @@ enum Elm.Illume_Command
155} 155}
156 156
157class Elm.Win (Elm.Widget, Elm.Interface_Atspi_Window, 157class Elm.Win (Elm.Widget, Elm.Interface_Atspi_Window,
158 Elm.Interface_Atspi_Widget_Action) 158 Elm.Interface_Atspi_Widget_Action,
159 Elm.Focus_Manager)
159{ 160{
160 eo_prefix: elm_obj_win; 161 eo_prefix: elm_obj_win;
161 methods { 162 methods {
@@ -1287,6 +1288,9 @@ class Elm.Win (Elm.Widget, Elm.Interface_Atspi_Window,
1287 Elm.Interface_Atspi_Accessible.state_set.get; 1288 Elm.Interface_Atspi_Accessible.state_set.get;
1288 Elm.Interface_Atspi_Accessible.name.get; 1289 Elm.Interface_Atspi_Accessible.name.get;
1289 Elm.Interface_Atspi_Widget_Action.elm_actions.get; 1290 Elm.Interface_Atspi_Widget_Action.elm_actions.get;
1291 Elm.Focus_Manager.register;
1292 Elm.Focus_Manager.register_simple;
1293 Elm.Focus_Manager.unregister;
1290 } 1294 }
1291 constructors { 1295 constructors {
1292 .name; 1296 .name;