1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED
6 #define EFL_UI_FOCUS_LAYER_PROTECTED
7 
8 #include <Elementary.h>
9 #include "elm_priv.h"
10 
11 #define MY_CLASS EFL_UI_FOCUS_LAYER_MIXIN
12 
13 typedef struct {
14    Efl_Ui_Focus_Object *old_focus;
15    Efl_Ui_Focus_Manager *registered_manager;
16    Efl_Ui_Focus_Manager *manager;
17    Eina_Bool cycle;
18    Eina_Bool enable_on_visible;
19 } Efl_Ui_Focus_Layer_Data;
20 
21 EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_focus_layer_efl_ui_widget_focus_manager_focus_manager_create(Eo * obj,Efl_Ui_Focus_Layer_Data * pd EINA_UNUSED,Efl_Ui_Focus_Object * root)22 _efl_ui_focus_layer_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root)
23 {
24    pd->manager = efl_add(EFL_UI_FOCUS_MANAGER_ROOT_FOCUS_CLASS, obj, efl_ui_focus_manager_root_set(efl_added, root));
25    return pd->manager;
26 }
27 
28 EOLIAN static void
_efl_ui_focus_layer_efl_gfx_entity_visible_set(Eo * obj,Efl_Ui_Focus_Layer_Data * pd,Eina_Bool v)29 _efl_ui_focus_layer_efl_gfx_entity_visible_set(Eo *obj, Efl_Ui_Focus_Layer_Data *pd, Eina_Bool v)
30 {
31    efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), v);
32 
33    if (pd->enable_on_visible)
34      {
35         efl_ui_focus_layer_enable_set(obj, v);
36      }
37 }
38 
39 EOLIAN static Efl_Ui_Focus_Object*
_efl_ui_focus_layer_efl_ui_focus_manager_move(Eo * obj,Efl_Ui_Focus_Layer_Data * pd,Efl_Ui_Focus_Direction direction)40 _efl_ui_focus_layer_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Focus_Layer_Data *pd, Efl_Ui_Focus_Direction direction)
41 {
42    Eo *ret = efl_ui_focus_manager_move(pd->manager, direction);
43 
44    if (ret)
45      return ret;
46 
47    //ret is NULL here, if we do not want to cycle return NULL, which will result in obj being unset
48    if (!pd->cycle)
49      return NULL;
50 
51    if ((direction == EFL_UI_FOCUS_DIRECTION_PREVIOUS ) || (direction == EFL_UI_FOCUS_DIRECTION_NEXT))
52      efl_ui_focus_manager_focus_set(pd->manager, obj);
53 
54    return efl_ui_focus_manager_focus_get(obj);
55 }
56 
57 EOLIAN static void
_efl_ui_focus_layer_efl_object_invalidate(Eo * obj,Efl_Ui_Focus_Layer_Data * pd EINA_UNUSED)58 _efl_ui_focus_layer_efl_object_invalidate(Eo *obj, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED)
59 {
60    efl_ui_focus_layer_enable_set(obj, EINA_FALSE);
61    efl_invalidate(efl_super(obj, MY_CLASS));
62 }
63 
64 EOLIAN static Efl_Ui_Focus_Manager*
_efl_ui_focus_layer_efl_ui_focus_object_focus_manager_get(const Eo * obj EINA_UNUSED,Efl_Ui_Focus_Layer_Data * pd EINA_UNUSED)65 _efl_ui_focus_layer_efl_ui_focus_object_focus_manager_get(const Eo *obj EINA_UNUSED, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED)
66 {
67    if (pd->registered_manager)
68      return pd->registered_manager;
69    else
70      return NULL;
71 }
72 
73 EOLIAN static Efl_Ui_Focus_Object*
_efl_ui_focus_layer_efl_ui_focus_object_focus_parent_get(const Eo * obj EINA_UNUSED,Efl_Ui_Focus_Layer_Data * pd)74 _efl_ui_focus_layer_efl_ui_focus_object_focus_parent_get(const Eo *obj EINA_UNUSED, Efl_Ui_Focus_Layer_Data *pd)
75 {
76    if (pd->registered_manager)
77      return efl_ui_focus_manager_root_get(pd->registered_manager);
78    else
79      return NULL;
80 }
81 
82 EOLIAN static Eina_Bool
_efl_ui_focus_layer_efl_ui_widget_focus_state_apply(Eo * obj EINA_UNUSED,Efl_Ui_Focus_Layer_Data * pd EINA_UNUSED,Efl_Ui_Widget_Focus_State current_state EINA_UNUSED,Efl_Ui_Widget_Focus_State * configured_state EINA_UNUSED,Efl_Ui_Widget * redirect EINA_UNUSED)83 _efl_ui_focus_layer_efl_ui_widget_focus_state_apply(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Layer_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state EINA_UNUSED, Efl_Ui_Widget_Focus_State *configured_state EINA_UNUSED, Efl_Ui_Widget *redirect EINA_UNUSED)
84 {
85    return EINA_FALSE;
86 }
87 
88 EOLIAN static Efl_Object*
_efl_ui_focus_layer_efl_object_constructor(Eo * obj,Efl_Ui_Focus_Layer_Data * pd)89 _efl_ui_focus_layer_efl_object_constructor(Eo *obj, Efl_Ui_Focus_Layer_Data *pd)
90 {
91    obj = efl_constructor(efl_super(obj, MY_CLASS));
92    pd->enable_on_visible = EINA_TRUE;
93    pd->cycle = EINA_TRUE;
94    return obj;
95 }
96 
97 static void
_publish_state_change(Eo * obj,Efl_Ui_Focus_Manager * omanager,Efl_Ui_Focus_Object * oobj)98 _publish_state_change(Eo *obj, Efl_Ui_Focus_Manager *omanager, Efl_Ui_Focus_Object *oobj)
99 {
100    efl_event_callback_call(obj, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_MANAGER_CHANGED, omanager);
101    efl_event_callback_call(obj, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_PARENT_CHANGED, oobj);
102 }
103 
104 EOLIAN static void
_efl_ui_focus_layer_enable_set(Eo * obj,Efl_Ui_Focus_Layer_Data * pd,Eina_Bool v)105 _efl_ui_focus_layer_enable_set(Eo *obj, Efl_Ui_Focus_Layer_Data *pd, Eina_Bool v)
106 {
107    if (!elm_object_tree_focus_allow_get(obj))
108      v = EINA_FALSE;
109    if (v)
110      {
111         Efl_Ui_Focus_Manager *manager;
112 
113         pd->registered_manager = elm_widget_top_get(obj);
114         EINA_SAFETY_ON_FALSE_RETURN(efl_isa(pd->registered_manager, EFL_UI_WIN_CLASS));
115         manager = efl_ui_focus_util_active_manager(pd->registered_manager);
116 
117         efl_ui_focus_manager_calc_register_logical(pd->registered_manager, obj, efl_ui_focus_manager_root_get(pd->registered_manager), obj);
118         _publish_state_change(obj, NULL, NULL);
119 
120         pd->old_focus = efl_ui_focus_manager_focus_get(manager);
121         efl_ui_focus_manager_focus_set(pd->manager, obj);
122 
123      }
124    else
125      {
126         Eina_Bool fallback = EINA_TRUE;
127 
128         Eo *oobj;
129 
130         if (!pd->registered_manager) return;
131 
132         oobj = efl_ui_focus_manager_root_get(pd->registered_manager);
133 
134         //restore old focus
135         if (pd->old_focus)
136           {
137              Efl_Ui_Focus_Manager *manager;
138 
139              manager = efl_ui_focus_object_focus_manager_get(pd->old_focus);
140              if (manager)
141                {
142                   efl_ui_focus_manager_focus_set(manager, pd->old_focus);
143                   fallback = EINA_FALSE;
144                }
145           }
146 
147         pd->old_focus = NULL;
148 
149         if (fallback && efl_ui_focus_manager_redirect_get(pd->registered_manager) == obj)
150           {
151              Efl_Ui_Focus_Manager *m = pd->registered_manager;
152 
153              while (efl_ui_focus_manager_redirect_get(m))
154                {
155                   Efl_Ui_Focus_Manager *old = m;
156 
157                   m = efl_ui_focus_manager_redirect_get(m);
158                   efl_ui_focus_manager_redirect_set(old, NULL);
159                }
160           }
161 
162         efl_ui_focus_manager_calc_unregister(pd->registered_manager, obj);
163         pd->registered_manager = NULL;
164         _publish_state_change(obj, pd->registered_manager, oobj);
165      }
166 }
167 
168 EOLIAN static Eina_Bool
_efl_ui_focus_layer_enable_get(const Eo * obj,Efl_Ui_Focus_Layer_Data * pd)169 _efl_ui_focus_layer_enable_get(const Eo *obj, Efl_Ui_Focus_Layer_Data *pd)
170 {
171    if (!pd->registered_manager) return EINA_FALSE;
172    return (efl_ui_focus_manager_redirect_get(pd->registered_manager) == obj);
173 }
174 
175 EOLIAN static void
_efl_ui_focus_layer_behaviour_set(Eo * obj EINA_UNUSED,Efl_Ui_Focus_Layer_Data * pd,Eina_Bool enable_on_visible,Eina_Bool cycle)176 _efl_ui_focus_layer_behaviour_set(Eo *obj EINA_UNUSED, Efl_Ui_Focus_Layer_Data *pd, Eina_Bool enable_on_visible, Eina_Bool cycle)
177 {
178    pd->enable_on_visible = enable_on_visible;
179    pd->cycle = cycle;
180 }
181 
182 EOLIAN static void
_efl_ui_focus_layer_behaviour_get(const Eo * obj EINA_UNUSED,Efl_Ui_Focus_Layer_Data * pd,Eina_Bool * enable_on_visible,Eina_Bool * cycle)183 _efl_ui_focus_layer_behaviour_get(const Eo *obj EINA_UNUSED, Efl_Ui_Focus_Layer_Data *pd, Eina_Bool *enable_on_visible, Eina_Bool *cycle)
184 {
185    *cycle = pd->cycle;
186    *enable_on_visible = pd->enable_on_visible;
187 }
188 
189 #include "efl_ui_focus_layer.eo.c"
190