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