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