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