1 #define EFL_CANVAS_GROUP_PROTECTED
2
3 #include "eo_internal.h"
4 #include "evas_common_private.h"
5 #include "evas_private.h"
6
7 #define MY_CLASS EFL_CANVAS_GROUP_CLASS
8
9 #define MY_CLASS_NAME "Evas_Smart"
10 #define MY_CLASS_NAME_LEGACY "Evas_Object_Smart"
11
12 #define EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, ...) \
13 Evas_Smart_Data *o = efl_data_scope_safe_get(eo_obj, MY_CLASS); \
14 do { if (!o) { ERR("calling smart object API on non-smart object!"); return __VA_ARGS__; } } while (0)
15
16 extern Eina_Hash* signals_hash_table;
17
18 static Eina_Hash *_evas_smart_class_names_hash_table = NULL;
19
20 struct _Evas_Smart_Data
21 {
22 struct {
23 Eina_Rectangle bounding_box;
24 } cur, prev;
25 Evas_Object *object;
26 Evas_Object *filter_img;
27 void *engine_data;
28 void *data;
29 Eina_Inlist *callbacks;
30 Eina_Inlist *contained; /** list of smart member objects */
31
32 void *render_cache;
33 /* ptr array + data blob holding all interfaces private data for
34 * this object */
35 void **interface_privates;
36 Eina_Clist calc_entry;
37
38 Evas_Smart_Cb_Description_Array callbacks_descriptions;
39
40 int x, y;
41 int walking_list;
42 int member_count; /** number of smart member objects */
43
44 unsigned short recalculate_cycle;
45
46 Evas_BiDi_Direction paragraph_direction : 2;
47 Eina_Bool inherit_paragraph_direction : 1;
48 Eina_Bool deletions_waiting : 1;
49 Eina_Bool need_recalculate : 1;
50 Eina_Bool update_boundingbox_needed : 1;
51 Eina_Bool group_del_called : 1;
52 Eina_Bool clipped : 1; /* If true, smart clipped */
53 Eina_Bool data_nofree : 1; /* If true, do NOT free the data */
54 Eina_Bool constructed : 1; /* constructor finished */
55 Eina_Bool cb_move : 1; /* has "move" cb added */
56 Eina_Bool cb_resize : 1; /* has "resize" cb added */
57 Eina_Bool cb_restack : 1; /* has "restack" cb added */
58 Eina_Bool cb_member_added : 1; /* has "member,added" cb added */
59 Eina_Bool cb_member_removed : 1; /* has "member,removed" cb added */
60 };
61
62 typedef struct
63 {
64 EINA_INLIST;
65 Evas_Smart_Cb func;
66 void *data;
67 const Efl_Event_Description *event;
68 } _eo_evas_smart_cb_info;
69
70
71 typedef struct _Evas_Object_Smart_Iterator Evas_Object_Smart_Iterator;
72 struct _Evas_Object_Smart_Iterator
73 {
74 Eina_Iterator iterator;
75
76 const Eina_Inlist *current;
77 Evas_Object *parent;
78 };
79
80 static void
_eo_evas_smart_cb(void * data,const Efl_Event * event)81 _eo_evas_smart_cb(void *data, const Efl_Event *event)
82 {
83 _eo_evas_smart_cb_info *info = data;
84 if (info->func) info->func(info->data, event->object, event->info);
85 }
86
87 /* private methods for smart objects */
88 static void evas_object_smart_render(Evas_Object *eo_obj,
89 Evas_Object_Protected_Data *obj,
90 void *type_private_data,
91 void *engine, void *output, void *context, void *surface,
92 int x, int y, Eina_Bool do_async);
93 static void evas_object_smart_render_pre(Evas_Object *eo_obj,
94 Evas_Object_Protected_Data *obj,
95 void *type_private_data);
96 static void evas_object_smart_render_post(Evas_Object *eo_obj,
97 Evas_Object_Protected_Data *obj,
98 void *type_private_data);
99
100 static void *evas_object_smart_engine_data_get(Evas_Object *eo_obj);
101 static void _efl_canvas_group_group_paragraph_direction_set_internal(Eo *eo_obj,
102 Evas_BiDi_Direction dir);
103
104 static const Evas_Object_Func object_func =
105 {
106 /* methods (compulsory) */
107 NULL,
108 evas_object_smart_render,
109 evas_object_smart_render_pre,
110 evas_object_smart_render_post,
111 evas_object_smart_engine_data_get,
112 /* these are optional. NULL = nothing */
113 NULL,
114 NULL,
115 NULL,
116 NULL,
117 NULL,
118 NULL,
119 NULL,
120 NULL,
121 NULL,
122 NULL,
123 NULL // render_prepare
124 };
125
126 /* helpers */
127 static inline Evas_Object *
_smart_clipper_get(Evas_Smart_Data * o)128 _smart_clipper_get(Evas_Smart_Data *o)
129 {
130 Evas_Object_Smart_Clipped_Data *cso = o->clipped ? o->data : NULL;
131 return cso ? cso->clipper : NULL;
132 }
133
134 /* public funcs */
135 EAPI void
evas_object_smart_data_set(Evas_Object * eo_obj,void * data)136 evas_object_smart_data_set(Evas_Object *eo_obj, void *data)
137 {
138 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj);
139 if (o->data != data)
140 {
141 if (o->data && !o->data_nofree)
142 free(o->data);
143 o->data = data;
144 o->data_nofree = EINA_TRUE;
145 }
146 }
147
148 EAPI void *
evas_object_smart_data_get(const Evas_Object * eo_obj)149 evas_object_smart_data_get(const Evas_Object *eo_obj)
150 {
151 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, NULL);
152 return o->data;
153 }
154
155 EAPI const void *
evas_object_smart_interface_get(const Evas_Object * eo_obj,const char * name)156 evas_object_smart_interface_get(const Evas_Object *eo_obj,
157 const char *name)
158 {
159 Evas_Smart *s;
160 unsigned int i;
161
162 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, NULL);
163 s = evas_object_smart_smart_get(eo_obj);
164 if (!s) return NULL;
165
166 for (i = 0; i < s->interfaces.size; i++)
167 {
168 const Evas_Smart_Interface *iface;
169
170 iface = s->interfaces.array[i];
171
172 if (iface->name == name)
173 return iface;
174 }
175
176 return NULL;
177 }
178
179 EAPI void *
evas_object_smart_interface_data_get(const Evas_Object * eo_obj,const Evas_Smart_Interface * iface)180 evas_object_smart_interface_data_get(const Evas_Object *eo_obj,
181 const Evas_Smart_Interface *iface)
182 {
183 unsigned int i;
184 Evas_Smart *s;
185
186 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, NULL);
187 s = evas_object_smart_smart_get(eo_obj);
188 if (!s) return NULL;
189
190 if (s)
191 {
192 for (i = 0; i < s->interfaces.size; i++)
193 {
194 if (iface == s->interfaces.array[i])
195 return o->interface_privates[i];
196 }
197 }
198
199 return NULL;
200 }
201
202 EAPI Evas_Smart*
evas_object_smart_smart_get(const Efl_Canvas_Group * eo_obj)203 evas_object_smart_smart_get(const Efl_Canvas_Group *eo_obj)
204 {
205 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, NULL);
206 return obj->smart.smart;
207 }
208
209 EAPI void
evas_object_smart_member_add(Evas_Object * eo_obj,Evas_Object * smart_obj)210 evas_object_smart_member_add(Evas_Object *eo_obj, Evas_Object *smart_obj)
211 {
212 efl_canvas_group_member_add(smart_obj, eo_obj);
213 }
214
215 static void
_evas_object_smart_member_cache_invalidate(Evas_Object_Protected_Data * obj,Evas_Smart_Data * sd)216 _evas_object_smart_member_cache_invalidate(Evas_Object_Protected_Data *obj, Evas_Smart_Data *sd)
217 {
218 Evas_Object_Protected_Data *member;
219 Evas_Smart_Data *msd;
220
221 obj->parent_cache.pass_events_valid = EINA_FALSE;
222 obj->parent_cache.freeze_events_valid = EINA_FALSE;
223 obj->parent_cache.src_invisible_valid = EINA_FALSE;
224 if (!sd) return;
225
226 EINA_INLIST_FOREACH(sd->contained, member)
227 {
228 if (member->is_smart)
229 msd = efl_data_scope_get(member->object, MY_CLASS);
230 else msd = NULL;
231 _evas_object_smart_member_cache_invalidate(member, msd);
232 }
233 }
234
235 EOLIAN static void
_efl_canvas_group_group_member_add(Eo * smart_obj,Evas_Smart_Data * o,Evas_Object * eo_obj)236 _efl_canvas_group_group_member_add(Eo *smart_obj, Evas_Smart_Data *o, Evas_Object *eo_obj)
237 {
238
239 Evas_Object_Protected_Data *obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
240 Evas_Object_Protected_Data *smart = efl_data_scope_get(smart_obj, EFL_CANVAS_OBJECT_CLASS);
241 Evas_Smart_Data *member_o = NULL;
242
243 if ((!obj) || (!smart)) return;
244 if (obj->delete_me)
245 {
246 CRI("Adding deleted object %p to smart obj %p", eo_obj, smart_obj);
247 return;
248 }
249 if (smart->delete_me)
250 {
251 CRI("Adding object %p to deleted smart obj %p", eo_obj, smart_obj);
252 return;
253 }
254 if (!smart->layer)
255 {
256 CRI("No evas surface associated with smart object (%p)", smart_obj);
257 return;
258 }
259 if ((obj->layer && smart->layer) &&
260 (obj->layer->evas != smart->layer->evas))
261 {
262 CRI("Adding object %p from Evas (%p) from another Evas (%p)", eo_obj, obj->layer->evas, smart->layer->evas);
263 return;
264 }
265
266 if (obj->smart.parent == smart_obj) return;
267
268 evas_object_async_block(obj);
269 if (obj->smart.parent) evas_object_smart_member_del(eo_obj);
270
271 if (obj->layer != smart->layer)
272 {
273 if (obj->in_layer)
274 evas_object_release(eo_obj, obj, 1);
275 else if (obj->layer && ((--obj->layer->usage) == 0))
276 evas_layer_del(obj->layer);
277 }
278 else if (obj->in_layer)
279 {
280 evas_object_release(eo_obj, obj, 1);
281 }
282 obj->layer = smart->layer;
283 obj->layer->usage++;
284 if (obj->layer->layer != obj->cur->layer)
285 {
286 EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
287 state_write->layer = obj->layer->layer;
288 EINA_COW_STATE_WRITE_END(obj, state_write, cur);
289 }
290
291 o->member_count++;
292 obj->smart.parent = smart_obj;
293 obj->smart.parent_data = o;
294 obj->smart.parent_object_data = smart;
295 o->contained = eina_inlist_append(o->contained, EINA_INLIST_GET(obj));
296
297 if (obj->is_smart) member_o = efl_data_scope_get(eo_obj, MY_CLASS);
298 _evas_object_smart_member_cache_invalidate(obj, member_o);
299 obj->restack = 1;
300
301 if (obj->is_smart)
302 {
303 if ((member_o->inherit_paragraph_direction) &&
304 (member_o->paragraph_direction != o->paragraph_direction))
305 {
306 member_o->paragraph_direction = o->paragraph_direction;
307 _efl_canvas_group_group_paragraph_direction_set_internal(eo_obj, o->paragraph_direction);
308 }
309 }
310
311 if (!smart->is_frame_top && (smart->is_frame != obj->is_frame))
312 efl_canvas_object_is_frame_object_set(eo_obj, smart->is_frame);
313
314 if (o->clipped)
315 {
316 Evas_Object *clipper = _smart_clipper_get(o);
317 Eina_Bool had_clippees = evas_object_clipees_has(clipper);
318
319 if (EINA_UNLIKELY(!clipper && !o->constructed))
320 {
321 _evas_object_smart_clipped_init(smart_obj);
322 clipper = _smart_clipper_get(o);
323 }
324
325 if (clipper != eo_obj)
326 {
327 EINA_SAFETY_ON_NULL_RETURN(clipper);
328 efl_canvas_object_clipper_set(eo_obj, clipper);
329 if (!had_clippees && smart->cur->visible)
330 efl_gfx_entity_visible_set(clipper, 1);
331 }
332 }
333
334 evas_object_change(eo_obj, obj);
335 evas_object_mapped_clip_across_mark(eo_obj, obj);
336 if (smart->smart.smart && smart->smart.smart->smart_class->member_add)
337 smart->smart.smart->smart_class->member_add(smart_obj, eo_obj);
338 evas_object_update_bounding_box(eo_obj, obj, member_o);
339 if (o->cb_member_added)
340 efl_event_callback_call(smart_obj, EFL_CANVAS_GROUP_EVENT_MEMBER_ADDED, eo_obj);
341 }
342
343 EAPI void
evas_object_smart_member_del(Evas_Object * eo_obj)344 evas_object_smart_member_del(Evas_Object *eo_obj)
345 {
346 Evas_Object_Protected_Data *obj;
347
348 if (!eo_obj) return ;
349 obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
350 if (!obj) return;
351 if (!obj->smart.parent) return;
352 Evas_Object *smart_obj = obj->smart.parent;
353 efl_canvas_group_member_remove(smart_obj, eo_obj);
354 }
355
356 EOLIAN static void
_efl_canvas_group_group_member_remove(Eo * smart_obj,Evas_Smart_Data * sd,Evas_Object * eo_obj)357 _efl_canvas_group_group_member_remove(Eo *smart_obj, Evas_Smart_Data *sd, Evas_Object *eo_obj)
358 {
359 Evas_Object_Protected_Data *obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
360 Evas_Object_Protected_Data *smart;
361 Evas_Smart_Data *member_o = NULL, *o;
362
363 if (!obj || !obj->smart.parent) return;
364
365 evas_object_async_block(obj);
366
367 if (sd->cb_member_removed)
368 efl_event_callback_call(smart_obj, EFL_CANVAS_GROUP_EVENT_MEMBER_REMOVED, eo_obj);
369
370 smart = efl_data_scope_get(smart_obj, EFL_CANVAS_OBJECT_CLASS);
371 if (smart->smart.smart && smart->smart.smart->smart_class->member_del)
372 smart->smart.smart->smart_class->member_del(smart_obj, eo_obj);
373
374 o = efl_data_scope_get(smart_obj, MY_CLASS);
375
376 if (o->clipped)
377 {
378 Evas_Object *clipper = _smart_clipper_get(o);
379
380 EINA_SAFETY_ON_NULL_RETURN(clipper);
381 efl_canvas_object_clipper_set(eo_obj, NULL);
382 if (!evas_object_clipees_has(clipper))
383 efl_gfx_entity_visible_set(clipper, 0);
384 }
385
386 o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(obj));
387 o->member_count--;
388 obj->smart.parent = NULL;
389
390 if (obj->is_smart) member_o = efl_data_scope_get(eo_obj, MY_CLASS);
391 _evas_object_smart_member_cache_invalidate(obj, member_o);
392
393 if (obj->layer->layer != obj->cur->layer)
394 {
395 EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
396 state_write->layer = obj->layer->layer;
397 EINA_COW_STATE_WRITE_END(obj, state_write, cur);
398 }
399
400 if (obj->is_smart)
401 {
402 if ((member_o->inherit_paragraph_direction) &&
403 (member_o->paragraph_direction != EVAS_BIDI_DIRECTION_NEUTRAL))
404 {
405 member_o->paragraph_direction = EVAS_BIDI_DIRECTION_NEUTRAL;
406 _efl_canvas_group_group_paragraph_direction_set_internal(eo_obj, EVAS_BIDI_DIRECTION_NEUTRAL);
407 }
408 }
409
410 if (EINA_UNLIKELY(obj->in_layer))
411 {
412 ERR("Invalid internal state of object %p (child marked as being a"
413 "top-level object)!", obj->object);
414 evas_object_release(obj->object, obj, 1);
415 }
416 else
417 {
418 // Layer usage shouldn't reach 0 here (as parent is still in layer)
419 obj->layer->usage--;
420 }
421 /* layer may be destroyed in evas_object_release() call */
422 if (obj->layer)
423 evas_object_inject(eo_obj, obj, obj->layer->evas->evas);
424 obj->restack = 1;
425 evas_object_change(eo_obj, obj);
426 evas_object_mapped_clip_across_mark(eo_obj, obj);
427 }
428
429 EAPI Eina_Bool
evas_object_smart_type_check(const Evas_Object * eo_obj,const char * type)430 evas_object_smart_type_check(const Evas_Object *eo_obj, const char *type)
431 {
432 const Evas_Smart_Class *sc;
433 Efl_Class *klass;
434 Eina_Bool type_check = EINA_FALSE;
435
436 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE);
437
438 klass = eina_hash_find(_evas_smart_class_names_hash_table, type);
439 if (klass) type_check = efl_isa(eo_obj, klass);
440
441 /* Backward compatibility - walk over smart classes and compare type */
442 if (EINA_FALSE == type_check)
443 {
444 if (obj->smart.smart)
445 {
446 sc = obj->smart.smart->smart_class;
447 while (sc)
448 {
449 if (!strcmp(sc->name, type)) return EINA_TRUE;
450 sc = sc->parent;
451 }
452 }
453 }
454
455 return type_check;
456 }
457
458 EAPI Eina_Bool
evas_object_smart_type_check_ptr(const Eo * eo_obj,const char * type)459 evas_object_smart_type_check_ptr(const Eo *eo_obj, const char* type)
460 {
461 Efl_Class *klass;
462 const Evas_Smart_Class *sc;
463 Eina_Bool type_check = EINA_FALSE;
464
465 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj, EINA_FALSE);
466
467 klass = eina_hash_find(_evas_smart_class_names_hash_table, type);
468 if (klass) type_check = efl_isa(eo_obj, klass);
469
470 /* Backward compatibility - walk over smart classes and compare type */
471 if (EINA_FALSE == type_check)
472 {
473 if (obj->smart.smart)
474 {
475 sc = obj->smart.smart->smart_class;
476 while (sc)
477 {
478 if (sc->name == type) return EINA_TRUE;
479 sc = sc->parent;
480 }
481 }
482 }
483
484 return type_check;
485 }
486
487 EAPI void
evas_smart_legacy_type_register(const char * type,const Efl_Class * klass)488 evas_smart_legacy_type_register(const char *type, const Efl_Class *klass)
489 {
490 eina_hash_set(_evas_smart_class_names_hash_table, type, klass);
491 }
492
493 static Eina_Bool
_efl_canvas_group_group_iterator_next(Evas_Object_Smart_Iterator * it,void ** data)494 _efl_canvas_group_group_iterator_next(Evas_Object_Smart_Iterator *it, void **data)
495 {
496 Evas_Object *eo;
497
498 if (!it->current) return EINA_FALSE;
499
500 eo = ((const Evas_Object_Protected_Data*)(it->current))->object;
501 if (data) *data = eo;
502
503 it->current = it->current->next;
504
505 return EINA_TRUE;
506 }
507
508 static Evas_Object *
_efl_canvas_group_group_iterator_get_container(Evas_Object_Smart_Iterator * it)509 _efl_canvas_group_group_iterator_get_container(Evas_Object_Smart_Iterator *it)
510 {
511 return it->parent;
512 }
513
514 static void
_efl_canvas_group_group_iterator_free(Evas_Object_Smart_Iterator * it)515 _efl_canvas_group_group_iterator_free(Evas_Object_Smart_Iterator *it)
516 {
517 efl_unref(it->parent);
518 free(it);
519 }
520
521 // Should we have an efl_children_iterator_new API and just inherit from it ?
522 // No, because each hierarchy is different (Eo, Smart, Widget) -- jpeg
523 EOLIAN static Eina_Iterator*
_efl_canvas_group_group_members_iterate(const Eo * eo_obj,Evas_Smart_Data * priv)524 _efl_canvas_group_group_members_iterate(const Eo *eo_obj, Evas_Smart_Data *priv)
525 {
526 Evas_Object_Smart_Iterator *it;
527 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
528
529 if (!priv->contained) return NULL;
530
531 evas_object_async_block(obj);
532 it = calloc(1, sizeof(Evas_Object_Smart_Iterator));
533 if (!it) return NULL;
534
535 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
536 it->parent = efl_ref(eo_obj);
537 it->current = priv->contained;
538
539 it->iterator.next = FUNC_ITERATOR_NEXT(_efl_canvas_group_group_iterator_next);
540 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_efl_canvas_group_group_iterator_get_container);
541 it->iterator.free = FUNC_ITERATOR_FREE(_efl_canvas_group_group_iterator_free);
542
543 return &it->iterator;
544 }
545
546 EOLIAN static Eina_Bool
_efl_canvas_group_group_member_is(const Eo * eo_obj,Evas_Smart_Data * pd EINA_UNUSED,const Eo * sub_obj)547 _efl_canvas_group_group_member_is(const Eo *eo_obj, Evas_Smart_Data *pd EINA_UNUSED, const Eo *sub_obj)
548 {
549 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
550 Evas_Object_Protected_Data *sub = efl_data_scope_safe_get(sub_obj, EFL_CANVAS_OBJECT_CLASS);
551
552 evas_object_async_block(obj);
553
554 if (!sub) return EINA_FALSE;
555 return (sub->smart.parent == eo_obj);
556 }
557
558 EAPI Eina_List*
evas_object_smart_members_get(const Evas_Object * eo_obj)559 evas_object_smart_members_get(const Evas_Object *eo_obj)
560 {
561 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, NULL);
562 Eina_List *members = NULL;
563 Eina_Inlist *member;
564
565 for (member = o->contained; member; member = member->next)
566 members = eina_list_append(members, ((Evas_Object_Protected_Data *)member)->object);
567
568 return members;
569 }
570
571 void
evas_object_smart_render_cache_clear(Evas_Object * eo_obj)572 evas_object_smart_render_cache_clear(Evas_Object *eo_obj)
573 {
574 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
575 if (!o) return;
576 if (!o->render_cache) return;
577 evas_render_object_render_cache_free(eo_obj, o->render_cache);
578 o->render_cache = NULL;
579 }
580
581 void *
evas_object_smart_render_cache_get(const Evas_Object * eo_obj)582 evas_object_smart_render_cache_get(const Evas_Object *eo_obj)
583 {
584 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
585 if (!o) return NULL;
586 return o->render_cache;
587 }
588
589 void
evas_object_smart_render_cache_set(Evas_Object * eo_obj,void * data)590 evas_object_smart_render_cache_set(Evas_Object *eo_obj, void *data)
591 {
592 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
593 if (!o) return;
594 o->render_cache = data;
595 }
596
597 const Eina_Inlist *
evas_object_smart_members_get_direct(const Evas_Object * eo_obj)598 evas_object_smart_members_get_direct(const Evas_Object *eo_obj)
599 {
600 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
601 if (!o) return NULL;
602 return o->contained;
603 }
604
605 static void
_efl_canvas_group_group_members_all_del_internal(Evas_Smart_Data * o)606 _efl_canvas_group_group_members_all_del_internal(Evas_Smart_Data *o)
607 {
608 Evas_Object *clipper;
609 Evas_Object_Protected_Data *memobj;
610 Eina_Inlist *itrn;
611
612 clipper = _smart_clipper_get(o);
613 if (clipper)
614 {
615 EINA_INLIST_FOREACH_SAFE(o->contained, itrn, memobj)
616 {
617 if (memobj->object != clipper)
618 _evas_wrap_del(&memobj->object, memobj);
619 }
620 _evas_wrap_del(&clipper, efl_data_scope_get(clipper, EFL_CANVAS_OBJECT_CLASS));
621 }
622
623 o->group_del_called = EINA_TRUE;
624 }
625
626 void
_efl_canvas_group_group_members_all_del(Evas_Object * eo_obj)627 _efl_canvas_group_group_members_all_del(Evas_Object *eo_obj)
628 {
629 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
630 _efl_canvas_group_group_members_all_del_internal(o);
631 }
632
633 static void
_evas_smart_class_ifaces_private_data_alloc(Evas_Object * eo_obj,Evas_Smart * s)634 _evas_smart_class_ifaces_private_data_alloc(Evas_Object *eo_obj,
635 Evas_Smart *s)
636 {
637 Evas_Smart_Data *obj;
638 const Evas_Smart_Class *sc;
639 unsigned char *ptr;
640 unsigned int i, total_priv_sz = 0;
641
642 /* get total size of interfaces private data */
643 for (sc = s->smart_class; sc; sc = sc->parent)
644 {
645 const Evas_Smart_Interface **ifaces_array = sc->interfaces;
646 if (!ifaces_array) continue;
647
648 while (*ifaces_array)
649 {
650 const Evas_Smart_Interface *iface = *ifaces_array;
651
652 if (!iface->name) break;
653
654 if (iface->private_size > 0)
655 {
656 unsigned int size = iface->private_size;
657
658 if (size % sizeof(void *) != 0)
659 size += sizeof(void *) - (size % sizeof(void *));
660 total_priv_sz += size;
661 }
662
663 ifaces_array++;
664 }
665 }
666
667 if (!s->interfaces.size && !total_priv_sz) return;
668
669 obj = efl_data_scope_get(eo_obj, MY_CLASS);
670 obj->interface_privates = malloc(s->interfaces.size * sizeof(void *) + total_priv_sz);
671 if (!obj->interface_privates)
672 {
673 ERR("malloc failed!");
674 return;
675 }
676
677 /* make private data array ptrs point to right places, WHICH LIE ON
678 * THE SAME STRUCT, AFTER THE # OF INTERFACES COUNT */
679 ptr = (unsigned char *)(obj->interface_privates + s->interfaces.size);
680 for (i = 0; i < s->interfaces.size; i++)
681 {
682 unsigned int size;
683
684 size = s->interfaces.array[i]->private_size;
685
686 if (size == 0)
687 {
688 obj->interface_privates[i] = NULL;
689 continue;
690 }
691
692 obj->interface_privates[i] = ptr;
693 memset(ptr, 0, size);
694
695 if (size % sizeof(void *) != 0)
696 size += sizeof(void *) - (size % sizeof(void *));
697 ptr += size;
698 }
699 }
700
701 EAPI Evas_Object *
evas_object_smart_add(Evas * eo_e,Evas_Smart * s)702 evas_object_smart_add(Evas *eo_e, Evas_Smart *s)
703 {
704 Evas_Object *eo_obj;
705
706 eo_e = evas_find(eo_e);
707 EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(eo_e, EVAS_CANVAS_CLASS), NULL);
708 eo_obj = efl_add(MY_CLASS, eo_e, efl_canvas_object_legacy_ctor(efl_added));
709 evas_object_smart_attach(eo_obj, s);
710 return eo_obj;
711 }
712
713 EOLIAN static Eo *
_efl_canvas_group_efl_object_constructor(Eo * eo_obj,Evas_Smart_Data * sd)714 _efl_canvas_group_efl_object_constructor(Eo *eo_obj, Evas_Smart_Data *sd)
715 {
716 Evas_Object_Protected_Data *obj;
717
718 sd->object = eo_obj;
719 sd->inherit_paragraph_direction = EINA_TRUE;
720
721 eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS));
722 EINA_SAFETY_ON_NULL_RETURN_VAL(eo_obj, NULL);
723
724 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
725 obj->is_smart = EINA_TRUE;
726 obj->func = &object_func;
727 obj->private_data = efl_data_ref(eo_obj, MY_CLASS);
728 if (sd->clipped && !sd->data)
729 _evas_object_smart_clipped_init(eo_obj);
730
731 efl_canvas_object_type_set(eo_obj, MY_CLASS_NAME_LEGACY);
732 efl_canvas_group_add(eo_obj);
733
734 sd->constructed = EINA_TRUE;
735 return eo_obj;
736 }
737
738 EOLIAN static void
_efl_canvas_group_efl_object_destructor(Eo * eo_obj,Evas_Smart_Data * o)739 _efl_canvas_group_efl_object_destructor(Eo *eo_obj, Evas_Smart_Data *o)
740 {
741 efl_destructor(efl_super(eo_obj, MY_CLASS));
742 if (o->data && !o->data_nofree)
743 free(o->data);
744 if (!o->group_del_called)
745 {
746 ERR("efl_canvas_group_del() was not called on this object: %p (%s)",
747 eo_obj, efl_class_name_get(eo_obj));
748 }
749 }
750
751 EOLIAN static void
_efl_canvas_group_efl_object_debug_name_override(Eo * eo_obj,Evas_Smart_Data * o,Eina_Strbuf * sb)752 _efl_canvas_group_efl_object_debug_name_override(Eo *eo_obj, Evas_Smart_Data *o, Eina_Strbuf *sb)
753 {
754 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
755 const char *smart_class = NULL;
756
757 if (obj->smart.smart && obj->smart.smart->smart_class)
758 smart_class = obj->smart.smart->smart_class->name;
759
760 efl_debug_name_override(efl_super(eo_obj, MY_CLASS), sb);
761 if (smart_class)
762 {
763 eina_strbuf_append_printf(sb, ":children=%d:smart_class=%s",
764 eina_inlist_count(o->contained), smart_class);
765 }
766 else
767 {
768 eina_strbuf_append_printf(sb, ":children=%d", eina_inlist_count(o->contained));
769 }
770 }
771
772 static inline void
_evas_object_smart_move_relative_internal(Evas_Smart_Data * o,Evas_Coord dx,Evas_Coord dy)773 _evas_object_smart_move_relative_internal(Evas_Smart_Data *o, Evas_Coord dx, Evas_Coord dy)
774 {
775 Evas_Object_Protected_Data *child;
776
777 EINA_INLIST_FOREACH(o->contained, child)
778 {
779 Evas_Coord orig_x, orig_y;
780
781 if (child->delete_me) continue;
782 if (child->is_static_clip) continue;
783 orig_x = child->cur->geometry.x;
784 orig_y = child->cur->geometry.y;
785 evas_object_move(child->object, orig_x + dx, orig_y + dy);
786 }
787 }
788
789 EAPI void
evas_object_smart_move_children_relative(Eo * eo_obj,Evas_Coord dx,Evas_Coord dy)790 evas_object_smart_move_children_relative(Eo *eo_obj, Evas_Coord dx, Evas_Coord dy)
791 {
792 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj);
793
794 if ((dx == 0) && (dy == 0)) return;
795 _evas_object_smart_move_relative_internal(o, dx, dy);
796 }
797
798 void
_evas_object_smart_clipped_smart_move_internal(Evas_Object * eo_obj,Evas_Coord x,Evas_Coord y)799 _evas_object_smart_clipped_smart_move_internal(Evas_Object *eo_obj, Evas_Coord x, Evas_Coord y)
800 {
801 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
802 Evas_Coord orig_x, orig_y;
803
804 orig_x = o->x;
805 orig_y = o->y;
806 o->x = x;
807 o->y = y;
808 _evas_object_smart_move_relative_internal(o, x - orig_x, y - orig_y);
809 }
810
811 void
_evas_object_smart_clipped_init(Evas_Object * eo_obj)812 _evas_object_smart_clipped_init(Evas_Object *eo_obj)
813 {
814 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj);
815 Evas_Object_Smart_Clipped_Data *cso;
816 Evas_Object *clipper;
817
818 // user may realloc this... (legacy only!)
819 cso = o->data;
820 if (!cso)
821 {
822 cso = calloc(1, sizeof(*cso));
823 o->data = cso;
824 o->data_nofree = EINA_FALSE;
825 }
826
827 cso->evas = evas_object_evas_get(eo_obj);
828 clipper = evas_object_rectangle_add(cso->evas);
829 evas_object_static_clip_set(clipper, 1);
830 cso->clipper = clipper;
831 o->clipped = 0;
832 evas_object_smart_member_add(clipper, eo_obj);
833 o->clipped = 1;
834 evas_object_color_set(cso->clipper, 255, 255, 255, 255);
835 evas_object_move(cso->clipper, -100000, -100000);
836 evas_object_resize(cso->clipper, 200000, 200000);
837 evas_object_pass_events_set(cso->clipper, 1);
838 evas_object_hide(cso->clipper); /* show when have something clipped to it */
839 efl_canvas_object_no_render_set(cso->clipper, 1);
840 }
841
842 EOLIAN static void
_efl_canvas_group_group_add(Eo * eo_obj EINA_UNUSED,Evas_Smart_Data * o EINA_UNUSED)843 _efl_canvas_group_group_add(Eo *eo_obj EINA_UNUSED, Evas_Smart_Data *o EINA_UNUSED)
844 {
845 }
846
847 EOLIAN static void
_efl_canvas_group_group_del(Eo * eo_obj EINA_UNUSED,Evas_Smart_Data * o)848 _efl_canvas_group_group_del(Eo *eo_obj EINA_UNUSED, Evas_Smart_Data *o)
849 {
850 if (o->clipped)
851 {
852 _efl_canvas_group_group_members_all_del_internal(o);
853 }
854 o->group_del_called = EINA_TRUE;
855 }
856
857 EOLIAN static void
_efl_canvas_group_efl_canvas_object_no_render_set(Eo * eo_obj,Evas_Smart_Data * o,Eina_Bool enable)858 _efl_canvas_group_efl_canvas_object_no_render_set(Eo *eo_obj, Evas_Smart_Data *o, Eina_Bool enable)
859 {
860 Evas_Object_Protected_Data *obj2;
861 Eo *clipper;
862
863 enable = !!enable;
864 if (efl_canvas_object_no_render_get(eo_obj) == enable) return;
865
866 efl_canvas_object_no_render_set(efl_super(eo_obj, MY_CLASS), enable);
867
868 clipper = (o->clipped) ? _smart_clipper_get(o) : NULL;
869 EINA_INLIST_FOREACH(o->contained, obj2)
870 {
871 if (obj2->object != clipper)
872 efl_canvas_object_no_render_set(obj2->object, enable);
873 }
874 }
875
876 EOLIAN static void
_efl_canvas_group_efl_gfx_color_color_set(Eo * eo_obj,Evas_Smart_Data * o,int r,int g,int b,int a)877 _efl_canvas_group_efl_gfx_color_color_set(Eo *eo_obj, Evas_Smart_Data *o, int r, int g, int b, int a)
878 {
879 if (_evas_object_intercept_call(eo_obj, EVAS_OBJECT_INTERCEPT_CB_COLOR_SET, 0, r, g, b, a))
880 return;
881
882 efl_gfx_color_set(efl_super(eo_obj, MY_CLASS), r, g, b, a);
883
884 if (o->clipped)
885 {
886 Evas_Object *clipper = _smart_clipper_get(o);
887 EINA_SAFETY_ON_NULL_RETURN(clipper);
888
889 efl_gfx_color_set(clipper, r, g, b, a);
890 // Note: Legacy impl (and Widget) didn't call super in this case...
891 }
892 }
893
894 EOLIAN static void
_efl_canvas_group_efl_gfx_entity_visible_set(Eo * eo_obj,Evas_Smart_Data * o,Eina_Bool vis)895 _efl_canvas_group_efl_gfx_entity_visible_set(Eo *eo_obj, Evas_Smart_Data *o, Eina_Bool vis)
896 {
897 if (_evas_object_intercept_call(eo_obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
898 return;
899
900 efl_gfx_entity_visible_set(efl_super(eo_obj, MY_CLASS), vis);
901
902 if (o->clipped)
903 {
904 Evas_Object *clipper = _smart_clipper_get(o);
905 EINA_SAFETY_ON_NULL_RETURN(clipper);
906
907 // note: maybe this is not necessary with no_render set on the clipper
908 if (vis && !evas_object_clipees_has(clipper))
909 return;
910
911 efl_gfx_entity_visible_set(clipper, vis);
912 }
913
914 if (o->filter_img)
915 efl_gfx_entity_visible_set(o->filter_img, vis);
916 }
917
918 EOLIAN static void
_efl_canvas_group_efl_gfx_entity_position_set(Eo * eo_obj,Evas_Smart_Data * o,Eina_Position2D pos)919 _efl_canvas_group_efl_gfx_entity_position_set(Eo *eo_obj, Evas_Smart_Data *o, Eina_Position2D pos)
920 {
921 Eina_Bool is_overridden;
922 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
923
924 if (_evas_object_intercept_call(eo_obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
925 return;
926
927 is_overridden = (obj->is_smart && obj->smart.smart &&
928 obj->smart.smart->smart_class->move !=
929 (void *)evas_object_smart_clipped_smart_move);
930
931 if (o->clipped && !is_overridden)
932 _evas_object_smart_clipped_smart_move_internal(eo_obj, pos.x, pos.y);
933 efl_gfx_entity_position_set(efl_super(eo_obj, MY_CLASS), pos);
934 if (o->filter_img) efl_gfx_entity_position_set(o->filter_img, pos);
935 }
936
937 EOLIAN static void
_efl_canvas_group_efl_gfx_entity_size_set(Eo * obj,Evas_Smart_Data * o,Eina_Size2D size)938 _efl_canvas_group_efl_gfx_entity_size_set(Eo *obj, Evas_Smart_Data *o, Eina_Size2D size)
939 {
940 if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, size.w, size.h))
941 return;
942
943 efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), size);
944 if (o->filter_img) efl_gfx_entity_size_set(o->filter_img, size);
945 }
946
947 EOLIAN static void
_efl_canvas_group_efl_gfx_filter_filter_program_set(Eo * eo_obj,Evas_Smart_Data * o,const char * code,const char * name)948 _efl_canvas_group_efl_gfx_filter_filter_program_set(Eo *eo_obj, Evas_Smart_Data *o,
949 const char *code, const char *name)
950 {
951 Evas_Object_Protected_Data *obj, *fobj;
952 obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
953
954 if (!code && !name)
955 {
956 if (o->filter_img)
957 {
958 evas_object_del(o->filter_img);
959 o->filter_img = NULL;
960 }
961 return;
962 }
963
964 if (o->filter_img)
965 {
966 efl_gfx_filter_program_set(o->filter_img, code, name);
967 return;
968 }
969
970 o->filter_img = efl_add(EFL_CANVAS_PROXY_CLASS, eo_obj,
971 efl_gfx_fill_auto_set(efl_added, EINA_TRUE),
972 efl_canvas_group_member_add(obj->object, efl_added),
973 efl_canvas_proxy_source_events_set(efl_added, EINA_TRUE),
974 efl_canvas_proxy_source_set(efl_added, eo_obj),
975 evas_object_repeat_events_set(efl_added, EINA_TRUE),
976 efl_gfx_filter_program_set(efl_added, code, name),
977 efl_gfx_entity_geometry_set(efl_added, (Eina_Rect)obj->cur->geometry),
978 efl_gfx_entity_visible_set(efl_added, obj->cur->visible));
979
980 fobj = efl_data_scope_get(o->filter_img, EFL_CANVAS_OBJECT_CLASS);
981 if (!fobj) return;
982 fobj->is_filter_object = EINA_TRUE;
983 }
984
985 EOLIAN static void
_efl_canvas_group_efl_canvas_object_clipper_set(Eo * eo_obj,Evas_Smart_Data * o,Evas_Object * clip)986 _efl_canvas_group_efl_canvas_object_clipper_set(Eo *eo_obj, Evas_Smart_Data *o, Evas_Object *clip)
987 {
988 EINA_SAFETY_ON_FALSE_RETURN(!clip || efl_isa(clip, EFL_CANVAS_OBJECT_CLASS));
989 if (_evas_object_intercept_call(eo_obj, EVAS_OBJECT_INTERCEPT_CB_CLIP_SET, 0, clip))
990 return;
991
992 efl_canvas_object_clipper_set(efl_super(eo_obj, MY_CLASS), clip);
993
994 if (o->clipped)
995 {
996 Evas_Object *clipper = _smart_clipper_get(o);
997 EINA_SAFETY_ON_NULL_RETURN(clipper);
998
999 efl_canvas_object_clipper_set(clipper, clip);
1000 }
1001 }
1002
1003 void
evas_object_smart_attach(Evas_Object * eo_obj,Evas_Smart * s)1004 evas_object_smart_attach(Evas_Object *eo_obj, Evas_Smart *s)
1005 {
1006 Evas_Object_Protected_Data *obj = EVAS_OBJ_GET_OR_RETURN(eo_obj);
1007 unsigned int i;
1008
1009 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
1010 return;
1011 MAGIC_CHECK_END();
1012
1013 obj->smart.smart = s;
1014 obj->type = s->smart_class->name;
1015 evas_object_smart_use(s);
1016
1017 _evas_smart_class_ifaces_private_data_alloc(eo_obj, s);
1018
1019 for (i = 0; i < s->interfaces.size; i++)
1020 {
1021 const Evas_Smart_Interface *iface;
1022
1023 iface = s->interfaces.array[i];
1024 if (iface->add)
1025 {
1026 if (!iface->add(eo_obj))
1027 {
1028 ERR("failed to create interface %s\n", iface->name);
1029 evas_object_del(eo_obj);
1030 return;
1031 }
1032 }
1033 }
1034
1035 //efl_canvas_group_add(eo_obj);
1036 if (s->smart_class->add) s->smart_class->add(eo_obj);
1037 }
1038
1039 EAPI void
evas_object_smart_callback_add(Evas_Object * eo_obj,const char * event,Evas_Smart_Cb func,const void * data)1040 evas_object_smart_callback_add(Evas_Object *eo_obj, const char *event, Evas_Smart_Cb func, const void *data)
1041 {
1042 evas_object_smart_callback_priority_add(eo_obj, event,
1043 EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
1044 }
1045
1046 static void
_smart_cb_check(Evas_Smart_Data * o,const char * event)1047 _smart_cb_check(Evas_Smart_Data *o, const char *event)
1048 {
1049 if (!o->cb_move)
1050 {
1051 if (eina_streq(event, "move"))
1052 {
1053 o->cb_move = EINA_TRUE;
1054 return;
1055 }
1056 }
1057 if (!o->cb_resize)
1058 {
1059 if (eina_streq(event, "resize"))
1060 {
1061 o->cb_resize = EINA_TRUE;
1062 return;
1063 }
1064 }
1065 if (!o->cb_restack)
1066 {
1067 if (eina_streq(event, "restack"))
1068 {
1069 o->cb_restack = EINA_TRUE;
1070 return;
1071 }
1072 }
1073 }
1074
1075 EAPI void
evas_object_smart_callback_priority_add(Evas_Object * eo_obj,const char * event,Evas_Callback_Priority priority,Evas_Smart_Cb func,const void * data)1076 evas_object_smart_callback_priority_add(Evas_Object *eo_obj, const char *event, Evas_Callback_Priority priority, Evas_Smart_Cb func, const void *data)
1077 {
1078 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj);
1079
1080 if (!event) return;
1081 if (!func) return;
1082
1083 const Efl_Event_Description *eo_desc = efl_object_legacy_only_event_description_get(event);
1084 _eo_evas_smart_cb_info *cb_info = calloc(1, sizeof(*cb_info));
1085 cb_info->func = func;
1086 cb_info->data = (void *)data;
1087 cb_info->event = eo_desc;
1088 _smart_cb_check(o, event);
1089
1090 o->callbacks = eina_inlist_append(o->callbacks,
1091 EINA_INLIST_GET(cb_info));
1092
1093 efl_event_callback_priority_add(eo_obj, eo_desc, priority, _eo_evas_smart_cb, cb_info);
1094 }
1095
1096 EAPI void *
evas_object_smart_callback_del(Evas_Object * eo_obj,const char * event,Evas_Smart_Cb func)1097 evas_object_smart_callback_del(Evas_Object *eo_obj, const char *event, Evas_Smart_Cb func)
1098 {
1099 _eo_evas_smart_cb_info *info;
1100
1101 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, NULL);
1102
1103 if (!event) return NULL;
1104
1105 const Efl_Event_Description *eo_desc = efl_object_legacy_only_event_description_get(event);
1106
1107 EINA_INLIST_FOREACH(o->callbacks, info)
1108 {
1109 if ((info->func == func) && (info->event == eo_desc))
1110 {
1111 void *tmp = info->data;
1112 efl_event_callback_del(eo_obj, eo_desc, _eo_evas_smart_cb, info);
1113
1114 o->callbacks =
1115 eina_inlist_remove(o->callbacks, EINA_INLIST_GET(info));
1116 free(info);
1117 return tmp;
1118 }
1119 }
1120 return NULL;
1121 }
1122
1123 EAPI void *
evas_object_smart_callback_del_full(Evas_Object * eo_obj,const char * event,Evas_Smart_Cb func,const void * data)1124 evas_object_smart_callback_del_full(Evas_Object *eo_obj, const char *event, Evas_Smart_Cb func, const void *data)
1125 {
1126 _eo_evas_smart_cb_info *info;
1127
1128 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, NULL);
1129
1130 if (!event) return NULL;
1131
1132 const Efl_Event_Description *eo_desc = efl_object_legacy_only_event_description_get(event);
1133
1134 EINA_INLIST_FOREACH(o->callbacks, info)
1135 {
1136 if ((info->func == func) && (info->event == eo_desc) && (info->data == data))
1137 {
1138 void *tmp = info->data;
1139 efl_event_callback_del(eo_obj, eo_desc, _eo_evas_smart_cb, info);
1140
1141 o->callbacks =
1142 eina_inlist_remove(o->callbacks, EINA_INLIST_GET(info));
1143 free(info);
1144 return tmp;
1145 }
1146 }
1147 return NULL;
1148 }
1149
1150 EAPI void
evas_object_smart_callback_call(Evas_Object * eo_obj,const char * event,void * event_info)1151 evas_object_smart_callback_call(Evas_Object *eo_obj, const char *event, void *event_info)
1152 {
1153 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
1154 return;
1155 MAGIC_CHECK_END();
1156
1157 if (!event) return;
1158 const Efl_Event_Description *eo_desc = efl_object_legacy_only_event_description_get(event);
1159 efl_event_callback_legacy_call(eo_obj, eo_desc, event_info);
1160 }
1161
1162 void
_evas_object_smart_callback_call_internal(Evas_Object * eo_obj,const Efl_Event_Description * efl_event_desc)1163 _evas_object_smart_callback_call_internal(Evas_Object *eo_obj, const Efl_Event_Description *efl_event_desc)
1164 {
1165 const char *event = NULL;
1166 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj);
1167
1168 if (efl_event_desc == EFL_GFX_ENTITY_EVENT_POSITION_CHANGED)
1169 {
1170 if (!o->cb_move) return;
1171 event = "move";
1172 }
1173 else if (efl_event_desc == EFL_GFX_ENTITY_EVENT_SIZE_CHANGED)
1174 {
1175 if (!o->cb_resize) return;
1176 event = "resize";
1177 }
1178 else if (efl_event_desc == EFL_GFX_ENTITY_EVENT_STACKING_CHANGED)
1179 {
1180 if (!o->cb_restack) return;
1181 event = "restack";
1182 }
1183 else //invalidate
1184 return;
1185 const Efl_Event_Description *eo_desc = efl_object_legacy_only_event_description_get(event);
1186 efl_event_callback_legacy_call(eo_obj, eo_desc, NULL);
1187 }
1188
1189 EAPI Eina_Bool
evas_object_smart_callbacks_descriptions_set(Eo * eo_obj,const Evas_Smart_Cb_Description * descriptions)1190 evas_object_smart_callbacks_descriptions_set(Eo *eo_obj, const Evas_Smart_Cb_Description *descriptions)
1191 {
1192 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj, EINA_FALSE);
1193 const Evas_Smart_Cb_Description *d;
1194 unsigned int i, count = 0;
1195
1196 if ((!descriptions) || (!descriptions->name))
1197 {
1198 evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
1199 return EINA_TRUE;
1200 }
1201
1202 for (count = 0, d = descriptions; d->name; d++)
1203 count++;
1204
1205 evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, count);
1206 if (count == 0) return EINA_TRUE;
1207
1208 for (i = 0, d = descriptions; i < count; d++, i++)
1209 o->callbacks_descriptions.array[i] = d;
1210
1211 evas_smart_cb_descriptions_fix(&o->callbacks_descriptions);
1212
1213 return EINA_TRUE;
1214 }
1215
1216 EAPI void
evas_object_smart_callbacks_descriptions_get(const Eo * eo_obj,const Evas_Smart_Cb_Description *** class_descriptions,unsigned int * class_count,const Evas_Smart_Cb_Description *** instance_descriptions,unsigned int * instance_count)1217 evas_object_smart_callbacks_descriptions_get(const Eo *eo_obj, const Evas_Smart_Cb_Description ***class_descriptions, unsigned int *class_count, const Evas_Smart_Cb_Description ***instance_descriptions, unsigned int *instance_count)
1218 {
1219 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj);
1220 if (class_descriptions) *class_descriptions = NULL;
1221 if (class_count) *class_count = 0;
1222
1223 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1224 if (obj->smart.smart && class_descriptions)
1225 *class_descriptions = obj->smart.smart->callbacks.array;
1226 if (obj->smart.smart && class_count)
1227 *class_count = obj->smart.smart->callbacks.size;
1228
1229 if (instance_descriptions)
1230 *instance_descriptions = o->callbacks_descriptions.array;
1231 if (instance_count)
1232 *instance_count = o->callbacks_descriptions.size;
1233 }
1234
1235 EAPI void
evas_object_smart_callback_description_find(const Eo * eo_obj,const char * name,const Evas_Smart_Cb_Description ** class_description,const Evas_Smart_Cb_Description ** instance_description)1236 evas_object_smart_callback_description_find(const Eo *eo_obj, const char *name, const Evas_Smart_Cb_Description **class_description, const Evas_Smart_Cb_Description **instance_description)
1237 {
1238 EVAS_OBJECT_SMART_GET_OR_RETURN(eo_obj);
1239
1240 if (!name)
1241 {
1242 if (class_description) *class_description = NULL;
1243 if (instance_description) *instance_description = NULL;
1244 return;
1245 }
1246
1247 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1248 if (class_description)
1249 *class_description = evas_smart_cb_description_find
1250 (&obj->smart.smart->callbacks, name);
1251
1252 if (instance_description)
1253 *instance_description = evas_smart_cb_description_find
1254 (&o->callbacks_descriptions, name);
1255 }
1256
1257 EOLIAN static void
_efl_canvas_group_group_need_recalculate_set(Eo * eo_obj,Evas_Smart_Data * o,Eina_Bool value)1258 _efl_canvas_group_group_need_recalculate_set(Eo *eo_obj, Evas_Smart_Data *o, Eina_Bool value)
1259 {
1260 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1261
1262 // XXX: do i need this?
1263 if (!obj || !obj->layer || obj->delete_me) return;
1264
1265 evas_object_async_block(obj);
1266 /* remove this entry from calc_list or processed list */
1267 if (eina_clist_element_is_linked(&o->calc_entry))
1268 eina_clist_remove(&o->calc_entry);
1269
1270 value = !!value;
1271 if (value)
1272 eina_clist_add_tail(&obj->layer->evas->calc_list, &o->calc_entry);
1273 else
1274 eina_clist_add_tail(&obj->layer->evas->calc_done, &o->calc_entry);
1275
1276 if (o->need_recalculate == value) return;
1277
1278 if (o->recalculate_cycle > 16382)
1279 {
1280 ERR("Object %p is not stable during recalc loop", eo_obj);
1281 return;
1282 }
1283 if (obj->layer->evas->in_smart_calc) o->recalculate_cycle++;
1284 o->need_recalculate = value;
1285 }
1286
1287 EOLIAN static Eina_Bool
_efl_canvas_group_group_need_recalculate_get(const Eo * eo_obj EINA_UNUSED,Evas_Smart_Data * o)1288 _efl_canvas_group_group_need_recalculate_get(const Eo *eo_obj EINA_UNUSED, Evas_Smart_Data *o)
1289 {
1290 return o->need_recalculate;
1291 }
1292
1293 EOLIAN static void
_efl_canvas_group_group_calculate(Eo * eo_obj,Evas_Smart_Data * o)1294 _efl_canvas_group_group_calculate(Eo *eo_obj, Evas_Smart_Data *o)
1295 {
1296 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1297
1298 if (!obj->smart.smart || !obj->smart.smart->smart_class->calculate)
1299 return;
1300
1301 evas_object_async_block(obj);
1302 o->need_recalculate = 0;
1303 obj->smart.smart->smart_class->calculate(eo_obj);
1304 }
1305
1306 /**
1307 * Call calculate() on all smart objects that need_recalculate.
1308 *
1309 * @internal
1310 */
1311 void
evas_call_smarts_calculate(Evas * eo_e)1312 evas_call_smarts_calculate(Evas *eo_e)
1313 {
1314 Evas_Smart_Data *o;
1315 Eina_Clist *elem;
1316 Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
1317
1318 evas_canvas_async_block(e);
1319 evas_event_freeze(eo_e);
1320 e->in_smart_calc++;
1321
1322 while (NULL != (elem = eina_clist_head(&e->calc_list)))
1323 {
1324 Evas_Object_Protected_Data *obj;
1325
1326 /* move the item to the processed list */
1327 o = EINA_CLIST_ENTRY(elem, Evas_Smart_Data, calc_entry);
1328 eina_clist_remove(&o->calc_entry);
1329 obj = efl_data_scope_get(o->object, EFL_CANVAS_OBJECT_CLASS);
1330
1331 if (obj->delete_me) continue;
1332 eina_clist_add_tail(&e->calc_done, &o->calc_entry);
1333
1334 if (o->need_recalculate)
1335 {
1336 o->need_recalculate = 0;
1337 if (obj->smart.smart && obj->smart.smart->smart_class->calculate)
1338 obj->smart.smart->smart_class->calculate(obj->object);
1339 else
1340 efl_canvas_group_calculate(obj->object);
1341 }
1342 }
1343
1344 while (NULL != (elem = eina_clist_head(&e->calc_done)))
1345 {
1346 o = EINA_CLIST_ENTRY(elem, Evas_Smart_Data, calc_entry);
1347 o->recalculate_cycle = 0;
1348 eina_clist_remove(&o->calc_entry);
1349 }
1350
1351 e->in_smart_calc--;
1352 if (e->in_smart_calc == 0) e->smart_calc_count++;
1353 evas_event_thaw(eo_e);
1354 evas_event_thaw_eval(eo_e);
1355 }
1356
1357 EOLIAN static void
_efl_canvas_group_group_change(Eo * eo_obj,Evas_Smart_Data * o EINA_UNUSED)1358 _efl_canvas_group_group_change(Eo *eo_obj, Evas_Smart_Data *o EINA_UNUSED)
1359 {
1360 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1361 evas_object_async_block(obj);
1362 evas_object_change(eo_obj, obj);
1363 efl_canvas_group_need_recalculate_set(eo_obj, 1);
1364 }
1365
1366 Eina_Bool
evas_object_smart_changed_get(Evas_Object_Protected_Data * obj)1367 evas_object_smart_changed_get(Evas_Object_Protected_Data *obj)
1368 {
1369 Eina_Bool has_map = EINA_FALSE;
1370
1371 /* If object is invisible, it's meaningless to figure out changed state
1372 for rendering. */
1373
1374 //a. Object itself visibility
1375 if (obj->no_render || (!obj->prev->visible && !obj->cur->visible) ||
1376 ((obj->prev->color.a == 0) && (obj->cur->color.a == 0)))
1377 return EINA_FALSE;
1378
1379 //b. Object clipper visibility
1380 if ((obj->prev->clipper && obj->cur->clipper) &&
1381 ((!obj->prev->clipper->cur->visible &&
1382 !obj->cur->clipper->cur->visible) ||
1383 ((obj->prev->clipper->cur->color.a == 0) &&
1384 (obj->cur->clipper->cur->color.a == 0))))
1385 return EINA_FALSE;
1386
1387 if (!obj->clip.clipees)
1388 {
1389 has_map = _evas_render_has_map(obj) && !_evas_render_can_map(obj);
1390 if (obj->changed && !obj->is_smart && !has_map) return EINA_TRUE;
1391
1392 if (has_map)
1393 {
1394 if ((obj->need_surface_clear && obj->changed && !obj->is_smart) ||
1395 ((obj->changed_pchange) && (obj->changed_map)))
1396 return EINA_TRUE;
1397 }
1398 }
1399
1400 if (obj->is_smart)
1401 {
1402 Evas_Object_Protected_Data *o2;
1403
1404 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj->object), o2)
1405 if (evas_object_smart_changed_get(o2)) return EINA_TRUE;
1406 }
1407
1408 return EINA_FALSE;
1409 }
1410
1411 void
evas_object_smart_del(Evas_Object * eo_obj)1412 evas_object_smart_del(Evas_Object *eo_obj)
1413 {
1414 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1415 Evas_Smart_Data *sobj;
1416 Evas_Smart *s;
1417 unsigned int i;
1418
1419 if (obj->delete_me) return;
1420
1421 sobj = efl_data_scope_get(eo_obj, MY_CLASS);
1422 s = obj->smart.smart;
1423 if (s && s->smart_class->del)
1424 {
1425 s->smart_class->del(eo_obj);
1426 //this is legacy, this will never be called..., smart things dont have inheritance
1427 sobj->group_del_called = EINA_TRUE;
1428 }
1429 else
1430 efl_canvas_group_del(eo_obj);
1431 if (obj->smart.parent) evas_object_smart_member_del(eo_obj);
1432
1433 if (s)
1434 {
1435 for (i = 0; i < s->interfaces.size; i++)
1436 {
1437 const Evas_Smart_Interface *iface;
1438
1439 iface = s->interfaces.array[i];
1440 if (iface->del) iface->del(eo_obj);
1441 }
1442 }
1443
1444 free(sobj->interface_privates);
1445 sobj->interface_privates = NULL;
1446
1447 if (s) evas_object_smart_unuse(s);
1448 }
1449
1450 void
evas_object_update_bounding_box(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,Evas_Smart_Data * s)1451 evas_object_update_bounding_box(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, Evas_Smart_Data *s)
1452 {
1453 Eina_Bool propagate = EINA_FALSE;
1454 Eina_Bool computeminmax = EINA_FALSE;
1455 Evas_Coord x, y, w, h;
1456 Evas_Coord px, py, pw, ph;
1457 Eina_Bool noclip;
1458
1459 if (!obj->smart.parent) return;
1460
1461 if (obj->child_has_map) return; /* Disable bounding box computation for this object and its parent */
1462 /* We could also remove object that are not visible from the bounding box, use the clipping information
1463 to reduce the bounding of the object they are clipping, but for the moment this will do it's jobs */
1464 noclip = !(obj->clip.clipees || obj->is_static_clip);
1465
1466 if (obj->is_smart)
1467 {
1468 if (!s) s = obj->private_data;
1469
1470 x = s->cur.bounding_box.x;
1471 y = s->cur.bounding_box.y;
1472 w = s->cur.bounding_box.w;
1473 h = s->cur.bounding_box.h;
1474 px = s->prev.bounding_box.x;
1475 py = s->prev.bounding_box.y;
1476 pw = s->prev.bounding_box.w;
1477 ph = s->prev.bounding_box.h;
1478 }
1479 else
1480 {
1481 x = obj->cur->geometry.x;
1482 y = obj->cur->geometry.y;
1483 w = obj->cur->geometry.w;
1484 h = obj->cur->geometry.h;
1485 px = obj->prev->geometry.x;
1486 py = obj->prev->geometry.y;
1487 pw = obj->prev->geometry.w;
1488 ph = obj->prev->geometry.h;
1489 }
1490
1491 /* We are not yet trying to find the smallest bounding box, but we want to find a good approximation quickly.
1492 * That's why we initialiaze min and max search to geometry of the parent object.
1493 */
1494 Evas_Object_Protected_Data *smart_obj = obj->smart.parent_object_data;
1495 Evas_Smart_Data *smart_parent = obj->smart.parent_data;
1496 if (!smart_parent || !smart_obj) return;
1497
1498 if (smart_obj->cur->valid_bounding_box)
1499 {
1500 /* Update left limit */
1501 if (noclip && x < smart_parent->cur.bounding_box.x)
1502 {
1503 smart_parent->cur.bounding_box.w += smart_parent->cur.bounding_box.x - x;
1504 smart_parent->cur.bounding_box.x = x;
1505
1506 propagate = EINA_TRUE;
1507 }
1508 else if ((px == smart_parent->prev.bounding_box.x &&
1509 x > smart_parent->cur.bounding_box.x)
1510 || (!noclip && x == smart_parent->cur.bounding_box.x))
1511 {
1512 computeminmax = EINA_TRUE;
1513 }
1514
1515 /* Update top limit */
1516 if (noclip && y < smart_parent->cur.bounding_box.y)
1517 {
1518 smart_parent->cur.bounding_box.h += smart_parent->cur.bounding_box.y - y;
1519 smart_parent->cur.bounding_box.y = y;
1520
1521 propagate = EINA_TRUE;
1522 }
1523 else if ((py == smart_parent->prev.bounding_box.y &&
1524 y > smart_parent->cur.bounding_box.y)
1525 || (!noclip && y == smart_parent->cur.bounding_box.y))
1526 {
1527 computeminmax = EINA_TRUE;
1528 }
1529
1530 /* Update right limit */
1531 if (noclip && x + w > smart_parent->cur.bounding_box.x + smart_parent->cur.bounding_box.w)
1532 {
1533 smart_parent->cur.bounding_box.w = x + w - smart_parent->cur.bounding_box.x;
1534 propagate = EINA_TRUE;
1535 }
1536 else if ((px + pw == smart_parent->prev.bounding_box.x + smart_parent->prev.bounding_box.w &&
1537 x + w < smart_parent->cur.bounding_box.x + smart_parent->cur.bounding_box.w)
1538 || (!noclip && x + w == smart_parent->cur.bounding_box.x + smart_parent->cur.bounding_box.w))
1539 {
1540 computeminmax = EINA_TRUE;
1541 }
1542
1543 /* Update bottom limit */
1544 if (noclip && y + h > smart_parent->cur.bounding_box.y + smart_parent->cur.bounding_box.h)
1545 {
1546 smart_parent->cur.bounding_box.h = y + h - smart_parent->cur.bounding_box.y;
1547
1548 propagate = EINA_TRUE;
1549 }
1550 else if ((py + ph == smart_parent->prev.bounding_box.y + smart_parent->prev.bounding_box.h &&
1551 y + h < smart_parent->cur.bounding_box.y + smart_parent->cur.bounding_box.h) ||
1552 (!noclip && y + h == smart_parent->cur.bounding_box.y + smart_parent->cur.bounding_box.h))
1553 {
1554 computeminmax = EINA_TRUE;
1555 }
1556
1557 if (computeminmax)
1558 {
1559 evas_object_smart_need_bounding_box_update(obj->smart.parent_data,
1560 obj->smart.parent_object_data);
1561 }
1562 }
1563 else
1564 {
1565 if (noclip)
1566 {
1567 smart_parent->cur.bounding_box.x = x;
1568 smart_parent->cur.bounding_box.y = y;
1569 smart_parent->cur.bounding_box.w = w;
1570 smart_parent->cur.bounding_box.h = h;
1571
1572 EINA_COW_STATE_WRITE_BEGIN(smart_obj, smart_write, cur)
1573 smart_write->valid_bounding_box = EINA_TRUE;
1574 EINA_COW_STATE_WRITE_END(smart_obj, smart_write, cur);
1575
1576 propagate = EINA_TRUE;
1577 }
1578 }
1579
1580 if (propagate)
1581 evas_object_update_bounding_box(obj->smart.parent, smart_obj, smart_parent);
1582 }
1583
1584 void
evas_object_smart_bounding_box_get(Evas_Object_Protected_Data * obj,Eina_Rectangle * cur_bounding_box,Eina_Rectangle * prev_bounding_box)1585 evas_object_smart_bounding_box_get(Evas_Object_Protected_Data *obj,
1586 Eina_Rectangle *cur_bounding_box,
1587 Eina_Rectangle *prev_bounding_box)
1588 {
1589 Evas_Smart_Data *s = obj->private_data;
1590
1591 if (cur_bounding_box) memcpy(cur_bounding_box,
1592 &s->cur.bounding_box,
1593 sizeof (*cur_bounding_box));
1594 if (prev_bounding_box) memcpy(prev_bounding_box,
1595 &s->prev.bounding_box,
1596 sizeof (*prev_bounding_box));
1597 }
1598
1599 void
evas_object_smart_cleanup(Evas_Object * eo_obj)1600 evas_object_smart_cleanup(Evas_Object *eo_obj)
1601 {
1602 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1603
1604 if (obj->smart.parent)
1605 evas_object_smart_member_del(eo_obj);
1606
1607 if (obj->is_smart)
1608 {
1609 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
1610 if (o->calc_entry.next)
1611 eina_clist_remove(&o->calc_entry);
1612
1613 if (o->render_cache)
1614 {
1615 evas_render_object_render_cache_free(eo_obj, o->render_cache);
1616 o->render_cache = NULL;
1617 }
1618
1619 while (o->contained)
1620 {
1621 Evas_Object_Protected_Data *contained =
1622 (Evas_Object_Protected_Data *)o->contained;
1623 Evas_Object *contained_obj = contained->object;
1624
1625 if (!contained_obj)
1626 {
1627 ERR("Found an undefined object %p in %s.", contained, efl_debug_name_get(eo_obj));
1628 o->contained = eina_inlist_remove
1629 (o->contained, EINA_INLIST_GET(contained));
1630 }
1631 else if (contained->smart.parent != eo_obj)
1632 {
1633 Evas_Layer *lay = obj->layer;
1634
1635 ERR("This is bad - object %p in child list for %p has parent %p", contained_obj, eo_obj, contained->smart.parent);
1636 o->contained = eina_inlist_remove
1637 (o->contained, EINA_INLIST_GET(contained));
1638 if (lay)
1639 {
1640 // this SHOULD be eina_inlist_append() BUT seemingly
1641 // if we call this this object gets magically added
1642 // back to o->contained above NOT lay->objects. this
1643 // is utterly bizarre and the only explanation i
1644 // can come up with right now is a compiler bug.
1645 lay->objects = (Evas_Object_Protected_Data *)
1646 eina_inlist_prepend(EINA_INLIST_GET(lay->objects),
1647 EINA_INLIST_GET(contained));
1648 if (contained->layer != lay)
1649 {
1650 if (contained->layer) contained->layer->usage--;
1651 contained->layer = lay;
1652 contained->in_layer = 1;
1653 lay->usage++;
1654 }
1655 }
1656 }
1657 else evas_object_smart_member_del(contained_obj);
1658 }
1659
1660 while (o->callbacks)
1661 {
1662 _eo_evas_smart_cb_info *info = (_eo_evas_smart_cb_info *)o->callbacks;
1663 efl_event_callback_del(eo_obj, info->event, _eo_evas_smart_cb, info);
1664 o->callbacks = eina_inlist_remove(o->callbacks, EINA_INLIST_GET(info));
1665 free(info);
1666 }
1667
1668 if (o->render_cache)
1669 {
1670 evas_render_object_render_cache_free(eo_obj, o->render_cache);
1671 o->render_cache = NULL;
1672 }
1673
1674 evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
1675 if (o->data) evas_object_smart_data_set(eo_obj, NULL);
1676 }
1677
1678 obj->smart.parent = NULL;
1679 obj->smart.smart = NULL;
1680 }
1681
1682 void
evas_object_smart_member_cache_invalidate(Evas_Object * eo_obj,Eina_Bool pass_events,Eina_Bool freeze_events,Eina_Bool source_invisible)1683 evas_object_smart_member_cache_invalidate(Evas_Object *eo_obj,
1684 Eina_Bool pass_events,
1685 Eina_Bool freeze_events,
1686 Eina_Bool source_invisible)
1687 {
1688 MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
1689 return;
1690 MAGIC_CHECK_END();
1691
1692 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1693 Evas_Object_Protected_Data *member;
1694
1695 if (pass_events)
1696 obj->parent_cache.pass_events_valid = EINA_FALSE;
1697 if (freeze_events)
1698 obj->parent_cache.freeze_events_valid = EINA_FALSE;
1699 if (source_invisible)
1700 obj->parent_cache.src_invisible_valid = EINA_FALSE;
1701
1702 if (!obj->is_smart) return;
1703 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
1704 EINA_INLIST_FOREACH(o->contained, member)
1705 {
1706 Evas_Object *eo_member = member->object;
1707 evas_object_smart_member_cache_invalidate(eo_member, pass_events,
1708 freeze_events,
1709 source_invisible);
1710 }
1711 }
1712
1713 void
evas_object_smart_member_raise(Evas_Object * eo_member)1714 evas_object_smart_member_raise(Evas_Object *eo_member)
1715 {
1716 Evas_Smart_Data *o;
1717 Evas_Object_Protected_Data *member = efl_data_scope_get(eo_member, EFL_CANVAS_OBJECT_CLASS);
1718 o = efl_data_scope_get(member->smart.parent, MY_CLASS);
1719 o->contained = eina_inlist_demote(o->contained, EINA_INLIST_GET(member));
1720 }
1721
1722 void
evas_object_smart_member_lower(Evas_Object * eo_member)1723 evas_object_smart_member_lower(Evas_Object *eo_member)
1724 {
1725 Evas_Smart_Data *o;
1726 Evas_Object_Protected_Data *member = efl_data_scope_get(eo_member, EFL_CANVAS_OBJECT_CLASS);
1727 o = efl_data_scope_get(member->smart.parent, MY_CLASS);
1728 o->contained = eina_inlist_promote(o->contained, EINA_INLIST_GET(member));
1729 }
1730
1731 void
evas_object_smart_member_stack_above(Evas_Object * eo_member,Evas_Object * eo_other)1732 evas_object_smart_member_stack_above(Evas_Object *eo_member, Evas_Object *eo_other)
1733 {
1734 Evas_Smart_Data *o;
1735 Evas_Object_Protected_Data *member = efl_data_scope_get(eo_member, EFL_CANVAS_OBJECT_CLASS);
1736 Evas_Object_Protected_Data *other = efl_data_scope_get(eo_other, EFL_CANVAS_OBJECT_CLASS);
1737 o = efl_data_scope_get(member->smart.parent, MY_CLASS);
1738 o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
1739 o->contained = eina_inlist_append_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
1740 }
1741
1742 void
evas_object_smart_member_stack_below(Evas_Object * eo_member,Evas_Object * eo_other)1743 evas_object_smart_member_stack_below(Evas_Object *eo_member, Evas_Object *eo_other)
1744 {
1745 Evas_Smart_Data *o;
1746 Evas_Object_Protected_Data *member = efl_data_scope_get(eo_member, EFL_CANVAS_OBJECT_CLASS);
1747 Evas_Object_Protected_Data *other = efl_data_scope_get(eo_other, EFL_CANVAS_OBJECT_CLASS);
1748 o = efl_data_scope_get(member->smart.parent, MY_CLASS);
1749 o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
1750 o->contained = eina_inlist_prepend_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
1751 }
1752
1753 void
evas_object_smart_need_bounding_box_update(Evas_Smart_Data * o,Evas_Object_Protected_Data * obj)1754 evas_object_smart_need_bounding_box_update(Evas_Smart_Data *o, Evas_Object_Protected_Data *obj)
1755 {
1756 if (o->update_boundingbox_needed) return;
1757 o->update_boundingbox_needed = EINA_TRUE;
1758 if (!obj->cur->cache.clip.dirty)
1759 {
1760 EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
1761 state_write->cache.clip.dirty = EINA_TRUE;
1762 EINA_COW_STATE_WRITE_END(obj, state_write, cur);
1763 }
1764
1765 if (obj->smart.parent)
1766 evas_object_smart_need_bounding_box_update(obj->smart.parent_data,
1767 obj->smart.parent_object_data);
1768 }
1769
1770 void
evas_object_smart_bounding_box_update(Evas_Object_Protected_Data * obj)1771 evas_object_smart_bounding_box_update(Evas_Object_Protected_Data *obj)
1772 {
1773 Evas_Smart_Data *os;
1774 Eina_Inlist *list;
1775 Evas_Object_Protected_Data *o;
1776 Evas_Coord minx = 0x7fffffff;
1777 Evas_Coord miny = 0x7fffffff;
1778 Evas_Coord maxx = 0x80000000;
1779 Evas_Coord maxy = 0x80000000;
1780 Evas_Coord tx1, ty1, tx2, ty2;
1781 Eina_Bool none = EINA_TRUE;
1782
1783 os = obj->private_data;
1784
1785 if (!os->update_boundingbox_needed) return;
1786 os->update_boundingbox_needed = EINA_FALSE;
1787
1788 list = os->contained;
1789 EINA_INLIST_FOREACH(list, o)
1790 {
1791 if (o == obj) continue ;
1792 if (o->clip.clipees || o->is_static_clip) continue ;
1793 if (!o->cur->visible) continue;
1794
1795 none = EINA_FALSE;
1796
1797 if (o->is_smart)
1798 {
1799 Evas_Smart_Data *s = o->private_data;
1800
1801 evas_object_smart_bounding_box_update(o);
1802
1803 tx1 = s->cur.bounding_box.x;
1804 ty1 = s->cur.bounding_box.y;
1805 tx2 = tx1 + s->cur.bounding_box.w;
1806 ty2 = ty1 + s->cur.bounding_box.h;
1807 }
1808 else
1809 {
1810 tx1 = o->cur->geometry.x;
1811 ty1 = o->cur->geometry.y;
1812 tx2 = tx1 + o->cur->geometry.w;
1813 ty2 = ty1 + o->cur->geometry.h;
1814 }
1815
1816 if (tx1 < minx) minx = tx1;
1817 if (ty1 < miny) miny = ty1;
1818 if (tx2 > maxx) maxx = tx2;
1819 if (ty2 > maxy) maxy = ty2;
1820 }
1821 if (none)
1822 {
1823 minx = obj->cur->geometry.x;
1824 miny = obj->cur->geometry.y;
1825 maxx = obj->cur->geometry.x + obj->cur->geometry.w;
1826 maxy = obj->cur->geometry.y + obj->cur->geometry.h;
1827 }
1828
1829 os->cur.bounding_box.x = minx;
1830 os->cur.bounding_box.y = miny;
1831 os->cur.bounding_box.w = maxx - minx;
1832 os->cur.bounding_box.h = maxy - miny;
1833
1834 EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
1835 {
1836 state_write->cache.clip.dirty = EINA_TRUE;
1837 }
1838 EINA_COW_STATE_WRITE_END(obj, state_write, cur);
1839 evas_object_clip_recalc(obj);
1840 if (obj->cur->clipper) evas_object_clip_recalc(obj->cur->clipper);
1841 }
1842
1843 /* all nice and private */
1844 static void
evas_object_smart_render(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj EINA_UNUSED,void * type_private_data EINA_UNUSED,void * engine EINA_UNUSED,void * output EINA_UNUSED,void * context EINA_UNUSED,void * surface EINA_UNUSED,int x EINA_UNUSED,int y EINA_UNUSED,Eina_Bool do_async EINA_UNUSED)1845 evas_object_smart_render(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj EINA_UNUSED, void *type_private_data EINA_UNUSED, void *engine EINA_UNUSED, void *output EINA_UNUSED, void *context EINA_UNUSED, void *surface EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, Eina_Bool do_async EINA_UNUSED)
1846 {
1847 return;
1848 }
1849
1850 static void
evas_object_smart_render_pre(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,void * type_private_data EINA_UNUSED)1851 evas_object_smart_render_pre(Evas_Object *eo_obj,
1852 Evas_Object_Protected_Data *obj,
1853 void *type_private_data EINA_UNUSED)
1854 {
1855 if (obj->pre_render_done) return;
1856
1857 if (obj->changed_map || obj->changed_src_visible)
1858 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1859 eo_obj, obj);
1860
1861 obj->pre_render_done = EINA_TRUE;
1862 }
1863
1864 static void
evas_object_smart_render_post(Evas_Object * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,void * type_private_data)1865 evas_object_smart_render_post(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, void *type_private_data)
1866 {
1867 Evas_Smart_Data *o = type_private_data;
1868 evas_object_cur_prev(obj);
1869 o->prev = o->cur;
1870 }
1871
evas_object_smart_engine_data_get(Evas_Object * eo_obj)1872 static void *evas_object_smart_engine_data_get(Evas_Object *eo_obj)
1873 {
1874 Evas_Smart_Data *o = efl_data_scope_get(eo_obj, MY_CLASS);
1875 if (!o) return NULL;
1876 return o->engine_data;
1877 }
1878
1879 static void
_efl_canvas_group_class_constructor(Efl_Class * klass EINA_UNUSED)1880 _efl_canvas_group_class_constructor(Efl_Class *klass EINA_UNUSED)
1881 {
1882 _evas_smart_class_names_hash_table = eina_hash_string_small_new(NULL);
1883 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1884 }
1885
1886 static void
_efl_canvas_group_class_destructor(Efl_Class * klass EINA_UNUSED)1887 _efl_canvas_group_class_destructor(Efl_Class *klass EINA_UNUSED)
1888 {
1889 eina_hash_free(_evas_smart_class_names_hash_table);
1890 }
1891
1892 static void
_efl_canvas_group_group_paragraph_direction_set_internal(Eo * eo_obj,Evas_BiDi_Direction dir)1893 _efl_canvas_group_group_paragraph_direction_set_internal(Eo *eo_obj,
1894 Evas_BiDi_Direction dir)
1895 {
1896 Evas_Object_Protected_Data *o;
1897 Evas_Smart_Data *member_o;
1898
1899 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(eo_obj), o)
1900 {
1901 evas_object_change(o->object, o);
1902
1903 if (o->is_smart)
1904 {
1905 member_o = efl_data_scope_get(o->object, MY_CLASS);
1906
1907 if ((member_o->inherit_paragraph_direction) &&
1908 (member_o->paragraph_direction != dir))
1909 {
1910 member_o->paragraph_direction = dir;
1911 _efl_canvas_group_group_paragraph_direction_set_internal(o->object, dir);
1912 }
1913 }
1914 }
1915 }
1916
1917 EOLIAN static void
_efl_canvas_group_efl_canvas_object_paragraph_direction_set(Eo * eo_obj,Evas_Smart_Data * o,Efl_Text_Bidirectional_Type dir)1918 _efl_canvas_group_efl_canvas_object_paragraph_direction_set(Eo *eo_obj, Evas_Smart_Data *o,
1919 Efl_Text_Bidirectional_Type dir)
1920 {
1921 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
1922 Evas_Smart_Data *parent;
1923
1924 if ((!(o->inherit_paragraph_direction) && (o->paragraph_direction == (Evas_BiDi_Direction)dir)) ||
1925 (o->inherit_paragraph_direction && ((Evas_BiDi_Direction)dir == EVAS_BIDI_DIRECTION_INHERIT)))
1926 return;
1927
1928 if (dir == (Efl_Text_Bidirectional_Type)EVAS_BIDI_DIRECTION_INHERIT)
1929 {
1930 o->inherit_paragraph_direction = EINA_TRUE;
1931 Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
1932
1933 if (obj->smart.parent)
1934 {
1935 parent = efl_data_scope_get(obj->smart.parent, MY_CLASS);
1936
1937 if (parent)
1938 parent_dir = parent->paragraph_direction;
1939 }
1940
1941 if (parent_dir != o->paragraph_direction)
1942 {
1943 o->paragraph_direction = parent_dir;
1944 evas_object_change(eo_obj, obj);
1945 }
1946 }
1947 else
1948 {
1949 o->inherit_paragraph_direction = EINA_FALSE;
1950 o->paragraph_direction = dir;
1951 evas_object_change(eo_obj, obj);
1952 }
1953
1954 _efl_canvas_group_group_paragraph_direction_set_internal(eo_obj, o->paragraph_direction);
1955 }
1956
1957 EOLIAN static Efl_Text_Bidirectional_Type
_efl_canvas_group_efl_canvas_object_paragraph_direction_get(const Eo * eo_obj EINA_UNUSED,Evas_Smart_Data * o)1958 _efl_canvas_group_efl_canvas_object_paragraph_direction_get(const Eo *eo_obj EINA_UNUSED, Evas_Smart_Data *o)
1959 {
1960 return (Efl_Text_Bidirectional_Type)o->paragraph_direction;
1961 }
1962
1963 EOLIAN static const Eo *
_efl_canvas_group_group_clipper_get(const Eo * eo_obj EINA_UNUSED,Evas_Smart_Data * o)1964 _efl_canvas_group_group_clipper_get(const Eo *eo_obj EINA_UNUSED, Evas_Smart_Data *o)
1965 {
1966 // NOTE: This may be NULL until all EO smart objects are clipped!
1967 return _smart_clipper_get(o);
1968 }
1969
1970 /* Internal EO */
1971 static void
_efl_canvas_group_group_clipped_set(Eo * eo_obj EINA_UNUSED,Evas_Smart_Data * sd,Eina_Bool clipped)1972 _efl_canvas_group_group_clipped_set(Eo *eo_obj EINA_UNUSED, Evas_Smart_Data *sd, Eina_Bool clipped)
1973 {
1974 // We must call this function BEFORE the constructor (yes, it's hacky)
1975 EINA_SAFETY_ON_FALSE_RETURN(!sd->object);
1976 sd->clipped = !!clipped;
1977 }
1978
1979 /* Internal EO APIs */
1980 EOLIAN static Eina_Bool
_efl_canvas_group_efl_object_event_callback_priority_add(Eo * obj,Evas_Smart_Data * sd,const Efl_Event_Description * desc,Efl_Callback_Priority priority,Efl_Event_Cb func,const void * user_data)1981 _efl_canvas_group_efl_object_event_callback_priority_add(Eo *obj, Evas_Smart_Data *sd, const Efl_Event_Description *desc, Efl_Callback_Priority priority, Efl_Event_Cb func, const void *user_data)
1982 {
1983 if (desc == EFL_CANVAS_GROUP_EVENT_MEMBER_ADDED)
1984 {
1985 sd->cb_member_added = EINA_TRUE;
1986 }
1987 else if (desc == EFL_CANVAS_GROUP_EVENT_MEMBER_REMOVED)
1988 {
1989 sd->cb_member_added = EINA_TRUE;
1990 }
1991
1992 return efl_event_callback_priority_add(efl_super(obj, MY_CLASS), desc, priority, func, user_data);
1993 }
1994
1995 EOLIAN static Eina_Bool
_efl_canvas_group_efl_object_event_callback_array_priority_add(Eo * obj,Evas_Smart_Data * sd,const Efl_Callback_Array_Item * array,Efl_Callback_Priority priority,const void * user_data)1996 _efl_canvas_group_efl_object_event_callback_array_priority_add(Eo *obj, Evas_Smart_Data *sd, const Efl_Callback_Array_Item *array, Efl_Callback_Priority priority, const void *user_data)
1997 {
1998 for (int i = 0; array[i].desc; ++i)
1999 {
2000 if (array[i].desc == EFL_CANVAS_GROUP_EVENT_MEMBER_ADDED)
2001 {
2002 sd->cb_member_added = EINA_TRUE;
2003 }
2004 else if (array[i].desc == EFL_CANVAS_GROUP_EVENT_MEMBER_REMOVED)
2005 {
2006 sd->cb_member_removed = EINA_TRUE;
2007 }
2008 }
2009 return efl_event_callback_array_priority_add(efl_super(obj, MY_CLASS), array, priority, user_data);
2010 }
2011 EOAPI EFL_VOID_FUNC_BODY(efl_canvas_group_add)
2012 EOAPI EFL_VOID_FUNC_BODY(efl_canvas_group_del)
2013 EOAPI EFL_VOID_FUNC_BODYV(efl_canvas_group_clipped_set, EFL_FUNC_CALL(enable), Eina_Bool enable)
2014
2015 #define EFL_CANVAS_GROUP_EXTRA_OPS \
2016 EFL_OBJECT_OP_FUNC(efl_canvas_group_add, _efl_canvas_group_group_add), \
2017 EFL_OBJECT_OP_FUNC(efl_canvas_group_del, _efl_canvas_group_group_del), \
2018 EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_canvas_group_efl_object_event_callback_priority_add), \
2019 EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_canvas_group_efl_object_event_callback_array_priority_add), \
2020 EFL_OBJECT_OP_FUNC(efl_canvas_group_clipped_set, _efl_canvas_group_group_clipped_set)
2021
2022 #include "canvas/efl_canvas_group.eo.c"
2023 #include "canvas/efl_canvas_group_eo.legacy.c"
2024