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