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