111a855c9d6da6f0ef6bbd20b6feb98ff923114e
[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, data);
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 EAPI Elm_Theme *
2290 elm_widget_theme_get(const Evas_Object *obj)
2291 {
2292    API_ENTRY return NULL;
2293    if (!sd->theme)
2294      {
2295         if (sd->parent_obj)
2296           return elm_widget_theme_get(sd->parent_obj);
2297         else
2298           return NULL;
2299      }
2300    return sd->theme;
2301 }
2302
2303 EAPI void
2304 elm_widget_style_set(Evas_Object *obj,
2305                      const char  *style)
2306 {
2307    API_ENTRY return;
2308
2309    if (eina_stringshare_replace(&sd->style, style))
2310      elm_widget_theme(obj);
2311 }
2312
2313 EAPI const char *
2314 elm_widget_style_get(const Evas_Object *obj)
2315 {
2316    API_ENTRY return NULL;
2317    if (sd->style) return sd->style;
2318    return "default";
2319 }
2320
2321 EAPI void
2322 elm_widget_type_set(Evas_Object *obj,
2323                     const char  *type)
2324 {
2325    API_ENTRY return;
2326    eina_stringshare_replace(&sd->type, type);
2327 }
2328
2329 EAPI const char *
2330 elm_widget_type_get(const Evas_Object *obj)
2331 {
2332    API_ENTRY return NULL;
2333    if (sd->type) return sd->type;
2334    return "";
2335 }
2336
2337 EAPI void
2338 elm_widget_tooltip_add(Evas_Object *obj,
2339                        Elm_Tooltip *tt)
2340 {
2341    API_ENTRY return;
2342    sd->tooltips = eina_list_append(sd->tooltips, tt);
2343 }
2344
2345 EAPI void
2346 elm_widget_tooltip_del(Evas_Object *obj,
2347                        Elm_Tooltip *tt)
2348 {
2349    API_ENTRY return;
2350    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2351 }
2352
2353 EAPI void
2354 elm_widget_cursor_add(Evas_Object *obj,
2355                       Elm_Cursor  *cur)
2356 {
2357    API_ENTRY return;
2358    sd->cursors = eina_list_append(sd->cursors, cur);
2359 }
2360
2361 EAPI void
2362 elm_widget_cursor_del(Evas_Object *obj,
2363                       Elm_Cursor  *cur)
2364 {
2365    API_ENTRY return;
2366    sd->cursors = eina_list_remove(sd->cursors, cur);
2367 }
2368
2369 EAPI void
2370 elm_widget_drag_lock_x_set(Evas_Object *obj,
2371                            Eina_Bool    lock)
2372 {
2373    API_ENTRY return;
2374    if (sd->drag_x_locked == lock) return;
2375    sd->drag_x_locked = lock;
2376    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2377    else _propagate_x_drag_lock(obj, -1);
2378 }
2379
2380 EAPI void
2381 elm_widget_drag_lock_y_set(Evas_Object *obj,
2382                            Eina_Bool    lock)
2383 {
2384    API_ENTRY return;
2385    if (sd->drag_y_locked == lock) return;
2386    sd->drag_y_locked = lock;
2387    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2388    else _propagate_y_drag_lock(obj, -1);
2389 }
2390
2391 EAPI Eina_Bool
2392 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2393 {
2394    API_ENTRY return EINA_FALSE;
2395    return sd->drag_x_locked;
2396 }
2397
2398 EAPI Eina_Bool
2399 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2400 {
2401    API_ENTRY return EINA_FALSE;
2402    return sd->drag_y_locked;
2403 }
2404
2405 EAPI int
2406 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2407 {
2408    API_ENTRY return 0;
2409    return sd->child_drag_x_locked;
2410 }
2411
2412 EAPI int
2413 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2414 {
2415    API_ENTRY return 0;
2416    return sd->child_drag_y_locked;
2417 }
2418
2419 EAPI Eina_Bool
2420 elm_widget_theme_object_set(Evas_Object *obj,
2421                             Evas_Object *edj,
2422                             const char  *wname,
2423                             const char  *welement,
2424                             const char  *wstyle)
2425 {
2426    API_ENTRY return EINA_FALSE;
2427    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2428 }
2429
2430 EAPI Eina_Bool
2431 elm_widget_is_check(const Evas_Object *obj)
2432 {
2433    static int abort_on_warn = -1;
2434    if (elm_widget_is(obj))
2435       return EINA_TRUE;
2436
2437    ERR("Passing Object: %p.", obj);
2438    if (abort_on_warn == -1)
2439      {
2440         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2441         else abort_on_warn = 0;
2442      }
2443    if (abort_on_warn == 1) abort();
2444    return EINA_FALSE;
2445 }
2446
2447 EAPI Eina_Bool
2448 elm_widget_type_check(const Evas_Object *obj,
2449                       const char        *type,
2450                       const char        *func)
2451 {
2452    const char *provided, *expected = "(unknown)";
2453    static int abort_on_warn = -1;
2454    provided = elm_widget_type_get(obj);
2455    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2456    if (type) expected = type;
2457    if ((!provided) || (!provided[0]))
2458      {
2459         provided = evas_object_type_get(obj);
2460         if ((!provided) || (!provided[0]))
2461           provided = "(unknown)";
2462      }
2463    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
2464    if (abort_on_warn == -1)
2465      {
2466         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2467         else abort_on_warn = 0;
2468      }
2469    if (abort_on_warn == 1) abort();
2470    return EINA_FALSE;
2471 }
2472
2473 /**
2474  * @internal
2475  *
2476  * Split string in words
2477  *
2478  * @param str Source string
2479  * @return List of const words
2480  *
2481  * @see elm_widget_stringlist_free()
2482  * @ingroup Widget
2483  */
2484 EAPI Eina_List *
2485 elm_widget_stringlist_get(const char *str)
2486 {
2487    Eina_List *list = NULL;
2488    const char *s, *b;
2489    if (!str) return NULL;
2490    for (b = s = str; 1; s++)
2491      {
2492         if ((*s == ' ') || (!*s))
2493           {
2494              char *t = malloc(s - b + 1);
2495              if (t)
2496                {
2497                   strncpy(t, b, s - b);
2498                   t[s - b] = 0;
2499                   list = eina_list_append(list, eina_stringshare_add(t));
2500                   free(t);
2501                }
2502              b = s + 1;
2503           }
2504         if (!*s) break;
2505      }
2506    return list;
2507 }
2508
2509 EAPI void
2510 elm_widget_stringlist_free(Eina_List *list)
2511 {
2512    const char *s;
2513    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2514 }
2515
2516 EAPI void
2517 elm_widget_focus_hide_handle(Evas_Object *obj)
2518 {
2519    _if_focused_revert(obj, EINA_TRUE);
2520 }
2521
2522 EAPI void
2523 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2524 {
2525    Evas_Object *o = obj;
2526    do
2527      {
2528         if (_elm_widget_is(o)) break;
2529         o = evas_object_smart_parent_get(o);
2530      }
2531    while (o);
2532    if (!o) return;
2533    if (!_is_focusable(o)) return;
2534    elm_widget_focus_steal(o);
2535 }
2536
2537 EAPI void
2538 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2539 {
2540    API_ENTRY return;
2541
2542    if (!elm_widget_parent_get(obj))
2543      elm_widget_focused_object_clear(obj);
2544    else
2545      _if_focused_revert(obj, EINA_TRUE);
2546 }
2547
2548 EAPI void
2549 elm_widget_focus_disabled_handle(Evas_Object *obj)
2550 {
2551    API_ENTRY return;
2552
2553    elm_widget_focus_tree_unfocusable_handle(obj);
2554 }
2555
2556 /**
2557  * @internal
2558  *
2559  * Allocate a new Elm_Widget_Item-derived structure.
2560  *
2561  * The goal of this structure is to provide common ground for actions
2562  * that a widget item have, such as the owner widget, callback to
2563  * notify deletion, data pointer and maybe more.
2564  *
2565  * @param widget the owner widget that holds this item, must be an elm_widget!
2566  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2567  *        be used to allocate memory.
2568  *
2569  * @return allocated memory that is already zeroed out, or NULL on errors.
2570  *
2571  * @see elm_widget_item_new() convenience macro.
2572  * @see elm_widget_item_del() to release memory.
2573  * @ingroup Widget
2574  */
2575 EAPI Elm_Widget_Item *
2576 _elm_widget_item_new(Evas_Object *widget,
2577                      size_t       alloc_size)
2578 {
2579    if (!_elm_widget_is(widget))
2580      return NULL;
2581
2582    Elm_Widget_Item *item;
2583
2584    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2585    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2586
2587    item = calloc(1, alloc_size);
2588    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2589
2590    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2591    item->widget = widget;
2592    return item;
2593 }
2594
2595 /**
2596  * @internal
2597  *
2598  * Releases widget item memory, calling back del_cb() if it exists.
2599  *
2600  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2601  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2602  * this function and then unset it, thus being useful for 2 step
2603  * cleanup whenever the del_cb may use any of the data that must be
2604  * deleted from item.
2605  *
2606  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2607  * is presented!
2608  *
2609  * @param item a valid #Elm_Widget_Item to be deleted.
2610  * @see elm_widget_item_del() convenience macro.
2611  * @ingroup Widget
2612  */
2613 EAPI void
2614 _elm_widget_item_del(Elm_Widget_Item *item)
2615 {
2616    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2617
2618    if (item->del_cb)
2619      item->del_cb((void *)item->data, item->widget, item);
2620
2621    if (item->view)
2622      evas_object_del(item->view);
2623
2624    if (item->access)
2625      {
2626         _elm_access_clear(item->access);
2627         free(item->access);
2628         item->access = NULL;
2629      }
2630    if (item->access_info)
2631      {
2632         eina_stringshare_del(item->access_info);
2633         item->access_info = NULL;
2634      }
2635
2636    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2637    free(item);
2638 }
2639
2640 /**
2641  * @internal
2642  *
2643  * Notify object will be deleted without actually deleting it.
2644  *
2645  * This function will callback Elm_Widget_Item::del_cb if it is set
2646  * and then unset it so it is not called twice (ie: from
2647  * elm_widget_item_del()).
2648  *
2649  * @param item a valid #Elm_Widget_Item to be notified
2650  * @see elm_widget_item_pre_notify_del() convenience macro.
2651  * @ingroup Widget
2652  */
2653 EAPI void
2654 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2655 {
2656    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2657    if (!item->del_cb) return;
2658    item->del_cb((void *)item->data, item->widget, item);
2659    item->del_cb = NULL;
2660 }
2661
2662 /**
2663  * @internal
2664  *
2665  * Set the function to notify when item is being deleted.
2666  *
2667  * This function will complain if there was a callback set already,
2668  * however it will set the new one.
2669  *
2670  * The callback will be called from elm_widget_item_pre_notify_del()
2671  * or elm_widget_item_del() will be called with:
2672  *   - data: the Elm_Widget_Item::data value.
2673  *   - obj: the Elm_Widget_Item::widget evas object.
2674  *   - event_info: the item being deleted.
2675  *
2676  * @param item a valid #Elm_Widget_Item to be notified
2677  * @see elm_widget_item_del_cb_set() convenience macro.
2678  * @ingroup Widget
2679  */
2680 EAPI void
2681 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2682                             Evas_Smart_Cb    del_cb)
2683 {
2684    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2685
2686    if ((item->del_cb) && (item->del_cb != del_cb))
2687      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2688          item->del_cb, item, del_cb);
2689
2690    item->del_cb = del_cb;
2691 }
2692
2693 /**
2694  * @internal
2695  *
2696  * Set user-data in this item.
2697  *
2698  * User data may be used to identify this item or just store any
2699  * application data. It is automatically given as the first parameter
2700  * of the deletion notify callback.
2701  *
2702  * @param item a valid #Elm_Widget_Item to store data in.
2703  * @param data user data to store.
2704  * @see elm_widget_item_del_cb_set() convenience macro.
2705  * @ingroup Widget
2706  */
2707 EAPI void
2708 _elm_widget_item_data_set(Elm_Widget_Item *item,
2709                           const void      *data)
2710 {
2711    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2712    if ((item->data) && (item->data != data))
2713      DBG("Replacing item %p data %p with %p", item, item->data, data);
2714    item->data = data;
2715 }
2716
2717 /**
2718  * @internal
2719  *
2720  * Retrieves user-data of this item.
2721  *
2722  * @param item a valid #Elm_Widget_Item to get data from.
2723  * @see elm_widget_item_data_set()
2724  * @ingroup Widget
2725  */
2726 EAPI void *
2727 _elm_widget_item_data_get(const Elm_Widget_Item *item)
2728 {
2729    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2730    return (void *)item->data;
2731 }
2732
2733 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
2734
2735 struct _Elm_Widget_Item_Tooltip
2736 {
2737    Elm_Widget_Item            *item;
2738    Elm_Tooltip_Item_Content_Cb func;
2739    Evas_Smart_Cb               del_cb;
2740    const void                 *data;
2741 };
2742
2743 static Evas_Object *
2744 _elm_widget_item_tooltip_label_create(void        *data,
2745                                       Evas_Object *obj __UNUSED__,
2746                                       Evas_Object *tooltip,
2747                                       void        *item __UNUSED__)
2748 {
2749    Evas_Object *label = elm_label_add(tooltip);
2750    if (!label)
2751      return NULL;
2752    elm_object_style_set(label, "tooltip");
2753    elm_object_text_set(label, data);
2754    return label;
2755 }
2756
2757 static void
2758 _elm_widget_item_tooltip_label_del_cb(void        *data,
2759                                       Evas_Object *obj __UNUSED__,
2760                                       void        *event_info __UNUSED__)
2761 {
2762    eina_stringshare_del(data);
2763 }
2764
2765 /**
2766  * @internal
2767  *
2768  * Set the text to be shown in the widget item.
2769  *
2770  * @param item Target item
2771  * @param text The text to set in the content
2772  *
2773  * Setup the text as tooltip to object. The item can have only one tooltip,
2774  * so any previous tooltip data is removed.
2775  *
2776  * @ingroup Widget
2777  */
2778 EAPI void
2779 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
2780                                   const char      *text)
2781 {
2782    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2783    EINA_SAFETY_ON_NULL_RETURN(text);
2784
2785    text = eina_stringshare_add(text);
2786    _elm_widget_item_tooltip_content_cb_set
2787      (item, _elm_widget_item_tooltip_label_create, text,
2788      _elm_widget_item_tooltip_label_del_cb);
2789 }
2790
2791 static Evas_Object *
2792 _elm_widget_item_tooltip_create(void        *data,
2793                                 Evas_Object *obj,
2794                                 Evas_Object *tooltip)
2795 {
2796    Elm_Widget_Item_Tooltip *wit = data;
2797    return wit->func((void *)wit->data, obj, tooltip, wit->item);
2798 }
2799
2800 static void
2801 _elm_widget_item_tooltip_del_cb(void        *data,
2802                                 Evas_Object *obj,
2803                                 void        *event_info __UNUSED__)
2804 {
2805    Elm_Widget_Item_Tooltip *wit = data;
2806    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
2807    free(wit);
2808 }
2809
2810 /**
2811  * @internal
2812  *
2813  * Set the content to be shown in the tooltip item
2814  *
2815  * Setup the tooltip to item. The item can have only one tooltip,
2816  * so any previous tooltip data is removed. @p func(with @p data) will
2817  * be called every time that need show the tooltip and it should
2818  * return a valid Evas_Object. This object is then managed fully by
2819  * tooltip system and is deleted when the tooltip is gone.
2820  *
2821  * @param item the widget item being attached a tooltip.
2822  * @param func the function used to create the tooltip contents.
2823  * @param data what to provide to @a func as callback data/context.
2824  * @param del_cb called when data is not needed anymore, either when
2825  *        another callback replaces @func, the tooltip is unset with
2826  *        elm_widget_item_tooltip_unset() or the owner @a item
2827  *        dies. This callback receives as the first parameter the
2828  *        given @a data, and @c event_info is the item.
2829  *
2830  * @ingroup Widget
2831  */
2832 EAPI void
2833 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
2834                                         Elm_Tooltip_Item_Content_Cb func,
2835                                         const void                 *data,
2836                                         Evas_Smart_Cb               del_cb)
2837 {
2838    Elm_Widget_Item_Tooltip *wit;
2839
2840    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
2841
2842    if (!func)
2843      {
2844         _elm_widget_item_tooltip_unset(item);
2845         return;
2846      }
2847
2848    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
2849    if (!wit) goto error;
2850    wit->item = item;
2851    wit->func = func;
2852    wit->data = data;
2853    wit->del_cb = del_cb;
2854
2855    elm_object_sub_tooltip_content_cb_set
2856      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
2857      _elm_widget_item_tooltip_del_cb);
2858
2859    return;
2860
2861 error_noitem:
2862    if (del_cb) del_cb((void *)data, NULL, item);
2863    return;
2864 error:
2865    if (del_cb) del_cb((void *)data, item->widget, item);
2866 }
2867
2868 /**
2869  * @internal
2870  *
2871  * Unset tooltip from item
2872  *
2873  * @param item widget item to remove previously set tooltip.
2874  *
2875  * Remove tooltip from item. The callback provided as del_cb to
2876  * elm_widget_item_tooltip_content_cb_set() will be called to notify
2877  * it is not used anymore.
2878  *
2879  * @see elm_widget_item_tooltip_content_cb_set()
2880  *
2881  * @ingroup Widget
2882  */
2883 EAPI void
2884 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
2885 {
2886    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2887    elm_object_tooltip_unset(item->view);
2888 }
2889
2890 /**
2891  * @internal
2892  *
2893  * Sets a different style for this item tooltip.
2894  *
2895  * @note before you set a style you should define a tooltip with
2896  *       elm_widget_item_tooltip_content_cb_set() or
2897  *       elm_widget_item_tooltip_text_set()
2898  *
2899  * @param item widget item with tooltip already set.
2900  * @param style the theme style to use (default, transparent, ...)
2901  *
2902  * @ingroup Widget
2903  */
2904 EAPI void
2905 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
2906                                    const char      *style)
2907 {
2908    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2909    elm_object_tooltip_style_set(item->view, style);
2910 }
2911
2912 EAPI Eina_Bool
2913 _elm_widget_item_tooltip_size_restrict_disable(Elm_Widget_Item *item, Eina_Bool disable)
2914 {
2915    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2916    return elm_tooltip_size_restrict_disable(item->view, disable);
2917 }
2918
2919 EAPI Eina_Bool
2920 _elm_widget_item_tooltip_size_restrict_disabled_get(const Elm_Widget_Item *item)
2921 {
2922    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2923    return elm_tooltip_size_restrict_disabled_get(item->view);
2924 }
2925
2926 /**
2927  * @internal
2928  *
2929  * Get the style for this item tooltip.
2930  *
2931  * @param item widget item with tooltip already set.
2932  * @return style the theme style in use, defaults to "default". If the
2933  *         object does not have a tooltip set, then NULL is returned.
2934  *
2935  * @ingroup Widget
2936  */
2937 EAPI const char *
2938 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
2939 {
2940    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2941    return elm_object_tooltip_style_get(item->view);
2942 }
2943
2944 EAPI void
2945 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
2946                             const char      *cursor)
2947 {
2948    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2949    elm_object_sub_cursor_set(item->view, item->widget, cursor);
2950 }
2951
2952 EAPI const char *
2953 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
2954 {
2955    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2956    return elm_object_cursor_get(item->view);
2957 }
2958
2959 EAPI void
2960 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
2961 {
2962    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2963    elm_object_cursor_unset(item->view);
2964 }
2965
2966 /**
2967  * @internal
2968  *
2969  * Sets a different style for this item cursor.
2970  *
2971  * @note before you set a style you should define a cursor with
2972  *       elm_widget_item_cursor_set()
2973  *
2974  * @param item widget item with cursor already set.
2975  * @param style the theme style to use (default, transparent, ...)
2976  *
2977  * @ingroup Widget
2978  */
2979 EAPI void
2980 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
2981                                   const char      *style)
2982 {
2983    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2984    elm_object_cursor_style_set(item->view, style);
2985 }
2986
2987 /**
2988  * @internal
2989  *
2990  * Get the style for this item cursor.
2991  *
2992  * @param item widget item with cursor already set.
2993  * @return style the theme style in use, defaults to "default". If the
2994  *         object does not have a cursor set, then NULL is returned.
2995  *
2996  * @ingroup Widget
2997  */
2998 EAPI const char *
2999 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
3000 {
3001    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3002    return elm_object_cursor_style_get(item->view);
3003 }
3004
3005 /**
3006  * @internal
3007  *
3008  * Set if the cursor set should be searched on the theme or should use
3009  * the provided by the engine, only.
3010  *
3011  * @note before you set if should look on theme you should define a cursor
3012  * with elm_object_cursor_set(). By default it will only look for cursors
3013  * provided by the engine.
3014  *
3015  * @param item widget item with cursor already set.
3016  * @param engine_only boolean to define it cursors should be looked only
3017  * between the provided by the engine or searched on widget's theme as well.
3018  *
3019  * @ingroup Widget
3020  */
3021 EAPI void
3022 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
3023                                         Eina_Bool        engine_only)
3024 {
3025    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3026    elm_object_cursor_engine_only_set(item->view, engine_only);
3027 }
3028
3029 /**
3030  * @internal
3031  *
3032  * Get the cursor engine only usage for this item cursor.
3033  *
3034  * @param item widget item with cursor already set.
3035  * @return engine_only boolean to define it cursors should be looked only
3036  * between the provided by the engine or searched on widget's theme as well. If
3037  *         the object does not have a cursor set, then EINA_FALSE is returned.
3038  *
3039  * @ingroup Widget
3040  */
3041 EAPI Eina_Bool
3042 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
3043 {
3044    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3045    return elm_object_cursor_engine_only_get(item->view);
3046 }
3047
3048 // smart object funcs
3049 static void
3050 _smart_reconfigure(Smart_Data *sd)
3051 {
3052    if (sd->resize_obj)
3053      {
3054         evas_object_move(sd->resize_obj, sd->x, sd->y);
3055         evas_object_resize(sd->resize_obj, sd->w, sd->h);
3056      }
3057    if (sd->hover_obj)
3058      {
3059         evas_object_move(sd->hover_obj, sd->x, sd->y);
3060         evas_object_resize(sd->hover_obj, sd->w, sd->h);
3061      }
3062 }
3063
3064 EAPI void
3065 _elm_widget_item_content_part_set(Elm_Widget_Item *item,
3066                                  const char *part,
3067                                  Evas_Object *content)
3068 {
3069    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3070    if (!item->on_content_set_func) return;
3071    item->on_content_set_func((Elm_Object_Item *) item, part, content);
3072 }
3073
3074 EAPI Evas_Object *
3075 _elm_widget_item_content_part_get(const Elm_Widget_Item *item,
3076                                   const char *part)
3077 {
3078    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3079    if (!item->on_content_get_func) return NULL;
3080    return item->on_content_get_func((Elm_Object_Item *) item, part);
3081 }
3082
3083 EAPI Evas_Object *
3084 _elm_widget_item_content_part_unset(Elm_Widget_Item *item,
3085                                     const char *part)
3086 {
3087    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3088    if (!item->on_content_unset_func) return NULL;
3089    return item->on_content_unset_func((Elm_Object_Item *) item, part);
3090 }
3091
3092 EAPI void
3093 _elm_widget_item_text_part_set(Elm_Widget_Item *item,
3094                               const char *part,
3095                               const char *label)
3096 {
3097    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3098    if (!item->on_text_set_func) return;
3099    item->on_text_set_func((Elm_Object_Item *) item, part, label);
3100 }
3101
3102 EAPI void
3103 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
3104                              const char *emission,
3105                              const char *source)
3106 {
3107    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3108    if (item->on_signal_emit_func)
3109      item->on_signal_emit_func((Elm_Object_Item *) item, emission, source);
3110 }
3111
3112 EAPI const char *
3113 _elm_widget_item_text_part_get(const Elm_Widget_Item *item,
3114                                const char *part)
3115 {
3116    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3117    if (!item->on_text_get_func) return NULL;
3118    return item->on_text_get_func((Elm_Object_Item *) item, part);
3119 }
3120
3121 EAPI void
3122 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3123                                       Elm_Widget_On_Content_Set_Cb func)
3124 {
3125    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3126    item->on_content_set_func = func;
3127 }
3128
3129 EAPI void
3130 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3131                                       Elm_Widget_On_Content_Get_Cb func)
3132 {
3133    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3134    item->on_content_get_func = func;
3135 }
3136
3137 EAPI void
3138 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3139                                         Elm_Widget_On_Content_Unset_Cb func)
3140 {
3141    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3142    item->on_content_unset_func = func;
3143 }
3144
3145 EAPI void
3146 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3147                                    Elm_Widget_On_Text_Set_Cb func)
3148 {
3149    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3150    item->on_text_set_func = func;
3151 }
3152
3153 EAPI void
3154 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3155                                    Elm_Widget_On_Text_Get_Cb func)
3156 {
3157    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3158    item->on_text_get_func = func;
3159 }
3160
3161 EAPI void
3162 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
3163                                       Elm_Widget_On_Signal_Emit_Cb func)
3164 {
3165    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3166    item->on_signal_emit_func = func;
3167 }
3168
3169 EAPI void
3170 _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
3171 {
3172    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3173    if (item->access_info) eina_stringshare_del(item->access_info);
3174    if (!txt) item->access_info = NULL;
3175    else item->access_info = eina_stringshare_add(txt);
3176 }
3177
3178
3179 static void
3180 _smart_add(Evas_Object *obj)
3181 {
3182    Smart_Data *sd;
3183
3184    sd = calloc(1, sizeof(Smart_Data));
3185    if (!sd) return;
3186    sd->obj = obj;
3187    sd->x = sd->y = sd->w = sd->h = 0;
3188    sd->can_focus = 1;
3189    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3190    evas_object_smart_data_set(obj, sd);
3191 }
3192
3193 static Evas_Object *
3194 _newest_focus_order_get(Evas_Object  *obj,
3195                         unsigned int *newest_focus_order,
3196                         Eina_Bool     can_focus_only)
3197 {
3198    const Eina_List *l;
3199    Evas_Object *child, *ret, *best;
3200
3201    API_ENTRY return NULL;
3202
3203    if (!evas_object_visible_get(obj)
3204        || (elm_widget_disabled_get(obj))
3205        || (elm_widget_tree_unfocusable_get(obj)))
3206      return NULL;
3207
3208    best = NULL;
3209    if (*newest_focus_order < sd->focus_order)
3210      {
3211         *newest_focus_order = sd->focus_order;
3212         best = obj;
3213      }
3214    EINA_LIST_FOREACH(sd->subobjs, l, child)
3215      {
3216         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3217         if (!ret) continue;
3218         best = ret;
3219      }
3220    if (can_focus_only)
3221      {
3222         if ((!best) || (!elm_widget_can_focus_get(best)))
3223           return NULL;
3224      }
3225    return best;
3226 }
3227
3228 static void
3229 _if_focused_revert(Evas_Object *obj,
3230                    Eina_Bool    can_focus_only)
3231 {
3232    Evas_Object *top;
3233    Evas_Object *newest = NULL;
3234    unsigned int newest_focus_order = 0;
3235
3236    INTERNAL_ENTRY
3237
3238    if (!sd->focused) return;
3239    if (!sd->parent_obj) return;
3240
3241    top = elm_widget_top_get(sd->parent_obj);
3242    if (top)
3243      {
3244         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3245         if (newest)
3246           {
3247              elm_object_focus_set(newest, EINA_FALSE);
3248              elm_object_focus_set(newest, EINA_TRUE);
3249           }
3250      }
3251 }
3252
3253 static void
3254 _smart_del(Evas_Object *obj)
3255 {
3256    Evas_Object *sobj;
3257    Edje_Signal_Data *esd;
3258
3259    INTERNAL_ENTRY
3260
3261    if (sd->del_pre_func) sd->del_pre_func(obj);
3262    if (sd->resize_obj)
3263      {
3264         sobj = sd->resize_obj;
3265         sd->resize_obj = NULL;
3266         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3267         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3268         evas_object_del(sobj);
3269      }
3270    if (sd->hover_obj)
3271      {
3272         sobj = sd->hover_obj;
3273         sd->hover_obj = NULL;
3274         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3275         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3276         evas_object_del(sobj);
3277      }
3278    EINA_LIST_FREE(sd->subobjs, sobj)
3279      {
3280         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3281         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3282         evas_object_del(sobj);
3283      }
3284    eina_list_free(sd->tooltips); /* should be empty anyway */
3285    eina_list_free(sd->cursors); /* should be empty anyway */
3286    EINA_LIST_FREE(sd->edje_signals, esd)
3287      {
3288         eina_stringshare_del(esd->emission);
3289         eina_stringshare_del(esd->source);
3290         free(esd);
3291      }
3292    eina_list_free(sd->event_cb); /* should be empty anyway */
3293    if (sd->del_func) sd->del_func(obj);
3294    if (sd->style) eina_stringshare_del(sd->style);
3295    if (sd->type) eina_stringshare_del(sd->type);
3296    if (sd->theme) elm_theme_free(sd->theme);
3297    _if_focused_revert(obj, EINA_TRUE);
3298    if (sd->access_info) eina_stringshare_del(sd->access_info);
3299    free(sd);
3300 }
3301
3302 static void
3303 _smart_move(Evas_Object *obj,
3304             Evas_Coord   x,
3305             Evas_Coord   y)
3306 {
3307    INTERNAL_ENTRY
3308    sd->x = x;
3309    sd->y = y;
3310    _smart_reconfigure(sd);
3311 }
3312
3313 static void
3314 _smart_resize(Evas_Object *obj,
3315               Evas_Coord   w,
3316               Evas_Coord   h)
3317 {
3318    INTERNAL_ENTRY
3319    sd->w = w;
3320    sd->h = h;
3321    _smart_reconfigure(sd);
3322 }
3323
3324 static void
3325 _smart_show(Evas_Object *obj)
3326 {
3327    Eina_List *list;
3328    Evas_Object *o;
3329    INTERNAL_ENTRY
3330    if ((list = evas_object_smart_members_get(obj)))
3331      {
3332         EINA_LIST_FREE(list, o)
3333           {
3334              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3335              evas_object_show(o);
3336           }
3337      }
3338 }
3339
3340 static void
3341 _smart_hide(Evas_Object *obj)
3342 {
3343    Eina_List *list;
3344    Evas_Object *o;
3345    INTERNAL_ENTRY
3346
3347    list = evas_object_smart_members_get(obj);
3348    EINA_LIST_FREE(list, o)
3349      {
3350         if (evas_object_data_get(o, "_elm_leaveme")) continue;
3351         evas_object_hide(o);
3352      }
3353 }
3354
3355 static void
3356 _smart_color_set(Evas_Object *obj,
3357                  int          r,
3358                  int          g,
3359                  int          b,
3360                  int          a)
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_color_set(o, r, g, b, a);
3371           }
3372      }
3373 }
3374
3375 static void
3376 _smart_clip_set(Evas_Object *obj,
3377                 Evas_Object *clip)
3378 {
3379    Eina_List *list;
3380    Evas_Object *o;
3381    INTERNAL_ENTRY
3382    if ((list = evas_object_smart_members_get(obj)))
3383      {
3384         EINA_LIST_FREE(list, o)
3385           {
3386              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3387              evas_object_clip_set(o, clip);
3388           }
3389      }
3390 }
3391
3392 static void
3393 _smart_clip_unset(Evas_Object *obj)
3394 {
3395    Eina_List *list;
3396    Evas_Object *o;
3397    INTERNAL_ENTRY
3398    if ((list = evas_object_smart_members_get(obj)))
3399      {
3400         EINA_LIST_FREE(list, o)
3401           {
3402              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3403              evas_object_clip_unset(o);
3404           }
3405      }
3406 }
3407
3408 static void
3409 _smart_calculate(Evas_Object *obj)
3410 {
3411    INTERNAL_ENTRY
3412    if (sd->changed_func) sd->changed_func(obj);
3413 }
3414
3415 /* never need to touch this */
3416 static void
3417 _smart_init(void)
3418 {
3419    if (_e_smart) return;
3420      {
3421         static const Evas_Smart_Class sc =
3422           {
3423              SMART_NAME,
3424              EVAS_SMART_CLASS_VERSION,
3425              _smart_add,
3426              _smart_del,
3427              _smart_move,
3428              _smart_resize,
3429              _smart_show,
3430              _smart_hide,
3431              _smart_color_set,
3432              _smart_clip_set,
3433              _smart_clip_unset,
3434              _smart_calculate,
3435              NULL,
3436              NULL,
3437              NULL,
3438              NULL,
3439              NULL,
3440              NULL
3441           };
3442         _e_smart = evas_smart_class_new(&sc);
3443      }
3444 }
3445
3446 /* happy debug functions */
3447 #ifdef ELM_DEBUG
3448 static void
3449 _sub_obj_tree_dump(const Evas_Object *obj,
3450                    int                lvl)
3451 {
3452    int i;
3453
3454    for (i = 0; i < lvl * 3; i++)
3455      putchar(' ');
3456
3457    if (_elm_widget_is(obj))
3458      {
3459         Eina_List *l;
3460         INTERNAL_ENTRY
3461         printf("+ %s(%p)\n",
3462                sd->type,
3463                obj);
3464         if (sd->resize_obj)
3465           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3466         EINA_LIST_FOREACH(sd->subobjs, l, obj)
3467           {
3468              if (obj != sd->resize_obj)
3469                _sub_obj_tree_dump(obj, lvl + 1);
3470           }
3471      }
3472    else
3473      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3474 }
3475
3476 static void
3477 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3478                        FILE              *output)
3479 {
3480    if (!_elm_widget_is(obj))
3481      return;
3482    INTERNAL_ENTRY
3483
3484    Eina_Bool visible = evas_object_visible_get(obj);
3485    Eina_Bool disabled = elm_widget_disabled_get(obj);
3486    Eina_Bool focused = elm_widget_focus_get(obj);
3487    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3488
3489    if (sd->parent_obj)
3490      {
3491         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3492
3493         if (focused)
3494           fprintf(output, ", style=bold");
3495
3496         if (!visible)
3497           fprintf(output, ", color=gray28");
3498
3499         fprintf(output, " ];\n");
3500      }
3501
3502    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3503                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3504            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3505            sd->focus_order);
3506
3507    if (focused)
3508      fprintf(output, ", style=bold");
3509
3510    if (!visible)
3511      fprintf(output, ", fontcolor=gray28");
3512
3513    if ((disabled) || (!visible))
3514      fprintf(output, ", color=gray");
3515
3516    fprintf(output, " ];\n");
3517
3518    Eina_List *l;
3519    Evas_Object *o;
3520    EINA_LIST_FOREACH(sd->subobjs, l, o)
3521      _sub_obj_tree_dot_dump(o, output);
3522 }
3523 #endif
3524
3525 EAPI void
3526 elm_widget_tree_dump(const Evas_Object *top)
3527 {
3528 #ifdef ELM_DEBUG
3529    _sub_obj_tree_dump(top, 0);
3530 #else
3531    return;
3532    (void)top;
3533 #endif
3534 }
3535
3536 EAPI void
3537 elm_widget_tree_dot_dump(const Evas_Object *top,
3538                          FILE              *output)
3539 {
3540 #ifdef ELM_DEBUG
3541    if (!_elm_widget_is(top))
3542      return;
3543    fprintf(output, "graph " " { node [shape=record];\n");
3544    _sub_obj_tree_dot_dump(top, output);
3545    fprintf(output, "}\n");
3546 #else
3547    return;
3548    (void)top;
3549    (void)output;
3550 #endif
3551 }