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