* evas: Fix SEGV when smart object's child come from another layer than
[profile/ivi/evas.git] / src / lib / canvas / evas_layer.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 void
5 evas_object_inject(Evas_Object *obj, Evas *e)
6 {
7    Evas_Layer *lay;
8
9    if (obj->in_layer) return;
10    lay = evas_layer_find(e, obj->cur.layer);
11    if (!lay)
12      {
13         lay = evas_layer_new(e);
14         lay->layer = obj->cur.layer;
15         evas_layer_add(lay);
16      }
17    lay->objects = (Evas_Object *)eina_inlist_append(EINA_INLIST_GET(lay->objects), EINA_INLIST_GET(obj));
18    lay->usage++;
19    obj->layer = lay;
20    obj->in_layer = 1;
21 }
22
23 void
24 evas_object_release(Evas_Object *obj, int clean_layer)
25 {
26    if (!obj->in_layer) return;
27    obj->layer->objects = (Evas_Object *)eina_inlist_remove(EINA_INLIST_GET(obj->layer->objects), EINA_INLIST_GET(obj));
28    obj->layer->usage--;
29    if (clean_layer)
30      {
31         if (obj->layer->usage <= 0)
32           {
33              evas_layer_del(obj->layer);
34              evas_layer_free(obj->layer);
35           }
36      }
37    obj->layer = NULL;
38    obj->in_layer = 0;
39 }
40
41 Evas_Layer *
42 evas_layer_new(Evas *e)
43 {
44    Evas_Layer *lay;
45
46    lay = calloc(1, sizeof(Evas_Layer));
47    if (!lay) return NULL;
48    lay->evas = e;
49    return lay;
50 }
51
52 void
53 evas_layer_pre_free(Evas_Layer *lay)
54 {
55    Evas_Object *obj;
56
57    EINA_INLIST_FOREACH(lay->objects, obj)
58      {
59         if ((!obj->smart.parent) && (!obj->delete_me))
60           evas_object_del(obj);
61      }
62 }
63
64 void
65 evas_layer_free(Evas_Layer *lay)
66 {
67    while (lay->objects)
68      {
69         Evas_Object *obj;
70
71         obj = (Evas_Object *)lay->objects;
72         evas_object_free(obj, 0);
73      }
74 }
75
76 void
77 evas_layer_clean(Evas *e)
78 {
79    Evas_Layer *tmp;
80
81    while (e->layers)
82      {
83         tmp = e->layers;
84         evas_layer_del(tmp);
85         free(tmp);
86      }
87 }
88
89 Evas_Layer *
90 evas_layer_find(Evas *e, short layer_num)
91 {
92    Evas_Layer *layer;
93
94    EINA_INLIST_FOREACH(e->layers, layer)
95      {
96         if (layer->layer == layer_num) return layer;
97      }
98    return NULL;
99 }
100
101 void
102 evas_layer_add(Evas_Layer *lay)
103 {
104    Evas_Layer *layer;
105
106    EINA_INLIST_FOREACH(lay->evas->layers, layer)
107      {
108         if (layer->layer > lay->layer)
109           {
110              lay->evas->layers = (Evas_Layer *)eina_inlist_prepend_relative(EINA_INLIST_GET(lay->evas->layers),
111                                                                             EINA_INLIST_GET(lay),
112                                                                             EINA_INLIST_GET(layer));
113              return;
114           }
115      }
116    lay->evas->layers = (Evas_Layer *)eina_inlist_append(EINA_INLIST_GET(lay->evas->layers), EINA_INLIST_GET(lay));
117 }
118
119 void
120 evas_layer_del(Evas_Layer *lay)
121 {
122    Evas *e;
123
124    e = lay->evas;
125    e->layers = (Evas_Layer *)eina_inlist_remove(EINA_INLIST_GET(e->layers), EINA_INLIST_GET(lay));
126 }
127
128 /* public functions */
129
130 /**
131  * @addtogroup Evas_Object_Group
132  * @{
133  */
134
135 /**
136  * Sets the layer of the evas that the given object will be part of.
137  *
138  * It is not possible to change the layer of a smart object's child.
139  *
140  * @param   obj The given evas object.
141  * @param   l   The number of the layer to place the object on.
142  */
143 EAPI void
144 evas_object_layer_set(Evas_Object *obj, short l)
145 {
146    Evas *e;
147
148    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
149    return;
150    MAGIC_CHECK_END();
151    if (evas_object_intercept_call_layer_set(obj, l)) return;
152    if (obj->smart.parent) return;
153    if (obj->cur.layer == l)
154      {
155         evas_object_raise(obj);
156         return;
157      }
158    e = obj->layer->evas;
159    evas_object_release(obj, 1);
160    obj->cur.layer = l;
161    evas_object_inject(obj, e);
162    obj->restack = 1;
163    evas_object_change(obj);
164    if (obj->clip.clipees)
165      {
166         evas_object_inform_call_restack(obj);
167         return;
168      }
169    evas_object_change(obj);
170    if (!obj->smart.smart)
171      {
172         if (evas_object_is_in_output_rect(obj,
173                                           obj->layer->evas->pointer.x,
174                                           obj->layer->evas->pointer.y, 1, 1) &&
175             obj->cur.visible)
176           if (eina_list_data_find(obj->layer->evas->pointer.object.in, obj))
177             evas_event_feed_mouse_move(obj->layer->evas,
178                                        obj->layer->evas->pointer.x,
179                                        obj->layer->evas->pointer.y,
180                                        obj->layer->evas->last_timestamp,
181                                        NULL);
182      }
183    evas_object_inform_call_restack(obj);
184 }
185
186 /**
187  * Retrieves the layer of the evas that the given object is part of.
188  *
189  * Be carefull, it doesn't make sense to change the layer of smart object's
190  * child. So the returned value could be wrong in some case. Don't rely on
191  * it's accuracy.
192  *
193  * @param   obj The given evas object.
194  * @return  Number of the layer.
195  */
196 EAPI short
197 evas_object_layer_get(const Evas_Object *obj)
198 {
199    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
200    return 0;
201    MAGIC_CHECK_END();
202    if (obj->smart.parent)
203      {
204         return obj->smart.parent->cur.layer;
205      }
206    return obj->cur.layer;
207 }
208
209 /**
210  * @}
211  */