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