elementary/elm_widget : When elm_widget_sub_object_del is called with
[framework/uifw/elementary.git] / src / lib / elm_widget.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static const char SMART_NAME[] = "elm_widget";
5
6 #define API_ENTRY                                    \
7   Smart_Data * sd = evas_object_smart_data_get(obj); \
8   if ((!obj) || (!sd) || (!_elm_widget_is(obj)))
9 #define INTERNAL_ENTRY                               \
10   Smart_Data * sd = evas_object_smart_data_get(obj); \
11   if (!sd) return;
12
13 #undef elm_widget_text_set_hook_set
14 #undef elm_widget_text_get_hook_set
15 #undef elm_widget_content_set_hook_set
16 #undef elm_widget_content_get_hook_set
17 #undef elm_widget_content_unset_hook_set
18
19 typedef struct _Smart_Data        Smart_Data;
20 typedef struct _Edje_Signal_Data  Edje_Signal_Data;
21 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
22 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
23
24 struct _Smart_Data
25 {
26    Evas_Object *obj;
27    const char  *type;
28    Evas_Object *parent_obj;
29    Evas_Object *parent2;
30    Evas_Coord   x, y, w, h;
31    Eina_List   *subobjs;
32    Evas_Object *resize_obj;
33    Evas_Object *hover_obj;
34    Eina_List   *tooltips, *cursors;
35    void       (*del_func)(Evas_Object *obj);
36    void       (*del_pre_func)(Evas_Object *obj);
37    void       (*focus_func)(Evas_Object *obj);
38    void       (*activate_func)(Evas_Object *obj);
39    void       (*disable_func)(Evas_Object *obj);
40    void       (*theme_func)(Evas_Object *obj);
41    void       (*translate_func)(Evas_Object *obj);
42    Eina_Bool  (*event_func)(Evas_Object       *obj,
43                             Evas_Object       *source,
44                             Evas_Callback_Type type,
45                             void              *event_info);
46    void       (*signal_func)(Evas_Object *obj,
47                              const char  *emission,
48                              const char  *source);
49    void       (*callback_add_func)(Evas_Object   *obj,
50                                    const char    *emission,
51                                    const char    *source,
52                                    Edje_Signal_Cb func,
53                                    void          *data);
54    void       (*callback_del_func)(Evas_Object   *obj,
55                                    const char    *emission,
56                                    const char    *source,
57                                    Edje_Signal_Cb func,
58                                    void          *data);
59    void       (*changed_func)(Evas_Object *obj);
60    Eina_Bool  (*focus_next_func)(const Evas_Object  *obj,
61                                  Elm_Focus_Direction dir,
62                                  Evas_Object       **next);
63    void       (*on_focus_func)(void        *data,
64                                Evas_Object *obj);
65    void        *on_focus_data;
66    void       (*on_change_func)(void        *data,
67                                 Evas_Object *obj);
68    void        *on_change_data;
69    void       (*on_show_region_func)(void        *data,
70                                      Evas_Object *obj);
71    void        *on_show_region_data;
72    void       (*focus_region_func)(Evas_Object *obj,
73                                    Evas_Coord   x,
74                                    Evas_Coord   y,
75                                    Evas_Coord   w,
76                                    Evas_Coord   h);
77    void       (*on_focus_region_func)(const Evas_Object *obj,
78                                       Evas_Coord        *x,
79                                       Evas_Coord        *y,
80                                       Evas_Coord        *w,
81                                       Evas_Coord        *h);
82    Elm_Widget_On_Text_Set_Cb on_text_set_func;
83    Elm_Widget_On_Text_Get_Cb on_text_get_func;
84    Elm_Widget_On_Content_Set_Cb on_content_set_func;
85    Elm_Widget_On_Content_Get_Cb on_content_get_func;
86    Elm_Widget_On_Content_Unset_Cb on_content_unset_func;
87    void        *data;
88    Evas_Coord   rx, ry, rw, rh;
89    int          scroll_hold;
90    int          scroll_freeze;
91    double       scale;
92    Elm_Theme   *theme;
93    const char  *style;
94    const char  *access_info;
95    unsigned int focus_order;
96    Eina_Bool    focus_order_on_calc;
97
98    int          child_drag_x_locked;
99    int          child_drag_y_locked;
100
101    Eina_List   *edje_signals;
102    Eina_List   *translate_strings;
103
104    Eina_Bool    drag_x_locked : 1;
105    Eina_Bool    drag_y_locked : 1;
106
107    Eina_Bool    can_focus : 1;
108    Eina_Bool    child_can_focus : 1;
109    Eina_Bool    focused : 1;
110    Eina_Bool    top_win_focused : 1;
111    Eina_Bool    tree_unfocusable : 1;
112    Eina_Bool    highlight_ignore : 1;
113    Eina_Bool    highlight_in_theme : 1;
114    Eina_Bool    disabled : 1;
115    Eina_Bool    is_mirrored : 1;
116    Eina_Bool    mirrored_auto_mode : 1;   /* This is TRUE by default */
117    Eina_Bool    still_in : 1;
118
119    Eina_List   *focus_chain;
120    Eina_List   *event_cb;
121 };
122
123 struct _Edje_Signal_Data
124 {
125    Evas_Object   *obj;
126    Edje_Signal_Cb func;
127    const char    *emission;
128    const char    *source;
129    void          *data;
130 };
131
132 struct _Elm_Event_Cb_Data
133 {
134    Elm_Event_Cb func;
135    const void  *data;
136 };
137
138 struct _Elm_Translate_String_Data
139 {
140    const char *id;
141    const char *domain;
142    const char *string;
143 };
144
145 /* local subsystem functions */
146 static void _smart_reconfigure(Smart_Data *sd);
147 static void _smart_add(Evas_Object *obj);
148 static void _smart_del(Evas_Object *obj);
149 static void _smart_move(Evas_Object *obj,
150                         Evas_Coord   x,
151                         Evas_Coord   y);
152 static void _smart_resize(Evas_Object *obj,
153                           Evas_Coord   w,
154                           Evas_Coord   h);
155 static void _smart_show(Evas_Object *obj);
156 static void _smart_hide(Evas_Object *obj);
157 static void _smart_color_set(Evas_Object *obj,
158                              int          r,
159                              int          g,
160                              int          b,
161                              int          a);
162 static void _smart_clip_set(Evas_Object *obj,
163                             Evas_Object *clip);
164 static void _smart_clip_unset(Evas_Object *obj);
165 static void _smart_calculate(Evas_Object *obj);
166 static void _smart_init(void);
167
168 static void _if_focused_revert(Evas_Object *obj,
169                                Eina_Bool    can_focus_only);
170 static Evas_Object *_newest_focus_order_get(Evas_Object  *obj,
171                                             unsigned int *newest_focus_order,
172                                             Eina_Bool     can_focus_only);
173
174 /* local subsystem globals */
175 static Evas_Smart *_e_smart = NULL;
176 static Eina_List  *widtypes = NULL;
177
178 static unsigned int focus_order = 0;
179
180 // internal funcs
181 static inline Eina_Bool
182 _elm_widget_is(const Evas_Object *obj)
183 {
184    const char *type = evas_object_type_get(obj);
185    return type == SMART_NAME;
186 }
187
188 static inline Eina_Bool
189 _is_focusable(Evas_Object *obj)
190 {
191    API_ENTRY return EINA_FALSE;
192    return sd->can_focus || (sd->child_can_focus);
193 }
194
195 static void
196 _unfocus_parents(Evas_Object *obj)
197 {
198    for (; obj; obj = elm_widget_parent_get(obj))
199      {
200         INTERNAL_ENTRY
201         if (!sd->focused) return;
202         sd->focused = 0;
203      }
204 }
205
206 static void
207 _focus_parents(Evas_Object *obj)
208 {
209    for (; obj; obj = elm_widget_parent_get(obj))
210      {
211         INTERNAL_ENTRY
212         if (sd->focused) return;
213         sd->focused = 1;
214      }
215 }
216
217 static void
218 _sub_obj_del(void        *data,
219              Evas        *e __UNUSED__,
220              Evas_Object *obj,
221              void        *event_info __UNUSED__)
222 {
223    Smart_Data *sd = data;
224
225    if (_elm_widget_is(obj))
226      {
227         if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
228      }
229    if (obj == sd->resize_obj)
230      sd->resize_obj = NULL;
231    else if (obj == sd->hover_obj)
232      sd->hover_obj = NULL;
233    else
234      sd->subobjs = eina_list_remove(sd->subobjs, obj);
235    evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
236 }
237
238 static void
239 _sub_obj_hide(void        *data __UNUSED__,
240               Evas        *e __UNUSED__,
241               Evas_Object *obj,
242               void        *event_info __UNUSED__)
243 {
244    elm_widget_focus_hide_handle(obj);
245 }
246
247 static void
248 _sub_obj_mouse_down(void        *data,
249                     Evas        *e __UNUSED__,
250                     Evas_Object *obj __UNUSED__,
251                     void        *event_info)
252 {
253    Smart_Data *sd = data;
254    Evas_Event_Mouse_Down *ev = event_info;
255    if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
256      sd->still_in = EINA_TRUE;
257 }
258
259 static void
260 _sub_obj_mouse_move(void        *data,
261                     Evas        *e __UNUSED__,
262                     Evas_Object *obj,
263                     void        *event_info)
264 {
265    Smart_Data *sd = data;
266    Evas_Event_Mouse_Move *ev = event_info;
267    if (sd->still_in)
268      {
269         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
270           sd->still_in = EINA_FALSE;
271         else
272           {
273              Evas_Coord x, y, w, h;
274              evas_object_geometry_get(obj, &x, &y, &w, &h);
275              if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
276                  (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
277                sd->still_in = EINA_FALSE;
278           }
279      }
280 }
281
282 static void
283 _sub_obj_mouse_up(void        *data,
284                   Evas        *e __UNUSED__,
285                   Evas_Object *obj,
286                   void        *event_info __UNUSED__)
287 {
288    Smart_Data *sd = data;
289    if (sd->still_in)
290      elm_widget_focus_mouse_up_handle(obj);
291    sd->still_in = EINA_FALSE;
292 }
293
294 static void
295 _propagate_x_drag_lock(Evas_Object *obj,
296                        int          dir)
297 {
298    INTERNAL_ENTRY
299    if (sd->parent_obj)
300      {
301         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
302         if (sd2)
303           {
304              sd2->child_drag_x_locked += dir;
305              _propagate_x_drag_lock(sd->parent_obj, dir);
306           }
307      }
308 }
309
310 static void
311 _propagate_y_drag_lock(Evas_Object *obj,
312                        int          dir)
313 {
314    INTERNAL_ENTRY
315    if (sd->parent_obj)
316      {
317         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
318         if (sd2)
319           {
320              sd2->child_drag_y_locked += dir;
321              _propagate_y_drag_lock(sd->parent_obj, dir);
322           }
323      }
324 }
325
326 static void
327 _propagate_event(void        *data,
328                  Evas        *e __UNUSED__,
329                  Evas_Object *obj,
330                  void        *event_info)
331 {
332    INTERNAL_ENTRY
333    Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
334    Evas_Event_Flags *event_flags = NULL;
335
336    switch (type)
337      {
338       case EVAS_CALLBACK_KEY_DOWN:
339           {
340             Evas_Event_Key_Down *ev = event_info;
341             event_flags = &(ev->event_flags);
342           }
343         break;
344
345       case EVAS_CALLBACK_KEY_UP:
346           {
347              Evas_Event_Key_Up *ev = event_info;
348              event_flags = &(ev->event_flags);
349           }
350         break;
351
352       case EVAS_CALLBACK_MOUSE_WHEEL:
353           {
354             Evas_Event_Mouse_Wheel *ev = event_info;
355             event_flags = &(ev->event_flags);
356           }
357         break;
358
359       default:
360         break;
361      }
362
363    elm_widget_event_propagate(obj, type, event_info, event_flags);
364 }
365
366 static void
367 _parent_focus(Evas_Object *obj)
368 {
369    API_ENTRY return;
370    if (sd->focused) return;
371
372    Evas_Object *o = elm_widget_parent_get(obj);
373    sd->focus_order_on_calc = EINA_TRUE;
374
375    if (o) _parent_focus(o);
376
377    if (!sd->focus_order_on_calc)
378      return; /* we don't want to override it if by means of any of the
379                 callbacks below one gets to calculate our order
380                 first. */
381
382    focus_order++;
383    sd->focus_order = focus_order;
384    if (sd->top_win_focused)
385      {
386         sd->focused = EINA_TRUE;
387         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
388         if (sd->focus_func) sd->focus_func(obj);
389         _elm_widget_focus_region_show(obj);
390      }
391    sd->focus_order_on_calc = EINA_FALSE;
392 }
393
394 static void
395 _elm_object_focus_chain_del_cb(void        *data,
396                                Evas        *e __UNUSED__,
397                                Evas_Object *obj,
398                                void        *event_info __UNUSED__)
399 {
400    Smart_Data *sd = data;
401
402    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
403 }
404
405 // exposed util funcs to elm
406 void
407 _elm_widget_type_clear(void)
408 {
409    const char **ptr;
410
411    EINA_LIST_FREE(widtypes, ptr)
412      {
413         eina_stringshare_del(*ptr);
414         *ptr = NULL;
415      }
416 }
417
418 void
419 _elm_widget_focus_region_show(const Evas_Object *obj)
420 {
421    Evas_Coord x, y, w, h, ox, oy;
422    Smart_Data *sd2;
423    Evas_Object *o;
424
425    API_ENTRY return;
426
427    o = elm_widget_parent_get(obj);
428    if (!o) return;
429
430    elm_widget_focus_region_get(obj, &x, &y, &w, &h);
431    evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
432    while (o)
433      {
434         Evas_Coord px, py;
435         sd2 = evas_object_smart_data_get(o);
436         if (sd2->focus_region_func)
437           {
438              sd2->focus_region_func(o, x, y, w, h);
439              elm_widget_focus_region_get(o, &x, &y, &w, &h);
440           }
441         else
442           {
443              evas_object_geometry_get(o, &px, &py, NULL, NULL);
444              x += ox - px;
445              y += oy - py;
446              ox = px;
447              oy = py;
448           }
449         o = elm_widget_parent_get(o);
450      }
451 }
452
453 /**
454  * @defgroup Widget Widget
455  *
456  * @internal
457  * Exposed api for making widgets
458  */
459 EAPI void
460 elm_widget_type_register(const char **ptr)
461 {
462    widtypes = eina_list_append(widtypes, (void *)ptr);
463 }
464
465 /**
466  * @defgroup Widget Widget
467  *
468  * @internal
469  * Disposed api for making widgets
470  */
471 EAPI void
472 elm_widget_type_unregister(const char **ptr)
473 {
474    widtypes = eina_list_remove(widtypes, (void *)ptr);
475 }
476
477 EAPI Eina_Bool
478 elm_widget_api_check(int ver)
479 {
480    if (ver != ELM_INTERNAL_API_VERSION)
481      {
482         CRITICAL("Elementary widget api versions do not match");
483         return EINA_FALSE;
484      }
485    return EINA_TRUE;
486 }
487
488 EAPI Evas_Object *
489 elm_widget_add(Evas *evas)
490 {
491    Evas_Object *obj;
492    _smart_init();
493    obj = evas_object_smart_add(evas, _e_smart);
494    elm_widget_mirrored_set(obj, elm_mirrored_get());
495    return obj;
496 }
497
498 EAPI void
499 elm_widget_del_hook_set(Evas_Object *obj,
500                         void       (*func)(Evas_Object *obj))
501 {
502    API_ENTRY return;
503    sd->del_func = func;
504 }
505
506 EAPI void
507 elm_widget_del_pre_hook_set(Evas_Object *obj,
508                             void       (*func)(Evas_Object *obj))
509 {
510    API_ENTRY return;
511    sd->del_pre_func = func;
512 }
513
514 EAPI void
515 elm_widget_focus_hook_set(Evas_Object *obj,
516                           void       (*func)(Evas_Object *obj))
517 {
518    API_ENTRY return;
519    sd->focus_func = func;
520 }
521
522 EAPI void
523 elm_widget_activate_hook_set(Evas_Object *obj,
524                              void       (*func)(Evas_Object *obj))
525 {
526    API_ENTRY return;
527    sd->activate_func = func;
528 }
529
530 EAPI void
531 elm_widget_disable_hook_set(Evas_Object *obj,
532                             void       (*func)(Evas_Object *obj))
533 {
534    API_ENTRY return;
535    sd->disable_func = func;
536 }
537
538 EAPI void
539 elm_widget_theme_hook_set(Evas_Object *obj,
540                           void       (*func)(Evas_Object *obj))
541 {
542    API_ENTRY return;
543    sd->theme_func = func;
544 }
545
546 EAPI void
547 elm_widget_translate_hook_set(Evas_Object *obj,
548                               void       (*func)(Evas_Object *obj))
549 {
550    API_ENTRY return;
551    sd->translate_func = func;
552 }
553
554 EAPI void
555 elm_widget_event_hook_set(Evas_Object *obj,
556                           Eina_Bool  (*func)(Evas_Object       *obj,
557                                              Evas_Object       *source,
558                                              Evas_Callback_Type type,
559                                              void              *event_info))
560 {
561    API_ENTRY return;
562    sd->event_func = func;
563 }
564
565 EAPI void
566 elm_widget_text_set_hook_set(Evas_Object *obj,
567                              Elm_Widget_On_Text_Set_Cb func)
568 {
569    API_ENTRY return;
570    sd->on_text_set_func = func;
571 }
572
573 EAPI void
574 elm_widget_text_get_hook_set(Evas_Object *obj,
575                              Elm_Widget_On_Text_Get_Cb func)
576 {
577    API_ENTRY return;
578    sd->on_text_get_func = func;
579 }
580
581 EAPI void
582 elm_widget_content_set_hook_set(Evas_Object *obj,
583                                 Elm_Widget_On_Content_Set_Cb func)
584 {
585    API_ENTRY return;
586    sd->on_content_set_func = func;
587 }
588
589 EAPI void
590 elm_widget_content_get_hook_set(Evas_Object *obj,
591                                 Elm_Widget_On_Content_Get_Cb func)
592 {
593    API_ENTRY return;
594    sd->on_content_get_func = func;
595 }
596
597 EAPI void
598 elm_widget_content_unset_hook_set(Evas_Object *obj,
599                                   Elm_Widget_On_Content_Unset_Cb func)
600 {
601    API_ENTRY return;
602    sd->on_content_unset_func = func;
603 }
604
605 EAPI void
606 elm_widget_changed_hook_set(Evas_Object *obj,
607                             void       (*func)(Evas_Object *obj))
608 {
609    API_ENTRY return;
610    sd->changed_func = func;
611 }
612
613 EAPI void
614 elm_widget_signal_emit_hook_set(Evas_Object *obj,
615                                 void       (*func)(Evas_Object *obj,
616                                                    const char *emission,
617                                                    const char *source))
618 {
619    API_ENTRY return;
620    sd->signal_func = func;
621 }
622
623 EAPI void
624 elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
625                                         void       (*func)(Evas_Object   *obj,
626                                                            const char    *emission,
627                                                            const char    *source,
628                                                            Edje_Signal_Cb func_cb,
629                                                            void          *data))
630 {
631    API_ENTRY return;
632    sd->callback_add_func = func;
633 }
634
635 EAPI void
636 elm_widget_signal_callback_del_hook_set(Evas_Object *obj,
637                                         void       (*func)(Evas_Object   *obj,
638                                                            const char    *emission,
639                                                            const char    *source,
640                                                            Edje_Signal_Cb func_cb,
641                                                            void          *data))
642 {
643    API_ENTRY return;
644    sd->callback_del_func = func;
645 }
646
647 EAPI void
648 elm_widget_theme(Evas_Object *obj)
649 {
650    const Eina_List *l;
651    Evas_Object *child;
652    Elm_Tooltip *tt;
653    Elm_Cursor *cur;
654
655    API_ENTRY return;
656    EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_theme(child);
657    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
658    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
659    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
660    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
661    if (sd->theme_func) sd->theme_func(obj);
662 }
663
664 EAPI void
665 elm_widget_theme_specific(Evas_Object *obj,
666                           Elm_Theme   *th,
667                           Eina_Bool    force)
668 {
669    const Eina_List *l;
670    Evas_Object *child;
671    Elm_Tooltip *tt;
672    Elm_Cursor *cur;
673    Elm_Theme *th2, *thdef;
674
675    API_ENTRY return;
676    thdef = elm_theme_default_get();
677    if (!th) th = thdef;
678    if (!force)
679      {
680         th2 = sd->theme;
681         if (!th2) th2 = thdef;
682         while (th2)
683           {
684              if (th2 == th)
685                {
686                   force = EINA_TRUE;
687                   break;
688                }
689              if (th2 == thdef) break;
690              th2 = th2->ref_theme;
691              if (!th2) th2 = thdef;
692           }
693      }
694    if (!force) return;
695    EINA_LIST_FOREACH(sd->subobjs, l, child)
696      elm_widget_theme_specific(child, th, force);
697    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
698    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
699    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
700    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
701    if (sd->theme_func) sd->theme_func(obj);
702 }
703
704 /**
705  * @internal
706  *
707  * Set hook to get next object in object focus chain.
708  *
709  * @param obj The widget object.
710  * @param func The hook to be used with this widget.
711  *
712  * @ingroup Widget
713  */
714 EAPI void
715 elm_widget_focus_next_hook_set(Evas_Object *obj,
716                                Eina_Bool  (*func)(const Evas_Object   *obj,
717                                                    Elm_Focus_Direction dir,
718                                                    Evas_Object       **next))
719 {
720    API_ENTRY return;
721    sd->focus_next_func = func;
722 }
723
724 /**
725  * Returns the widget's mirrored mode.
726  *
727  * @param obj The widget.
728  * @return mirrored mode of the object.
729  *
730  **/
731 EAPI Eina_Bool
732 elm_widget_mirrored_get(const Evas_Object *obj)
733 {
734    API_ENTRY return EINA_FALSE;
735    return sd->is_mirrored;
736 }
737
738 /**
739  * Sets the widget's mirrored mode.
740  *
741  * @param obj The widget.
742  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
743  */
744 EAPI void
745 elm_widget_mirrored_set(Evas_Object *obj,
746                         Eina_Bool    mirrored)
747 {
748    API_ENTRY return;
749    if (sd->is_mirrored != mirrored)
750      {
751         sd->is_mirrored = mirrored;
752         elm_widget_theme(obj);
753      }
754 }
755
756 /**
757  * @internal
758  * Resets the mirrored mode from the system mirror mode for widgets that are in
759  * automatic mirroring mode. This function does not call elm_widget_theme.
760  *
761  * @param obj The widget.
762  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
763  */
764 void
765 _elm_widget_mirrored_reload(Evas_Object *obj)
766 {
767    API_ENTRY return;
768    Eina_Bool mirrored = elm_mirrored_get();
769    if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
770      {
771         sd->is_mirrored = mirrored;
772      }
773 }
774
775 /**
776  * Returns the widget's mirrored mode setting.
777  *
778  * @param obj The widget.
779  * @return mirrored mode setting of the object.
780  *
781  **/
782 EAPI Eina_Bool
783 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
784 {
785    API_ENTRY return EINA_FALSE;
786    return sd->mirrored_auto_mode;
787 }
788
789 /**
790  * Sets the widget's mirrored mode setting.
791  * When widget in automatic mode, it follows the system mirrored mode set by
792  * elm_mirrored_set().
793  * @param obj The widget.
794  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
795  */
796 EAPI void
797 elm_widget_mirrored_automatic_set(Evas_Object *obj,
798                                   Eina_Bool    automatic)
799 {
800    API_ENTRY return;
801    if (sd->mirrored_auto_mode != automatic)
802      {
803         sd->mirrored_auto_mode = automatic;
804
805         if (automatic)
806           {
807              elm_widget_mirrored_set(obj, elm_mirrored_get());
808           }
809      }
810 }
811
812 EAPI void
813 elm_widget_on_focus_hook_set(Evas_Object *obj,
814                              void       (*func)(void *data,
815                                                 Evas_Object *obj),
816                              void        *data)
817 {
818    API_ENTRY return;
819    sd->on_focus_func = func;
820    sd->on_focus_data = data;
821 }
822
823 EAPI void
824 elm_widget_on_change_hook_set(Evas_Object *obj,
825                               void       (*func)(void *data,
826                                                  Evas_Object *obj),
827                               void        *data)
828 {
829    API_ENTRY return;
830    sd->on_change_func = func;
831    sd->on_change_data = data;
832 }
833
834 EAPI void
835 elm_widget_on_show_region_hook_set(Evas_Object *obj,
836                                    void       (*func)(void *data,
837                                                       Evas_Object *obj),
838                                    void        *data)
839 {
840    API_ENTRY return;
841    sd->on_show_region_func = func;
842    sd->on_show_region_data = data;
843 }
844
845 /**
846  * @internal
847  *
848  * Set the hook to use to show the focused region.
849  *
850  * Whenever a new widget gets focused or it's needed to show the focused
851  * area of the current one, this hook will be called on objects that may
852  * want to move their children into their visible area.
853  * The area given in the hook function is relative to the @p obj widget.
854  *
855  * @param obj The widget object
856  * @param func The function to call to show the specified area.
857  *
858  * @ingroup Widget
859  */
860 EAPI void
861 elm_widget_focus_region_hook_set(Evas_Object *obj,
862                                  void       (*func)(Evas_Object *obj,
863                                                     Evas_Coord x,
864                                                     Evas_Coord y,
865                                                     Evas_Coord w,
866                                                     Evas_Coord h))
867 {
868    API_ENTRY return;
869    sd->focus_region_func = func;
870 }
871
872 /**
873  * @internal
874  *
875  * Set the hook to retrieve the focused region of a widget.
876  *
877  * This hook will be called by elm_widget_focus_region_get() whenever
878  * it's needed to get the focused area of a widget. The area must be relative
879  * to the widget itself and if no hook is set, it will default to the entire
880  * object.
881  *
882  * @param obj The widget object
883  * @param func The function used to retrieve the focus region.
884  *
885  * @ingroup Widget
886  */
887 EAPI void
888 elm_widget_on_focus_region_hook_set(Evas_Object *obj,
889                                     void       (*func)(const Evas_Object *obj,
890                                                        Evas_Coord *x,
891                                                        Evas_Coord *y,
892                                                        Evas_Coord *w,
893                                                        Evas_Coord *h))
894 {
895    API_ENTRY return;
896    sd->on_focus_region_func = func;
897 }
898
899 EAPI void
900 elm_widget_data_set(Evas_Object *obj,
901                     void        *data)
902 {
903    API_ENTRY return;
904    sd->data = data;
905 }
906
907 EAPI void *
908 elm_widget_data_get(const Evas_Object *obj)
909 {
910    API_ENTRY return NULL;
911    return sd->data;
912 }
913
914 EAPI void
915 elm_widget_sub_object_add(Evas_Object *obj,
916                           Evas_Object *sobj)
917 {
918    API_ENTRY return;
919    double scale, pscale = elm_widget_scale_get(sobj);
920    Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
921    Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
922
923    if (_elm_widget_is(sobj))
924      {
925         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
926         if (sd2)
927           {
928              if (sd2->parent_obj == obj)
929                return;
930              if (sd2->parent_obj)
931                elm_widget_sub_object_del(sd2->parent_obj, sobj);
932              sd2->parent_obj = obj;
933              sd2->top_win_focused = sd->top_win_focused;
934              if (!sd->child_can_focus && (_is_focusable(sobj)))
935                sd->child_can_focus = EINA_TRUE;
936           }
937      }
938    else
939      {
940         void *data = evas_object_data_get(sobj, "elm-parent");
941         if (data)
942           {
943              if (data == obj) return;
944              evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
945                                             _sub_obj_del);
946           }
947      }
948
949    sd->subobjs = eina_list_append(sd->subobjs, sobj);
950    evas_object_data_set(sobj, "elm-parent", obj);
951    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
952    if (_elm_widget_is(sobj))
953      evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
954    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
955    scale = elm_widget_scale_get(sobj);
956    th = elm_widget_theme_get(sobj);
957    mirrored = elm_widget_mirrored_get(sobj);
958    if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
959    if (elm_widget_focus_get(sobj)) _focus_parents(obj);
960 }
961
962 EAPI void
963 elm_widget_sub_object_del(Evas_Object *obj,
964                           Evas_Object *sobj)
965 {
966    Evas_Object *sobj_parent;
967    API_ENTRY return;
968    if (!sobj) return;
969
970    sobj_parent = evas_object_data_del(sobj, "elm-parent");
971    if (sobj_parent != obj)
972      {
973         static int abort_on_warn = -1;
974         ERR("removing sub object %p from parent %p, "
975             "but elm-parent is different %p!",
976             sobj, obj, sobj_parent);
977         if (EINA_UNLIKELY(abort_on_warn == -1))
978           {
979              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
980              else abort_on_warn = 0;
981           }
982         if (abort_on_warn == 1) abort();
983      }
984    if (_elm_widget_is(sobj))
985      {
986         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
987         if (sd2)
988           {
989              sd2->parent_obj = NULL;
990              if (sd2->resize_obj == sobj)
991                sd2->resize_obj = NULL;
992              else
993                sd->subobjs = eina_list_remove(sd->subobjs, sobj);
994           }
995         else
996           sd->subobjs = eina_list_remove(sd->subobjs, sobj);
997         if (elm_widget_focus_get(sobj))
998           {
999              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1000              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1001           }
1002         if ((sd->child_can_focus) && (_is_focusable(sobj)))
1003           {
1004              Evas_Object *subobj;
1005              const Eina_List *l;
1006              sd->child_can_focus = EINA_FALSE;
1007              EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1008                {
1009                   if (_is_focusable(subobj))
1010                     {
1011                        sd->child_can_focus = EINA_TRUE;
1012                        break;
1013                     }
1014                }
1015           }
1016      }
1017    else
1018      sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1019    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1020                                        _sub_obj_del, sd);
1021    if (_elm_widget_is(sobj))
1022      evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1023                                          _sub_obj_hide, sd);
1024    evas_object_smart_callback_call(obj, "sub-object-del", sobj);
1025 }
1026
1027 EAPI void
1028 elm_widget_resize_object_set(Evas_Object *obj,
1029                              Evas_Object *sobj)
1030 {
1031    API_ENTRY return;
1032    // orphan previous resize obj
1033    if (sd->resize_obj)
1034      {
1035         evas_object_clip_unset(sd->resize_obj);
1036         evas_object_data_del(sd->resize_obj, "elm-parent");
1037         if (_elm_widget_is(sd->resize_obj))
1038           {
1039              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1040              if (sd2) sd2->parent_obj = NULL;
1041              evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_HIDE,
1042                                                  _sub_obj_hide, sd);
1043           }
1044         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
1045                                             _sub_obj_del, sd);
1046         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_DOWN,
1047                                             _sub_obj_mouse_down, sd);
1048         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_MOVE,
1049                                             _sub_obj_mouse_move, sd);
1050         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_UP,
1051                                             _sub_obj_mouse_up, sd);
1052         evas_object_smart_member_del(sd->resize_obj);
1053         if (_elm_widget_is(sd->resize_obj))
1054           {
1055              if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
1056           }
1057      }
1058
1059    sd->resize_obj = sobj;
1060    if (!sobj) return;
1061
1062    // orphan new resize obj
1063    evas_object_data_del(sobj, "elm-parent");
1064    if (_elm_widget_is(sobj))
1065      {
1066         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1067         if (sd2) sd2->parent_obj = NULL;
1068         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1069                                             _sub_obj_hide, sd);
1070      }
1071    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1072                                        _sub_obj_del, sd);
1073    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1074                                        _sub_obj_mouse_down, sd);
1075    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1076                                        _sub_obj_mouse_move, sd);
1077    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_UP,
1078                                        _sub_obj_mouse_up, sd);
1079    evas_object_smart_member_del(sobj);
1080    if (_elm_widget_is(sobj))
1081      {
1082         if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
1083      }
1084
1085    // set the resize obj up
1086    if (_elm_widget_is(sobj))
1087      {
1088         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1089         if (sd2)
1090           {
1091              sd2->parent_obj = obj;
1092              sd2->top_win_focused = sd->top_win_focused;
1093           }
1094         evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
1095                                        _sub_obj_hide, sd);
1096      }
1097    evas_object_clip_set(sobj, evas_object_clip_get(obj));
1098    evas_object_smart_member_add(sobj, obj);
1099    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1100                                   _sub_obj_del, sd);
1101    evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1102                                   _sub_obj_mouse_down, sd);
1103    evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1104                                   _sub_obj_mouse_move, sd);
1105    evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_UP,
1106                                   _sub_obj_mouse_up, sd);
1107    _smart_reconfigure(sd);
1108    evas_object_data_set(sobj, "elm-parent", obj);
1109    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
1110    if (_elm_widget_is(sobj))
1111      {
1112         if (elm_widget_focus_get(sobj)) _focus_parents(obj);
1113      }
1114 }
1115
1116 EAPI void
1117 elm_widget_hover_object_set(Evas_Object *obj,
1118                             Evas_Object *sobj)
1119 {
1120    API_ENTRY return;
1121    if (sd->hover_obj)
1122      {
1123         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1124                                             _sub_obj_del, sd);
1125      }
1126    sd->hover_obj = sobj;
1127    if (sd->hover_obj)
1128      {
1129         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1130                                        _sub_obj_del, sd);
1131         _smart_reconfigure(sd);
1132      }
1133 }
1134
1135 EAPI void
1136 elm_widget_can_focus_set(Evas_Object *obj,
1137                          Eina_Bool    can_focus)
1138 {
1139    API_ENTRY return;
1140    sd->can_focus = can_focus;
1141    if (can_focus)
1142      {
1143         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1144                                        _propagate_event,
1145                                        (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1146         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1147                                        _propagate_event,
1148                                        (void *)(long)EVAS_CALLBACK_KEY_UP);
1149         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1150                                        _propagate_event,
1151                                        (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1152      }
1153    else
1154      {
1155         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1156                                        _propagate_event);
1157         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1158                                        _propagate_event);
1159         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1160                                        _propagate_event);
1161      }
1162 }
1163
1164 EAPI Eina_Bool
1165 elm_widget_can_focus_get(const Evas_Object *obj)
1166 {
1167    API_ENTRY return EINA_FALSE;
1168    return sd->can_focus;
1169 }
1170
1171 EAPI Eina_Bool
1172 elm_widget_child_can_focus_get(const Evas_Object *obj)
1173 {
1174    API_ENTRY return EINA_FALSE;
1175    return sd->child_can_focus;
1176 }
1177
1178 /**
1179  * @internal
1180  *
1181  * This API makes the widget object and its children to be unfocusable.
1182  *
1183  * This API can be helpful for an object to be deleted.
1184  * When an object will be deleted soon, it and its children may not
1185  * want to get focus (by focus reverting or by other focus controls).
1186  * Then, just use this API before deleting.
1187  *
1188  * @param obj The widget root of sub-tree
1189  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1190  *
1191  * @ingroup Widget
1192  */
1193 EAPI void
1194 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1195                                 Eina_Bool    tree_unfocusable)
1196 {
1197    API_ENTRY return;
1198
1199    if (sd->tree_unfocusable == tree_unfocusable) return;
1200    sd->tree_unfocusable = !!tree_unfocusable;
1201    elm_widget_focus_tree_unfocusable_handle(obj);
1202 }
1203
1204 /**
1205  * @internal
1206  *
1207  * This returns true, if the object sub-tree is unfocusable.
1208  *
1209  * @param obj The widget root of sub-tree
1210  * @return EINA_TRUE if the object sub-tree is unfocusable
1211  *
1212  * @ingroup Widget
1213  */
1214 EAPI Eina_Bool
1215 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1216 {
1217    API_ENTRY return EINA_FALSE;
1218    return sd->tree_unfocusable;
1219 }
1220
1221 /**
1222  * @internal
1223  *
1224  * Get the list of focusable child objects.
1225  *
1226  * This function retruns list of child objects which can get focus.
1227  *
1228  * @param obj The parent widget
1229  * @retrun list of focusable child objects.
1230  *
1231  * @ingroup Widget
1232  */
1233 EAPI Eina_List *
1234 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1235 {
1236    API_ENTRY return NULL;
1237
1238    const Eina_List *l;
1239    Eina_List *child_list = NULL;
1240    Evas_Object *child;
1241
1242    if (sd->subobjs)
1243      {
1244         EINA_LIST_FOREACH(sd->subobjs, l, child)
1245           {
1246              if ((elm_widget_can_focus_get(child)) &&
1247                  (evas_object_visible_get(child)) &&
1248                  (!elm_widget_disabled_get(child)))
1249                child_list = eina_list_append(child_list, child);
1250              else if (elm_widget_is(child))
1251                {
1252                   Eina_List *can_focus_list;
1253                   can_focus_list = elm_widget_can_focus_child_list_get(child);
1254                   if (can_focus_list)
1255                     child_list = eina_list_merge(child_list, can_focus_list);
1256                }
1257           }
1258      }
1259    return child_list;
1260 }
1261
1262 EAPI void
1263 elm_widget_highlight_ignore_set(Evas_Object *obj,
1264                                 Eina_Bool    ignore)
1265 {
1266    API_ENTRY return;
1267    sd->highlight_ignore = !!ignore;
1268 }
1269
1270 EAPI Eina_Bool
1271 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1272 {
1273    API_ENTRY return EINA_FALSE;
1274    return sd->highlight_ignore;
1275 }
1276
1277 EAPI void
1278 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1279                                   Eina_Bool    highlight)
1280 {
1281    API_ENTRY return;
1282    sd->highlight_in_theme = !!highlight;
1283    /* FIXME: if focused, it should switch from one mode to the other */
1284 }
1285
1286 EAPI Eina_Bool
1287 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1288 {
1289    API_ENTRY return EINA_FALSE;
1290    return sd->highlight_in_theme;
1291 }
1292
1293 EAPI Eina_Bool
1294 elm_widget_focus_get(const Evas_Object *obj)
1295 {
1296    API_ENTRY return EINA_FALSE;
1297    return sd->focused;
1298 }
1299
1300 EAPI Evas_Object *
1301 elm_widget_focused_object_get(const Evas_Object *obj)
1302 {
1303    const Evas_Object *subobj;
1304    const Eina_List *l;
1305    API_ENTRY return NULL;
1306
1307    if (!sd->focused) return NULL;
1308    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1309      {
1310         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1311         if (fobj) return fobj;
1312      }
1313    return (Evas_Object *)obj;
1314 }
1315
1316 EAPI Evas_Object *
1317 elm_widget_top_get(const Evas_Object *obj)
1318 {
1319    API_ENTRY return NULL;
1320    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1321    return (Evas_Object *)obj;
1322 }
1323
1324 EAPI Eina_Bool
1325 elm_widget_is(const Evas_Object *obj)
1326 {
1327    return _elm_widget_is(obj);
1328 }
1329
1330 EAPI Evas_Object *
1331 elm_widget_parent_widget_get(const Evas_Object *obj)
1332 {
1333    Evas_Object *parent;
1334
1335    if (_elm_widget_is(obj))
1336      {
1337         Smart_Data *sd = evas_object_smart_data_get(obj);
1338         if (!sd) return NULL;
1339         parent = sd->parent_obj;
1340      }
1341    else
1342      {
1343         parent = evas_object_data_get(obj, "elm-parent");
1344         if (!parent) parent = evas_object_smart_parent_get(obj);
1345      }
1346
1347    while (parent)
1348      {
1349         Evas_Object *elm_parent;
1350         if (_elm_widget_is(parent)) break;
1351         elm_parent = evas_object_data_get(parent, "elm-parent");
1352         if (elm_parent) parent = elm_parent;
1353         else parent = evas_object_smart_parent_get(parent);
1354      }
1355    return parent;
1356 }
1357
1358 EAPI Evas_Object *
1359 elm_widget_parent2_get(const Evas_Object *obj)
1360 {
1361    if (_elm_widget_is(obj))
1362      {
1363         Smart_Data *sd = evas_object_smart_data_get(obj);
1364         if (sd) return sd->parent2;
1365      }
1366    return NULL;
1367 }
1368
1369 EAPI void
1370 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1371 {
1372    API_ENTRY return;
1373    sd->parent2 = parent;
1374 }
1375
1376 EAPI void
1377 elm_widget_event_callback_add(Evas_Object *obj,
1378                               Elm_Event_Cb func,
1379                               const void  *data)
1380 {
1381    API_ENTRY return;
1382    EINA_SAFETY_ON_NULL_RETURN(func);
1383    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1384    ecb->func = func;
1385    ecb->data = data;
1386    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1387 }
1388
1389 EAPI void *
1390 elm_widget_event_callback_del(Evas_Object *obj,
1391                               Elm_Event_Cb func,
1392                               const void  *data)
1393 {
1394    API_ENTRY return NULL;
1395    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1396    Eina_List *l;
1397    Elm_Event_Cb_Data *ecd;
1398    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1399      if ((ecd->func == func) && (ecd->data == data))
1400        {
1401           free(ecd);
1402           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1403           return (void *)data;
1404        }
1405    return NULL;
1406 }
1407
1408 EAPI Eina_Bool
1409 elm_widget_event_propagate(Evas_Object       *obj,
1410                            Evas_Callback_Type type,
1411                            void              *event_info,
1412                            Evas_Event_Flags  *event_flags)
1413 {
1414    API_ENTRY return EINA_FALSE; //TODO reduce.
1415    if (!_elm_widget_is(obj)) return EINA_FALSE;
1416    Evas_Object *parent = obj;
1417    Elm_Event_Cb_Data *ecd;
1418    Eina_List *l, *l_prev;
1419
1420    while (parent &&
1421           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1422      {
1423         sd = evas_object_smart_data_get(parent);
1424         if ((!sd) || (!_elm_widget_is(obj)))
1425           return EINA_FALSE; //Not Elm Widget
1426
1427         if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1428           return EINA_TRUE;
1429
1430         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1431           {
1432              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1433                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1434                return EINA_TRUE;
1435           }
1436         parent = sd->parent_obj;
1437      }
1438
1439    return EINA_FALSE;
1440 }
1441
1442 /**
1443  * @internal
1444  *
1445  * Set custom focus chain.
1446  *
1447  * This function i set one new and overwrite any previous custom focus chain
1448  * with the list of objects. The previous list will be deleted and this list
1449  * will be managed. After setted, don't modity it.
1450  *
1451  * @note On focus cycle, only will be evaluated children of this container.
1452  *
1453  * @param obj The container widget
1454  * @param objs Chain of objects to pass focus
1455  * @ingroup Widget
1456  */
1457 EAPI void
1458 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1459                                   Eina_List   *objs)
1460 {
1461    API_ENTRY return;
1462    if (!sd->focus_next_func)
1463      return;
1464
1465    elm_widget_focus_custom_chain_unset(obj);
1466
1467    Eina_List *l;
1468    Evas_Object *o;
1469
1470    EINA_LIST_FOREACH(objs, l, o)
1471      {
1472         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1473                                        _elm_object_focus_chain_del_cb, sd);
1474      }
1475
1476    sd->focus_chain = objs;
1477 }
1478
1479 /**
1480  * @internal
1481  *
1482  * Get custom focus chain
1483  *
1484  * @param obj The container widget
1485  * @ingroup Widget
1486  */
1487 EAPI const Eina_List *
1488 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1489 {
1490    API_ENTRY return NULL;
1491    return (const Eina_List *)sd->focus_chain;
1492 }
1493
1494 /**
1495  * @internal
1496  *
1497  * Unset custom focus chain
1498  *
1499  * @param obj The container widget
1500  * @ingroup Widget
1501  */
1502 EAPI void
1503 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1504 {
1505    API_ENTRY return;
1506    Eina_List *l, *l_next;
1507    Evas_Object *o;
1508
1509    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1510      {
1511         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1512                                             _elm_object_focus_chain_del_cb, sd);
1513         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1514      }
1515 }
1516
1517 /**
1518  * @internal
1519  *
1520  * Append object to custom focus chain.
1521  *
1522  * @note If relative_child equal to NULL or not in custom chain, the object
1523  * will be added in end.
1524  *
1525  * @note On focus cycle, only will be evaluated children of this container.
1526  *
1527  * @param obj The container widget
1528  * @param child The child to be added in custom chain
1529  * @param relative_child The relative object to position the child
1530  * @ingroup Widget
1531  */
1532 EAPI void
1533 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1534                                      Evas_Object *child,
1535                                      Evas_Object *relative_child)
1536 {
1537    API_ENTRY return;
1538    EINA_SAFETY_ON_NULL_RETURN(child);
1539    if (!sd->focus_next_func)
1540      return;
1541
1542    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1543                                        _elm_object_focus_chain_del_cb, sd);
1544
1545    if (!relative_child)
1546      {
1547         sd->focus_chain = eina_list_append(sd->focus_chain, child);
1548         return;
1549      }
1550
1551    sd->focus_chain = eina_list_append_relative(sd->focus_chain, child, relative_child);
1552    return;
1553 }
1554
1555 /**
1556  * @internal
1557  *
1558  * Prepend object to custom focus chain.
1559  *
1560  * @note If relative_child equal to NULL or not in custom chain, the object
1561  * will be added in begin.
1562  *
1563  * @note On focus cycle, only will be evaluated children of this container.
1564  *
1565  * @param obj The container widget
1566  * @param child The child to be added in custom chain
1567  * @param relative_child The relative object to position the child
1568  * @ingroup Widget
1569  */
1570 EAPI void
1571 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1572                                       Evas_Object *child,
1573                                       Evas_Object *relative_child)
1574 {
1575    API_ENTRY return;
1576    EINA_SAFETY_ON_NULL_RETURN(child);
1577    if (!sd->focus_next_func)
1578      return;
1579
1580    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1581                                        _elm_object_focus_chain_del_cb, sd);
1582
1583    if (!relative_child)
1584      {
1585         sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1586         return;
1587      }
1588
1589    sd->focus_chain = eina_list_prepend_relative(sd->focus_chain, child, relative_child);
1590    return;
1591 }
1592
1593 /**
1594  * @internal
1595  *
1596  * Give focus to next object in object tree.
1597  *
1598  * Give focus to next object in focus chain of one object sub-tree.
1599  * If the last object of chain already have focus, the focus will go to the
1600  * first object of chain.
1601  *
1602  * @param obj The widget root of sub-tree
1603  * @param dir Direction to cycle the focus
1604  *
1605  * @ingroup Widget
1606  */
1607 EAPI void
1608 elm_widget_focus_cycle(Evas_Object        *obj,
1609                        Elm_Focus_Direction dir)
1610 {
1611    Evas_Object *target = NULL;
1612    if (!_elm_widget_is(obj))
1613      return;
1614    elm_widget_focus_next_get(obj, dir, &target);
1615    if (target)
1616      elm_widget_focus_steal(target);
1617 }
1618
1619 /**
1620  * @internal
1621  *
1622  * Give focus to near object in one direction.
1623  *
1624  * Give focus to near object in direction of one object.
1625  * If none focusable object in given direction, the focus will not change.
1626  *
1627  * @param obj The reference widget
1628  * @param x Horizontal component of direction to focus
1629  * @param y Vertical component of direction to focus
1630  *
1631  * @ingroup Widget
1632  */
1633 EAPI void
1634 elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1635                               int          x __UNUSED__,
1636                               int          y __UNUSED__)
1637 {
1638    return; /* TODO */
1639 }
1640
1641 /**
1642  * @internal
1643  *
1644  * Get next object in focus chain of object tree.
1645  *
1646  * Get next object in focus chain of one object sub-tree.
1647  * Return the next object by reference. If don't have any candidate to receive
1648  * focus before chain end, the first candidate will be returned.
1649  *
1650  * @param obj The widget root of sub-tree
1651  * @param dir Direction os focus chain
1652  * @param next The next object in focus chain
1653  * @return EINA_TRUE if don't need focus chain restart/loop back
1654  *         to use 'next' obj.
1655  *
1656  * @ingroup Widget
1657  */
1658 EAPI Eina_Bool
1659 elm_widget_focus_next_get(const Evas_Object  *obj,
1660                           Elm_Focus_Direction dir,
1661                           Evas_Object       **next)
1662 {
1663    if (!next)
1664      return EINA_FALSE;
1665    *next = NULL;
1666
1667    API_ENTRY return EINA_FALSE;
1668
1669    /* Ignore if disabled */
1670    if ((!evas_object_visible_get(obj))
1671        || (elm_widget_disabled_get(obj))
1672        || (elm_widget_tree_unfocusable_get(obj)))
1673      return EINA_FALSE;
1674
1675    /* Try use hook */
1676    if (sd->focus_next_func)
1677      return sd->focus_next_func(obj, dir, next);
1678
1679    if (!elm_widget_can_focus_get(obj))
1680      return EINA_FALSE;
1681
1682    /* Return */
1683    *next = (Evas_Object *)obj;
1684    return !elm_widget_focus_get(obj);
1685 }
1686
1687 /**
1688  * @internal
1689  *
1690  * Get next object in focus chain of object tree in list.
1691  *
1692  * Get next object in focus chain of one object sub-tree ordered by one list.
1693  * Return the next object by reference. If don't have any candidate to receive
1694  * focus before list end, the first candidate will be returned.
1695  *
1696  * @param obj The widget root of sub-tree
1697  * @param dir Direction os focus chain
1698  * @param items list with ordered objects
1699  * @param list_data_get function to get the object from one item of list
1700  * @param next The next object in focus chain
1701  * @return EINA_TRUE if don't need focus chain restart/loop back
1702  *         to use 'next' obj.
1703  *
1704  * @ingroup Widget
1705  */
1706 EAPI Eina_Bool
1707 elm_widget_focus_list_next_get(const Evas_Object  *obj,
1708                                const Eina_List    *items,
1709                                void *(*list_data_get)(const Eina_List * list),
1710                                Elm_Focus_Direction dir,
1711                                Evas_Object       **next)
1712 {
1713    Eina_List *(*list_next)(const Eina_List * list) = NULL;
1714
1715    if (!next)
1716      return EINA_FALSE;
1717    *next = NULL;
1718
1719    if (!_elm_widget_is(obj))
1720      return EINA_FALSE;
1721
1722    if (!items)
1723      return EINA_FALSE;
1724
1725    /* Direction */
1726    if (dir == ELM_FOCUS_PREVIOUS)
1727      {
1728         items = eina_list_last(items);
1729         list_next = eina_list_prev;
1730      }
1731    else if (dir == ELM_FOCUS_NEXT)
1732      list_next = eina_list_next;
1733    else
1734      return EINA_FALSE;
1735
1736    const Eina_List *l = items;
1737
1738    /* Recovery last focused sub item */
1739    if (elm_widget_focus_get(obj))
1740      for (; l; l = list_next(l))
1741        {
1742           Evas_Object *cur = list_data_get(l);
1743           if (elm_widget_focus_get(cur)) break;
1744        }
1745
1746    const Eina_List *start = l;
1747    Evas_Object *to_focus = NULL;
1748
1749    /* Interate sub items */
1750    /* Go to end of list */
1751    for (; l; l = list_next(l))
1752      {
1753         Evas_Object *tmp = NULL;
1754         Evas_Object *cur = list_data_get(l);
1755
1756         if (elm_widget_parent_get(cur) != obj)
1757           continue;
1758
1759         /* Try Focus cycle in subitem */
1760         if (elm_widget_focus_next_get(cur, dir, &tmp))
1761           {
1762              *next = tmp;
1763              return EINA_TRUE;
1764           }
1765         else if ((tmp) && (!to_focus))
1766           to_focus = tmp;
1767      }
1768
1769    l = items;
1770
1771    /* Get First possible */
1772    for (; l != start; l = list_next(l))
1773      {
1774         Evas_Object *tmp = NULL;
1775         Evas_Object *cur = list_data_get(l);
1776
1777         if (elm_widget_parent_get(cur) != obj)
1778           continue;
1779
1780         /* Try Focus cycle in subitem */
1781         elm_widget_focus_next_get(cur, dir, &tmp);
1782         if (tmp)
1783           {
1784              *next = tmp;
1785              return EINA_FALSE;
1786           }
1787      }
1788
1789    *next = to_focus;
1790    return EINA_FALSE;
1791 }
1792
1793 EAPI void
1794 elm_widget_signal_emit(Evas_Object *obj,
1795                        const char  *emission,
1796                        const char  *source)
1797 {
1798    API_ENTRY return;
1799    if (!sd->signal_func) return;
1800    sd->signal_func(obj, emission, source);
1801 }
1802
1803 static void
1804 _edje_signal_callback(void        *data,
1805                       Evas_Object *obj __UNUSED__,
1806                       const char  *emission,
1807                       const char  *source)
1808 {
1809    Edje_Signal_Data *esd = data;
1810    esd->func(esd->data, esd->obj, emission, source);
1811 }
1812
1813 EAPI void
1814 elm_widget_signal_callback_add(Evas_Object   *obj,
1815                                const char    *emission,
1816                                const char    *source,
1817                                Edje_Signal_Cb func,
1818                                void          *data)
1819 {
1820    Edje_Signal_Data *esd;
1821    API_ENTRY return;
1822    if (!sd->callback_add_func) return;
1823    EINA_SAFETY_ON_NULL_RETURN(func);
1824
1825    esd = ELM_NEW(Edje_Signal_Data);
1826    if (!esd) return;
1827
1828    esd->obj = obj;
1829    esd->func = func;
1830    esd->emission = eina_stringshare_add(emission);
1831    esd->source = eina_stringshare_add(source);
1832    esd->data = data;
1833    sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1834    sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1835 }
1836
1837 EAPI void *
1838 elm_widget_signal_callback_del(Evas_Object   *obj,
1839                                const char    *emission,
1840                                const char    *source,
1841                                Edje_Signal_Cb func)
1842 {
1843    Edje_Signal_Data *esd;
1844    Eina_List *l;
1845    void *data = NULL;
1846    API_ENTRY return NULL;
1847    if (!sd->callback_del_func) return NULL;
1848
1849    EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1850      {
1851         if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1852             (!strcmp(esd->source, source)))
1853           {
1854              sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1855              eina_stringshare_del(esd->emission);
1856              eina_stringshare_del(esd->source);
1857              data = esd->data;
1858              free(esd);
1859              break;
1860           }
1861      }
1862    sd->callback_del_func(obj, emission, source, _edje_signal_callback, esd);
1863    return data;
1864 }
1865
1866 EAPI void
1867 elm_widget_focus_set(Evas_Object *obj,
1868                      int          first)
1869 {
1870    API_ENTRY return;
1871    if (!sd->focused)
1872      {
1873         focus_order++;
1874         sd->focus_order = focus_order;
1875         sd->focused = EINA_TRUE;
1876         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1877      }
1878    if (sd->focus_func)
1879      {
1880         sd->focus_func(obj);
1881         return;
1882      }
1883    else
1884      {
1885         if (first)
1886           {
1887              if ((_is_focusable(sd->resize_obj)) &&
1888                  (!elm_widget_disabled_get(sd->resize_obj)))
1889                {
1890                   elm_widget_focus_set(sd->resize_obj, first);
1891                }
1892              else
1893                {
1894                   const Eina_List *l;
1895                   Evas_Object *child;
1896                   EINA_LIST_FOREACH(sd->subobjs, l, child)
1897                     {
1898                        if ((_is_focusable(child)) &&
1899                            (!elm_widget_disabled_get(child)))
1900                          {
1901                             elm_widget_focus_set(child, first);
1902                             break;
1903                          }
1904                     }
1905                }
1906           }
1907         else
1908           {
1909              const Eina_List *l;
1910              Evas_Object *child;
1911              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1912                {
1913                   if ((_is_focusable(child)) &&
1914                       (!elm_widget_disabled_get(child)))
1915                     {
1916                        elm_widget_focus_set(child, first);
1917                        break;
1918                     }
1919                }
1920              if (!l)
1921                {
1922                   if ((_is_focusable(sd->resize_obj)) &&
1923                       (!elm_widget_disabled_get(sd->resize_obj)))
1924                     {
1925                        elm_widget_focus_set(sd->resize_obj, first);
1926                     }
1927                }
1928           }
1929      }
1930 }
1931
1932 EAPI Evas_Object *
1933 elm_widget_parent_get(const Evas_Object *obj)
1934 {
1935    API_ENTRY return NULL;
1936    return sd->parent_obj;
1937 }
1938
1939 EAPI void
1940 elm_widget_focused_object_clear(Evas_Object *obj)
1941 {
1942    API_ENTRY return;
1943    if (!sd->focused) return;
1944    if (elm_widget_focus_get(sd->resize_obj))
1945      elm_widget_focused_object_clear(sd->resize_obj);
1946    else
1947      {
1948         const Eina_List *l;
1949         Evas_Object *child;
1950         EINA_LIST_FOREACH(sd->subobjs, l, child)
1951           {
1952              if (elm_widget_focus_get(child))
1953                {
1954                   elm_widget_focused_object_clear(child);
1955                   break;
1956                }
1957           }
1958      }
1959    sd->focused = EINA_FALSE;
1960    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1961    if (sd->focus_func) sd->focus_func(obj);
1962 }
1963
1964 EAPI void
1965 elm_widget_focus_steal(Evas_Object *obj)
1966 {
1967    Evas_Object *parent, *parent2, *o;
1968    API_ENTRY return;
1969
1970    if (sd->focused) return;
1971    if (sd->disabled) return;
1972    if (!sd->can_focus) return;
1973    if (sd->tree_unfocusable) return;
1974    parent = obj;
1975    for (;;)
1976      {
1977         o = elm_widget_parent_get(parent);
1978         if (!o) break;
1979         sd = evas_object_smart_data_get(o);
1980         if (sd->disabled || sd->tree_unfocusable) return;
1981         if (sd->focused) break;
1982         parent = o;
1983      }
1984    if ((!elm_widget_parent_get(parent)) &&
1985        (!elm_widget_parent2_get(parent)))
1986       elm_widget_focused_object_clear(parent);
1987    else
1988      {
1989         parent2 = elm_widget_parent_get(parent);
1990         if (!parent2) parent2 = elm_widget_parent2_get(parent);
1991         parent = parent2;
1992         sd = evas_object_smart_data_get(parent);
1993         if (sd)
1994           {
1995              if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
1996                 elm_widget_focused_object_clear(sd->resize_obj);
1997              else
1998                {
1999                   const Eina_List *l;
2000                   Evas_Object *child;
2001                   EINA_LIST_FOREACH(sd->subobjs, l, child)
2002                     {
2003                        if (elm_widget_focus_get(child))
2004                          {
2005                             elm_widget_focused_object_clear(child);
2006                             break;
2007                          }
2008                     }
2009                }
2010           }
2011      }
2012    _parent_focus(obj);
2013    return;
2014 }
2015
2016 EAPI void
2017 elm_widget_focus_restore(Evas_Object *obj)
2018 {
2019    Evas_Object *newest = NULL;
2020    unsigned int newest_focus_order = 0;
2021    API_ENTRY return;
2022
2023    newest = _newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2024    if (newest)
2025      {
2026         elm_object_focus_set(newest, EINA_FALSE);
2027         elm_object_focus_set(newest, EINA_TRUE);
2028      }
2029 }
2030
2031 void
2032 _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused)
2033 {
2034    const Eina_List *l;
2035    Evas_Object *child;
2036    API_ENTRY return;
2037
2038    if (sd->top_win_focused == top_win_focused) return;
2039    if (sd->resize_obj)
2040      _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2041    EINA_LIST_FOREACH(sd->subobjs, l, child)
2042      {
2043         _elm_widget_top_win_focused_set(child, top_win_focused);
2044      }
2045    sd->top_win_focused = top_win_focused;
2046 }
2047
2048 Eina_Bool
2049 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2050 {
2051    API_ENTRY return EINA_FALSE;
2052    return sd->top_win_focused;
2053 }
2054
2055 EAPI void
2056 elm_widget_activate(Evas_Object *obj)
2057 {
2058    API_ENTRY return;
2059    elm_widget_change(obj);
2060    if (sd->activate_func) sd->activate_func(obj);
2061 }
2062
2063 EAPI void
2064 elm_widget_change(Evas_Object *obj)
2065 {
2066    API_ENTRY return;
2067    elm_widget_change(elm_widget_parent_get(obj));
2068    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
2069 }
2070
2071 EAPI void
2072 elm_widget_disabled_set(Evas_Object *obj,
2073                         Eina_Bool    disabled)
2074 {
2075    API_ENTRY return;
2076
2077    if (sd->disabled == disabled) return;
2078    sd->disabled = !!disabled;
2079    elm_widget_focus_disabled_handle(obj);
2080    if (sd->disable_func) sd->disable_func(obj);
2081 }
2082
2083 EAPI Eina_Bool
2084 elm_widget_disabled_get(const Evas_Object *obj)
2085 {
2086    API_ENTRY return 0;
2087    return sd->disabled;
2088 }
2089
2090 EAPI void
2091 elm_widget_show_region_set(Evas_Object *obj,
2092                            Evas_Coord   x,
2093                            Evas_Coord   y,
2094                            Evas_Coord   w,
2095                            Evas_Coord   h,
2096                            Eina_Bool    forceshow)
2097 {
2098    Evas_Object *parent_obj, *child_obj;
2099    Evas_Coord px, py, cx, cy;
2100
2101    API_ENTRY return;
2102    if (!forceshow && (x == sd->rx) && (y == sd->ry)
2103             && (w == sd->rw) && (h == sd->rh)) return;
2104    sd->rx = x;
2105    sd->ry = y;
2106    sd->rw = w;
2107    sd->rh = h;
2108    if (sd->on_show_region_func)
2109      sd->on_show_region_func(sd->on_show_region_data, obj);
2110
2111    do
2112      {
2113         parent_obj = sd->parent_obj;
2114         child_obj = sd->obj;
2115         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2116         sd = evas_object_smart_data_get(parent_obj);
2117         if (!sd) break;
2118
2119         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2120         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2121
2122         x += (cx - px);
2123         y += (cy - py);
2124         sd->rx = x;
2125         sd->ry = y;
2126         sd->rw = w;
2127         sd->rh = h;
2128
2129         if (sd->on_show_region_func)
2130           {
2131              sd->on_show_region_func(sd->on_show_region_data, parent_obj);
2132           }
2133      }
2134    while (parent_obj);
2135 }
2136
2137 EAPI void
2138 elm_widget_show_region_get(const Evas_Object *obj,
2139                            Evas_Coord        *x,
2140                            Evas_Coord        *y,
2141                            Evas_Coord        *w,
2142                            Evas_Coord        *h)
2143 {
2144    API_ENTRY return;
2145    if (x) *x = sd->rx;
2146    if (y) *y = sd->ry;
2147    if (w) *w = sd->rw;
2148    if (h) *h = sd->rh;
2149 }
2150
2151 /**
2152  * @internal
2153  *
2154  * Get the focus region of the given widget.
2155  *
2156  * The focus region is the area of a widget that should brought into the
2157  * visible area when the widget is focused. Mostly used to show the part of
2158  * an entry where the cursor is, for example. The area returned is relative
2159  * to the object @p obj.
2160  * If the @p obj doesn't have the proper on_focus_region_hook set, this
2161  * function will return the full size of the object.
2162  *
2163  * @param obj The widget object
2164  * @param x Where to store the x coordinate of the area
2165  * @param y Where to store the y coordinate of the area
2166  * @param w Where to store the width of the area
2167  * @param h Where to store the height of the area
2168  *
2169  * @ingroup Widget
2170  */
2171 EAPI void
2172 elm_widget_focus_region_get(const Evas_Object *obj,
2173                             Evas_Coord        *x,
2174                             Evas_Coord        *y,
2175                             Evas_Coord        *w,
2176                             Evas_Coord        *h)
2177 {
2178    Smart_Data *sd;
2179
2180    if (!obj) return;
2181
2182    sd = evas_object_smart_data_get(obj);
2183    if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
2184      {
2185         evas_object_geometry_get(obj, NULL, NULL, w, h);
2186         if (x) *x = 0;
2187         if (y) *y = 0;
2188         return;
2189      }
2190    sd->on_focus_region_func(obj, x, y, w, h);
2191 }
2192
2193 EAPI void
2194 elm_widget_scroll_hold_push(Evas_Object *obj)
2195 {
2196    API_ENTRY return;
2197    sd->scroll_hold++;
2198    if (sd->scroll_hold == 1)
2199      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
2200    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2201    // FIXME: on delete/reparent hold pop
2202 }
2203
2204 EAPI void
2205 elm_widget_scroll_hold_pop(Evas_Object *obj)
2206 {
2207    API_ENTRY return;
2208    sd->scroll_hold--;
2209    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2210    if (!sd->scroll_hold)
2211      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
2212    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2213 }
2214
2215 EAPI int
2216 elm_widget_scroll_hold_get(const Evas_Object *obj)
2217 {
2218    API_ENTRY return 0;
2219    return sd->scroll_hold;
2220 }
2221
2222 EAPI void
2223 elm_widget_scroll_freeze_push(Evas_Object *obj)
2224 {
2225    API_ENTRY return;
2226    sd->scroll_freeze++;
2227    if (sd->scroll_freeze == 1)
2228      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
2229    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2230    // FIXME: on delete/reparent freeze pop
2231 }
2232
2233 EAPI void
2234 elm_widget_scroll_freeze_pop(Evas_Object *obj)
2235 {
2236    API_ENTRY return;
2237    sd->scroll_freeze--;
2238    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2239    if (!sd->scroll_freeze)
2240      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
2241    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
2242 }
2243
2244 EAPI int
2245 elm_widget_scroll_freeze_get(const Evas_Object *obj)
2246 {
2247    API_ENTRY return 0;
2248    return sd->scroll_freeze;
2249 }
2250
2251 EAPI void
2252 elm_widget_scale_set(Evas_Object *obj,
2253                      double       scale)
2254 {
2255    API_ENTRY return;
2256    if (scale <= 0.0) scale = 0.0;
2257    if (sd->scale != scale)
2258      {
2259         sd->scale = scale;
2260         elm_widget_theme(obj);
2261      }
2262 }
2263
2264 EAPI double
2265 elm_widget_scale_get(const Evas_Object *obj)
2266 {
2267    API_ENTRY return 1.0;
2268    // FIXME: save walking up the tree by storing/caching parent scale
2269    if (sd->scale == 0.0)
2270      {
2271         if (sd->parent_obj)
2272           return elm_widget_scale_get(sd->parent_obj);
2273         else
2274           return 1.0;
2275      }
2276    return sd->scale;
2277 }
2278
2279 EAPI void
2280 elm_widget_theme_set(Evas_Object *obj,
2281                      Elm_Theme   *th)
2282 {
2283    API_ENTRY return;
2284    if (sd->theme != th)
2285      {
2286         if (sd->theme) elm_theme_free(sd->theme);
2287         sd->theme = th;
2288         if (th) th->ref++;
2289         elm_widget_theme(obj);
2290      }
2291 }
2292
2293 EAPI void
2294 elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label)
2295 {
2296    API_ENTRY return;
2297
2298    if (!sd->on_text_set_func)
2299      return;
2300
2301    sd->on_text_set_func(obj, part, label);
2302 }
2303
2304 EAPI const char *
2305 elm_widget_text_part_get(const Evas_Object *obj, const char *part)
2306 {
2307    API_ENTRY return NULL;
2308
2309    if (!sd->on_text_get_func)
2310      return NULL;
2311
2312    return sd->on_text_get_func(obj, part);
2313 }
2314
2315 EAPI void
2316 elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
2317 {
2318    const char *str;
2319    Eina_List *l;
2320    Elm_Translate_String_Data *ts = NULL;
2321    API_ENTRY return;
2322
2323    str = eina_stringshare_add(part);
2324    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2325       if (ts->id == str)
2326         break;
2327       else
2328         ts = NULL;
2329
2330    if (!ts && !label)
2331      eina_stringshare_del(str);
2332    else if (!ts)
2333      {
2334         ts = malloc(sizeof(Elm_Translate_String_Data));
2335         if (!ts) return;
2336
2337         ts->id = str;
2338         ts->domain = eina_stringshare_add(domain);
2339         ts->string = eina_stringshare_add(label);
2340         sd->translate_strings = eina_list_append(sd->translate_strings, ts);
2341      }
2342    else
2343      {
2344         if (label)
2345           {
2346              eina_stringshare_replace(&ts->domain, domain);
2347              eina_stringshare_replace(&ts->string, label);
2348           }
2349         else
2350           {
2351              sd->translate_strings = eina_list_remove_list(
2352                                                 sd->translate_strings, l);
2353              eina_stringshare_del(ts->id);
2354              eina_stringshare_del(ts->domain);
2355              eina_stringshare_del(ts->string);
2356              free(ts);
2357           }
2358         eina_stringshare_del(str);
2359      }
2360
2361 #ifdef HAVE_GETTEXT
2362    if (label && label[0])
2363      label = dgettext(domain, label);
2364 #endif
2365    elm_widget_text_part_set(obj, part, label);
2366 }
2367
2368 EAPI const char *
2369 elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
2370 {
2371    const char *str, *ret = NULL;
2372    Eina_List *l;
2373    Elm_Translate_String_Data *ts;
2374    API_ENTRY return NULL;
2375
2376    str = eina_stringshare_add(part);
2377    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2378       if (ts->id == str)
2379         {
2380            ret = ts->string;
2381            break;
2382         }
2383    eina_stringshare_del(str);
2384    return ret;
2385 }
2386
2387 EAPI void
2388 elm_widget_translate(Evas_Object *obj)
2389 {
2390    const Eina_List *l;
2391    Evas_Object *child;
2392    Elm_Translate_String_Data *ts;
2393
2394    API_ENTRY return;
2395    EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
2396    if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
2397    if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
2398    if (sd->translate_func) sd->translate_func(obj);
2399
2400 #ifdef HAVE_GETTEXT
2401    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2402      {
2403         const char *s = dgettext(ts->domain, ts->string);
2404         elm_widget_text_part_set(obj, ts->id, s);
2405      }
2406 #endif
2407 }
2408
2409 EAPI void
2410 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
2411 {
2412    API_ENTRY return;
2413
2414    if (!sd->on_content_set_func)  return;
2415    sd->on_content_set_func(obj, part, content);
2416 }
2417
2418 EAPI Evas_Object *
2419 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
2420 {
2421    API_ENTRY return NULL;
2422
2423    if (!sd->on_content_get_func) return NULL;
2424    return sd->on_content_get_func(obj, part);
2425 }
2426
2427 EAPI Evas_Object *
2428 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
2429 {
2430    API_ENTRY return NULL;
2431
2432    if (!sd->on_content_unset_func) return NULL;
2433    return sd->on_content_unset_func(obj, part);
2434 }
2435
2436 EAPI void
2437 elm_widget_access_info_set(Evas_Object *obj, const char *txt)
2438 {
2439    API_ENTRY return;
2440    if (sd->access_info) eina_stringshare_del(sd->access_info);
2441    if (!txt) sd->access_info = NULL;
2442    else sd->access_info = eina_stringshare_add(txt);
2443 }
2444
2445 EAPI const char *
2446 elm_widget_access_info_get(Evas_Object *obj)
2447 {
2448    API_ENTRY return NULL;
2449    return sd->access_info;
2450 }
2451
2452 EAPI Elm_Theme *
2453 elm_widget_theme_get(const Evas_Object *obj)
2454 {
2455    API_ENTRY return NULL;
2456    if (!sd->theme)
2457      {
2458         if (sd->parent_obj)
2459           return elm_widget_theme_get(sd->parent_obj);
2460         else
2461           return NULL;
2462      }
2463    return sd->theme;
2464 }
2465
2466 EAPI void
2467 elm_widget_style_set(Evas_Object *obj,
2468                      const char  *style)
2469 {
2470    API_ENTRY return;
2471
2472    if (eina_stringshare_replace(&sd->style, style))
2473      elm_widget_theme(obj);
2474 }
2475
2476 EAPI const char *
2477 elm_widget_style_get(const Evas_Object *obj)
2478 {
2479    API_ENTRY return NULL;
2480    if (sd->style) return sd->style;
2481    return "default";
2482 }
2483
2484 EAPI void
2485 elm_widget_type_set(Evas_Object *obj,
2486                     const char  *type)
2487 {
2488    API_ENTRY return;
2489    eina_stringshare_replace(&sd->type, type);
2490 }
2491
2492 EAPI const char *
2493 elm_widget_type_get(const Evas_Object *obj)
2494 {
2495    API_ENTRY return NULL;
2496    if (sd->type) return sd->type;
2497    return "";
2498 }
2499
2500 EAPI void
2501 elm_widget_tooltip_add(Evas_Object *obj,
2502                        Elm_Tooltip *tt)
2503 {
2504    API_ENTRY return;
2505    sd->tooltips = eina_list_append(sd->tooltips, tt);
2506 }
2507
2508 EAPI void
2509 elm_widget_tooltip_del(Evas_Object *obj,
2510                        Elm_Tooltip *tt)
2511 {
2512    API_ENTRY return;
2513    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2514 }
2515
2516 EAPI void
2517 elm_widget_cursor_add(Evas_Object *obj,
2518                       Elm_Cursor  *cur)
2519 {
2520    API_ENTRY return;
2521    sd->cursors = eina_list_append(sd->cursors, cur);
2522 }
2523
2524 EAPI void
2525 elm_widget_cursor_del(Evas_Object *obj,
2526                       Elm_Cursor  *cur)
2527 {
2528    API_ENTRY return;
2529    sd->cursors = eina_list_remove(sd->cursors, cur);
2530 }
2531
2532 EAPI void
2533 elm_widget_drag_lock_x_set(Evas_Object *obj,
2534                            Eina_Bool    lock)
2535 {
2536    API_ENTRY return;
2537    if (sd->drag_x_locked == lock) return;
2538    sd->drag_x_locked = lock;
2539    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2540    else _propagate_x_drag_lock(obj, -1);
2541 }
2542
2543 EAPI void
2544 elm_widget_drag_lock_y_set(Evas_Object *obj,
2545                            Eina_Bool    lock)
2546 {
2547    API_ENTRY return;
2548    if (sd->drag_y_locked == lock) return;
2549    sd->drag_y_locked = lock;
2550    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2551    else _propagate_y_drag_lock(obj, -1);
2552 }
2553
2554 EAPI Eina_Bool
2555 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2556 {
2557    API_ENTRY return EINA_FALSE;
2558    return sd->drag_x_locked;
2559 }
2560
2561 EAPI Eina_Bool
2562 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2563 {
2564    API_ENTRY return EINA_FALSE;
2565    return sd->drag_y_locked;
2566 }
2567
2568 EAPI int
2569 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2570 {
2571    API_ENTRY return 0;
2572    return sd->child_drag_x_locked;
2573 }
2574
2575 EAPI int
2576 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2577 {
2578    API_ENTRY return 0;
2579    return sd->child_drag_y_locked;
2580 }
2581
2582 EAPI Eina_Bool
2583 elm_widget_theme_object_set(Evas_Object *obj,
2584                             Evas_Object *edj,
2585                             const char  *wname,
2586                             const char  *welement,
2587                             const char  *wstyle)
2588 {
2589    API_ENTRY return EINA_FALSE;
2590    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2591 }
2592
2593 EAPI Eina_Bool
2594 elm_widget_is_check(const Evas_Object *obj)
2595 {
2596    static int abort_on_warn = -1;
2597    if (elm_widget_is(obj))
2598       return EINA_TRUE;
2599
2600    ERR("Passing Object: %p.", obj);
2601    if (abort_on_warn == -1)
2602      {
2603         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2604         else abort_on_warn = 0;
2605      }
2606    if (abort_on_warn == 1) abort();
2607    return EINA_FALSE;
2608 }
2609
2610 EAPI Eina_Bool
2611 elm_widget_type_check(const Evas_Object *obj,
2612                       const char        *type,
2613                       const char        *func)
2614 {
2615    const char *provided, *expected = "(unknown)";
2616    static int abort_on_warn = -1;
2617    provided = elm_widget_type_get(obj);
2618    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2619    if (type) expected = type;
2620    if ((!provided) || (!provided[0]))
2621      {
2622         provided = evas_object_type_get(obj);
2623         if ((!provided) || (!provided[0]))
2624           provided = "(unknown)";
2625      }
2626    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
2627    if (abort_on_warn == -1)
2628      {
2629         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2630         else abort_on_warn = 0;
2631      }
2632    if (abort_on_warn == 1) abort();
2633    return EINA_FALSE;
2634 }
2635
2636 /**
2637  * @internal
2638  *
2639  * Split string in words
2640  *
2641  * @param str Source string
2642  * @return List of const words
2643  *
2644  * @see elm_widget_stringlist_free()
2645  * @ingroup Widget
2646  */
2647 EAPI Eina_List *
2648 elm_widget_stringlist_get(const char *str)
2649 {
2650    Eina_List *list = NULL;
2651    const char *s, *b;
2652    if (!str) return NULL;
2653    for (b = s = str; 1; s++)
2654      {
2655         if ((*s == ' ') || (!*s))
2656           {
2657              char *t = malloc(s - b + 1);
2658              if (t)
2659                {
2660                   strncpy(t, b, s - b);
2661                   t[s - b] = 0;
2662                   list = eina_list_append(list, eina_stringshare_add(t));
2663                   free(t);
2664                }
2665              b = s + 1;
2666           }
2667         if (!*s) break;
2668      }
2669    return list;
2670 }
2671
2672 EAPI void
2673 elm_widget_stringlist_free(Eina_List *list)
2674 {
2675    const char *s;
2676    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2677 }
2678
2679 EAPI void
2680 elm_widget_focus_hide_handle(Evas_Object *obj)
2681 {
2682    _if_focused_revert(obj, EINA_TRUE);
2683 }
2684
2685 EAPI void
2686 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2687 {
2688    Evas_Object *o = obj;
2689    do
2690      {
2691         if (_elm_widget_is(o)) break;
2692         o = evas_object_smart_parent_get(o);
2693      }
2694    while (o);
2695    if (!o) return;
2696    if (!_is_focusable(o)) return;
2697    elm_widget_focus_steal(o);
2698 }
2699
2700 EAPI void
2701 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2702 {
2703    API_ENTRY return;
2704
2705    if (!elm_widget_parent_get(obj))
2706      elm_widget_focused_object_clear(obj);
2707    else
2708      _if_focused_revert(obj, EINA_TRUE);
2709 }
2710
2711 EAPI void
2712 elm_widget_focus_disabled_handle(Evas_Object *obj)
2713 {
2714    API_ENTRY return;
2715
2716    elm_widget_focus_tree_unfocusable_handle(obj);
2717 }
2718
2719 /**
2720  * @internal
2721  *
2722  * Allocate a new Elm_Widget_Item-derived structure.
2723  *
2724  * The goal of this structure is to provide common ground for actions
2725  * that a widget item have, such as the owner widget, callback to
2726  * notify deletion, data pointer and maybe more.
2727  *
2728  * @param widget the owner widget that holds this item, must be an elm_widget!
2729  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2730  *        be used to allocate memory.
2731  *
2732  * @return allocated memory that is already zeroed out, or NULL on errors.
2733  *
2734  * @see elm_widget_item_new() convenience macro.
2735  * @see elm_widget_item_del() to release memory.
2736  * @ingroup Widget
2737  */
2738 EAPI Elm_Widget_Item *
2739 _elm_widget_item_new(Evas_Object *widget,
2740                      size_t       alloc_size)
2741 {
2742    if (!_elm_widget_is(widget))
2743      return NULL;
2744
2745    Elm_Widget_Item *item;
2746
2747    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2748    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2749
2750    item = calloc(1, alloc_size);
2751    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2752
2753    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2754    item->widget = widget;
2755    return item;
2756 }
2757
2758 /**
2759  * @internal
2760  *
2761  * Releases widget item memory, calling back del_cb() if it exists.
2762  *
2763  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2764  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2765  * this function and then unset it, thus being useful for 2 step
2766  * cleanup whenever the del_cb may use any of the data that must be
2767  * deleted from item.
2768  *
2769  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2770  * is presented!
2771  *
2772  * @param item a valid #Elm_Widget_Item to be deleted.
2773  * @see elm_widget_item_del() convenience macro.
2774  * @ingroup Widget
2775  */
2776 EAPI void
2777 _elm_widget_item_del(Elm_Widget_Item *item)
2778 {
2779    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2780
2781    if (item->del_cb)
2782      item->del_cb((void *)item->data, item->widget, item);
2783
2784    if (item->view)
2785      evas_object_del(item->view);
2786
2787    if (item->access)
2788      {
2789         _elm_access_clear(item->access);
2790         free(item->access);
2791         item->access = NULL;
2792      }
2793    if (item->access_info)
2794      {
2795         eina_stringshare_del(item->access_info);
2796         item->access_info = NULL;
2797      }
2798
2799    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2800    free(item);
2801 }
2802
2803 /**
2804  * @internal
2805  *
2806  * Notify object will be deleted without actually deleting it.
2807  *
2808  * This function will callback Elm_Widget_Item::del_cb if it is set
2809  * and then unset it so it is not called twice (ie: from
2810  * elm_widget_item_del()).
2811  *
2812  * @param item a valid #Elm_Widget_Item to be notified
2813  * @see elm_widget_item_pre_notify_del() convenience macro.
2814  * @ingroup Widget
2815  */
2816 EAPI void
2817 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2818 {
2819    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2820    if (!item->del_cb) return;
2821    item->del_cb((void *)item->data, item->widget, item);
2822    item->del_cb = NULL;
2823 }
2824
2825 /**
2826  * @internal
2827  *
2828  * Set the function to notify when item is being deleted.
2829  *
2830  * This function will complain if there was a callback set already,
2831  * however it will set the new one.
2832  *
2833  * The callback will be called from elm_widget_item_pre_notify_del()
2834  * or elm_widget_item_del() will be called with:
2835  *   - data: the Elm_Widget_Item::data value.
2836  *   - obj: the Elm_Widget_Item::widget evas object.
2837  *   - event_info: the item being deleted.
2838  *
2839  * @param item a valid #Elm_Widget_Item to be notified
2840  * @see elm_widget_item_del_cb_set() convenience macro.
2841  * @ingroup Widget
2842  */
2843 EAPI void
2844 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2845                             Evas_Smart_Cb    del_cb)
2846 {
2847    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2848
2849    if ((item->del_cb) && (item->del_cb != del_cb))
2850      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2851          item->del_cb, item, del_cb);
2852
2853    item->del_cb = del_cb;
2854 }
2855
2856 /**
2857  * @internal
2858  *
2859  * Set user-data in this item.
2860  *
2861  * User data may be used to identify this item or just store any
2862  * application data. It is automatically given as the first parameter
2863  * of the deletion notify callback.
2864  *
2865  * @param item a valid #Elm_Widget_Item to store data in.
2866  * @param data user data to store.
2867  * @see elm_widget_item_del_cb_set() convenience macro.
2868  * @ingroup Widget
2869  */
2870 EAPI void
2871 _elm_widget_item_data_set(Elm_Widget_Item *item,
2872                           const void      *data)
2873 {
2874    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2875    if ((item->data) && (item->data != data))
2876      DBG("Replacing item %p data %p with %p", item, item->data, data);
2877    item->data = data;
2878 }
2879
2880 /**
2881  * @internal
2882  *
2883  * Retrieves user-data of this item.
2884  *
2885  * @param item a valid #Elm_Widget_Item to get data from.
2886  * @see elm_widget_item_data_set()
2887  * @ingroup Widget
2888  */
2889 EAPI void *
2890 _elm_widget_item_data_get(const Elm_Widget_Item *item)
2891 {
2892    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2893    return (void *)item->data;
2894 }
2895
2896 EAPI void
2897 _elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_Bool disabled)
2898 {
2899    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2900
2901    if (item->disabled == disabled) return;
2902    item->disabled = !!disabled;
2903    if (item->disable_func) item->disable_func(item);
2904 }
2905
2906 EAPI Eina_Bool
2907 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
2908 {
2909    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2910    return item->disabled;
2911 }
2912
2913 EAPI void
2914 _elm_widget_item_disable_set_hook_set(Elm_Widget_Item *item,
2915                                       Elm_Widget_On_Disable_Set_Cb func)
2916 {
2917    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2918    item->disable_func = func;
2919 }
2920
2921 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
2922
2923 struct _Elm_Widget_Item_Tooltip
2924 {
2925    Elm_Widget_Item            *item;
2926    Elm_Tooltip_Item_Content_Cb func;
2927    Evas_Smart_Cb               del_cb;
2928    const void                 *data;
2929 };
2930
2931 static Evas_Object *
2932 _elm_widget_item_tooltip_label_create(void        *data,
2933                                       Evas_Object *obj __UNUSED__,
2934                                       Evas_Object *tooltip,
2935                                       void        *item __UNUSED__)
2936 {
2937    Evas_Object *label = elm_label_add(tooltip);
2938    if (!label)
2939      return NULL;
2940    elm_object_style_set(label, "tooltip");
2941    elm_object_text_set(label, data);
2942    return label;
2943 }
2944
2945 static Evas_Object *
2946 _elm_widget_item_tooltip_trans_label_create(void        *data,
2947                                             Evas_Object *obj __UNUSED__,
2948                                             Evas_Object *tooltip,
2949                                             void        *item __UNUSED__)
2950 {
2951    Evas_Object *label = elm_label_add(tooltip);
2952    if (!label)
2953      return NULL;
2954    elm_object_style_set(label, "tooltip");
2955    elm_object_translatable_text_set(label, data);
2956    return label;
2957 }
2958
2959 static void
2960 _elm_widget_item_tooltip_label_del_cb(void        *data,
2961                                       Evas_Object *obj __UNUSED__,
2962                                       void        *event_info __UNUSED__)
2963 {
2964    eina_stringshare_del(data);
2965 }
2966
2967 /**
2968  * @internal
2969  *
2970  * Set the text to be shown in the widget item.
2971  *
2972  * @param item Target item
2973  * @param text The text to set in the content
2974  *
2975  * Setup the text as tooltip to object. The item can have only one tooltip,
2976  * so any previous tooltip data is removed.
2977  *
2978  * @ingroup Widget
2979  */
2980 EAPI void
2981 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
2982                                   const char      *text)
2983 {
2984    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2985    EINA_SAFETY_ON_NULL_RETURN(text);
2986
2987    text = eina_stringshare_add(text);
2988    _elm_widget_item_tooltip_content_cb_set
2989      (item, _elm_widget_item_tooltip_label_create, text,
2990      _elm_widget_item_tooltip_label_del_cb);
2991 }
2992
2993 EAPI void
2994 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
2995                                                const char      *text)
2996 {
2997    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2998    EINA_SAFETY_ON_NULL_RETURN(text);
2999
3000    text = eina_stringshare_add(text);
3001    _elm_widget_item_tooltip_content_cb_set
3002      (item, _elm_widget_item_tooltip_trans_label_create, text,
3003      _elm_widget_item_tooltip_label_del_cb);
3004 }
3005
3006 static Evas_Object *
3007 _elm_widget_item_tooltip_create(void        *data,
3008                                 Evas_Object *obj,
3009                                 Evas_Object *tooltip)
3010 {
3011    Elm_Widget_Item_Tooltip *wit = data;
3012    return wit->func((void *)wit->data, obj, tooltip, wit->item);
3013 }
3014
3015 static void
3016 _elm_widget_item_tooltip_del_cb(void        *data,
3017                                 Evas_Object *obj,
3018                                 void        *event_info __UNUSED__)
3019 {
3020    Elm_Widget_Item_Tooltip *wit = data;
3021    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
3022    free(wit);
3023 }
3024
3025 /**
3026  * @internal
3027  *
3028  * Set the content to be shown in the tooltip item
3029  *
3030  * Setup the tooltip to item. The item can have only one tooltip,
3031  * so any previous tooltip data is removed. @p func(with @p data) will
3032  * be called every time that need show the tooltip and it should
3033  * return a valid Evas_Object. This object is then managed fully by
3034  * tooltip system and is deleted when the tooltip is gone.
3035  *
3036  * @param item the widget item being attached a tooltip.
3037  * @param func the function used to create the tooltip contents.
3038  * @param data what to provide to @a func as callback data/context.
3039  * @param del_cb called when data is not needed anymore, either when
3040  *        another callback replaces @func, the tooltip is unset with
3041  *        elm_widget_item_tooltip_unset() or the owner @a item
3042  *        dies. This callback receives as the first parameter the
3043  *        given @a data, and @c event_info is the item.
3044  *
3045  * @ingroup Widget
3046  */
3047 EAPI void
3048 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
3049                                         Elm_Tooltip_Item_Content_Cb func,
3050                                         const void                 *data,
3051                                         Evas_Smart_Cb               del_cb)
3052 {
3053    Elm_Widget_Item_Tooltip *wit;
3054
3055    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
3056
3057    if (!func)
3058      {
3059         _elm_widget_item_tooltip_unset(item);
3060         return;
3061      }
3062
3063    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
3064    if (!wit) goto error;
3065    wit->item = item;
3066    wit->func = func;
3067    wit->data = data;
3068    wit->del_cb = del_cb;
3069
3070    elm_object_sub_tooltip_content_cb_set
3071      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
3072      _elm_widget_item_tooltip_del_cb);
3073
3074    return;
3075
3076 error_noitem:
3077    if (del_cb) del_cb((void *)data, NULL, item);
3078    return;
3079 error:
3080    if (del_cb) del_cb((void *)data, item->widget, item);
3081 }
3082
3083 /**
3084  * @internal
3085  *
3086  * Unset tooltip from item
3087  *
3088  * @param item widget item to remove previously set tooltip.
3089  *
3090  * Remove tooltip from item. The callback provided as del_cb to
3091  * elm_widget_item_tooltip_content_cb_set() will be called to notify
3092  * it is not used anymore.
3093  *
3094  * @see elm_widget_item_tooltip_content_cb_set()
3095  *
3096  * @ingroup Widget
3097  */
3098 EAPI void
3099 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
3100 {
3101    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3102    elm_object_tooltip_unset(item->view);
3103 }
3104
3105 /**
3106  * @internal
3107  *
3108  * Sets a different style for this item tooltip.
3109  *
3110  * @note before you set a style you should define a tooltip with
3111  *       elm_widget_item_tooltip_content_cb_set() or
3112  *       elm_widget_item_tooltip_text_set()
3113  *
3114  * @param item widget item with tooltip already set.
3115  * @param style the theme style to use (default, transparent, ...)
3116  *
3117  * @ingroup Widget
3118  */
3119 EAPI void
3120 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
3121                                    const char      *style)
3122 {
3123    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3124    elm_object_tooltip_style_set(item->view, style);
3125 }
3126
3127 EAPI Eina_Bool
3128 _elm_widget_item_tooltip_size_restrict_disable(Elm_Widget_Item *item, Eina_Bool disable)
3129 {
3130    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3131    return elm_tooltip_size_restrict_disable(item->view, disable);
3132 }
3133
3134 EAPI Eina_Bool
3135 _elm_widget_item_tooltip_size_restrict_disabled_get(const Elm_Widget_Item *item)
3136 {
3137    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3138    return elm_tooltip_size_restrict_disabled_get(item->view);
3139 }
3140
3141 /**
3142  * @internal
3143  *
3144  * Get the style for this item tooltip.
3145  *
3146  * @param item widget item with tooltip already set.
3147  * @return style the theme style in use, defaults to "default". If the
3148  *         object does not have a tooltip set, then NULL is returned.
3149  *
3150  * @ingroup Widget
3151  */
3152 EAPI const char *
3153 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
3154 {
3155    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3156    return elm_object_tooltip_style_get(item->view);
3157 }
3158
3159 EAPI void
3160 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
3161                             const char      *cursor)
3162 {
3163    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3164    elm_object_sub_cursor_set(item->view, item->widget, cursor);
3165 }
3166
3167 EAPI const char *
3168 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
3169 {
3170    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3171    return elm_object_cursor_get(item->view);
3172 }
3173
3174 EAPI void
3175 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
3176 {
3177    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3178    elm_object_cursor_unset(item->view);
3179 }
3180
3181 /**
3182  * @internal
3183  *
3184  * Sets a different style for this item cursor.
3185  *
3186  * @note before you set a style you should define a cursor with
3187  *       elm_widget_item_cursor_set()
3188  *
3189  * @param item widget item with cursor already set.
3190  * @param style the theme style to use (default, transparent, ...)
3191  *
3192  * @ingroup Widget
3193  */
3194 EAPI void
3195 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
3196                                   const char      *style)
3197 {
3198    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3199    elm_object_cursor_style_set(item->view, style);
3200 }
3201
3202 /**
3203  * @internal
3204  *
3205  * Get the style for this item cursor.
3206  *
3207  * @param item widget item with cursor already set.
3208  * @return style the theme style in use, defaults to "default". If the
3209  *         object does not have a cursor set, then NULL is returned.
3210  *
3211  * @ingroup Widget
3212  */
3213 EAPI const char *
3214 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
3215 {
3216    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3217    return elm_object_cursor_style_get(item->view);
3218 }
3219
3220 /**
3221  * @internal
3222  *
3223  * Set if the cursor set should be searched on the theme or should use
3224  * the provided by the engine, only.
3225  *
3226  * @note before you set if should look on theme you should define a cursor
3227  * with elm_object_cursor_set(). By default it will only look for cursors
3228  * provided by the engine.
3229  *
3230  * @param item widget item with cursor already set.
3231  * @param engine_only boolean to define it cursors should be looked only
3232  * between the provided by the engine or searched on widget's theme as well.
3233  *
3234  * @ingroup Widget
3235  */
3236 EAPI void
3237 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
3238                                         Eina_Bool        engine_only)
3239 {
3240    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3241    elm_object_cursor_engine_only_set(item->view, engine_only);
3242 }
3243
3244 /**
3245  * @internal
3246  *
3247  * Get the cursor engine only usage for this item cursor.
3248  *
3249  * @param item widget item with cursor already set.
3250  * @return engine_only boolean to define it cursors should be looked only
3251  * between the provided by the engine or searched on widget's theme as well. If
3252  *         the object does not have a cursor set, then EINA_FALSE is returned.
3253  *
3254  * @ingroup Widget
3255  */
3256 EAPI Eina_Bool
3257 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
3258 {
3259    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3260    return elm_object_cursor_engine_only_get(item->view);
3261 }
3262
3263 // smart object funcs
3264 static void
3265 _smart_reconfigure(Smart_Data *sd)
3266 {
3267    if (sd->resize_obj)
3268      {
3269         evas_object_move(sd->resize_obj, sd->x, sd->y);
3270         evas_object_resize(sd->resize_obj, sd->w, sd->h);
3271      }
3272    if (sd->hover_obj)
3273      {
3274         evas_object_move(sd->hover_obj, sd->x, sd->y);
3275         evas_object_resize(sd->hover_obj, sd->w, sd->h);
3276      }
3277 }
3278
3279 EAPI void
3280 _elm_widget_item_content_part_set(Elm_Widget_Item *item,
3281                                  const char *part,
3282                                  Evas_Object *content)
3283 {
3284    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3285    if (!item->on_content_set_func) return;
3286    item->on_content_set_func((Elm_Object_Item *) item, part, content);
3287 }
3288
3289 EAPI Evas_Object *
3290 _elm_widget_item_content_part_get(const Elm_Widget_Item *item,
3291                                   const char *part)
3292 {
3293    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3294    if (!item->on_content_get_func) return NULL;
3295    return item->on_content_get_func((Elm_Object_Item *) item, part);
3296 }
3297
3298 EAPI Evas_Object *
3299 _elm_widget_item_content_part_unset(Elm_Widget_Item *item,
3300                                     const char *part)
3301 {
3302    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3303    if (!item->on_content_unset_func) return NULL;
3304    return item->on_content_unset_func((Elm_Object_Item *) item, part);
3305 }
3306
3307 EAPI void
3308 _elm_widget_item_text_part_set(Elm_Widget_Item *item,
3309                               const char *part,
3310                               const char *label)
3311 {
3312    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3313    if (!item->on_text_set_func) return;
3314    item->on_text_set_func((Elm_Object_Item *) item, part, label);
3315 }
3316
3317 EAPI void
3318 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
3319                              const char *emission,
3320                              const char *source)
3321 {
3322    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3323    if (item->on_signal_emit_func)
3324      item->on_signal_emit_func((Elm_Object_Item *) item, emission, source);
3325 }
3326
3327 EAPI const char *
3328 _elm_widget_item_text_part_get(const Elm_Widget_Item *item,
3329                                const char *part)
3330 {
3331    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3332    if (!item->on_text_get_func) return NULL;
3333    return item->on_text_get_func((Elm_Object_Item *) item, part);
3334 }
3335
3336 EAPI void
3337 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3338                                       Elm_Widget_On_Content_Set_Cb func)
3339 {
3340    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3341    item->on_content_set_func = func;
3342 }
3343
3344 EAPI void
3345 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3346                                       Elm_Widget_On_Content_Get_Cb func)
3347 {
3348    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3349    item->on_content_get_func = func;
3350 }
3351
3352 EAPI void
3353 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3354                                         Elm_Widget_On_Content_Unset_Cb func)
3355 {
3356    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3357    item->on_content_unset_func = func;
3358 }
3359
3360 EAPI void
3361 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3362                                    Elm_Widget_On_Text_Set_Cb func)
3363 {
3364    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3365    item->on_text_set_func = func;
3366 }
3367
3368 EAPI void
3369 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3370                                    Elm_Widget_On_Text_Get_Cb func)
3371 {
3372    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3373    item->on_text_get_func = func;
3374 }
3375
3376 EAPI void
3377 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
3378                                       Elm_Widget_On_Signal_Emit_Cb func)
3379 {
3380    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3381    item->on_signal_emit_func = func;
3382 }
3383
3384 EAPI void
3385 _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
3386 {
3387    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3388    if (item->access_info) eina_stringshare_del(item->access_info);
3389    if (!txt) item->access_info = NULL;
3390    else item->access_info = eina_stringshare_add(txt);
3391 }
3392
3393
3394 static void
3395 _smart_add(Evas_Object *obj)
3396 {
3397    Smart_Data *sd;
3398
3399    sd = calloc(1, sizeof(Smart_Data));
3400    if (!sd) return;
3401    sd->obj = obj;
3402    sd->x = sd->y = sd->w = sd->h = 0;
3403    sd->can_focus = 1;
3404    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3405    evas_object_smart_data_set(obj, sd);
3406 }
3407
3408 static Evas_Object *
3409 _newest_focus_order_get(Evas_Object  *obj,
3410                         unsigned int *newest_focus_order,
3411                         Eina_Bool     can_focus_only)
3412 {
3413    const Eina_List *l;
3414    Evas_Object *child, *ret, *best;
3415
3416    API_ENTRY return NULL;
3417
3418    if (!evas_object_visible_get(obj)
3419        || (elm_widget_disabled_get(obj))
3420        || (elm_widget_tree_unfocusable_get(obj)))
3421      return NULL;
3422
3423    best = NULL;
3424    if (*newest_focus_order < sd->focus_order)
3425      {
3426         *newest_focus_order = sd->focus_order;
3427         best = obj;
3428      }
3429    EINA_LIST_FOREACH(sd->subobjs, l, child)
3430      {
3431         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3432         if (!ret) continue;
3433         best = ret;
3434      }
3435    if (can_focus_only)
3436      {
3437         if ((!best) || (!elm_widget_can_focus_get(best)))
3438           return NULL;
3439      }
3440    return best;
3441 }
3442
3443 static void
3444 _if_focused_revert(Evas_Object *obj,
3445                    Eina_Bool    can_focus_only)
3446 {
3447    Evas_Object *top;
3448    Evas_Object *newest = NULL;
3449    unsigned int newest_focus_order = 0;
3450
3451    INTERNAL_ENTRY
3452
3453    if (!sd->focused) return;
3454    if (!sd->parent_obj) return;
3455
3456    top = elm_widget_top_get(sd->parent_obj);
3457    if (top)
3458      {
3459         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3460         if (newest)
3461           {
3462              elm_object_focus_set(newest, EINA_FALSE);
3463              elm_object_focus_set(newest, EINA_TRUE);
3464           }
3465      }
3466 }
3467
3468 static void
3469 _smart_del(Evas_Object *obj)
3470 {
3471    Evas_Object *sobj;
3472    Edje_Signal_Data *esd;
3473    Elm_Translate_String_Data *ts;
3474
3475    INTERNAL_ENTRY
3476
3477    if (sd->del_pre_func) sd->del_pre_func(obj);
3478    if (sd->resize_obj)
3479      {
3480         sobj = sd->resize_obj;
3481         sd->resize_obj = NULL;
3482         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3483         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3484         evas_object_del(sobj);
3485         sd->resize_obj = NULL;
3486      }
3487    if (sd->hover_obj)
3488      {
3489         sobj = sd->hover_obj;
3490         sd->hover_obj = NULL;
3491         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3492         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3493         evas_object_del(sobj);
3494         sd->hover_obj = NULL;
3495      }
3496    EINA_LIST_FREE(sd->subobjs, sobj)
3497      {
3498         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3499         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3500         evas_object_del(sobj);
3501      }
3502    sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
3503    sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
3504    EINA_LIST_FREE(sd->edje_signals, esd)
3505      {
3506         eina_stringshare_del(esd->emission);
3507         eina_stringshare_del(esd->source);
3508         free(esd);
3509      }
3510    EINA_LIST_FREE(sd->translate_strings, ts)
3511      {
3512         eina_stringshare_del(ts->id);
3513         eina_stringshare_del(ts->domain);
3514         eina_stringshare_del(ts->string);
3515         free(ts);
3516      }
3517    sd->event_cb = eina_list_free(sd->event_cb); /* should be empty anyway */
3518    if (sd->del_func) sd->del_func(obj);
3519    if (sd->style) eina_stringshare_del(sd->style);
3520    if (sd->type) eina_stringshare_del(sd->type);
3521    if (sd->theme) elm_theme_free(sd->theme);
3522    sd->data = NULL;
3523    _if_focused_revert(obj, EINA_TRUE);
3524    if (sd->access_info) eina_stringshare_del(sd->access_info);
3525    free(sd);
3526    evas_object_smart_data_set(obj, NULL);
3527 }
3528
3529 static void
3530 _smart_move(Evas_Object *obj,
3531             Evas_Coord   x,
3532             Evas_Coord   y)
3533 {
3534    INTERNAL_ENTRY
3535    sd->x = x;
3536    sd->y = y;
3537    _smart_reconfigure(sd);
3538 }
3539
3540 static void
3541 _smart_resize(Evas_Object *obj,
3542               Evas_Coord   w,
3543               Evas_Coord   h)
3544 {
3545    INTERNAL_ENTRY
3546    sd->w = w;
3547    sd->h = h;
3548    _smart_reconfigure(sd);
3549 }
3550
3551 static void
3552 _smart_show(Evas_Object *obj)
3553 {
3554    Eina_List *list;
3555    Evas_Object *o;
3556    INTERNAL_ENTRY
3557    if ((list = evas_object_smart_members_get(obj)))
3558      {
3559         EINA_LIST_FREE(list, o)
3560           {
3561              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3562              evas_object_show(o);
3563           }
3564      }
3565 }
3566
3567 static void
3568 _smart_hide(Evas_Object *obj)
3569 {
3570    Eina_List *list;
3571    Evas_Object *o;
3572    INTERNAL_ENTRY
3573
3574    list = evas_object_smart_members_get(obj);
3575    EINA_LIST_FREE(list, o)
3576      {
3577         if (evas_object_data_get(o, "_elm_leaveme")) continue;
3578         evas_object_hide(o);
3579      }
3580 }
3581
3582 static void
3583 _smart_color_set(Evas_Object *obj,
3584                  int          r,
3585                  int          g,
3586                  int          b,
3587                  int          a)
3588 {
3589    Eina_List *list;
3590    Evas_Object *o;
3591    INTERNAL_ENTRY
3592    if ((list = evas_object_smart_members_get(obj)))
3593      {
3594         EINA_LIST_FREE(list, o)
3595           {
3596              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3597              evas_object_color_set(o, r, g, b, a);
3598           }
3599      }
3600 }
3601
3602 static void
3603 _smart_clip_set(Evas_Object *obj,
3604                 Evas_Object *clip)
3605 {
3606    Eina_List *list;
3607    Evas_Object *o;
3608    INTERNAL_ENTRY
3609    if ((list = evas_object_smart_members_get(obj)))
3610      {
3611         EINA_LIST_FREE(list, o)
3612           {
3613              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3614              evas_object_clip_set(o, clip);
3615           }
3616      }
3617 }
3618
3619 static void
3620 _smart_clip_unset(Evas_Object *obj)
3621 {
3622    Eina_List *list;
3623    Evas_Object *o;
3624    INTERNAL_ENTRY
3625    if ((list = evas_object_smart_members_get(obj)))
3626      {
3627         EINA_LIST_FREE(list, o)
3628           {
3629              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3630              evas_object_clip_unset(o);
3631           }
3632      }
3633 }
3634
3635 static void
3636 _smart_calculate(Evas_Object *obj)
3637 {
3638    INTERNAL_ENTRY
3639    if (sd->changed_func) sd->changed_func(obj);
3640 }
3641
3642 /* never need to touch this */
3643 static void
3644 _smart_init(void)
3645 {
3646    if (_e_smart) return;
3647      {
3648         static const Evas_Smart_Class sc =
3649           {
3650              SMART_NAME,
3651              EVAS_SMART_CLASS_VERSION,
3652              _smart_add,
3653              _smart_del,
3654              _smart_move,
3655              _smart_resize,
3656              _smart_show,
3657              _smart_hide,
3658              _smart_color_set,
3659              _smart_clip_set,
3660              _smart_clip_unset,
3661              _smart_calculate,
3662              NULL,
3663              NULL,
3664              NULL,
3665              NULL,
3666              NULL,
3667              NULL
3668           };
3669         _e_smart = evas_smart_class_new(&sc);
3670      }
3671 }
3672
3673 /* happy debug functions */
3674 #ifdef ELM_DEBUG
3675 static void
3676 _sub_obj_tree_dump(const Evas_Object *obj,
3677                    int                lvl)
3678 {
3679    int i;
3680
3681    for (i = 0; i < lvl * 3; i++)
3682      putchar(' ');
3683
3684    if (_elm_widget_is(obj))
3685      {
3686         Eina_List *l;
3687         INTERNAL_ENTRY
3688         printf("+ %s(%p)\n",
3689                sd->type,
3690                obj);
3691         if (sd->resize_obj)
3692           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3693         EINA_LIST_FOREACH(sd->subobjs, l, obj)
3694           {
3695              if (obj != sd->resize_obj)
3696                _sub_obj_tree_dump(obj, lvl + 1);
3697           }
3698      }
3699    else
3700      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3701 }
3702
3703 static void
3704 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3705                        FILE              *output)
3706 {
3707    if (!_elm_widget_is(obj))
3708      return;
3709    INTERNAL_ENTRY
3710
3711    Eina_Bool visible = evas_object_visible_get(obj);
3712    Eina_Bool disabled = elm_widget_disabled_get(obj);
3713    Eina_Bool focused = elm_widget_focus_get(obj);
3714    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3715
3716    if (sd->parent_obj)
3717      {
3718         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3719
3720         if (focused)
3721           fprintf(output, ", style=bold");
3722
3723         if (!visible)
3724           fprintf(output, ", color=gray28");
3725
3726         fprintf(output, " ];\n");
3727      }
3728
3729    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3730                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3731            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3732            sd->focus_order);
3733
3734    if (focused)
3735      fprintf(output, ", style=bold");
3736
3737    if (!visible)
3738      fprintf(output, ", fontcolor=gray28");
3739
3740    if ((disabled) || (!visible))
3741      fprintf(output, ", color=gray");
3742
3743    fprintf(output, " ];\n");
3744
3745    Eina_List *l;
3746    Evas_Object *o;
3747    EINA_LIST_FOREACH(sd->subobjs, l, o)
3748      _sub_obj_tree_dot_dump(o, output);
3749 }
3750 #endif
3751
3752 EAPI void
3753 elm_widget_tree_dump(const Evas_Object *top)
3754 {
3755 #ifdef ELM_DEBUG
3756    _sub_obj_tree_dump(top, 0);
3757 #else
3758    return;
3759    (void)top;
3760 #endif
3761 }
3762
3763 EAPI void
3764 elm_widget_tree_dot_dump(const Evas_Object *top,
3765                          FILE              *output)
3766 {
3767 #ifdef ELM_DEBUG
3768    if (!_elm_widget_is(top))
3769      return;
3770    fprintf(output, "graph " " { node [shape=record];\n");
3771    _sub_obj_tree_dot_dump(top, output);
3772    fprintf(output, "}\n");
3773 #else
3774    return;
3775    (void)top;
3776    (void)output;
3777 #endif
3778 }