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