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