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