aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/canvas/evas_callbacks.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/canvas/evas_callbacks.c')
-rw-r--r--libraries/evas/src/lib/canvas/evas_callbacks.c534
1 files changed, 534 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/canvas/evas_callbacks.c b/libraries/evas/src/lib/canvas/evas_callbacks.c
new file mode 100644
index 0000000..33b93bc
--- /dev/null
+++ b/libraries/evas/src/lib/canvas/evas_callbacks.c
@@ -0,0 +1,534 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4static void evas_object_event_callback_clear(Evas_Object *obj);
5static void evas_event_callback_clear(Evas *e);
6int _evas_event_counter = 0;
7
8EVAS_MEMPOOL(_mp_fn);
9EVAS_MEMPOOL(_mp_cb);
10EVAS_MEMPOOL(_mp_pc);
11
12void
13_evas_post_event_callback_call(Evas *e)
14{
15 Evas_Post_Callback *pc;
16 int skip = 0;
17
18 if (e->delete_me) return;
19 _evas_walk(e);
20 EINA_LIST_FREE(e->post_events, pc)
21 {
22 if ((!skip) && (!e->delete_me) && (!pc->delete_me))
23 {
24 if (!pc->func((void*)pc->data, e)) skip = 1;
25 }
26 EVAS_MEMPOOL_FREE(_mp_pc, pc);
27 }
28 _evas_unwalk(e);
29}
30
31void
32_evas_post_event_callback_free(Evas *e)
33{
34 Evas_Post_Callback *pc;
35
36 EINA_LIST_FREE(e->post_events, pc)
37 {
38 EVAS_MEMPOOL_FREE(_mp_pc, pc);
39 }
40 _evas_unwalk(e);
41}
42
43void
44evas_event_callback_list_post_free(Eina_Inlist **list)
45{
46 Eina_Inlist *l;
47
48 /* MEM OK */
49 for (l = *list; l;)
50 {
51 Evas_Func_Node *fn;
52
53 fn = (Evas_Func_Node *)l;
54 l = l->next;
55 if (fn->delete_me)
56 {
57 *list = eina_inlist_remove(*list, EINA_INLIST_GET(fn));
58 EVAS_MEMPOOL_FREE(_mp_fn, fn);
59 }
60 }
61}
62
63static void
64evas_object_event_callback_clear(Evas_Object *obj)
65{
66 if (!obj->callbacks) return;
67 if (!obj->callbacks->deletions_waiting) return;
68 obj->callbacks->deletions_waiting = 0;
69 evas_event_callback_list_post_free(&obj->callbacks->callbacks);
70 if (!obj->callbacks->callbacks)
71 {
72 EVAS_MEMPOOL_FREE(_mp_cb, obj->callbacks);
73 obj->callbacks = NULL;
74 }
75}
76
77static void
78evas_event_callback_clear(Evas *e)
79{
80 if (!e->callbacks) return;
81 if (!e->callbacks->deletions_waiting) return;
82 e->callbacks->deletions_waiting = 0;
83 evas_event_callback_list_post_free(&e->callbacks->callbacks);
84 if (!e->callbacks->callbacks)
85 {
86 EVAS_MEMPOOL_FREE(_mp_cb, e->callbacks);
87 e->callbacks = NULL;
88 }
89}
90
91void
92evas_object_event_callback_all_del(Evas_Object *obj)
93{
94 Evas_Func_Node *fn;
95
96 if (!obj->callbacks) return;
97 EINA_INLIST_FOREACH(obj->callbacks->callbacks, fn)
98 fn->delete_me = 1;
99}
100
101void
102evas_object_event_callback_cleanup(Evas_Object *obj)
103{
104 /* MEM OK */
105 if (!obj->callbacks) return;
106 evas_event_callback_list_post_free(&obj->callbacks->callbacks);
107 EVAS_MEMPOOL_FREE(_mp_cb, obj->callbacks);
108 obj->callbacks = NULL;
109}
110
111void
112evas_event_callback_all_del(Evas *e)
113{
114 Evas_Func_Node *fn;
115
116 if (!e->callbacks) return;
117 EINA_INLIST_FOREACH(e->callbacks->callbacks, fn)
118 fn->delete_me = 1;
119}
120
121void
122evas_event_callback_cleanup(Evas *e)
123{
124 /* MEM OK */
125 if (!e->callbacks) return;
126 evas_event_callback_list_post_free(&e->callbacks->callbacks);
127 EVAS_MEMPOOL_FREE(_mp_cb, e->callbacks);
128 e->callbacks = NULL;
129}
130
131void
132evas_event_callback_call(Evas *e, Evas_Callback_Type type, void *event_info)
133{
134 Eina_Inlist **l_mod = NULL, *l;
135
136 _evas_walk(e);
137 if (e->callbacks)
138 {
139 l_mod = &e->callbacks->callbacks;
140 e->callbacks->walking_list++;
141 for (l = *l_mod; l; l = l->next)
142 {
143 Evas_Func_Node *fn;
144
145 fn = (Evas_Func_Node *)l;
146 if ((fn->type == type) && (!fn->delete_me))
147 {
148 Evas_Event_Cb func = fn->func;
149 if (func)
150 func(fn->data, e, event_info);
151 }
152 if (e->delete_me) break;
153 }
154 e->callbacks->walking_list--;
155 if (!e->callbacks->walking_list)
156 {
157 evas_event_callback_clear(e);
158 l_mod = NULL;
159 }
160 }
161 _evas_unwalk(e);
162}
163
164void
165evas_object_event_callback_call(Evas_Object *obj, Evas_Callback_Type type, void *event_info)
166{
167 /* MEM OK */
168 Eina_Inlist **l_mod = NULL, *l;
169 Evas_Button_Flags flags = EVAS_BUTTON_NONE;
170 Evas *e;
171
172 if ((obj->delete_me) || (!obj->layer)) return;
173 if ((obj->last_event == _evas_event_counter) &&
174 (obj->last_event_type == type)) return;
175 obj->last_event = _evas_event_counter;
176 obj->last_event_type = type;
177 if (!(e = obj->layer->evas)) return;
178
179 _evas_walk(e);
180 if (obj->callbacks)
181 {
182 l_mod = &obj->callbacks->callbacks;
183 switch (type)
184 {
185 case EVAS_CALLBACK_MOUSE_DOWN:
186 {
187 Evas_Event_Mouse_Down *ev = event_info;
188
189 flags = ev->flags;
190 if (ev->flags & (EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK))
191 {
192 if (obj->last_mouse_down_counter < (e->last_mouse_down_counter - 1))
193 ev->flags &= ~(EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK);
194 }
195 obj->last_mouse_down_counter = e->last_mouse_down_counter;
196 break;
197 }
198 case EVAS_CALLBACK_MOUSE_UP:
199 {
200 Evas_Event_Mouse_Up *ev = event_info;
201
202 flags = ev->flags;
203 if (ev->flags & (EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK))
204 {
205 if (obj->last_mouse_up_counter < (e->last_mouse_up_counter - 1))
206 ev->flags &= ~(EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK);
207 }
208 obj->last_mouse_up_counter = e->last_mouse_up_counter;
209 break;
210 }
211 default:
212 break;
213 }
214 obj->callbacks->walking_list++;
215 for (l = *l_mod; l; l = l->next)
216 {
217 Evas_Func_Node *fn;
218
219 fn = (Evas_Func_Node *)l;
220 if ((fn->type == type) && (!fn->delete_me))
221 {
222 Evas_Object_Event_Cb func = fn->func;
223 if (func)
224 func(fn->data, obj->layer->evas, obj, event_info);
225 }
226 if (obj->delete_me) break;
227 }
228 obj->callbacks->walking_list--;
229 if (!obj->callbacks->walking_list)
230 {
231 evas_object_event_callback_clear(obj);
232 l_mod = NULL;
233 }
234
235 if (type == EVAS_CALLBACK_MOUSE_DOWN)
236 {
237 Evas_Event_Mouse_Down *ev = event_info;
238 ev->flags = flags;
239 }
240 else if (type == EVAS_CALLBACK_MOUSE_UP)
241 {
242 Evas_Event_Mouse_Up *ev = event_info;
243 ev->flags = flags;
244 }
245 }
246
247 if (!((obj->no_propagate) && (l_mod) && (*l_mod)))
248 {
249 if (!obj->no_propagate)
250 {
251 if ((obj->smart.parent) && (type != EVAS_CALLBACK_FREE) &&
252 (type <= EVAS_CALLBACK_KEY_UP))
253 evas_object_event_callback_call(obj->smart.parent, type, event_info);
254 }
255 }
256 _evas_unwalk(e);
257}
258
259static int
260_callback_priority_cmp(const void *_a, const void *_b)
261{
262 const Evas_Func_Node *a, *b;
263 a = EINA_INLIST_CONTAINER_GET(_a, Evas_Func_Node);
264 b = EINA_INLIST_CONTAINER_GET(_b, Evas_Func_Node);
265 if (a->priority < b->priority)
266 return -1;
267 else
268 return 1;
269}
270
271EAPI void
272evas_object_event_callback_add(Evas_Object *obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
273{
274 evas_object_event_callback_priority_add(obj, type,
275 EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
276}
277
278EAPI void
279evas_object_event_callback_priority_add(Evas_Object *obj, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Object_Event_Cb func, const void *data)
280{
281 /* MEM OK */
282 Evas_Func_Node *fn;
283
284 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
285 return;
286 MAGIC_CHECK_END();
287
288 if (!func) return;
289
290 if (!obj->callbacks)
291 {
292 EVAS_MEMPOOL_INIT(_mp_cb, "evas_callbacks", Evas_Callbacks, 512, );
293 obj->callbacks = EVAS_MEMPOOL_ALLOC(_mp_cb, Evas_Callbacks);
294 if (!obj->callbacks) return;
295 EVAS_MEMPOOL_PREP(_mp_cb, obj->callbacks, Evas_Callbacks);
296 }
297
298 EVAS_MEMPOOL_INIT(_mp_fn, "evas_func_node", Evas_Func_Node, 2048, );
299 fn = EVAS_MEMPOOL_ALLOC(_mp_fn, Evas_Func_Node);
300 if (!fn) return;
301 EVAS_MEMPOOL_PREP(_mp_fn, fn, Evas_Func_Node);
302 fn->func = func;
303 fn->data = (void *)data;
304 fn->type = type;
305 fn->priority = priority;
306
307 obj->callbacks->callbacks =
308 eina_inlist_sorted_insert(obj->callbacks->callbacks, EINA_INLIST_GET(fn),
309 _callback_priority_cmp);
310}
311
312EAPI void *
313evas_object_event_callback_del(Evas_Object *obj, Evas_Callback_Type type, Evas_Object_Event_Cb func)
314{
315 /* MEM OK */
316 Evas_Func_Node *fn;
317
318 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
319 return NULL;
320 MAGIC_CHECK_END();
321
322 if (!func) return NULL;
323
324 if (!obj->callbacks) return NULL;
325
326 EINA_INLIST_FOREACH(obj->callbacks->callbacks, fn)
327 {
328 if ((fn->func == func) && (fn->type == type) && (!fn->delete_me))
329 {
330 void *tmp;
331
332 tmp = fn->data;
333 fn->delete_me = 1;
334 obj->callbacks->deletions_waiting = 1;
335 if (!obj->callbacks->walking_list)
336 evas_object_event_callback_clear(obj);
337 return tmp;
338 }
339 }
340 return NULL;
341}
342
343EAPI void *
344evas_object_event_callback_del_full(Evas_Object *obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
345{
346 /* MEM OK */
347 Evas_Func_Node *fn;
348
349 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
350 return NULL;
351 MAGIC_CHECK_END();
352
353 if (!func) return NULL;
354
355 if (!obj->callbacks) return NULL;
356
357 EINA_INLIST_FOREACH(obj->callbacks->callbacks, fn)
358 {
359 if ((fn->func == func) && (fn->type == type) && (fn->data == data) && (!fn->delete_me))
360 {
361 void *tmp;
362
363 tmp = fn->data;
364 fn->delete_me = 1;
365 obj->callbacks->deletions_waiting = 1;
366 if (!obj->callbacks->walking_list)
367 evas_object_event_callback_clear(obj);
368 return tmp;
369 }
370 }
371 return NULL;
372}
373
374EAPI void
375evas_event_callback_add(Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
376{
377 evas_event_callback_priority_add(e, type, EVAS_CALLBACK_PRIORITY_DEFAULT,
378 func, data);
379}
380
381EAPI void
382evas_event_callback_priority_add(Evas *e, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Event_Cb func, const void *data)
383{
384 /* MEM OK */
385 Evas_Func_Node *fn;
386
387 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
388 return;
389 MAGIC_CHECK_END();
390
391 if (!func) return;
392
393 if (!e->callbacks)
394 {
395 EVAS_MEMPOOL_INIT(_mp_cb, "evas_callbacks", Evas_Callbacks, 512, );
396 e->callbacks = EVAS_MEMPOOL_ALLOC(_mp_cb, Evas_Callbacks);
397 if (!e->callbacks) return;
398 EVAS_MEMPOOL_PREP(_mp_cb, e->callbacks, Evas_Callbacks);
399 }
400
401 EVAS_MEMPOOL_INIT(_mp_fn, "evas_func_node", Evas_Func_Node, 2048, );
402 fn = EVAS_MEMPOOL_ALLOC(_mp_fn, Evas_Func_Node);
403 if (!fn) return;
404 EVAS_MEMPOOL_PREP(_mp_fn, fn, Evas_Func_Node);
405 fn->func = func;
406 fn->data = (void *)data;
407 fn->type = type;
408 fn->priority = priority;
409
410 e->callbacks->callbacks = eina_inlist_sorted_insert(e->callbacks->callbacks,
411 EINA_INLIST_GET(fn), _callback_priority_cmp);
412}
413
414EAPI void *
415evas_event_callback_del(Evas *e, Evas_Callback_Type type, Evas_Event_Cb func)
416{
417 /* MEM OK */
418 Evas_Func_Node *fn;
419
420 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
421 return NULL;
422 MAGIC_CHECK_END();
423
424 if (!func) return NULL;
425
426 if (!e->callbacks) return NULL;
427
428 EINA_INLIST_FOREACH(e->callbacks->callbacks, fn)
429 {
430 if ((fn->func == func) && (fn->type == type) && (!fn->delete_me))
431 {
432 void *data;
433
434 data = fn->data;
435 fn->delete_me = 1;
436 e->callbacks->deletions_waiting = 1;
437 if (!e->callbacks->walking_list)
438 evas_event_callback_clear(e);
439 return data;
440 }
441 }
442 return NULL;
443}
444
445EAPI void *
446evas_event_callback_del_full(Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
447{
448 /* MEM OK */
449 Evas_Func_Node *fn;
450
451 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
452 return NULL;
453 MAGIC_CHECK_END();
454
455 if (!func) return NULL;
456
457 if (!e->callbacks) return NULL;
458
459 EINA_INLIST_FOREACH(e->callbacks->callbacks, fn)
460 {
461 if ((fn->func == func) && (fn->type == type) && (fn->data == data) && (!fn->delete_me))
462 {
463 void *tmp;
464
465 tmp = fn->data;
466 fn->delete_me = 1;
467 e->callbacks->deletions_waiting = 1;
468 if (!e->callbacks->walking_list)
469 evas_event_callback_clear(e);
470 return tmp;
471 }
472 }
473 return NULL;
474}
475
476EAPI void
477evas_post_event_callback_push(Evas *e, Evas_Object_Event_Post_Cb func, const void *data)
478{
479 Evas_Post_Callback *pc;
480
481 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
482 return;
483 MAGIC_CHECK_END();
484
485 EVAS_MEMPOOL_INIT(_mp_pc, "evas_post_callback", Evas_Post_Callback, 64, );
486 pc = EVAS_MEMPOOL_ALLOC(_mp_pc, Evas_Post_Callback);
487 if (!pc) return;
488 EVAS_MEMPOOL_PREP(_mp_pc, pc, Evas_Post_Callback);
489 if (e->delete_me) return;
490
491 pc->func = func;
492 pc->data = data;
493 e->post_events = eina_list_prepend(e->post_events, pc);
494}
495
496EAPI void
497evas_post_event_callback_remove(Evas *e, Evas_Object_Event_Post_Cb func)
498{
499 Evas_Post_Callback *pc;
500 Eina_List *l;
501
502 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
503 return;
504 MAGIC_CHECK_END();
505
506 EINA_LIST_FOREACH(e->post_events, l, pc)
507 {
508 if (pc->func == func)
509 {
510 pc->delete_me = 1;
511 return;
512 }
513 }
514}
515
516EAPI void
517evas_post_event_callback_remove_full(Evas *e, Evas_Object_Event_Post_Cb func, const void *data)
518{
519 Evas_Post_Callback *pc;
520 Eina_List *l;
521
522 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
523 return;
524 MAGIC_CHECK_END();
525
526 EINA_LIST_FOREACH(e->post_events, l, pc)
527 {
528 if ((pc->func == func) && (pc->data == data))
529 {
530 pc->delete_me = 1;
531 return;
532 }
533 }
534}