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