33b93bcbc6ef6ed886b90d283191cfc28295782b
[framework/uifw/evas.git] / src / lib / canvas / evas_callbacks.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 static void evas_object_event_callback_clear(Evas_Object *obj);
5 static void evas_event_callback_clear(Evas *e);
6 int _evas_event_counter = 0;
7
8 EVAS_MEMPOOL(_mp_fn);
9 EVAS_MEMPOOL(_mp_cb);
10 EVAS_MEMPOOL(_mp_pc);
11
12 void
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
31 void
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
43 void
44 evas_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
63 static void
64 evas_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
77 static void
78 evas_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
91 void
92 evas_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
101 void
102 evas_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
111 void
112 evas_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
121 void
122 evas_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
131 void
132 evas_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
164 void
165 evas_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
259 static 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
271 EAPI void
272 evas_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
278 EAPI void
279 evas_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
312 EAPI void *
313 evas_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
343 EAPI void *
344 evas_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
374 EAPI void
375 evas_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
381 EAPI void
382 evas_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
414 EAPI void *
415 evas_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
445 EAPI void *
446 evas_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
476 EAPI void
477 evas_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
496 EAPI void
497 evas_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
516 EAPI void
517 evas_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 }