1 #include "evas_common_private.h"
2 #include "evas_private.h"
3
4 /* private calls */
5
6 /* FIXME: this is not optimal, but works. i should have a hash of keys per */
7 /* Evas and then a linked lists of grabs for that key and what */
8 /* modifiers/not_modifers they use */
9
10 static Evas_Key_Grab *evas_key_grab_new (Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive);
11 static Evas_Key_Grab *evas_key_grab_find (Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers);
12
13 static Evas_Key_Grab *
evas_key_grab_new(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,const char * keyname,Evas_Modifier_Mask modifiers,Evas_Modifier_Mask not_modifiers,Eina_Bool exclusive)14 evas_key_grab_new(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive)
15 {
16 /* MEM OK */
17 Eina_List *l;
18 Evas_Key_Grab *g;
19 Eina_Bool have_exclusion = EINA_FALSE;
20
21 EINA_LIST_FOREACH(obj->layer->evas->grabs, l, g)
22 {
23 if ((g->modifiers == modifiers) &&
24 (g->not_modifiers == not_modifiers) &&
25 (!strcmp(g->keyname, keyname)) &&
26 (g->exclusive))
27 {
28 have_exclusion = EINA_TRUE;
29 break;
30 }
31 }
32
33 if (have_exclusion && exclusive) return NULL;
34
35 g = calloc(1, sizeof(Evas_Key_Grab));
36 if (!g) return NULL;
37 g->object = eo_obj;
38 g->modifiers = modifiers;
39 g->not_modifiers = not_modifiers;
40 g->exclusive = exclusive;
41 g->keyname = strdup(keyname);
42 if (obj->layer->evas->walking_grabs)
43 g->just_added = EINA_TRUE;
44 g->is_active = EINA_TRUE;
45 if (!g->keyname)
46 {
47 free(g);
48 return NULL;
49 }
50
51 if (exclusive)
52 {
53 Evas_Key_Grab *ge;
54 EINA_LIST_FOREACH(obj->layer->evas->grabs, l, ge)
55 {
56 if ((ge->modifiers == modifiers) &&
57 (ge->not_modifiers == not_modifiers) &&
58 (!strcmp(ge->keyname, keyname)))
59 {
60 ge->is_active = EINA_FALSE;
61 }
62 }
63 }
64 if (have_exclusion) g->is_active = EINA_FALSE;
65
66 obj->grabs = eina_list_append(obj->grabs, g);
67 obj->layer->evas->grabs = eina_list_append(obj->layer->evas->grabs, g);
68 return g;
69 }
70
71 static Evas_Key_Grab *
evas_key_grab_find(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,const char * keyname,Evas_Modifier_Mask modifiers,Evas_Modifier_Mask not_modifiers)72 evas_key_grab_find(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
73 {
74 /* MEM OK */
75 Eina_List *l;
76 Evas_Key_Grab *g;
77
78 EINA_LIST_FOREACH(obj->layer->evas->grabs, l, g)
79 {
80 if ((g->modifiers == modifiers) &&
81 (g->not_modifiers == not_modifiers) &&
82 (!strcmp(g->keyname, keyname)))
83 {
84 if (eo_obj == g->object) return g;
85 }
86 }
87 return NULL;
88 }
89
90 /* local calls */
91
92 void
evas_object_grabs_cleanup(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)93 evas_object_grabs_cleanup(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
94 {
95 if ((!obj->layer) || (!obj->layer->evas)) return;
96 if (obj->layer->evas->walking_grabs)
97 {
98 Eina_List *l;
99 Evas_Key_Grab *g;
100
101 EINA_LIST_FOREACH(obj->grabs, l, g)
102 g->delete_me = EINA_TRUE;
103 }
104 else
105 {
106 while (obj->grabs)
107 {
108 Evas_Key_Grab *g = obj->grabs->data;
109 obj->layer->evas->grabs =
110 eina_list_remove(obj->layer->evas->grabs, g);
111 obj->grabs = eina_list_remove(obj->grabs, g);
112 if (g->keyname) free(g->keyname);
113 free(g);
114 }
115 }
116 }
117
118 void
evas_key_grab_free(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,const char * keyname,Evas_Modifier_Mask modifiers,Evas_Modifier_Mask not_modifiers)119 evas_key_grab_free(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
120 {
121 /* MEM OK */
122 Evas_Key_Grab *g;
123
124 g = evas_key_grab_find(eo_obj, obj, keyname, modifiers, not_modifiers);
125 if (!g) return;
126 Evas_Object_Protected_Data *g_object = efl_data_scope_get(g->object, EFL_CANVAS_OBJECT_CLASS);
127 g_object->grabs = eina_list_remove(g_object->grabs, g);
128 obj->layer->evas->grabs = eina_list_remove(obj->layer->evas->grabs, g);
129 if (g->keyname) free(g->keyname);
130 free(g);
131 }
132
133 // Legacy implementation. TODO: remove use of Evas_Modifier_Mask
134
135 static Eina_Bool
_object_key_grab(Eo * eo_obj,Evas_Object_Protected_Data * obj,const char * keyname,Evas_Modifier_Mask modifiers,Evas_Modifier_Mask not_modifiers,Eina_Bool exclusive)136 _object_key_grab(Eo *eo_obj, Evas_Object_Protected_Data *obj, const char *keyname,
137 Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers,
138 Eina_Bool exclusive)
139 {
140 /* MEM OK */
141 Evas_Key_Grab *g;
142
143 if (((modifiers == not_modifiers) && (modifiers != 0)) || (!keyname)) return EINA_FALSE;
144 g = evas_key_grab_new(eo_obj, obj, keyname, modifiers, not_modifiers, exclusive);
145 return ((!g) ? EINA_FALSE : EINA_TRUE);
146 }
147
148 static void
_object_key_ungrab(Eo * eo_obj,Evas_Object_Protected_Data * obj,const char * keyname,Evas_Modifier_Mask modifiers,Evas_Modifier_Mask not_modifiers)149 _object_key_ungrab(Eo *eo_obj, Evas_Object_Protected_Data *obj, const char *keyname,
150 Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
151 {
152 /* MEM OK */
153 Evas_Key_Grab *g;
154 Eina_List *l;
155
156 if (!keyname) return;
157 g = evas_key_grab_find(eo_obj, obj, keyname, modifiers, not_modifiers);
158 if (!g) return;
159 Evas_Object_Protected_Data *g_object = efl_data_scope_get(g->object, EFL_CANVAS_OBJECT_CLASS);
160 if (g_object->layer->evas->walking_grabs)
161 {
162 if (!g->delete_me)
163 {
164 g_object->layer->evas->delete_grabs++;
165 g->delete_me = EINA_TRUE;
166 }
167 }
168 else
169 {
170 if (g->exclusive)
171 {
172 Evas_Key_Grab *ge;
173 EINA_LIST_FOREACH(obj->layer->evas->grabs, l, ge)
174 {
175 if ((ge->modifiers == modifiers) &&
176 (ge->not_modifiers == not_modifiers) &&
177 (!strcmp(ge->keyname, keyname)))
178 {
179 if (!ge->is_active) ge->is_active = EINA_TRUE;
180 }
181 }
182 }
183
184 evas_key_grab_free(g->object, g_object, keyname, modifiers, not_modifiers);
185 }
186 }
187
188 static inline Evas_Modifier_Mask
_efl_input_modifier_to_evas_modifier_mask(Evas_Public_Data * e,Efl_Input_Modifier in)189 _efl_input_modifier_to_evas_modifier_mask(Evas_Public_Data *e, Efl_Input_Modifier in)
190 {
191 Evas_Modifier_Mask out = 0;
192 size_t i;
193
194 static const Efl_Input_Modifier mods[] = {
195 EFL_INPUT_MODIFIER_ALT,
196 EFL_INPUT_MODIFIER_CONTROL,
197 EFL_INPUT_MODIFIER_SHIFT,
198 EFL_INPUT_MODIFIER_META,
199 EFL_INPUT_MODIFIER_ALTGR,
200 EFL_INPUT_MODIFIER_HYPER,
201 EFL_INPUT_MODIFIER_SUPER
202 };
203
204 for (i = 0; i < EINA_C_ARRAY_LENGTH(mods); i++)
205 if (in & mods[i])
206 {
207 out |= evas_key_modifier_mask_get
208 (e->evas, _efl_input_modifier_to_string(mods[i]));
209 }
210
211 return out;
212 }
213
214 // EO API
215
216 EOLIAN Eina_Bool
_efl_canvas_object_key_grab(Eo * eo_obj,Evas_Object_Protected_Data * obj,const char * keyname,Efl_Input_Modifier mod,Efl_Input_Modifier not_mod,Eina_Bool exclusive)217 _efl_canvas_object_key_grab(Eo *eo_obj, Evas_Object_Protected_Data *obj,
218 const char *keyname, Efl_Input_Modifier mod,
219 Efl_Input_Modifier not_mod, Eina_Bool exclusive)
220 {
221 Evas_Modifier_Mask modifiers, not_modifiers;
222
223 EVAS_OBJECT_DATA_VALID_CHECK(obj, EINA_FALSE);
224 modifiers = _efl_input_modifier_to_evas_modifier_mask(obj->layer->evas, mod);
225 not_modifiers = _efl_input_modifier_to_evas_modifier_mask(obj->layer->evas, not_mod);
226
227 return _object_key_grab(eo_obj, obj, keyname, modifiers, not_modifiers, exclusive);
228 }
229
230 EOLIAN void
_efl_canvas_object_key_ungrab(Eo * eo_obj,Evas_Object_Protected_Data * obj,const char * keyname,Efl_Input_Modifier mod,Efl_Input_Modifier not_mod)231 _efl_canvas_object_key_ungrab(Eo *eo_obj, Evas_Object_Protected_Data *obj,
232 const char *keyname, Efl_Input_Modifier mod,
233 Efl_Input_Modifier not_mod)
234 {
235 Evas_Modifier_Mask modifiers, not_modifiers;
236
237 EVAS_OBJECT_DATA_VALID_CHECK(obj);
238 modifiers = _efl_input_modifier_to_evas_modifier_mask(obj->layer->evas, mod);
239 not_modifiers = _efl_input_modifier_to_evas_modifier_mask(obj->layer->evas, not_mod);
240
241 _object_key_ungrab(eo_obj, obj, keyname, modifiers, not_modifiers);
242 }
243
244 // Legacy API
245
246 EAPI Eina_Bool
evas_object_key_grab(Evas_Object * eo_obj,const char * keyname,Evas_Modifier_Mask modifiers,Evas_Modifier_Mask not_modifiers,Eina_Bool exclusive)247 evas_object_key_grab(Evas_Object *eo_obj, const char *keyname,
248 Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers,
249 Eina_Bool exclusive)
250 {
251 Evas_Object_Protected_Data *obj;
252
253 obj = EVAS_OBJECT_DATA_SAFE_GET(eo_obj);
254 EVAS_OBJECT_DATA_VALID_CHECK(obj, EINA_FALSE);
255
256 return _object_key_grab(eo_obj, obj, keyname, modifiers, not_modifiers, exclusive);
257 }
258
259 EAPI void
evas_object_key_ungrab(Efl_Canvas_Object * eo_obj,const char * keyname,Evas_Modifier_Mask modifiers,Evas_Modifier_Mask not_modifiers)260 evas_object_key_ungrab(Efl_Canvas_Object *eo_obj, const char *keyname,
261 Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
262 {
263 Evas_Object_Protected_Data *obj;
264
265 obj = EVAS_OBJECT_DATA_SAFE_GET(eo_obj);
266 EVAS_OBJECT_DATA_VALID_CHECK(obj);
267
268 _object_key_ungrab(eo_obj, obj, keyname, modifiers, not_modifiers);
269 }
270