evas/map - fixed afterimage problem. now we don't need work-around code anymore.
[framework/uifw/evas.git] / src / lib / canvas / evas_object_smart.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 typedef struct _Evas_Object_Smart      Evas_Object_Smart;
5 typedef struct _Evas_Smart_Callback    Evas_Smart_Callback;
6
7 struct _Evas_Object_Smart
8 {
9    DATA32            magic;
10    void             *engine_data;
11    void             *data;
12    Eina_List        *callbacks;
13    Eina_Inlist      *contained;
14    Evas_Smart_Cb_Description_Array callbacks_descriptions;
15    int               walking_list;
16    Eina_Bool         deletions_waiting : 1;
17    Eina_Bool         need_recalculate : 1;
18 };
19
20 struct _Evas_Smart_Callback
21 {
22    const char *event;
23    Evas_Smart_Cb func;
24    void *func_data;
25    Evas_Callback_Priority priority;
26    char  delete_me : 1;
27 };
28
29 /* private methods for smart objects */
30 static void evas_object_smart_callbacks_clear(Evas_Object *obj);
31 static void evas_object_smart_init(Evas_Object *obj);
32 static void *evas_object_smart_new(void);
33 static void evas_object_smart_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
34 static void evas_object_smart_free(Evas_Object *obj);
35 static void evas_object_smart_render_pre(Evas_Object *obj);
36 static void evas_object_smart_render_post(Evas_Object *obj);
37
38 static unsigned int evas_object_smart_id_get(Evas_Object *obj);
39 static unsigned int evas_object_smart_visual_id_get(Evas_Object *obj);
40 static void *evas_object_smart_engine_data_get(Evas_Object *obj);
41
42 static const Evas_Object_Func object_func =
43 {
44    /* methods (compulsory) */
45    evas_object_smart_free,
46    evas_object_smart_render,
47    evas_object_smart_render_pre,
48    evas_object_smart_render_post,
49    evas_object_smart_id_get,
50    evas_object_smart_visual_id_get,
51    evas_object_smart_engine_data_get,
52    /* these are optional. NULL = nothing */
53    NULL,
54    NULL,
55    NULL,
56    NULL,
57    NULL,
58    NULL,
59    NULL,
60    NULL,
61    NULL,
62    NULL,
63    NULL,
64    NULL,
65    NULL
66 };
67
68 EVAS_MEMPOOL(_mp_obj);
69 EVAS_MEMPOOL(_mp_cb);
70
71 /* public funcs */
72 EAPI void
73 evas_object_smart_data_set(Evas_Object *obj, void *data)
74 {
75    Evas_Object_Smart *o;
76
77    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
78    return;
79    MAGIC_CHECK_END();
80    o = (Evas_Object_Smart *)(obj->object_data);
81    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
82    return;
83    MAGIC_CHECK_END();
84    o->data = data;
85 }
86
87 EAPI void *
88 evas_object_smart_data_get(const Evas_Object *obj)
89 {
90    Evas_Object_Smart *o;
91
92    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
93    return NULL;
94    MAGIC_CHECK_END();
95    o = (Evas_Object_Smart *)(obj->object_data);
96    if (!o) return NULL;
97    return o->data;
98 }
99
100 EAPI Evas_Smart *
101 evas_object_smart_smart_get(const Evas_Object *obj)
102 {
103    Evas_Object_Smart *o;
104
105    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
106    return NULL;
107    MAGIC_CHECK_END();
108    o = (Evas_Object_Smart *)(obj->object_data);
109    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
110    return NULL;
111    MAGIC_CHECK_END();
112    return obj->smart.smart;
113 }
114
115 EAPI void
116 evas_object_smart_member_add(Evas_Object *obj, Evas_Object *smart_obj)
117 {
118    Evas_Object_Smart *o;
119
120    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
121    return;
122    MAGIC_CHECK_END();
123    MAGIC_CHECK(smart_obj, Evas_Object, MAGIC_OBJ);
124    return;
125    MAGIC_CHECK_END();
126    o = (Evas_Object_Smart *)(smart_obj->object_data);
127    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
128    return;
129    MAGIC_CHECK_END();
130
131    if (obj->delete_me)
132      {
133         CRIT("Adding deleted object %p to smart obj %p", obj, smart_obj);
134         abort();
135         return;
136      }
137    if (smart_obj->delete_me)
138      {
139         CRIT("Adding object %p to deleted smart obj %p", obj, smart_obj);
140         abort();
141         return;
142      }
143    if (!smart_obj->layer)
144      {
145         CRIT("No evas surface associated with smart object (%p)", smart_obj);
146         abort();
147         return;
148      }
149    if ((obj->layer && smart_obj->layer) &&
150        (obj->layer->evas != smart_obj->layer->evas))
151      {
152         CRIT("Adding object %p from Evas (%p) from another Evas (%p)", obj, obj->layer->evas, smart_obj->layer->evas);
153         abort();
154         return;
155      }
156
157    if (obj->smart.parent == smart_obj) return;
158
159    if (obj->smart.parent) evas_object_smart_member_del(obj);
160
161    evas_object_release(obj, 1);
162    obj->layer = smart_obj->layer;
163    obj->cur.layer = obj->layer->layer;
164    obj->layer->usage++;
165    obj->smart.parent = smart_obj;
166    o->contained = eina_inlist_append(o->contained, EINA_INLIST_GET(obj));
167    evas_object_smart_member_cache_invalidate(obj, EINA_TRUE, EINA_TRUE);
168    obj->restack = 1;
169    evas_object_change(obj);
170    evas_object_mapped_clip_across_mark(obj);
171    if (smart_obj->smart.smart->smart_class->member_add)
172      smart_obj->smart.smart->smart_class->member_add(smart_obj, obj);
173 }
174
175 EAPI void
176 evas_object_smart_member_del(Evas_Object *obj)
177 {
178    Evas_Object_Smart *o;
179    Evas_Object *smart_obj;
180
181    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
182    return;
183    MAGIC_CHECK_END();
184
185    if (!obj->smart.parent) return;
186
187    smart_obj = obj->smart.parent;
188    if (smart_obj->smart.smart->smart_class->member_del)
189      smart_obj->smart.smart->smart_class->member_del(smart_obj, obj);
190
191    o = (Evas_Object_Smart *)(obj->smart.parent->object_data);
192    o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(obj));
193    obj->smart.parent = NULL;
194    evas_object_smart_member_cache_invalidate(obj, EINA_TRUE, EINA_TRUE);
195    obj->layer->usage--;
196    obj->cur.layer = obj->layer->layer;
197    evas_object_inject(obj, obj->layer->evas);
198    obj->restack = 1;
199    evas_object_change(obj);
200    evas_object_mapped_clip_across_mark(obj);
201 }
202
203 EAPI Evas_Object *
204 evas_object_smart_parent_get(const Evas_Object *obj)
205 {
206    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
207    return NULL;
208    MAGIC_CHECK_END();
209
210    return obj->smart.parent;
211 }
212
213 EAPI Eina_Bool
214 evas_object_smart_type_check(const Evas_Object *obj, const char *type)
215 {
216    const Evas_Smart_Class *sc;
217
218    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
219    return EINA_FALSE;
220    MAGIC_CHECK_END();
221
222    if (!obj->smart.smart)
223      return EINA_FALSE;
224    sc = obj->smart.smart->smart_class;
225    while (sc)
226      {
227         if (!strcmp(sc->name, type))
228           return EINA_TRUE;
229         sc = sc->parent;
230      }
231
232    return EINA_FALSE;
233 }
234
235 EAPI Eina_Bool
236 evas_object_smart_type_check_ptr(const Evas_Object *obj, const char *type)
237 {
238    const Evas_Smart_Class *sc;
239
240    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
241    return EINA_FALSE;
242    MAGIC_CHECK_END();
243
244    if (!obj->smart.smart)
245      return EINA_FALSE;
246    sc = obj->smart.smart->smart_class;
247    while (sc)
248      {
249         if (sc->name == type)
250           return EINA_TRUE;
251         sc = sc->parent;
252      }
253
254    return EINA_FALSE;
255 }
256
257 EAPI Eina_List *
258 evas_object_smart_members_get(const Evas_Object *obj)
259 {
260    Evas_Object_Smart *o;
261    Eina_List *members;
262    Eina_Inlist *member;
263
264    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
265    return NULL;
266    MAGIC_CHECK_END();
267    o = (Evas_Object_Smart *)(obj->object_data);
268    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
269    return NULL;
270    MAGIC_CHECK_END();
271
272    members = NULL;
273    for (member = o->contained; member; member = member->next)
274      members = eina_list_append(members, member);
275
276    return members;
277 }
278
279 const Eina_Inlist *
280 evas_object_smart_members_get_direct(const Evas_Object *obj)
281 {
282    Evas_Object_Smart *o;
283
284    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
285    return NULL;
286    MAGIC_CHECK_END();
287    o = (Evas_Object_Smart *)(obj->object_data);
288    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
289    return NULL;
290    MAGIC_CHECK_END();
291    return o->contained;
292 }
293
294 void
295 _evas_object_smart_members_all_del(Evas_Object *obj)
296 {
297    Evas_Object_Smart *o = (Evas_Object_Smart *)(obj->object_data);
298    while (o->contained)
299      evas_object_del((Evas_Object *)(o->contained));
300 }
301
302 EAPI Evas_Object *
303 evas_object_smart_add(Evas *e, Evas_Smart *s)
304 {
305    Evas_Object *obj;
306
307    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
308    return NULL;
309    MAGIC_CHECK_END();
310    MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
311    return NULL;
312    MAGIC_CHECK_END();
313
314    obj = evas_object_new(e);
315    if (!obj) return NULL;
316    obj->smart.smart = s;
317    obj->type = s->smart_class->name;
318    evas_object_smart_init(obj);
319    evas_object_inject(obj, e);
320
321    evas_object_smart_use(s);
322
323    if (s->smart_class->add) s->smart_class->add(obj);
324
325    return obj;
326 }
327
328 static int
329 _callback_priority_cmp(const void *_a, const void *_b)
330 {
331    const Evas_Smart_Callback *a, *b;
332    a = (const Evas_Smart_Callback *) _a;
333    b = (const Evas_Smart_Callback *) _b;
334    if (a->priority < b->priority)
335       return -1;
336    else
337       return 1;
338 }
339
340 EAPI void
341 evas_object_smart_callback_add(Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data)
342 {
343    evas_object_smart_callback_priority_add(obj, event,
344          EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
345 }
346
347 EAPI void
348 evas_object_smart_callback_priority_add(Evas_Object *obj, const char *event, Evas_Callback_Priority priority, Evas_Smart_Cb func, const void *data)
349 {
350    Evas_Object_Smart *o;
351    Evas_Smart_Callback *cb;
352
353    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
354    return;
355    MAGIC_CHECK_END();
356    o = (Evas_Object_Smart *)(obj->object_data);
357    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
358    return;
359    MAGIC_CHECK_END();
360    if (!event) return;
361    if (!func) return;
362    EVAS_MEMPOOL_INIT(_mp_cb, "evas_smart_callback", Evas_Smart_Callback, 512, );
363    cb = EVAS_MEMPOOL_ALLOC(_mp_cb, Evas_Smart_Callback);
364    if (!cb) return;
365    EVAS_MEMPOOL_PREP(_mp_cb, cb, Evas_Smart_Callback);
366    cb->event = eina_stringshare_add(event);
367    cb->func = func;
368    cb->func_data = (void *)data;
369    cb->priority = priority;
370    o->callbacks = eina_list_sorted_insert(o->callbacks, _callback_priority_cmp,
371          cb);
372 }
373
374 EAPI void *
375 evas_object_smart_callback_del(Evas_Object *obj, const char *event, Evas_Smart_Cb func)
376 {
377    Evas_Object_Smart *o;
378    Eina_List *l;
379    Evas_Smart_Callback *cb;
380
381    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
382    return NULL;
383    MAGIC_CHECK_END();
384    o = (Evas_Object_Smart *)(obj->object_data);
385    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
386    return NULL;
387    MAGIC_CHECK_END();
388    if (!event) return NULL;
389    EINA_LIST_FOREACH(o->callbacks, l, cb)
390      {
391         if ((!strcmp(cb->event, event)) && (cb->func == func))
392           {
393              void *data;
394
395              data = cb->func_data;
396              cb->delete_me = 1;
397              o->deletions_waiting = 1;
398              evas_object_smart_callbacks_clear(obj);
399              return data;
400           }
401      }
402    return NULL;
403 }
404
405 EAPI void *
406 evas_object_smart_callback_del_full(Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data)
407 {
408    Evas_Object_Smart *o;
409    Eina_List *l;
410    Evas_Smart_Callback *cb;
411
412    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
413    return NULL;
414    MAGIC_CHECK_END();
415    o = (Evas_Object_Smart *)(obj->object_data);
416    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
417    return NULL;
418    MAGIC_CHECK_END();
419    if (!event) return NULL;
420    EINA_LIST_FOREACH(o->callbacks, l, cb)
421      {
422         if ((!strcmp(cb->event, event)) && (cb->func == func) && (cb->func_data == data))
423           {
424              void *ret;
425
426              ret = cb->func_data;
427              cb->delete_me = 1;
428              o->deletions_waiting = 1;
429              evas_object_smart_callbacks_clear(obj);
430              return ret;
431           }
432      }
433    return NULL;
434 }
435
436 EAPI void
437 evas_object_smart_callback_call(Evas_Object *obj, const char *event, void *event_info)
438 {
439    Evas_Object_Smart *o;
440    Eina_List *l;
441    Evas_Smart_Callback *cb;
442    const char *strshare;
443
444    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
445    return;
446    MAGIC_CHECK_END();
447    o = (Evas_Object_Smart *)(obj->object_data);
448    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
449    return;
450    MAGIC_CHECK_END();
451    if (!event) return;
452    if (obj->delete_me) return;
453    o->walking_list++;
454    strshare = eina_stringshare_add(event);
455    EINA_LIST_FOREACH(o->callbacks, l, cb)
456      {
457         if (!cb->delete_me)
458           {
459              if (cb->event == strshare)
460                cb->func(cb->func_data, obj, event_info);
461           }
462         if (obj->delete_me)
463           break;
464      }
465    eina_stringshare_del(strshare);
466    o->walking_list--;
467    evas_object_smart_callbacks_clear(obj);
468 }
469
470 EAPI Eina_Bool
471 evas_object_smart_callbacks_descriptions_set(Evas_Object *obj, const Evas_Smart_Cb_Description *descriptions)
472 {
473    const Evas_Smart_Cb_Description *d;
474    Evas_Object_Smart *o;
475    unsigned int i, count = 0;
476
477    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
478    return EINA_FALSE;
479    MAGIC_CHECK_END();
480    o = (Evas_Object_Smart *)(obj->object_data);
481    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
482    return EINA_FALSE;
483    MAGIC_CHECK_END();
484
485    if ((!descriptions) || (!descriptions->name))
486      {
487         evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
488         return EINA_TRUE;
489      }
490
491    for (count = 0, d = descriptions; d->name; d++)
492      count++;
493
494    evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, count);
495    if (count == 0) return EINA_TRUE;
496
497    for (i = 0, d = descriptions; i < count; d++, i++)
498      o->callbacks_descriptions.array[i] = d;
499
500    evas_smart_cb_descriptions_fix(&o->callbacks_descriptions);
501
502    return EINA_TRUE;
503 }
504
505 EAPI void
506 evas_object_smart_callbacks_descriptions_get(const Evas_Object *obj, const Evas_Smart_Cb_Description ***class_descriptions, unsigned int *class_count, const Evas_Smart_Cb_Description ***instance_descriptions, unsigned int *instance_count)
507 {
508    Evas_Object_Smart *o;
509
510    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
511    if (class_descriptions) *class_descriptions = NULL;
512    if (class_count) *class_count = 0;
513    if (instance_descriptions) *instance_descriptions = NULL;
514    if (instance_count) *instance_count = 0;
515    return;
516    MAGIC_CHECK_END();
517    o = (Evas_Object_Smart *)(obj->object_data);
518    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
519    if (class_descriptions) *class_descriptions = NULL;
520    if (class_count) *class_count = 0;
521    if (instance_descriptions) *instance_descriptions = NULL;
522    if (instance_count) *instance_count = 0;
523    return;
524    MAGIC_CHECK_END();
525
526    if (class_descriptions)
527      *class_descriptions = obj->smart.smart->callbacks.array;
528    if (class_count)
529      *class_count = obj->smart.smart->callbacks.size;
530
531    if (instance_descriptions)
532      *instance_descriptions = o->callbacks_descriptions.array;
533    if (instance_count)
534      *instance_count = o->callbacks_descriptions.size;
535 }
536
537 EAPI void
538 evas_object_smart_callback_description_find(const Evas_Object *obj, const char *name, const Evas_Smart_Cb_Description **class_description, const Evas_Smart_Cb_Description **instance_description)
539 {
540    Evas_Object_Smart *o;
541
542    if (!name)
543      {
544         if (class_description) *class_description = NULL;
545         if (instance_description) *instance_description = NULL;
546         return;
547      }
548
549    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
550    if (class_description) *class_description = NULL;
551    if (instance_description) *instance_description = NULL;
552    return;
553    MAGIC_CHECK_END();
554    o = (Evas_Object_Smart *)(obj->object_data);
555    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
556    if (class_description) *class_description = NULL;
557    if (instance_description) *instance_description = NULL;
558    return;
559    MAGIC_CHECK_END();
560
561    if (class_description)
562      *class_description = evas_smart_cb_description_find
563         (&obj->smart.smart->callbacks, name);
564
565    if (instance_description)
566      *instance_description = evas_smart_cb_description_find
567         (&o->callbacks_descriptions, name);
568 }
569
570 EAPI void
571 evas_object_smart_need_recalculate_set(Evas_Object *obj, Eina_Bool value)
572 {
573    Evas_Object_Smart *o;
574    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
575    return;
576    MAGIC_CHECK_END();
577    o = obj->object_data;
578    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
579    return;
580    MAGIC_CHECK_END();
581
582    // XXX: do i need this?
583    if (obj->delete_me) return;
584
585    /* remove this entry from calc_list or processed list */
586    if (eina_clist_element_is_linked(&obj->calc_entry))
587      eina_clist_remove(&obj->calc_entry);
588
589    value = !!value;
590    if (value)
591      eina_clist_add_tail(&obj->layer->evas->calc_list, &obj->calc_entry);
592    else
593      eina_clist_add_tail(&obj->layer->evas->calc_done, &obj->calc_entry);
594
595    if (o->need_recalculate == value) return;
596
597    if (obj->recalculate_cycle > 254)
598      {
599         ERR("Object %p is not stable during recalc loop", obj);
600         return;
601      }
602    if (obj->layer->evas->in_smart_calc) obj->recalculate_cycle++;
603    o->need_recalculate = value;
604 }
605
606 EAPI Eina_Bool
607 evas_object_smart_need_recalculate_get(const Evas_Object *obj)
608 {
609    Evas_Object_Smart *o;
610    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
611    return EINA_FALSE;
612    MAGIC_CHECK_END();
613    o = obj->object_data;
614    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
615    return EINA_FALSE;
616    MAGIC_CHECK_END();
617
618    return o->need_recalculate;
619 }
620
621 EAPI void
622 evas_object_smart_calculate(Evas_Object *obj)
623 {
624    Evas_Object_Smart *o;
625    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
626    return;
627    MAGIC_CHECK_END();
628    o = obj->object_data;
629    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
630    return;
631    MAGIC_CHECK_END();
632
633    if (!obj->smart.smart->smart_class->calculate)
634      return;
635
636    o->need_recalculate = 0;
637    obj->smart.smart->smart_class->calculate(obj);
638 }
639
640 EAPI void
641 evas_smart_objects_calculate(Evas *e)
642 {
643    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
644    return;
645    MAGIC_CHECK_END();
646    evas_call_smarts_calculate(e);
647 }
648
649 EAPI int
650 evas_smart_objects_calculate_count_get(const Evas *e)
651 {
652    MAGIC_CHECK(e, Evas, MAGIC_EVAS);
653    return 0;
654    MAGIC_CHECK_END();
655    return e->smart_calc_count;
656 }
657
658 /**
659  * Call calculate() on all smart objects that need_recalculate.
660  *
661  * @internal
662  */
663 void
664 evas_call_smarts_calculate(Evas *e)
665 {
666    Eina_Clist *elem;
667    Evas_Object *obj;
668
669 //   printf("+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC-----------v\n");
670    evas_event_freeze(e);
671    e->in_smart_calc++;
672
673    while (NULL != (elem = eina_clist_head(&e->calc_list)))
674      {
675         Evas_Object_Smart *o;
676
677         /* move the item to the processed list */
678         obj = EINA_CLIST_ENTRY(elem, Evas_Object, calc_entry);
679         eina_clist_remove(&obj->calc_entry);
680         if (obj->delete_me) continue;
681         eina_clist_add_tail(&e->calc_done, &obj->calc_entry);
682
683         o = obj->object_data;
684
685         if (o->need_recalculate)
686           {
687              o->need_recalculate = 0;
688              obj->smart.smart->smart_class->calculate(obj);
689           }
690      }
691
692    while (NULL != (elem = eina_clist_head(&e->calc_done)))
693      {
694         obj = EINA_CLIST_ENTRY(elem, Evas_Object, calc_entry);
695         obj->recalculate_cycle = 0;
696         eina_clist_remove(&obj->calc_entry);
697      }
698
699    e->in_smart_calc--;
700    if (e->in_smart_calc == 0) e->smart_calc_count++;
701    evas_event_thaw(e);
702    evas_event_thaw_eval(e);
703 }
704
705 EAPI void
706 evas_object_smart_changed(Evas_Object *obj)
707 {
708    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
709    return;
710    MAGIC_CHECK_END();
711    evas_object_change(obj);
712    evas_object_smart_need_recalculate_set(obj, 1);
713 }
714
715 /* internal calls */
716 static void
717 evas_object_smart_callbacks_clear(Evas_Object *obj)
718 {
719    Evas_Object_Smart *o;
720    Eina_List *l;
721    Evas_Smart_Callback *cb;
722
723    o = (Evas_Object_Smart *)(obj->object_data);
724
725    if (o->walking_list) return;
726    if (!o->deletions_waiting) return;
727    for (l = o->callbacks; l;)
728      {
729         cb = eina_list_data_get(l);
730         l = eina_list_next(l);
731         if (cb->delete_me)
732           {
733              o->callbacks = eina_list_remove(o->callbacks, cb);
734              if (cb->event) eina_stringshare_del(cb->event);
735              EVAS_MEMPOOL_FREE(_mp_cb, cb);
736           }
737      }
738 }
739
740 void
741 evas_object_smart_del(Evas_Object *obj)
742 {
743    Evas_Smart *s;
744
745    if (obj->delete_me) return;
746    s = obj->smart.smart;
747    if ((s) && (s->smart_class->del)) s->smart_class->del(obj);
748    if (obj->smart.parent) evas_object_smart_member_del(obj);
749    if (s) evas_object_smart_unuse(s);
750 }
751
752 void
753 evas_object_smart_cleanup(Evas_Object *obj)
754 {
755    Evas_Object_Smart *o;
756
757    if (obj->smart.parent)
758      evas_object_smart_member_del(obj);
759
760    o = (Evas_Object_Smart *)(obj->object_data);
761    if (o->magic == MAGIC_OBJ_SMART)
762      {
763         if (obj->calc_entry.next)
764           eina_clist_remove(&obj->calc_entry);
765
766         while (o->contained)
767            evas_object_smart_member_del((Evas_Object *)o->contained);
768
769         while (o->callbacks)
770           {
771              Evas_Smart_Callback *cb = o->callbacks->data;
772              o->callbacks = eina_list_remove(o->callbacks, cb);
773              if (cb->event) eina_stringshare_del(cb->event);
774              EVAS_MEMPOOL_FREE(_mp_cb, cb);
775           }
776
777         evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
778         o->data = NULL;
779      }
780
781    obj->smart.parent = NULL;
782    obj->smart.smart = NULL;
783 }
784
785 void
786 evas_object_smart_member_cache_invalidate(Evas_Object *obj,
787                                           Eina_Bool pass_events,
788                                           Eina_Bool freeze_events)
789 {
790    Evas_Object_Smart *o;
791    Evas_Object *member;
792
793    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
794    return;
795    MAGIC_CHECK_END();
796
797    if (pass_events)
798      obj->parent_cache.pass_events_valid = EINA_FALSE;
799    if (freeze_events)
800      obj->parent_cache.freeze_events_valid = EINA_FALSE;
801
802    o = obj->object_data;
803    if (o->magic != MAGIC_OBJ_SMART) return;
804
805    EINA_INLIST_FOREACH(o->contained, member)
806      evas_object_smart_member_cache_invalidate(member,
807                                                pass_events,
808                                                freeze_events);
809 }
810
811 void
812 evas_object_smart_member_raise(Evas_Object *member)
813 {
814    Evas_Object_Smart *o;
815
816    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
817    o->contained = eina_inlist_demote(o->contained, EINA_INLIST_GET(member));
818 }
819
820 void
821 evas_object_smart_member_lower(Evas_Object *member)
822 {
823    Evas_Object_Smart *o;
824
825    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
826    o->contained = eina_inlist_promote(o->contained, EINA_INLIST_GET(member));
827 }
828
829 void
830 evas_object_smart_member_stack_above(Evas_Object *member, Evas_Object *other)
831 {
832    Evas_Object_Smart *o;
833
834    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
835    o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
836    o->contained = eina_inlist_append_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
837 }
838
839 void
840 evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *other)
841 {
842    Evas_Object_Smart *o;
843
844    o = (Evas_Object_Smart *)(member->smart.parent->object_data);
845    o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
846    o->contained = eina_inlist_prepend_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
847 }
848
849 /* all nice and private */
850 static void
851 evas_object_smart_init(Evas_Object *obj)
852 {
853    /* alloc smart obj, setup methods and default values */
854    obj->object_data = evas_object_smart_new();
855    /* set up default settings for this kind of object */
856    obj->cur.color.r = 255;
857    obj->cur.color.g = 255;
858    obj->cur.color.b = 255;
859    obj->cur.color.a = 255;
860    obj->cur.geometry.x = 0;
861    obj->cur.geometry.y = 0;
862    obj->cur.geometry.w = 0;
863    obj->cur.geometry.h = 0;
864    obj->cur.layer = 0;
865    /* set up object-specific settings */
866    obj->prev = obj->cur;
867    /* set up methods (compulsory) */
868    obj->func = &object_func;
869 }
870
871 static void *
872 evas_object_smart_new(void)
873 {
874    Evas_Object_Smart *o;
875
876    /* alloc obj private data */
877    EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_smart", Evas_Object_Smart, 256, NULL);
878    o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Smart);
879    if (!o) return NULL;
880    EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Smart);
881    o->magic = MAGIC_OBJ_SMART;
882    return o;
883 }
884
885 static void
886 evas_object_smart_free(Evas_Object *obj)
887 {
888    Evas_Object_Smart *o;
889
890    /* frees private object data. very simple here */
891    o = (Evas_Object_Smart *)(obj->object_data);
892    MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
893    return;
894    MAGIC_CHECK_END();
895    /* free obj */
896    o->magic = 0;
897    EVAS_MEMPOOL_FREE(_mp_obj, o);
898 }
899
900 static void
901 evas_object_smart_render(Evas_Object *obj __UNUSED__, void *output __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, int x __UNUSED__, int y __UNUSED__)
902 {
903    return;
904 }
905
906 static void
907 evas_object_smart_render_pre(Evas_Object *obj)
908 {
909    if (obj->pre_render_done) return;
910    if (!obj->child_has_map)
911      {
912 #if 0
913         Evas_Object_Smart *o;
914
915         o = (Evas_Object_Smart *)(obj->object_data);
916         if (o->member_count > 1 &&
917             obj->cur.bounding_box.w == obj->prev.bounding_box.w &&
918             obj->cur.bounding_box.h == obj->prev.bounding_box.h &&
919             (obj->cur.bounding_box.x != obj->prev.bounding_box.x ||
920              obj->cur.bounding_box.y != obj->prev.bounding_box.y))
921           {
922              fprintf(stderr, "Wouhou, I can detect moving smart object (%s, %p < %p)\n", evas_object_type_get(obj), obj, obj->smart.parent);
923           }
924 #endif
925      }
926    if (obj->changed_map)
927      evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
928
929    obj->pre_render_done = EINA_TRUE;
930 }
931
932 static void
933 evas_object_smart_render_post(Evas_Object *obj)
934 {
935    obj->prev = obj->cur;
936 }
937
938 static unsigned int evas_object_smart_id_get(Evas_Object *obj)
939 {
940    Evas_Object_Smart *o;
941
942    o = (Evas_Object_Smart *)(obj->object_data);
943    if (!o) return 0;
944    return MAGIC_OBJ_SMART;
945 }
946
947 static unsigned int evas_object_smart_visual_id_get(Evas_Object *obj)
948 {
949    Evas_Object_Smart *o;
950
951    o = (Evas_Object_Smart *)(obj->object_data);
952    if (!o) return 0;
953    return MAGIC_OBJ_CONTAINER;
954 }
955
956 static void *evas_object_smart_engine_data_get(Evas_Object *obj)
957 {
958    Evas_Object_Smart *o;
959
960    o = (Evas_Object_Smart *)(obj->object_data);
961    if (!o) return NULL;
962    return o->engine_data;
963 }