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