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