tizen 2.3.1 release
[framework/uifw/ecore.git] / src / lib / ecore_evas / ecore_evas_util.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <Ecore.h>
9 #include "ecore_private.h"
10
11 #include "ecore_evas_private.h"
12 #include "Ecore_Evas.h"
13
14 static const char ASSOCIATE_KEY[] = "__Ecore_Evas_Associate";
15
16 static void _ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags);
17 static void _ecore_evas_object_dissociate(Ecore_Evas *ee, Evas_Object *obj);
18
19
20 static Evas_Object *
21 _ecore_evas_associate_get(const Ecore_Evas *ee)
22 {
23    return ecore_evas_data_get(ee, ASSOCIATE_KEY);
24 }
25
26 static void
27 _ecore_evas_associate_set(Ecore_Evas *ee, Evas_Object *obj)
28 {
29    ecore_evas_data_set(ee, ASSOCIATE_KEY, obj);
30 }
31
32 static void
33 _ecore_evas_associate_del(Ecore_Evas *ee)
34 {
35    ecore_evas_data_set(ee, ASSOCIATE_KEY, NULL);
36 }
37
38 static Ecore_Evas *
39 _evas_object_associate_get(const Evas_Object *obj)
40 {
41    return evas_object_data_get(obj, ASSOCIATE_KEY);
42 }
43
44 static void
45 _evas_object_associate_set(Evas_Object *obj, Ecore_Evas *ee)
46 {
47    evas_object_data_set(obj, ASSOCIATE_KEY, ee);
48 }
49
50 static void
51 _evas_object_associate_del(Evas_Object *obj)
52 {
53    evas_object_data_del(obj, ASSOCIATE_KEY);
54 }
55
56 /** Associated Events: ******************************************************/
57
58 /* Interceptors Callbacks */
59
60 static void
61 _ecore_evas_obj_intercept_move(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y)
62 {
63    Ecore_Evas *ee = data;
64    // FIXME: account for frame
65    ecore_evas_move(ee, x, y);
66    if (ecore_evas_override_get(ee)) evas_object_move(obj, x, y);
67 }
68
69 static void
70 _ecore_evas_obj_intercept_raise(void *data, Evas_Object *obj __UNUSED__)
71 {
72    Ecore_Evas *ee = data;
73    ecore_evas_raise(ee);
74 }
75
76 static void
77 _ecore_evas_obj_intercept_lower(void *data, Evas_Object *obj __UNUSED__)
78 {
79    Ecore_Evas *ee = data;
80    ecore_evas_lower(ee);
81 }
82
83 static void
84 _ecore_evas_obj_intercept_stack_above(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Object *above __UNUSED__)
85 {
86    INF("TODO: %s", __FUNCTION__);
87 }
88
89 static void
90 _ecore_evas_obj_intercept_stack_below(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Object *below __UNUSED__)
91 {
92    INF("TODO: %s", __FUNCTION__);
93 }
94
95 static void
96 _ecore_evas_obj_intercept_layer_set(void *data, Evas_Object *obj __UNUSED__, int l)
97 {
98    Ecore_Evas *ee = data;
99    ecore_evas_layer_set(ee, l);
100 }
101
102 /* Event Callbacks */
103
104 static void
105 _ecore_evas_obj_callback_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
106 {
107    Ecore_Evas *ee = data;
108    ecore_evas_show(ee);
109 }
110
111 static void
112 _ecore_evas_obj_callback_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
113 {
114    Ecore_Evas *ee = data;
115    ecore_evas_hide(ee);
116 }
117
118 static void
119 _ecore_evas_obj_callback_resize(void *data, Evas *e, Evas_Object *obj, void *event_info __UNUSED__)
120 {
121    Ecore_Evas *ee = data;
122    Evas_Coord ow, oh, fw, fh;
123
124    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
125    evas_output_framespace_get(e, NULL, NULL, &fw, &fh);
126    ow += fw;
127    oh += fh;
128    ecore_evas_resize(ee, ow, oh);
129 }
130
131 static void
132 _ecore_evas_obj_callback_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
133 {
134    Ecore_Evas *ee = data;
135    Evas_Coord w, h;
136
137    evas_object_size_hint_min_get(obj, &w, &h);
138    ecore_evas_size_min_set(ee, w, h);
139
140    evas_object_size_hint_max_get(obj, &w, &h);
141    if (w < 1) w = -1;
142    if (h < 1) h = -1;
143    ecore_evas_size_max_set(ee, w, h);
144 }
145
146 static void
147 _ecore_evas_obj_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
148 {
149    Ecore_Evas *ee = data;
150    _ecore_evas_object_dissociate(ee, obj);
151    ecore_evas_free(ee);
152 }
153
154 static void
155 _ecore_evas_obj_callback_del_dissociate(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
156 {
157    Ecore_Evas *ee = data;
158    _ecore_evas_object_dissociate(ee, obj);
159 }
160
161 static void
162 _ecore_evas_delete_request(Ecore_Evas *ee)
163 {
164    Evas_Object *obj = _ecore_evas_associate_get(ee);
165    _ecore_evas_object_dissociate(ee, obj);
166    evas_object_del(obj);
167    ecore_evas_free(ee);
168 }
169
170 static void
171 _ecore_evas_destroy(Ecore_Evas *ee)
172 {
173    Evas_Object *obj = _ecore_evas_associate_get(ee);
174    if (!obj)
175      return;
176    _ecore_evas_object_dissociate(ee, obj);
177    evas_object_del(obj);
178 }
179
180 static void
181 _ecore_evas_resize(Ecore_Evas *ee)
182 {
183    Evas_Object *obj = _ecore_evas_associate_get(ee);
184    Evas_Coord w, h;
185    ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
186    evas_object_resize(obj, w, h);
187 }
188
189 static void
190 _ecore_evas_pre_free(Ecore_Evas *ee)
191 {
192    Evas_Object *obj = _ecore_evas_associate_get(ee);
193    if (!obj)
194      return;
195    _ecore_evas_object_dissociate(ee, obj);
196    evas_object_del(obj);
197 }
198
199 static int
200 _ecore_evas_object_evas_check(const char *function __UNUSED__, const Ecore_Evas *ee, const Evas_Object *obj)
201 {
202    const char *name, *type;
203    Evas *e;
204
205    e = evas_object_evas_get(obj);
206    if (e == ee->evas)
207      return 1;
208
209    name = evas_object_name_get(obj);
210    type = evas_object_type_get(obj);
211
212    ERR("ERROR: %s(): object %p (name=\"%s\", type=\"%s\") evas "
213        "is not the same as this Ecore_Evas evas: %p != %p",
214        function, obj,
215        name ? name : "", type ? type : "", e, ee->evas);
216    fflush(stderr);
217    if (getenv("ECORE_ERROR_ABORT")) abort();
218
219    return 0;
220 }
221
222 EAPI Eina_Bool
223 ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags)
224 {
225    Ecore_Evas *old_ee;
226    Evas_Object *old_obj;
227
228    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
229    {
230       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
231       return EINA_FALSE;
232    }
233
234    CHECK_PARAM_POINTER_RETURN("obj", obj, EINA_FALSE);
235    if (!_ecore_evas_object_evas_check(__FUNCTION__, ee, obj))
236      return EINA_FALSE;
237
238    old_ee = _evas_object_associate_get(obj);;
239    if (old_ee)
240      ecore_evas_object_dissociate(old_ee, obj);
241
242    old_obj = _ecore_evas_associate_get(ee);
243    if (old_obj)
244      ecore_evas_object_dissociate(ee, old_obj);
245
246    _ecore_evas_object_associate(ee, obj, flags);
247    return EINA_TRUE;
248 }
249
250 EAPI Eina_Bool
251 ecore_evas_object_dissociate(Ecore_Evas *ee, Evas_Object *obj)
252 {
253    Ecore_Evas *old_ee;
254    Evas_Object *old_obj;
255
256    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
257    {
258       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
259       return EINA_FALSE;
260    }
261
262    CHECK_PARAM_POINTER_RETURN("obj", obj, EINA_FALSE);
263    old_ee = _evas_object_associate_get(obj);
264    if (ee != old_ee) {
265       ERR("ERROR: trying to dissociate object that is not using "
266           "this Ecore_Evas: %p != %p", ee, old_ee);
267       return EINA_FALSE;
268    }
269
270    old_obj = _ecore_evas_associate_get(ee);
271    if (old_obj != obj) {
272       ERR("ERROR: trying to dissociate object that is not being "
273           "used by this Ecore_Evas: %p != %p", old_obj, obj);
274       return EINA_FALSE;
275    }
276
277    _ecore_evas_object_dissociate(ee, obj);
278
279    return EINA_TRUE;
280 }
281
282 EAPI Evas_Object *
283 ecore_evas_object_associate_get(const Ecore_Evas *ee)
284 {
285    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
286    {
287       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
288       return NULL;
289    }
290    return _ecore_evas_associate_get(ee);
291 }
292
293 static void
294 _ecore_evas_object_associate(Ecore_Evas *ee, Evas_Object *obj, Ecore_Evas_Object_Associate_Flags flags)
295 {
296    evas_object_event_callback_add
297      (obj, EVAS_CALLBACK_SHOW,
298       _ecore_evas_obj_callback_show, ee);
299    evas_object_event_callback_add
300      (obj, EVAS_CALLBACK_HIDE,
301       _ecore_evas_obj_callback_hide, ee);
302    evas_object_event_callback_add
303      (obj, EVAS_CALLBACK_RESIZE,
304       _ecore_evas_obj_callback_resize, ee);
305    evas_object_event_callback_add
306      (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
307       _ecore_evas_obj_callback_changed_size_hints, ee);
308    if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_DEL)
309      evas_object_event_callback_add
310        (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del, ee);
311    else
312      evas_object_event_callback_add
313        (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del_dissociate, ee);
314
315    evas_object_intercept_move_callback_add
316      (obj, _ecore_evas_obj_intercept_move, ee);
317
318    if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_STACK)
319      {
320         evas_object_intercept_raise_callback_add
321           (obj, _ecore_evas_obj_intercept_raise, ee);
322         evas_object_intercept_lower_callback_add
323           (obj, _ecore_evas_obj_intercept_lower, ee);
324         evas_object_intercept_stack_above_callback_add
325           (obj, _ecore_evas_obj_intercept_stack_above, ee);
326         evas_object_intercept_stack_below_callback_add
327           (obj, _ecore_evas_obj_intercept_stack_below, ee);
328      }
329
330    if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_LAYER)
331      evas_object_intercept_layer_set_callback_add
332        (obj, _ecore_evas_obj_intercept_layer_set, ee);
333
334    if (flags & ECORE_EVAS_OBJECT_ASSOCIATE_DEL)
335      {
336         ecore_evas_callback_delete_request_set(ee, _ecore_evas_delete_request);
337         ecore_evas_callback_destroy_set(ee, _ecore_evas_destroy);
338      }
339    ecore_evas_callback_pre_free_set(ee, _ecore_evas_pre_free);
340    ecore_evas_callback_resize_set(ee, _ecore_evas_resize);
341
342    _evas_object_associate_set(obj, ee);
343    _ecore_evas_associate_set(ee, obj);
344 }
345
346 static void
347 _ecore_evas_object_dissociate(Ecore_Evas *ee, Evas_Object *obj)
348 {
349    evas_object_event_callback_del_full
350      (obj, EVAS_CALLBACK_SHOW,
351       _ecore_evas_obj_callback_show, ee);
352    evas_object_event_callback_del_full
353      (obj, EVAS_CALLBACK_HIDE,
354       _ecore_evas_obj_callback_hide, ee);
355    evas_object_event_callback_del_full
356      (obj, EVAS_CALLBACK_RESIZE,
357       _ecore_evas_obj_callback_resize, ee);
358    evas_object_event_callback_del_full
359      (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
360       _ecore_evas_obj_callback_changed_size_hints, ee);
361    evas_object_event_callback_del_full
362      (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del, ee);
363    evas_object_event_callback_del_full
364      (obj, EVAS_CALLBACK_DEL, _ecore_evas_obj_callback_del_dissociate, ee);
365
366    evas_object_intercept_move_callback_del
367      (obj, _ecore_evas_obj_intercept_move);
368
369    evas_object_intercept_raise_callback_del
370      (obj, _ecore_evas_obj_intercept_raise);
371    evas_object_intercept_lower_callback_del
372      (obj, _ecore_evas_obj_intercept_lower);
373    evas_object_intercept_stack_above_callback_del
374      (obj, _ecore_evas_obj_intercept_stack_above);
375    evas_object_intercept_stack_below_callback_del
376      (obj, _ecore_evas_obj_intercept_stack_below);
377
378    evas_object_intercept_layer_set_callback_del
379      (obj, _ecore_evas_obj_intercept_layer_set);
380
381    if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
382    {
383       ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, __FUNCTION__);
384    }
385    else
386    {
387       if (ee->func.fn_delete_request == _ecore_evas_delete_request)
388         ecore_evas_callback_delete_request_set(ee, NULL);
389       if (ee->func.fn_destroy == _ecore_evas_destroy)
390         ecore_evas_callback_destroy_set(ee, NULL);
391       if (ee->func.fn_resize == _ecore_evas_resize)
392         ecore_evas_callback_resize_set(ee, NULL);
393       if (ee->func.fn_pre_free == _ecore_evas_pre_free)
394         ecore_evas_callback_pre_free_set(ee, NULL);
395
396       _ecore_evas_associate_del(ee);
397    }
398
399    _evas_object_associate_del(obj);
400 }
401
402 /**
403  * Helper ecore_getopt callback to list available Ecore_Evas engines.
404  *
405  * This will list all available engines except buffer, this is useful
406  * for applications to let user choose how they should create windows
407  * with ecore_evas_new().
408  *
409  * @c callback_data value is used as @c FILE* and says where to output
410  * messages, by default it is @c stdout. You can specify this value
411  * with ECORE_GETOPT_CALLBACK_FULL() or ECORE_GETOPT_CALLBACK_ARGS().
412  *
413  * If there is a boolean storage provided, then it is marked with 1
414  * when this option is executed.
415  * @param parser This parameter isn't in use.
416  * @param desc This parameter isn't in use.
417  * @param str This parameter isn't in use.
418  * @param data The data to be used.
419  * @param storage The storage to be used.
420  * @return The function always return 1.
421  */
422 unsigned char
423 ecore_getopt_callback_ecore_evas_list_engines(const Ecore_Getopt *parser __UNUSED__, const Ecore_Getopt_Desc *desc __UNUSED__, const char *str __UNUSED__, void *data, Ecore_Getopt_Value *storage)
424 {
425    Eina_List  *lst, *n;
426    const char *engine;
427
428    if (!storage)
429      {
430         ERR("Storage is missing");
431         return 0;
432      }
433
434    FILE *fp = data;
435    if (!fp)
436      fp = stdout;
437
438    lst = ecore_evas_engines_get();
439
440    fputs("supported engines:\n", fp);
441    EINA_LIST_FOREACH(lst, n, engine)
442      if (strcmp(engine, "buffer") != 0)
443        fprintf(fp, "\t%s\n", engine);
444
445    ecore_evas_engines_free(lst);
446
447    if (storage->boolp)
448      *storage->boolp = 1;
449
450    return 1;
451 }