1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_UI_FOCUS_COMPOSITION_ADAPTER_PROTECTED
6 #define EFL_UI_FOCUS_OBJECT_PROTECTED
7
8 #include <Elementary.h>
9 #include "elm_priv.h"
10
11 #include "efl_ui_focus_composition_adapter.eo.h"
12
13 #define MY_CLASS EFL_UI_FOCUS_MANAGER_ROOT_FOCUS_CLASS
14
15 typedef struct {
16 Efl_Ui_Focus_Object *replacement_object;
17
18 Evas_Object *rect;
19 Eina_Bool rect_registered;
20
21 Eina_List *iterator_list;
22 Eina_Future *focus_transfer;
23 } Efl_Ui_Focus_Manager_Root_Focus_Data;
24
25 static Eina_Value
_unregister_rect(Eo * obj,void * data EINA_UNUSED,const Eina_Value v EINA_UNUSED)26 _unregister_rect(Eo *obj, void *data EINA_UNUSED, const Eina_Value v EINA_UNUSED)
27 {
28 Efl_Ui_Focus_Manager_Root_Focus_Data *pd = efl_data_scope_get(obj, MY_CLASS);
29
30 efl_ui_focus_manager_calc_unregister(obj, pd->rect);
31 pd->rect_registered = EINA_FALSE;
32 efl_ui_focus_composition_adapter_focus_manager_parent_set(pd->rect, NULL);
33 efl_ui_focus_composition_adapter_focus_manager_object_set(pd->rect, NULL);
34 pd->focus_transfer = NULL;
35 return EINA_VALUE_EMPTY;
36 }
37
38 static Efl_Ui_Focus_Object*
_trap(Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Object * obj)39 _trap(Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *obj)
40 {
41 if (pd->rect == obj) return pd->replacement_object;
42 return obj;
43 }
44
45 static void
_state_eval(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)46 _state_eval(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
47 {
48 Efl_Ui_Focus_Object *sub;
49
50 sub = efl_ui_focus_manager_request_subchild(obj, efl_ui_focus_manager_root_get(obj));
51
52 if (sub == pd->rect)
53 {
54 sub = efl_ui_focus_manager_request_move(obj, EFL_UI_FOCUS_DIRECTION_NEXT, pd->rect, EINA_FALSE);
55 if (sub == pd->rect)
56 sub = NULL;
57 }
58
59 EINA_SAFETY_ON_TRUE_RETURN(sub == pd->rect);
60
61 if (sub && pd->rect_registered)
62 {
63 pd->focus_transfer = efl_loop_job(efl_main_loop_get());
64 efl_future_then(obj, pd->focus_transfer, _unregister_rect);
65 }
66 else if (!sub && !pd->rect_registered)
67 {
68 Efl_Ui_Focus_Object *root;
69
70 if (pd->focus_transfer)
71 eina_future_cancel(pd->focus_transfer);
72 pd->focus_transfer = NULL;
73
74 root = efl_ui_focus_manager_root_get(obj);
75 efl_ui_focus_manager_calc_register(obj, pd->rect, root, NULL);
76 efl_ui_focus_composition_adapter_focus_manager_parent_set(pd->rect, root);
77 efl_ui_focus_composition_adapter_focus_manager_object_set(pd->rect, obj);
78 pd->rect_registered = EINA_TRUE;
79 }
80 }
81
82 EOLIAN static Eina_Bool
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_register(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Object * child,Efl_Ui_Focus_Object * parent,Efl_Ui_Focus_Manager * redirect)83 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_register(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect)
84 {
85 if (efl_ui_focus_manager_calc_register(efl_super(obj, MY_CLASS), child, parent, redirect))
86 {
87 if (child != pd->rect && pd->rect_registered)
88 _state_eval(obj, pd);
89
90 return EINA_TRUE;
91 }
92 return EINA_FALSE;
93 }
94
95 EOLIAN static Eina_Bool
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_register_logical(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Object * child,Efl_Ui_Focus_Object * parent,Efl_Ui_Focus_Manager * redirect)96 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_register_logical(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child, Efl_Ui_Focus_Object *parent, Efl_Ui_Focus_Manager *redirect)
97 {
98 if (efl_ui_focus_manager_calc_register_logical(efl_super(obj, MY_CLASS), child, parent, redirect))
99 {
100 if (redirect && pd->rect_registered)
101 _state_eval(obj, pd);
102
103 return EINA_TRUE;
104 }
105 return EINA_FALSE;
106 }
107
108 EOLIAN static void
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_unregister(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Object * child)109 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_calc_unregister(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child)
110 {
111 efl_ui_focus_manager_calc_unregister(efl_super(obj, MY_CLASS), child);
112
113 if (child != pd->rect)
114 _state_eval(obj, pd);
115 }
116
117 EOLIAN static void
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_manager_focus_set(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Object * focus)118 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_manager_focus_set(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *focus)
119 {
120 EINA_SAFETY_ON_NULL_RETURN(focus);
121 efl_ui_focus_manager_focus_set(efl_super(obj, MY_CLASS), _trap(pd, focus));
122 }
123
124 EOLIAN static Efl_Ui_Focus_Object*
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_manager_focus_get(const Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)125 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_manager_focus_get(const Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
126 {
127 return _trap(pd, efl_ui_focus_manager_focus_get(efl_super(obj, MY_CLASS)));
128 }
129
130 EOLIAN static Efl_Ui_Focus_Relations *
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_fetch(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Object * child)131 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_fetch(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Object *child)
132 {
133 return efl_ui_focus_manager_fetch(efl_super(obj, MY_CLASS), _trap(pd, child));
134 }
135
136 EOLIAN static Efl_Ui_Focus_Manager_Logical_End_Detail
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_logical_end(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)137 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_logical_end(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
138 {
139 Efl_Ui_Focus_Manager_Logical_End_Detail res;
140
141 res = efl_ui_focus_manager_logical_end(efl_super(obj, MY_CLASS));
142
143 res.element = _trap(pd, res.element);
144 return res;
145 }
146
147 EOLIAN static Eina_Iterator *
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_border_elements_get(const Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)148 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_border_elements_get(const Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
149 {
150 if (pd->rect_registered)
151 return eina_list_iterator_new(pd->iterator_list);
152
153 return efl_ui_focus_manager_border_elements_get(efl_super(obj, MY_CLASS));
154 }
155
156 EOLIAN static Eina_Iterator *
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_viewport_elements_get(const Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Eina_Rect viewport EINA_UNUSED)157 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_viewport_elements_get(const Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Eina_Rect viewport EINA_UNUSED)
158 {
159 if (pd->rect_registered)
160 return eina_list_iterator_new(pd->iterator_list);
161
162 return efl_ui_focus_manager_border_elements_get(efl_super(obj, MY_CLASS));
163 }
164
165 EOLIAN static Efl_Ui_Focus_Object*
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_request_move(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Direction direction,Efl_Ui_Focus_Object * child,Eina_Bool logical)166 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_request_move(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Direction direction, Efl_Ui_Focus_Object *child, Eina_Bool logical)
167 {
168 return _trap(pd, efl_ui_focus_manager_request_move(efl_super(obj, MY_CLASS), direction, child, logical));
169 }
170
171 EOLIAN static Efl_Ui_Focus_Object*
_efl_ui_focus_manager_root_focus_efl_ui_focus_manager_move(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Ui_Focus_Direction direction)172 _efl_ui_focus_manager_root_focus_efl_ui_focus_manager_move(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Ui_Focus_Direction direction)
173 {
174 return _trap(pd, efl_ui_focus_manager_move(efl_super(obj, MY_CLASS), direction));
175 }
176
177 EOLIAN static Efl_Canvas_Object*
_efl_ui_focus_manager_root_focus_canvas_object_get(const Eo * obj EINA_UNUSED,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)178 _efl_ui_focus_manager_root_focus_canvas_object_get(const Eo *obj EINA_UNUSED, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
179 {
180 return pd->replacement_object;
181 }
182
183 EOLIAN static void
_efl_ui_focus_manager_root_focus_canvas_object_set(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd,Efl_Canvas_Object * canvas_object)184 _efl_ui_focus_manager_root_focus_canvas_object_set(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd, Efl_Canvas_Object *canvas_object)
185 {
186 //if canvas object is NULL trigger it as root
187 if (!canvas_object)
188 canvas_object = efl_ui_focus_manager_root_get(obj);
189
190 if (canvas_object == pd->replacement_object) return;
191
192 if (pd->replacement_object)
193 {
194 pd->iterator_list = eina_list_remove(pd->iterator_list, pd->rect);
195 pd->replacement_object = NULL;
196 }
197
198 pd->replacement_object = canvas_object;
199 if (pd->replacement_object)
200 {
201 efl_ui_focus_composition_adapter_canvas_object_set(pd->rect, pd->replacement_object);
202 pd->iterator_list = eina_list_append(pd->iterator_list, pd->rect);
203 }
204 }
205
206 static void
_focus_changed(void * data,const Efl_Event * ev)207 _focus_changed(void *data, const Efl_Event *ev)
208 {
209 Eo *root;
210
211 root = efl_ui_focus_manager_root_get(data);
212
213 efl_ui_focus_object_focus_set(root, efl_ui_focus_object_focus_get(ev->object));
214 }
215
216 EFL_CALLBACKS_ARRAY_DEFINE(composition_cb,
217 { EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED, _focus_changed },
218 )
219
220 EOLIAN static Efl_Object*
_efl_ui_focus_manager_root_focus_efl_object_constructor(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)221 _efl_ui_focus_manager_root_focus_efl_object_constructor(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
222 {
223 pd->rect = efl_add_ref(EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS, NULL);
224 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->rect, NULL);
225 efl_event_callback_array_add(pd->rect, composition_cb(), obj);
226
227 return efl_constructor(efl_super(obj, MY_CLASS));
228 }
229
230 EOLIAN static void
_efl_ui_focus_manager_root_focus_efl_object_destructor(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)231 _efl_ui_focus_manager_root_focus_efl_object_destructor(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
232 {
233 efl_unref(pd->rect);
234 pd->rect = NULL;
235
236 efl_destructor(efl_super(obj, MY_CLASS));
237 }
238
239 EOLIAN static Efl_Object*
_efl_ui_focus_manager_root_focus_efl_object_finalize(Eo * obj,Efl_Ui_Focus_Manager_Root_Focus_Data * pd)240 _efl_ui_focus_manager_root_focus_efl_object_finalize(Eo *obj, Efl_Ui_Focus_Manager_Root_Focus_Data *pd)
241 {
242 //set it to NULL so the root manager is passed to the manager
243 if (!pd->replacement_object)
244 efl_ui_focus_manager_root_focus_canvas_object_set(obj, NULL);
245
246 _state_eval(obj, pd);
247
248 return efl_finalize(efl_super(obj, MY_CLASS));
249 }
250
251 #include "efl_ui_focus_manager_root_focus.eo.c"
252