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