summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/efl_input_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/evas/canvas/efl_input_device.c')
-rw-r--r--src/lib/evas/canvas/efl_input_device.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/src/lib/evas/canvas/efl_input_device.c b/src/lib/evas/canvas/efl_input_device.c
new file mode 100644
index 0000000..52eae92
--- /dev/null
+++ b/src/lib/evas/canvas/efl_input_device.c
@@ -0,0 +1,331 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include "Evas.h"
6#define EFL_INTERNAL_UNSTABLE
7#include "Evas_Internal.h"
8#include "evas_common_private.h"
9#include "evas_private.h"
10
11#define MY_CLASS EFL_INPUT_DEVICE_CLASS
12
13/* Efl Input Device = Evas Device */
14typedef struct _Efl_Input_Device_Data Efl_Input_Device_Data;
15struct _Efl_Input_Device_Data
16{
17 Eo *eo;
18 Eo *evas; /* Evas */
19 Efl_Input_Device *source; /* ref */
20 Eina_List *children; /* ref'ed by efl_parent, not by this list */
21 Eina_Hash *grabs; /* Hash of all the object that might grab this device.
22 We expect thousand of them to be registered here,
23 that is why we use a hash. */
24 unsigned int id;
25 Efl_Input_Device_Type klass;
26 unsigned int subclass; // Evas_Device_Subclass (unused)
27 unsigned int pointer_count;
28};
29
30typedef struct _Child_Device_Iterator Child_Device_Iterator;
31
32struct _Child_Device_Iterator
33{
34 Eina_Iterator iterator;
35 Eina_List *list;
36 Eina_Iterator *real_iterator;
37 Eo *object;
38};
39
40static Eina_Bool
41_is_pointer(Efl_Input_Device_Data *pd)
42{
43 return (pd->klass == EFL_INPUT_DEVICE_TYPE_MOUSE ||
44 pd->klass == EFL_INPUT_DEVICE_TYPE_TOUCH ||
45 pd->klass == EFL_INPUT_DEVICE_TYPE_PEN ||
46 pd->klass == EFL_INPUT_DEVICE_TYPE_WAND);
47}
48
49static void
50_seat_pointers_update(Efl_Input_Device_Data *seat, Efl_Input_Device_Data *dev)
51{
52 if (seat && _is_pointer(dev))
53 seat->pointer_count++;
54}
55
56EOLIAN static Efl_Object *
57_efl_input_device_efl_object_constructor(Eo *obj, Efl_Input_Device_Data *pd)
58{
59 obj = efl_constructor(efl_super(obj, MY_CLASS));
60 pd->eo = obj;
61 return obj;
62}
63
64EOLIAN static void
65_efl_input_device_efl_object_destructor(Eo *obj, Efl_Input_Device_Data *pd)
66{
67 pd->children = eina_list_free(pd->children);
68 if (pd->klass != EFL_INPUT_DEVICE_TYPE_SEAT)
69 {
70 Efl_Input_Device_Data *p;
71 Eo *seat;
72
73 seat = efl_input_device_seat_get(obj);
74 p = efl_data_scope_get(seat, MY_CLASS);
75 if (p) p->children = eina_list_remove(p->children, obj);
76 }
77 efl_unref(pd->source);
78
79 if (pd->grabs)
80 {
81 eina_hash_free(pd->grabs);
82 pd->grabs = NULL;
83 }
84
85 return efl_destructor(efl_super(obj, MY_CLASS));
86}
87
88EOLIAN static void
89_efl_input_device_efl_object_parent_set(Eo *obj, Efl_Input_Device_Data *pd EINA_UNUSED, Eo *parent)
90{
91 Efl_Input_Device_Data *p;
92
93 if (parent)
94 {
95 if (efl_isa(parent, MY_CLASS))
96 {
97 p = efl_data_scope_get(parent, MY_CLASS);
98 EINA_SAFETY_ON_FALSE_RETURN(p->klass == EFL_INPUT_DEVICE_TYPE_SEAT);
99 if (!eina_list_data_find(p->children, obj))
100 {
101 p->children = eina_list_append(p->children, obj);
102 _seat_pointers_update(p, pd);
103 }
104 }
105 else if(!efl_isa(parent, EFL_CANVAS_SCENE_INTERFACE))
106 {
107 EINA_SAFETY_ERROR("The parent of a device must be a seat or the canvas");
108 return;
109 }
110 }
111 else
112 {
113 Eo *old_parent = efl_parent_get(obj);
114 if (old_parent && efl_isa(old_parent, MY_CLASS))
115 {
116 p = efl_data_scope_get(old_parent, MY_CLASS);
117 p->children = eina_list_remove(p->children, obj);
118 if (_is_pointer(pd))
119 p->pointer_count--;
120 }
121 }
122
123 efl_parent_set(efl_super(obj, MY_CLASS), parent);
124}
125
126EOLIAN static void
127_efl_input_device_device_type_set(Eo *obj, Efl_Input_Device_Data *pd, Efl_Input_Device_Type klass)
128{
129 EINA_SAFETY_ON_TRUE_RETURN(pd->klass);
130 pd->klass = klass;
131 if (klass != EFL_INPUT_DEVICE_TYPE_SEAT)
132 {
133 Efl_Input_Device_Data *seat = efl_data_scope_get(efl_input_device_seat_get(obj), MY_CLASS);
134 _seat_pointers_update(seat, pd);
135 }
136}
137
138EOLIAN static Efl_Input_Device_Type
139_efl_input_device_device_type_get(const Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
140{
141 return pd->klass;
142}
143
144EOLIAN static void
145_efl_input_device_source_set(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd, Efl_Input_Device *src)
146{
147 if (pd->source == src) return;
148 efl_unref(pd->source);
149 pd->source = efl_ref(src);
150}
151
152EOLIAN static Efl_Input_Device *
153_efl_input_device_source_get(const Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
154{
155 return pd->source;
156}
157
158EOLIAN static void
159_efl_input_device_seat_id_set(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd, unsigned int id)
160{
161 EINA_SAFETY_ON_TRUE_RETURN(pd->klass != EFL_INPUT_DEVICE_TYPE_SEAT);
162 pd->id = id;
163}
164
165EOLIAN static unsigned int
166_efl_input_device_seat_id_get(const Eo *obj, Efl_Input_Device_Data *pd)
167{
168 if (pd->klass == EFL_INPUT_DEVICE_TYPE_SEAT)
169 return pd->id;
170 return efl_input_device_seat_id_get(efl_input_device_seat_get(obj));
171}
172
173EOLIAN static Efl_Input_Device *
174_efl_input_device_seat_get(const Eo *obj, Efl_Input_Device_Data *pd)
175{
176 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
177
178 if (pd->klass == EFL_INPUT_DEVICE_TYPE_SEAT)
179 return pd->eo;
180
181 while ((obj = efl_parent_get(obj)))
182 {
183 if (!efl_isa(obj, MY_CLASS)) break;
184 pd = efl_data_scope_get(obj, MY_CLASS);
185 if (pd->klass == EFL_INPUT_DEVICE_TYPE_SEAT)
186 return pd->eo;
187 }
188
189 return NULL;
190}
191
192static Eina_Bool
193_child_device_iterator_next(Child_Device_Iterator *it, void **data)
194{
195 Eo *sub;
196
197 if (!eina_iterator_next(it->real_iterator, (void **) &sub))
198 return EINA_FALSE;
199
200 if (data) *data = sub;
201 return EINA_TRUE;
202}
203
204static Eo *
205_child_device_iterator_get_container(Child_Device_Iterator *it)
206{
207 return it->object;
208}
209
210static void
211_child_device_iterator_free(Child_Device_Iterator *it)
212{
213 eina_iterator_free(it->real_iterator);
214 free(it);
215}
216
217EOLIAN static Eina_Iterator *
218_efl_input_device_children_iterate(Eo *obj, Efl_Input_Device_Data *pd)
219{
220 Child_Device_Iterator *it;
221
222 it = calloc(1, sizeof(*it));
223 if (!it) return NULL;
224
225 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
226
227 it->list = pd->children;
228 it->real_iterator = eina_list_iterator_new(it->list);
229 it->iterator.version = EINA_ITERATOR_VERSION;
230 it->iterator.next = FUNC_ITERATOR_NEXT(_child_device_iterator_next);
231 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_child_device_iterator_get_container);
232 it->iterator.free = FUNC_ITERATOR_FREE(_child_device_iterator_free);
233 it->object = obj;
234
235 return &it->iterator;
236}
237
238EOLIAN static int
239_efl_input_device_pointer_device_count_get(const Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
240{
241 if (pd->klass == EFL_INPUT_DEVICE_TYPE_SEAT)
242 return pd->pointer_count;
243 return -1;
244}
245
246EOLIAN static Eina_Bool
247_efl_input_device_is_pointer_type_get(const Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
248{
249 return _is_pointer(pd);
250}
251
252static const Eina_List *
253_efl_input_device_children_get(const Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
254{
255 return pd->children;
256}
257
258EOAPI EFL_FUNC_BODY_CONST(efl_input_device_children_get, const Eina_List *, NULL);
259
260static Evas *
261_efl_input_device_evas_get(const Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
262{
263 return pd->evas;
264}
265
266EOAPI EFL_FUNC_BODY_CONST(efl_input_device_evas_get, Evas *, NULL);
267
268static void
269_efl_input_device_evas_set(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd, Evas *e)
270{
271 pd->evas = e;
272}
273
274EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_evas_set, EFL_FUNC_CALL(e), Evas *e);
275
276static Evas_Device_Subclass
277_efl_input_device_subclass_get(const Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
278{
279 return pd->subclass;
280}
281
282EOAPI EFL_FUNC_BODY_CONST(efl_input_device_subclass_get, Evas_Device_Subclass, 0);
283
284static void
285_efl_input_device_subclass_set(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd,
286 Evas_Device_Subclass sub_clas)
287{
288 pd->subclass = sub_clas;
289}
290
291EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_subclass_set, EFL_FUNC_CALL(sub_clas), Evas_Device_Subclass sub_clas);
292
293static void
294_grab_del(void *data)
295{
296 Evas_Object_Pointer_Data *pdata = data;
297
298 evas_object_pointer_grab_del(pdata->obj, pdata);
299}
300
301static void
302_efl_input_device_grab_register(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd,
303 Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata)
304{
305 if (!pd->grabs) pd->grabs = eina_hash_pointer_new(_grab_del);
306 eina_hash_add(pd->grabs, &grab, pdata);
307}
308
309EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_register, EFL_FUNC_CALL(grab, pdata),
310 Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata);
311
312static void
313_efl_input_device_grab_unregister(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd,
314 Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata)
315{
316 eina_hash_del(pd->grabs, &grab, pdata);
317}
318
319EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_unregister, EFL_FUNC_CALL(grab, pdata),
320 Efl_Canvas_Object *grab, Evas_Object_Pointer_Data *pdata);
321
322#define EFL_INPUT_DEVICE_EXTRA_OPS \
323 EFL_OBJECT_OP_FUNC(efl_input_device_evas_get, _efl_input_device_evas_get), \
324 EFL_OBJECT_OP_FUNC(efl_input_device_evas_set, _efl_input_device_evas_set), \
325 EFL_OBJECT_OP_FUNC(efl_input_device_subclass_get, _efl_input_device_subclass_get), \
326 EFL_OBJECT_OP_FUNC(efl_input_device_subclass_set, _efl_input_device_subclass_set), \
327 EFL_OBJECT_OP_FUNC(efl_input_device_children_get, _efl_input_device_children_get), \
328 EFL_OBJECT_OP_FUNC(efl_input_device_grab_register, _efl_input_device_grab_register), \
329 EFL_OBJECT_OP_FUNC(efl_input_device_grab_unregister, _efl_input_device_grab_unregister),
330
331#include "efl_input_device.eo.c"