1 #include "evas_common_private.h"
2 #include "evas_private.h"
3 
4 void
evas_object_inject(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,Evas * e)5 evas_object_inject(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas *e)
6 {
7    Evas_Layer *lay;
8    Evas_Public_Data *evas;
9 
10    if (!obj) return;
11    if (!e) return;
12    if (obj->in_layer) return;
13    evas = efl_data_scope_get(e, EVAS_CANVAS_CLASS);
14    if (!evas) return;
15    evas_canvas_async_block(evas);
16    lay = evas_layer_find(e, obj->cur->layer);
17    if (!lay)
18      {
19         lay = evas_layer_new(e);
20         lay->layer = obj->cur->layer;
21         evas_layer_add(lay);
22      }
23    efl_data_ref(eo_obj, EFL_CANVAS_OBJECT_CLASS);
24    lay->objects = (Evas_Object_Protected_Data *)eina_inlist_append(EINA_INLIST_GET(lay->objects), EINA_INLIST_GET(obj));
25    lay->usage++;
26    obj->layer = lay;
27    obj->in_layer = 1;
28 }
29 
30 void
evas_object_release(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,int clean_layer)31 evas_object_release(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, int clean_layer)
32 {
33    if (!obj->in_layer) return;
34    if (!obj->layer->walking_objects)
35      obj->layer->objects = (Evas_Object_Protected_Data *)eina_inlist_remove(EINA_INLIST_GET(obj->layer->objects), EINA_INLIST_GET(obj));
36    efl_data_unref(eo_obj, obj);
37    if (!obj->layer->walking_objects)
38      {
39         obj->layer->usage--;
40         if (clean_layer)
41           {
42              if (obj->layer->usage <= 0)
43                {
44                   evas_layer_del(obj->layer);
45                }
46           }
47         obj->layer = NULL;
48         obj->in_layer = 0;
49      }
50    else
51      obj->layer->removes = eina_list_append(obj->layer->removes, obj);
52 }
53 
54 Evas_Layer *
evas_layer_new(Evas * eo_e)55 evas_layer_new(Evas *eo_e)
56 {
57    Evas_Public_Data *e = efl_data_ref(eo_e, EVAS_CANVAS_CLASS);
58    Evas_Layer *lay;
59 
60    lay = calloc(1, sizeof(Evas_Layer));
61    if (!lay) return NULL;
62    lay->evas = e;
63    return lay;
64 }
65 
66 void
_evas_layer_flush_removes(Evas_Layer * lay)67 _evas_layer_flush_removes(Evas_Layer *lay)
68 {
69    Evas_Object_Protected_Data *obj;
70 
71    if (lay->walking_objects) return;
72    EINA_LIST_FREE(lay->removes, obj)
73      {
74         lay->objects = (Evas_Object_Protected_Data *)
75           eina_inlist_remove(EINA_INLIST_GET(lay->objects),
76                              EINA_INLIST_GET(obj));
77         obj->layer = NULL;
78         obj->in_layer = 0;
79         if (lay->usage > 0) lay->usage--;
80      }
81    if (lay->usage <= 0)
82      {
83         evas_layer_del(lay);
84      }
85 }
86 
87 void
evas_layer_pre_free(Evas_Layer * lay)88 evas_layer_pre_free(Evas_Layer *lay)
89 {
90    Evas_Object_Protected_Data *obj;
91 
92    lay->walking_objects++;
93    EINA_INLIST_FOREACH(lay->objects, obj)
94      {
95         if ((!obj->smart.parent) && (!obj->delete_me))
96           evas_object_del(obj->object);
97      }
98    lay->walking_objects--;
99    _evas_layer_flush_removes(lay);
100 }
101 
102 void
evas_layer_free_objects(Evas_Layer * lay)103 evas_layer_free_objects(Evas_Layer *lay)
104 {
105    Evas_Object_Protected_Data *obj;
106 
107    EINA_INLIST_FREE(lay->objects, obj)
108      {
109         if (obj->object == NULL)
110           {
111              ERR("Object still present in the canvas stack, but without a valid object pointer (%s@%p).", obj->type, obj);
112           }
113         evas_object_free(obj, EINA_FALSE);
114      }
115 }
116 
117 void
evas_layer_clean(Evas * eo_e)118 evas_layer_clean(Evas *eo_e)
119 {
120    Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
121    Evas_Layer *tmp;
122 
123    while (e->layers)
124      {
125         tmp = e->layers;
126         evas_layer_del(tmp);
127      }
128 }
129 
130 Evas_Layer *
evas_layer_find(Evas * eo_e,short layer_num)131 evas_layer_find(Evas *eo_e, short layer_num)
132 {
133    Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
134    Evas_Layer *layer;
135 
136    EINA_INLIST_FOREACH(e->layers, layer)
137      {
138         if (layer->layer == layer_num) return layer;
139      }
140    return NULL;
141 }
142 
143 void
evas_layer_add(Evas_Layer * lay)144 evas_layer_add(Evas_Layer *lay)
145 {
146    Evas_Layer *layer;
147 
148    EINA_INLIST_FOREACH(lay->evas->layers, layer)
149      {
150         if (layer->layer > lay->layer)
151           {
152              lay->evas->layers = (Evas_Layer *)eina_inlist_prepend_relative(EINA_INLIST_GET(lay->evas->layers),
153                                                                             EINA_INLIST_GET(lay),
154                                                                             EINA_INLIST_GET(layer));
155              return;
156           }
157      }
158    lay->evas->layers = (Evas_Layer *)eina_inlist_append(EINA_INLIST_GET(lay->evas->layers), EINA_INLIST_GET(lay));
159 }
160 
161 void
evas_layer_del(Evas_Layer * lay)162 evas_layer_del(Evas_Layer *lay)
163 {
164    Evas_Public_Data *e;
165 
166    e = lay->evas;
167    e->layers = (Evas_Layer *)eina_inlist_remove(EINA_INLIST_GET(e->layers), EINA_INLIST_GET(lay));
168    efl_data_unref(e->evas, e);
169    eina_freeq_ptr_main_add(lay, free, sizeof(*lay));
170 }
171 
172 static void
_evas_object_layer_set_child(Evas_Object_Protected_Data * obj,Evas_Object_Protected_Data * par_obj,short l)173 _evas_object_layer_set_child(Evas_Object_Protected_Data *obj, Evas_Object_Protected_Data *par_obj, short l)
174 {
175    if (obj->delete_me) return;
176    if (obj->cur->layer == l) return;
177    if (EINA_UNLIKELY(obj->in_layer))
178      {
179         ERR("Invalid internal state of object %p (child marked as being a "
180             "top-level object)!", obj->object);
181         evas_object_release(obj->object, obj, 1);
182      }
183    else if ((--obj->layer->usage) == 0)
184      {
185         evas_layer_del(obj->layer);
186      }
187 
188    EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
189      {
190        state_write->layer = l;
191      }
192    EINA_COW_STATE_WRITE_END(obj, state_write, cur);
193 
194    obj->layer = par_obj->layer;
195    obj->layer->usage++;
196    if (obj->is_smart)
197      {
198         Eina_Inlist *contained;
199         Evas_Object_Protected_Data *member;
200 
201         contained = (Eina_Inlist *)evas_object_smart_members_get_direct(obj->object);
202         EINA_INLIST_FOREACH(contained, member)
203           {
204              _evas_object_layer_set_child(member, obj, l);
205           }
206      }
207 }
208 
209 /* public functions */
210 
211 EAPI void
evas_object_layer_set(Evas_Object * obj,short l)212 evas_object_layer_set(Evas_Object *obj, short l)
213 {
214    efl_gfx_stack_layer_set((Evas_Object *)obj, l);
215 }
216 
217 EOLIAN void
_efl_canvas_object_efl_gfx_stack_layer_set(Eo * eo_obj,Evas_Object_Protected_Data * obj,short l)218 _efl_canvas_object_efl_gfx_stack_layer_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, short l)
219 {
220    Evas *eo_e;
221 
222    if (obj->delete_me) return;
223    evas_object_async_block(obj);
224    if (_evas_object_intercept_call_evas(obj, EVAS_OBJECT_INTERCEPT_CB_LAYER_SET, 1, l)) return;
225    if (obj->smart.parent) return;
226    if (obj->cur->layer == l)
227      {
228         evas_object_raise(eo_obj);
229         return;
230      }
231    eo_e = obj->layer->evas->evas;
232    evas_object_release(eo_obj, obj, 1);
233    EINA_COW_STATE_WRITE_BEGIN(obj, state_write, cur)
234      {
235        state_write->layer = l;
236      }
237    EINA_COW_STATE_WRITE_END(obj, state_write, cur);
238 
239    evas_object_inject(eo_obj, obj, eo_e);
240    obj->restack = 1;
241    evas_object_change(eo_obj, obj);
242    if (obj->clip.clipees)
243      {
244         evas_object_inform_call_restack(eo_obj, obj);
245         return;
246      }
247    evas_object_change(eo_obj, obj);
248    if (!obj->is_smart && obj->cur->visible)
249      {
250         _evas_canvas_event_pointer_in_rect_mouse_move_feed(obj->layer->evas, eo_obj, obj,
251                                                            1, 1, EINA_TRUE,
252                                                            NULL);
253      }
254    else if (obj->is_smart)
255      {
256         Eina_Inlist *contained;
257         Evas_Object_Protected_Data *member;
258 
259         contained = (Eina_Inlist *)evas_object_smart_members_get_direct(eo_obj);
260         EINA_INLIST_FOREACH(contained, member)
261           {
262             _evas_object_layer_set_child(member, obj, l);
263           }
264      }
265    evas_object_inform_call_restack(eo_obj, obj);
266 }
267 
268 EAPI short
evas_object_layer_get(const Evas_Object * obj)269 evas_object_layer_get(const Evas_Object *obj)
270 {
271    return efl_gfx_stack_layer_get((Evas_Object *)obj);
272 }
273 
274 EOLIAN short
_efl_canvas_object_efl_gfx_stack_layer_get(const Eo * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)275 _efl_canvas_object_efl_gfx_stack_layer_get(const Eo *eo_obj EINA_UNUSED,
276                                      Evas_Object_Protected_Data *obj)
277 {
278    if (obj->smart.parent)
279      {
280         Evas_Object_Protected_Data *smart_parent_obj = efl_data_scope_get(obj->smart.parent, EFL_CANVAS_OBJECT_CLASS);
281         return smart_parent_obj->cur->layer;
282      }
283    return obj->cur->layer;
284 }
285 
286