Merge "[TC] removed deprecated elm_entry_wrap_width_get function from entry TC"
[framework/uifw/elementary.git] / src / lib / elm_widget.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static const char SMART_NAME[] = "elm_widget";
5
6 #define API_ENTRY                                    \
7   Smart_Data * sd = evas_object_smart_data_get(obj); \
8   if ((!obj) || (!sd) || (!_elm_widget_is(obj)))
9 #define INTERNAL_ENTRY                               \
10   Smart_Data * sd = evas_object_smart_data_get(obj); \
11   if (!sd) return;
12
13 #undef elm_widget_text_set_hook_set
14 #undef elm_widget_text_get_hook_set
15 #undef elm_widget_content_set_hook_set
16 #undef elm_widget_content_get_hook_set
17 #undef elm_widget_content_unset_hook_set
18
19 typedef struct _Smart_Data        Smart_Data;
20 typedef struct _Edje_Signal_Data  Edje_Signal_Data;
21 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
22 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
23
24 struct _Smart_Data
25 {
26    Evas_Object *obj;
27    const char  *type;
28    Evas_Object *parent_obj;
29    Evas_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_On_Text_Set_Cb on_text_set_func;
83    Elm_Widget_On_Text_Get_Cb on_text_get_func;
84    Elm_Widget_On_Content_Set_Cb on_content_set_func;
85    Elm_Widget_On_Content_Get_Cb on_content_get_func;
86    Elm_Widget_On_Content_Unset_Cb on_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_On_Text_Set_Cb func)
568 {
569    API_ENTRY return;
570    sd->on_text_set_func = func;
571 }
572
573 EAPI void
574 elm_widget_text_get_hook_set(Evas_Object *obj,
575                              Elm_Widget_On_Text_Get_Cb func)
576 {
577    API_ENTRY return;
578    sd->on_text_get_func = func;
579 }
580
581 EAPI void
582 elm_widget_content_set_hook_set(Evas_Object *obj,
583                                 Elm_Widget_On_Content_Set_Cb func)
584 {
585    API_ENTRY return;
586    sd->on_content_set_func = func;
587 }
588
589 EAPI void
590 elm_widget_content_get_hook_set(Evas_Object *obj,
591                                 Elm_Widget_On_Content_Get_Cb func)
592 {
593    API_ENTRY return;
594    sd->on_content_get_func = func;
595 }
596
597 EAPI void
598 elm_widget_content_unset_hook_set(Evas_Object *obj,
599                                   Elm_Widget_On_Content_Unset_Cb func)
600 {
601    API_ENTRY return;
602    sd->on_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 (_elm_widget_is(sobj))
924      {
925         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
926         if (sd2)
927           {
928              if (sd2->parent_obj == obj)
929                return;
930              if (sd2->parent_obj)
931                elm_widget_sub_object_del(sd2->parent_obj, sobj);
932              sd2->parent_obj = obj;
933              sd2->top_win_focused = sd->top_win_focused;
934              if (!sd->child_can_focus && (_is_focusable(sobj)))
935                sd->child_can_focus = EINA_TRUE;
936           }
937      }
938    else
939      {
940         void *data = evas_object_data_get(sobj, "elm-parent");
941         if (data)
942           {
943              if (data == obj) return;
944              evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
945                                             _sub_obj_del);
946           }
947      }
948
949    sd->subobjs = eina_list_append(sd->subobjs, sobj);
950    evas_object_data_set(sobj, "elm-parent", obj);
951    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
952    if (_elm_widget_is(sobj))
953      evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
954    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
955    scale = elm_widget_scale_get(sobj);
956    th = elm_widget_theme_get(sobj);
957    mirrored = elm_widget_mirrored_get(sobj);
958    if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
959    if (elm_widget_focus_get(sobj)) _focus_parents(obj);
960 }
961
962 EAPI void
963 elm_widget_sub_object_del(Evas_Object *obj,
964                           Evas_Object *sobj)
965 {
966    Evas_Object *sobj_parent;
967    API_ENTRY return;
968    if (!sobj) return;
969
970    sobj_parent = evas_object_data_del(sobj, "elm-parent");
971    if (sobj_parent != obj)
972      {
973         static int abort_on_warn = -1;
974         ERR("removing sub object %p from parent %p, "
975             "but elm-parent is different %p!",
976             sobj, obj, sobj_parent);
977         if (EINA_UNLIKELY(abort_on_warn == -1))
978           {
979              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
980              else abort_on_warn = 0;
981           }
982         if (abort_on_warn == 1) abort();
983      }
984    if (_elm_widget_is(sobj))
985      {
986         if (elm_widget_focus_get(sobj))
987           {
988              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
989              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
990           }
991         if ((sd->child_can_focus) && (_is_focusable(sobj)))
992           {
993              Evas_Object *subobj;
994              const Eina_List *l;
995              sd->child_can_focus = EINA_FALSE;
996              EINA_LIST_FOREACH(sd->subobjs, l, subobj)
997                {
998                   if (_is_focusable(subobj))
999                     {
1000                        sd->child_can_focus = EINA_TRUE;
1001                        break;
1002                     }
1003                }
1004           }
1005         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1006         if (sd2)
1007           {
1008              sd2->parent_obj = NULL;
1009              if (sd2->resize_obj == sobj)
1010                sd2->resize_obj = NULL;
1011              else
1012                sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1013           }
1014         else
1015           sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1016      }
1017    else
1018      sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1019    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1020                                        _sub_obj_del, sd);
1021    if (_elm_widget_is(sobj))
1022      evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1023                                          _sub_obj_hide, sd);
1024    evas_object_smart_callback_call(obj, "sub-object-del", sobj);
1025 }
1026
1027 EAPI void
1028 elm_widget_resize_object_set(Evas_Object *obj,
1029                              Evas_Object *sobj)
1030 {
1031    API_ENTRY return;
1032    // orphan previous resize obj
1033    if (sd->resize_obj)
1034      {
1035         evas_object_clip_unset(sd->resize_obj);
1036         evas_object_data_del(sd->resize_obj, "elm-parent");
1037         if (_elm_widget_is(sd->resize_obj))
1038           {
1039              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1040              if (sd2) sd2->parent_obj = NULL;
1041              evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_HIDE,
1042                                                  _sub_obj_hide, sd);
1043           }
1044         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
1045                                             _sub_obj_del, sd);
1046         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_DOWN,
1047                                             _sub_obj_mouse_down, sd);
1048         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_MOVE,
1049                                             _sub_obj_mouse_move, sd);
1050         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_UP,
1051                                             _sub_obj_mouse_up, sd);
1052         evas_object_smart_member_del(sd->resize_obj);
1053         if (_elm_widget_is(sd->resize_obj))
1054           {
1055              if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
1056           }
1057      }
1058    // orphan new resize obj
1059    if (sobj)
1060      {
1061         evas_object_data_del(sobj, "elm-parent");
1062         if (_elm_widget_is(sobj))
1063           {
1064              Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1065              if (sd2) sd2->parent_obj = NULL;
1066              evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1067                                                  _sub_obj_hide, sd);
1068           }
1069         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1070                                             _sub_obj_del, sd);
1071         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1072                                             _sub_obj_mouse_down, sd);
1073         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1074                                             _sub_obj_mouse_move, sd);
1075         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_UP,
1076                                             _sub_obj_mouse_up, sd);
1077         evas_object_smart_member_del(sobj);
1078         if (_elm_widget_is(sobj))
1079           {
1080              if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
1081           }
1082      }
1083    // set the resize obj up
1084    sd->resize_obj = sobj;
1085    if (sd->resize_obj)
1086      {
1087         if (_elm_widget_is(sd->resize_obj))
1088           {
1089              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1090              if (sd2)
1091                {
1092                   sd2->parent_obj = obj;
1093                   sd2->top_win_focused = sd->top_win_focused;
1094                }
1095              evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
1096                                             _sub_obj_hide, sd);
1097           }
1098         evas_object_clip_set(sobj, evas_object_clip_get(obj));
1099         evas_object_smart_member_add(sobj, obj);
1100         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1101                                        _sub_obj_del, sd);
1102         evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1103                                        _sub_obj_mouse_down, sd);
1104         evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1105                                        _sub_obj_mouse_move, sd);
1106         evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_UP,
1107                                        _sub_obj_mouse_up, sd);
1108         _smart_reconfigure(sd);
1109         evas_object_data_set(sobj, "elm-parent", obj);
1110         evas_object_smart_callback_call(obj, "sub-object-add", sobj);
1111         if (_elm_widget_is(sobj))
1112           {
1113              if (elm_widget_focus_get(sobj)) _focus_parents(obj);
1114           }
1115      }
1116 }
1117
1118 EAPI void
1119 elm_widget_hover_object_set(Evas_Object *obj,
1120                             Evas_Object *sobj)
1121 {
1122    API_ENTRY return;
1123    if (sd->hover_obj)
1124      {
1125         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1126                                             _sub_obj_del, sd);
1127      }
1128    sd->hover_obj = sobj;
1129    if (sd->hover_obj)
1130      {
1131         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1132                                        _sub_obj_del, sd);
1133         _smart_reconfigure(sd);
1134      }
1135 }
1136
1137 EAPI void
1138 elm_widget_can_focus_set(Evas_Object *obj,
1139                          Eina_Bool    can_focus)
1140 {
1141    API_ENTRY return;
1142    sd->can_focus = can_focus;
1143    if (can_focus)
1144      {
1145         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1146                                        _propagate_event,
1147                                        (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1148         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1149                                        _propagate_event,
1150                                        (void *)(long)EVAS_CALLBACK_KEY_UP);
1151         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1152                                        _propagate_event,
1153                                        (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1154      }
1155    else
1156      {
1157         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1158                                        _propagate_event);
1159         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1160                                        _propagate_event);
1161         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1162                                        _propagate_event);
1163      }
1164 }
1165
1166 EAPI Eina_Bool
1167 elm_widget_can_focus_get(const Evas_Object *obj)
1168 {
1169    API_ENTRY return EINA_FALSE;
1170    return sd->can_focus;
1171 }
1172
1173 EAPI Eina_Bool
1174 elm_widget_child_can_focus_get(const Evas_Object *obj)
1175 {
1176    API_ENTRY return EINA_FALSE;
1177    return sd->child_can_focus;
1178 }
1179
1180 /**
1181  * @internal
1182  *
1183  * This API makes the widget object and its children to be unfocusable.
1184  *
1185  * This API can be helpful for an object to be deleted.
1186  * When an object will be deleted soon, it and its children may not
1187  * want to get focus (by focus reverting or by other focus controls).
1188  * Then, just use this API before deleting.
1189  *
1190  * @param obj The widget root of sub-tree
1191  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1192  *
1193  * @ingroup Widget
1194  */
1195 EAPI void
1196 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1197                                 Eina_Bool    tree_unfocusable)
1198 {
1199    API_ENTRY return;
1200
1201    if (sd->tree_unfocusable == tree_unfocusable) return;
1202    sd->tree_unfocusable = !!tree_unfocusable;
1203    elm_widget_focus_tree_unfocusable_handle(obj);
1204 }
1205
1206 /**
1207  * @internal
1208  *
1209  * This returns true, if the object sub-tree is unfocusable.
1210  *
1211  * @param obj The widget root of sub-tree
1212  * @return EINA_TRUE if the object sub-tree is unfocusable
1213  *
1214  * @ingroup Widget
1215  */
1216 EAPI Eina_Bool
1217 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1218 {
1219    API_ENTRY return EINA_FALSE;
1220    return sd->tree_unfocusable;
1221 }
1222
1223 /**
1224  * @internal
1225  *
1226  * Get the list of focusable child objects.
1227  *
1228  * This function retruns list of child objects which can get focus.
1229  *
1230  * @param obj The parent widget
1231  * @retrun list of focusable child objects.
1232  *
1233  * @ingroup Widget
1234  */
1235 EAPI Eina_List *
1236 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1237 {
1238    API_ENTRY return NULL;
1239
1240    const Eina_List *l;
1241    Eina_List *child_list = NULL;
1242    Evas_Object *child;
1243
1244    if (sd->subobjs)
1245      {
1246         EINA_LIST_FOREACH(sd->subobjs, l, child)
1247           {
1248              if ((elm_widget_can_focus_get(child)) &&
1249                  (evas_object_visible_get(child)) &&
1250                  (!elm_widget_disabled_get(child)))
1251                child_list = eina_list_append(child_list, child);
1252              else if (elm_widget_is(child))
1253                {
1254                   Eina_List *can_focus_list;
1255                   can_focus_list = elm_widget_can_focus_child_list_get(child);
1256                   if (can_focus_list)
1257                     child_list = eina_list_merge(child_list, can_focus_list);
1258                }
1259           }
1260      }
1261    return child_list;
1262 }
1263
1264 EAPI void
1265 elm_widget_highlight_ignore_set(Evas_Object *obj,
1266                                 Eina_Bool    ignore)
1267 {
1268    API_ENTRY return;
1269    sd->highlight_ignore = !!ignore;
1270 }
1271
1272 EAPI Eina_Bool
1273 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1274 {
1275    API_ENTRY return EINA_FALSE;
1276    return sd->highlight_ignore;
1277 }
1278
1279 EAPI void
1280 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1281                                   Eina_Bool    highlight)
1282 {
1283    API_ENTRY return;
1284    sd->highlight_in_theme = !!highlight;
1285    /* FIXME: if focused, it should switch from one mode to the other */
1286 }
1287
1288 EAPI Eina_Bool
1289 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1290 {
1291    API_ENTRY return EINA_FALSE;
1292    return sd->highlight_in_theme;
1293 }
1294
1295 EAPI Eina_Bool
1296 elm_widget_focus_get(const Evas_Object *obj)
1297 {
1298    API_ENTRY return EINA_FALSE;
1299    return sd->focused;
1300 }
1301
1302 EAPI Evas_Object *
1303 elm_widget_focused_object_get(const Evas_Object *obj)
1304 {
1305    const Evas_Object *subobj;
1306    const Eina_List *l;
1307    API_ENTRY return NULL;
1308
1309    if (!sd->focused) return NULL;
1310    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1311      {
1312         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1313         if (fobj) return fobj;
1314      }
1315    return (Evas_Object *)obj;
1316 }
1317
1318 EAPI Evas_Object *
1319 elm_widget_top_get(const Evas_Object *obj)
1320 {
1321    API_ENTRY return NULL;
1322    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1323    return (Evas_Object *)obj;
1324 }
1325
1326 EAPI Eina_Bool
1327 elm_widget_is(const Evas_Object *obj)
1328 {
1329    return _elm_widget_is(obj);
1330 }
1331
1332 EAPI Evas_Object *
1333 elm_widget_parent_widget_get(const Evas_Object *obj)
1334 {
1335    Evas_Object *parent;
1336
1337    if (_elm_widget_is(obj))
1338      {
1339         Smart_Data *sd = evas_object_smart_data_get(obj);
1340         if (!sd) return NULL;
1341         parent = sd->parent_obj;
1342      }
1343    else
1344      {
1345         parent = evas_object_data_get(obj, "elm-parent");
1346         if (!parent) parent = evas_object_smart_parent_get(obj);
1347      }
1348
1349    while (parent)
1350      {
1351         Evas_Object *elm_parent;
1352         if (_elm_widget_is(parent)) break;
1353         elm_parent = evas_object_data_get(parent, "elm-parent");
1354         if (elm_parent) parent = elm_parent;
1355         else parent = evas_object_smart_parent_get(parent);
1356      }
1357    return parent;
1358 }
1359
1360 EAPI Evas_Object *
1361 elm_widget_parent2_get(const Evas_Object *obj)
1362 {
1363    if (_elm_widget_is(obj))
1364      {
1365         Smart_Data *sd = evas_object_smart_data_get(obj);
1366         if (sd) return sd->parent2;
1367      }
1368    return NULL;
1369 }
1370
1371 EAPI void
1372 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1373 {
1374    API_ENTRY return;
1375    sd->parent2 = parent;
1376 }
1377
1378 EAPI void
1379 elm_widget_event_callback_add(Evas_Object *obj,
1380                               Elm_Event_Cb func,
1381                               const void  *data)
1382 {
1383    API_ENTRY return;
1384    EINA_SAFETY_ON_NULL_RETURN(func);
1385    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1386    ecb->func = func;
1387    ecb->data = data;
1388    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1389 }
1390
1391 EAPI void *
1392 elm_widget_event_callback_del(Evas_Object *obj,
1393                               Elm_Event_Cb func,
1394                               const void  *data)
1395 {
1396    API_ENTRY return NULL;
1397    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1398    Eina_List *l;
1399    Elm_Event_Cb_Data *ecd;
1400    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1401      if ((ecd->func == func) && (ecd->data == data))
1402        {
1403           free(ecd);
1404           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1405           return (void *)data;
1406        }
1407    return NULL;
1408 }
1409
1410 EAPI Eina_Bool
1411 elm_widget_event_propagate(Evas_Object       *obj,
1412                            Evas_Callback_Type type,
1413                            void              *event_info,
1414                            Evas_Event_Flags  *event_flags)
1415 {
1416    API_ENTRY return EINA_FALSE; //TODO reduce.
1417    if (!_elm_widget_is(obj)) return EINA_FALSE;
1418    Evas_Object *parent = obj;
1419    Elm_Event_Cb_Data *ecd;
1420    Eina_List *l, *l_prev;
1421
1422    while (parent &&
1423           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1424      {
1425         sd = evas_object_smart_data_get(parent);
1426         if ((!sd) || (!_elm_widget_is(obj)))
1427           return EINA_FALSE; //Not Elm Widget
1428
1429         if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1430           return EINA_TRUE;
1431
1432         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1433           {
1434              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1435                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1436                return EINA_TRUE;
1437           }
1438         parent = sd->parent_obj;
1439      }
1440
1441    return EINA_FALSE;
1442 }
1443
1444 /**
1445  * @internal
1446  *
1447  * Set custom focus chain.
1448  *
1449  * This function i set one new and overwrite any previous custom focus chain
1450  * with the list of objects. The previous list will be deleted and this list
1451  * will be managed. After setted, don't modity it.
1452  *
1453  * @note On focus cycle, only will be evaluated children of this container.
1454  *
1455  * @param obj The container widget
1456  * @param objs Chain of objects to pass focus
1457  * @ingroup Widget
1458  */
1459 EAPI void
1460 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1461                                   Eina_List   *objs)
1462 {
1463    API_ENTRY return;
1464    if (!sd->focus_next_func)
1465      return;
1466
1467    elm_widget_focus_custom_chain_unset(obj);
1468
1469    Eina_List *l;
1470    Evas_Object *o;
1471
1472    EINA_LIST_FOREACH(objs, l, o)
1473      {
1474         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1475                                        _elm_object_focus_chain_del_cb, sd);
1476      }
1477
1478    sd->focus_chain = objs;
1479 }
1480
1481 /**
1482  * @internal
1483  *
1484  * Get custom focus chain
1485  *
1486  * @param obj The container widget
1487  * @ingroup Widget
1488  */
1489 EAPI const Eina_List *
1490 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1491 {
1492    API_ENTRY return NULL;
1493    return (const Eina_List *)sd->focus_chain;
1494 }
1495
1496 /**
1497  * @internal
1498  *
1499  * Unset custom focus chain
1500  *
1501  * @param obj The container widget
1502  * @ingroup Widget
1503  */
1504 EAPI void
1505 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1506 {
1507    API_ENTRY return;
1508    Eina_List *l, *l_next;
1509    Evas_Object *o;
1510
1511    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1512      {
1513         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1514                                             _elm_object_focus_chain_del_cb, sd);
1515         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1516      }
1517 }
1518
1519 /**
1520  * @internal
1521  *
1522  * Append object to custom focus chain.
1523  *
1524  * @note If relative_child equal to NULL or not in custom chain, the object
1525  * will be added in end.
1526  *
1527  * @note On focus cycle, only will be evaluated children of this container.
1528  *
1529  * @param obj The container widget
1530  * @param child The child to be added in custom chain
1531  * @param relative_child The relative object to position the child
1532  * @ingroup Widget
1533  */
1534 EAPI void
1535 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1536                                      Evas_Object *child,
1537                                      Evas_Object *relative_child)
1538 {
1539    API_ENTRY return;
1540    EINA_SAFETY_ON_NULL_RETURN(child);
1541    if (!sd->focus_next_func)
1542      return;
1543
1544    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1545                                        _elm_object_focus_chain_del_cb, sd);
1546
1547    if (!relative_child)
1548      {
1549         sd->focus_chain = eina_list_append(sd->focus_chain, child);
1550         return;
1551      }
1552
1553    sd->focus_chain = eina_list_append_relative(sd->focus_chain, child, relative_child);
1554    return;
1555 }
1556
1557 /**
1558  * @internal
1559  *
1560  * Prepend object to custom focus chain.
1561  *
1562  * @note If relative_child equal to NULL or not in custom chain, the object
1563  * will be added in begin.
1564  *
1565  * @note On focus cycle, only will be evaluated children of this container.
1566  *
1567  * @param obj The container widget
1568  * @param child The child to be added in custom chain
1569  * @param relative_child The relative object to position the child
1570  * @ingroup Widget
1571  */
1572 EAPI void
1573 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1574                                       Evas_Object *child,
1575                                       Evas_Object *relative_child)
1576 {
1577    API_ENTRY return;
1578    EINA_SAFETY_ON_NULL_RETURN(child);
1579    if (!sd->focus_next_func)
1580      return;
1581
1582    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1583                                        _elm_object_focus_chain_del_cb, sd);
1584
1585    if (!relative_child)
1586      {
1587         sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1588         return;
1589      }
1590
1591    sd->focus_chain = eina_list_prepend_relative(sd->focus_chain, child, relative_child);
1592    return;
1593 }
1594
1595 /**
1596  * @internal
1597  *
1598  * Give focus to next object in object tree.
1599  *
1600  * Give focus to next object in focus chain of one object sub-tree.
1601  * If the last object of chain already have focus, the focus will go to the
1602  * first object of chain.
1603  *
1604  * @param obj The widget root of sub-tree
1605  * @param dir Direction to cycle the focus
1606  *
1607  * @ingroup Widget
1608  */
1609 EAPI void
1610 elm_widget_focus_cycle(Evas_Object        *obj,
1611                        Elm_Focus_Direction dir)
1612 {
1613    Evas_Object *target = NULL;
1614    if (!_elm_widget_is(obj))
1615      return;
1616    elm_widget_focus_next_get(obj, dir, &target);
1617    if (target)
1618      elm_widget_focus_steal(target);
1619 }
1620
1621 /**
1622  * @internal
1623  *
1624  * Give focus to near object in one direction.
1625  *
1626  * Give focus to near object in direction of one object.
1627  * If none focusable object in given direction, the focus will not change.
1628  *
1629  * @param obj The reference widget
1630  * @param x Horizontal component of direction to focus
1631  * @param y Vertical component of direction to focus
1632  *
1633  * @ingroup Widget
1634  */
1635 EAPI void
1636 elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1637                               int          x __UNUSED__,
1638                               int          y __UNUSED__)
1639 {
1640    return; /* TODO */
1641 }
1642
1643 /**
1644  * @internal
1645  *
1646  * Get next object in focus chain of object tree.
1647  *
1648  * Get next object in focus chain of one object sub-tree.
1649  * Return the next object by reference. If don't have any candidate to receive
1650  * focus before chain end, the first candidate will be returned.
1651  *
1652  * @param obj The widget root of sub-tree
1653  * @param dir Direction os focus chain
1654  * @param next The next object in focus chain
1655  * @return EINA_TRUE if don't need focus chain restart/loop back
1656  *         to use 'next' obj.
1657  *
1658  * @ingroup Widget
1659  */
1660 EAPI Eina_Bool
1661 elm_widget_focus_next_get(const Evas_Object  *obj,
1662                           Elm_Focus_Direction dir,
1663                           Evas_Object       **next)
1664 {
1665    if (!next)
1666      return EINA_FALSE;
1667    *next = NULL;
1668
1669    API_ENTRY return EINA_FALSE;
1670
1671    /* Ignore if disabled */
1672    if ((!evas_object_visible_get(obj))
1673        || (elm_widget_disabled_get(obj))
1674        || (elm_widget_tree_unfocusable_get(obj)))
1675      return EINA_FALSE;
1676
1677    /* Try use hook */
1678    if (sd->focus_next_func)
1679      return sd->focus_next_func(obj, dir, next);
1680
1681    if (!elm_widget_can_focus_get(obj))
1682      return EINA_FALSE;
1683
1684    /* Return */
1685    *next = (Evas_Object *)obj;
1686    return !elm_widget_focus_get(obj);
1687 }
1688
1689 /**
1690  * @internal
1691  *
1692  * Get next object in focus chain of object tree in list.
1693  *
1694  * Get next object in focus chain of one object sub-tree ordered by one list.
1695  * Return the next object by reference. If don't have any candidate to receive
1696  * focus before list end, the first candidate will be returned.
1697  *
1698  * @param obj The widget root of sub-tree
1699  * @param dir Direction os focus chain
1700  * @param items list with ordered objects
1701  * @param list_data_get function to get the object from one item of list
1702  * @param next The next object in focus chain
1703  * @return EINA_TRUE if don't need focus chain restart/loop back
1704  *         to use 'next' obj.
1705  *
1706  * @ingroup Widget
1707  */
1708 EAPI Eina_Bool
1709 elm_widget_focus_list_next_get(const Evas_Object  *obj,
1710                                const Eina_List    *items,
1711                                void *(*list_data_get)(const Eina_List * list),
1712                                Elm_Focus_Direction dir,
1713                                Evas_Object       **next)
1714 {
1715    Eina_List *(*list_next)(const Eina_List * list) = NULL;
1716
1717    if (!next)
1718      return EINA_FALSE;
1719    *next = NULL;
1720
1721    if (!_elm_widget_is(obj))
1722      return EINA_FALSE;
1723
1724    if (!items)
1725      return EINA_FALSE;
1726
1727    /* Direction */
1728    if (dir == ELM_FOCUS_PREVIOUS)
1729      {
1730         items = eina_list_last(items);
1731         list_next = eina_list_prev;
1732      }
1733    else if (dir == ELM_FOCUS_NEXT)
1734      list_next = eina_list_next;
1735    else
1736      return EINA_FALSE;
1737
1738    const Eina_List *l = items;
1739
1740    /* Recovery last focused sub item */
1741    if (elm_widget_focus_get(obj))
1742      for (; l; l = list_next(l))
1743        {
1744           Evas_Object *cur = list_data_get(l);
1745           if (elm_widget_focus_get(cur)) break;
1746        }
1747
1748    const Eina_List *start = l;
1749    Evas_Object *to_focus = NULL;
1750
1751    /* Interate sub items */
1752    /* Go to end of list */
1753    for (; l; l = list_next(l))
1754      {
1755         Evas_Object *tmp = NULL;
1756         Evas_Object *cur = list_data_get(l);
1757
1758         if (elm_widget_parent_get(cur) != obj)
1759           continue;
1760
1761         /* Try Focus cycle in subitem */
1762         if (elm_widget_focus_next_get(cur, dir, &tmp))
1763           {
1764              *next = tmp;
1765              return EINA_TRUE;
1766           }
1767         else if ((tmp) && (!to_focus))
1768           to_focus = tmp;
1769      }
1770
1771    l = items;
1772
1773    /* Get First possible */
1774    for (; l != start; l = list_next(l))
1775      {
1776         Evas_Object *tmp = NULL;
1777         Evas_Object *cur = list_data_get(l);
1778
1779         if (elm_widget_parent_get(cur) != obj)
1780           continue;
1781
1782         /* Try Focus cycle in subitem */
1783         elm_widget_focus_next_get(cur, dir, &tmp);
1784         if (tmp)
1785           {
1786              *next = tmp;
1787              return EINA_FALSE;
1788           }
1789      }
1790
1791    *next = to_focus;
1792    return EINA_FALSE;
1793 }
1794
1795 EAPI void
1796 elm_widget_signal_emit(Evas_Object *obj,
1797                        const char  *emission,
1798                        const char  *source)
1799 {
1800    API_ENTRY return;
1801    if (!sd->signal_func) return;
1802    sd->signal_func(obj, emission, source);
1803 }
1804
1805 static void
1806 _edje_signal_callback(void        *data,
1807                       Evas_Object *obj __UNUSED__,
1808                       const char  *emission,
1809                       const char  *source)
1810 {
1811    Edje_Signal_Data *esd = data;
1812    esd->func(esd->data, esd->obj, emission, source);
1813 }
1814
1815 EAPI void
1816 elm_widget_signal_callback_add(Evas_Object   *obj,
1817                                const char    *emission,
1818                                const char    *source,
1819                                Edje_Signal_Cb func,
1820                                void          *data)
1821 {
1822    Edje_Signal_Data *esd;
1823    API_ENTRY return;
1824    if (!sd->callback_add_func) return;
1825    EINA_SAFETY_ON_NULL_RETURN(func);
1826
1827    esd = ELM_NEW(Edje_Signal_Data);
1828    if (!esd) return;
1829
1830    esd->obj = obj;
1831    esd->func = func;
1832    esd->emission = eina_stringshare_add(emission);
1833    esd->source = eina_stringshare_add(source);
1834    esd->data = data;
1835    sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1836    sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1837 }
1838
1839 EAPI void *
1840 elm_widget_signal_callback_del(Evas_Object   *obj,
1841                                const char    *emission,
1842                                const char    *source,
1843                                Edje_Signal_Cb func)
1844 {
1845    Edje_Signal_Data *esd;
1846    Eina_List *l;
1847    void *data = NULL;
1848    API_ENTRY return NULL;
1849    if (!sd->callback_del_func) return NULL;
1850
1851    EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1852      {
1853         if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1854             (!strcmp(esd->source, source)))
1855           {
1856              sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1857              eina_stringshare_del(esd->emission);
1858              eina_stringshare_del(esd->source);
1859              data = esd->data;
1860              free(esd);
1861              break;
1862           }
1863      }
1864    sd->callback_del_func(obj, emission, source, _edje_signal_callback, data);
1865    return data;
1866 }
1867
1868 EAPI void
1869 elm_widget_focus_set(Evas_Object *obj,
1870                      int          first)
1871 {
1872    API_ENTRY return;
1873    if (!sd->focused)
1874      {
1875         focus_order++;
1876         sd->focus_order = focus_order;
1877         sd->focused = EINA_TRUE;
1878         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1879      }
1880    if (sd->focus_func)
1881      {
1882         sd->focus_func(obj);
1883         return;
1884      }
1885    else
1886      {
1887         if (first)
1888           {
1889              if ((_is_focusable(sd->resize_obj)) &&
1890                  (!elm_widget_disabled_get(sd->resize_obj)))
1891                {
1892                   elm_widget_focus_set(sd->resize_obj, first);
1893                }
1894              else
1895                {
1896                   const Eina_List *l;
1897                   Evas_Object *child;
1898                   EINA_LIST_FOREACH(sd->subobjs, l, child)
1899                     {
1900                        if ((_is_focusable(child)) &&
1901                            (!elm_widget_disabled_get(child)))
1902                          {
1903                             elm_widget_focus_set(child, first);
1904                             break;
1905                          }
1906                     }
1907                }
1908           }
1909         else
1910           {
1911              const Eina_List *l;
1912              Evas_Object *child;
1913              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1914                {
1915                   if ((_is_focusable(child)) &&
1916                       (!elm_widget_disabled_get(child)))
1917                     {
1918                        elm_widget_focus_set(child, first);
1919                        break;
1920                     }
1921                }
1922              if (!l)
1923                {
1924                   if ((_is_focusable(sd->resize_obj)) &&
1925                       (!elm_widget_disabled_get(sd->resize_obj)))
1926                     {
1927                        elm_widget_focus_set(sd->resize_obj, first);
1928                     }
1929                }
1930           }
1931      }
1932 }
1933
1934 EAPI Evas_Object *
1935 elm_widget_parent_get(const Evas_Object *obj)
1936 {
1937    API_ENTRY return NULL;
1938    return sd->parent_obj;
1939 }
1940
1941 EAPI void
1942 elm_widget_focused_object_clear(Evas_Object *obj)
1943 {
1944    API_ENTRY return;
1945    if (!sd->focused) return;
1946    if (elm_widget_focus_get(sd->resize_obj))
1947      elm_widget_focused_object_clear(sd->resize_obj);
1948    else
1949      {
1950         const Eina_List *l;
1951         Evas_Object *child;
1952         EINA_LIST_FOREACH(sd->subobjs, l, child)
1953           {
1954              if (elm_widget_focus_get(child))
1955                {
1956                   elm_widget_focused_object_clear(child);
1957                   break;
1958                }
1959           }
1960      }
1961    sd->focused = EINA_FALSE;
1962    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1963    if (sd->focus_func) sd->focus_func(obj);
1964 }
1965
1966 EAPI void
1967 elm_widget_focus_steal(Evas_Object *obj)
1968 {
1969    Evas_Object *parent, *parent2, *o;
1970    API_ENTRY return;
1971
1972    if (sd->focused) return;
1973    if (sd->disabled) return;
1974    if (!sd->can_focus) return;
1975    if (sd->tree_unfocusable) return;
1976    parent = obj;
1977    for (;;)
1978      {
1979         o = elm_widget_parent_get(parent);
1980         if (!o) break;
1981         sd = evas_object_smart_data_get(o);
1982         if (sd->disabled || sd->tree_unfocusable) return;
1983         if (sd->focused) break;
1984         parent = o;
1985      }
1986    if ((!elm_widget_parent_get(parent)) &&
1987        (!elm_widget_parent2_get(parent)))
1988       elm_widget_focused_object_clear(parent);
1989    else
1990      {
1991         parent2 = elm_widget_parent_get(parent);
1992         if (!parent2) parent2 = elm_widget_parent2_get(parent);
1993         parent = parent2;
1994         sd = evas_object_smart_data_get(parent);
1995         if (sd)
1996           {
1997              if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
1998                 elm_widget_focused_object_clear(sd->resize_obj);
1999              else
2000                {
2001                   const Eina_List *l;
2002                   Evas_Object *child;
2003                   EINA_LIST_FOREACH(sd->subobjs, l, child)
2004                     {
2005                        if (elm_widget_focus_get(child))
2006                          {
2007                             elm_widget_focused_object_clear(child);
2008                             break;
2009                          }
2010                     }
2011                }
2012           }
2013      }
2014    _parent_focus(obj);
2015    return;
2016 }
2017
2018 EAPI void
2019 elm_widget_focus_restore(Evas_Object *obj)
2020 {
2021    Evas_Object *newest = NULL;
2022    unsigned int newest_focus_order = 0;
2023    API_ENTRY return;
2024
2025    newest = _newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2026    if (newest)
2027      {
2028         elm_object_focus_set(newest, EINA_FALSE);
2029         elm_object_focus_set(newest, EINA_TRUE);
2030      }
2031 }
2032
2033 void
2034 _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused)
2035 {
2036    const Eina_List *l;
2037    Evas_Object *child;
2038    API_ENTRY return;
2039
2040    if (sd->top_win_focused == top_win_focused) return;
2041    if (sd->resize_obj)
2042      _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2043    EINA_LIST_FOREACH(sd->subobjs, l, child)
2044      {
2045         _elm_widget_top_win_focused_set(child, top_win_focused);
2046      }
2047    sd->top_win_focused = top_win_focused;
2048 }
2049
2050 Eina_Bool
2051 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2052 {
2053    API_ENTRY return EINA_FALSE;
2054    return sd->top_win_focused;
2055 }
2056
2057 EAPI void
2058 elm_widget_activate(Evas_Object *obj)
2059 {
2060    API_ENTRY return;
2061    elm_widget_change(obj);
2062    if (sd->activate_func) sd->activate_func(obj);
2063 }
2064
2065 EAPI void
2066 elm_widget_change(Evas_Object *obj)
2067 {
2068    API_ENTRY return;
2069    elm_widget_change(elm_widget_parent_get(obj));
2070    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
2071 }
2072
2073 EAPI void
2074 elm_widget_disabled_set(Evas_Object *obj,
2075                         Eina_Bool    disabled)
2076 {
2077    API_ENTRY return;
2078
2079    if (sd->disabled == disabled) return;
2080    sd->disabled = !!disabled;
2081    elm_widget_focus_disabled_handle(obj);
2082    if (sd->disable_func) sd->disable_func(obj);
2083 }
2084
2085 EAPI Eina_Bool
2086 elm_widget_disabled_get(const Evas_Object *obj)
2087 {
2088    API_ENTRY return 0;
2089    return sd->disabled;
2090 }
2091
2092 EAPI void
2093 elm_widget_show_region_set(Evas_Object *obj,
2094                            Evas_Coord   x,
2095                            Evas_Coord   y,
2096                            Evas_Coord   w,
2097                            Evas_Coord   h,
2098                            Eina_Bool    forceshow)
2099 {
2100    Evas_Object *parent_obj, *child_obj;
2101    Evas_Coord px, py, cx, cy;
2102
2103    evas_smart_objects_calculate(evas_object_evas_get(obj));
2104
2105    API_ENTRY return;
2106    if (!forceshow && (x == sd->rx) && (y == sd->ry)
2107             && (w == sd->rw) && (h == sd->rh)) return;
2108    sd->rx = x;
2109    sd->ry = y;
2110    sd->rw = w;
2111    sd->rh = h;
2112    if (sd->on_show_region_func)
2113      sd->on_show_region_func(sd->on_show_region_data, obj);
2114
2115    do
2116      {
2117         parent_obj = sd->parent_obj;
2118         child_obj = sd->obj;
2119         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2120         sd = evas_object_smart_data_get(parent_obj);
2121         if (!sd) break;
2122
2123         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2124         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2125
2126         x += (cx - px);
2127         y += (cy - py);
2128         sd->rx = x;
2129         sd->ry = y;
2130         sd->rw = w;
2131         sd->rh = h;
2132
2133         if (sd->on_show_region_func)
2134           {
2135              sd->on_show_region_func(sd->on_show_region_data, parent_obj);
2136           }
2137      }
2138    while (parent_obj);
2139 }
2140
2141 EAPI void
2142 elm_widget_show_region_get(const Evas_Object *obj,
2143                            Evas_Coord        *x,
2144                            Evas_Coord        *y,
2145                            Evas_Coord        *w,
2146                            Evas_Coord        *h)
2147 {
2148    API_ENTRY return;
2149    if (x) *x = sd->rx;
2150    if (y) *y = sd->ry;
2151    if (w) *w = sd->rw;
2152    if (h) *h = sd->rh;
2153 }
2154
2155 /**
2156  * @internal
2157  *
2158  * Get the focus region of the given widget.
2159  *
2160  * The focus region is the area of a widget that should brought into the
2161  * visible area when the widget is focused. Mostly used to show the part of
2162  * an entry where the cursor is, for example. The area returned is relative
2163  * to the object @p obj.
2164  * If the @p obj doesn't have the proper on_focus_region_hook set, this
2165  * function will return the full size of the object.
2166  *
2167  * @param obj The widget object
2168  * @param x Where to store the x coordinate of the area
2169  * @param y Where to store the y coordinate of the area
2170  * @param w Where to store the width of the area
2171  * @param h Where to store the height of the area
2172  *
2173  * @ingroup Widget
2174  */
2175 EAPI void
2176 elm_widget_focus_region_get(const Evas_Object *obj,
2177                             Evas_Coord        *x,
2178                             Evas_Coord        *y,
2179                             Evas_Coord        *w,
2180                             Evas_Coord        *h)
2181 {
2182    Smart_Data *sd;
2183
2184    if (!obj) return;
2185
2186    sd = evas_object_smart_data_get(obj);
2187    if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
2188      {
2189         evas_object_geometry_get(obj, NULL, NULL, w, h);
2190         if (x) *x = 0;
2191         if (y) *y = 0;
2192         return;
2193      }
2194    sd->on_focus_region_func(obj, x, y, w, h);
2195 }
2196
2197 EAPI void
2198 elm_widget_scroll_hold_push(Evas_Object *obj)
2199 {
2200    API_ENTRY return;
2201    sd->scroll_hold++;
2202    if (sd->scroll_hold == 1)
2203      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
2204    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2205    // FIXME: on delete/reparent hold pop
2206 }
2207
2208 EAPI void
2209 elm_widget_scroll_hold_pop(Evas_Object *obj)
2210 {
2211    API_ENTRY return;
2212    sd->scroll_hold--;
2213    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2214    if (!sd->scroll_hold)
2215      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
2216    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2217 }
2218
2219 EAPI int
2220 elm_widget_scroll_hold_get(const Evas_Object *obj)
2221 {
2222    API_ENTRY return 0;
2223    return sd->scroll_hold;
2224 }
2225
2226 EAPI void
2227 elm_widget_scroll_freeze_push(Evas_Object *obj)
2228 {
2229    API_ENTRY return;
2230    sd->scroll_freeze++;
2231    if (sd->scroll_freeze == 1)
2232      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
2233    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2234    // FIXME: on delete/reparent freeze pop
2235 }
2236
2237 EAPI void
2238 elm_widget_scroll_freeze_pop(Evas_Object *obj)
2239 {
2240    API_ENTRY return;
2241    sd->scroll_freeze--;
2242    if (!sd->scroll_freeze)
2243      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
2244    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
2245    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2246 }
2247
2248 EAPI int
2249 elm_widget_scroll_freeze_get(const Evas_Object *obj)
2250 {
2251    API_ENTRY return 0;
2252    return sd->scroll_freeze;
2253 }
2254
2255 EAPI void
2256 elm_widget_scale_set(Evas_Object *obj,
2257                      double       scale)
2258 {
2259    API_ENTRY return;
2260    if (scale <= 0.0) scale = 0.0;
2261    if (sd->scale != scale)
2262      {
2263         sd->scale = scale;
2264         elm_widget_theme(obj);
2265      }
2266 }
2267
2268 EAPI double
2269 elm_widget_scale_get(const Evas_Object *obj)
2270 {
2271    API_ENTRY return 1.0;
2272    // FIXME: save walking up the tree by storing/caching parent scale
2273    if (sd->scale == 0.0)
2274      {
2275         if (sd->parent_obj)
2276           return elm_widget_scale_get(sd->parent_obj);
2277         else
2278           return 1.0;
2279      }
2280    return sd->scale;
2281 }
2282
2283 EAPI void
2284 elm_widget_theme_set(Evas_Object *obj,
2285                      Elm_Theme   *th)
2286 {
2287    API_ENTRY return;
2288    if (sd->theme != th)
2289      {
2290         if (sd->theme) elm_theme_free(sd->theme);
2291         sd->theme = th;
2292         if (th) th->ref++;
2293         elm_widget_theme(obj);
2294      }
2295 }
2296
2297 EAPI void
2298 elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label)
2299 {
2300    API_ENTRY return;
2301
2302    if (!sd->on_text_set_func)
2303      return;
2304
2305    sd->on_text_set_func(obj, part, label);
2306 }
2307
2308 EAPI const char *
2309 elm_widget_text_part_get(const Evas_Object *obj, const char *part)
2310 {
2311    API_ENTRY return NULL;
2312
2313    if (!sd->on_text_get_func)
2314      return NULL;
2315
2316    return sd->on_text_get_func(obj, part);
2317 }
2318
2319 EAPI void
2320 elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
2321 {
2322    const char *str;
2323    Eina_List *l;
2324    Elm_Translate_String_Data *ts = NULL;
2325    API_ENTRY return;
2326
2327    str = eina_stringshare_add(part);
2328    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2329       if (ts->id == str)
2330         break;
2331       else
2332         ts = NULL;
2333
2334    if (!ts && !label)
2335      eina_stringshare_del(str);
2336    else if (!ts)
2337      {
2338         ts = malloc(sizeof(Elm_Translate_String_Data));
2339         if (!ts) return;
2340
2341         ts->id = str;
2342         ts->domain = eina_stringshare_add(domain);
2343         ts->string = eina_stringshare_add(label);
2344         sd->translate_strings = eina_list_append(sd->translate_strings, ts);
2345      }
2346    else
2347      {
2348         if (label)
2349           {
2350              eina_stringshare_replace(&ts->domain, domain);
2351              eina_stringshare_replace(&ts->string, label);
2352           }
2353         else
2354           {
2355              sd->translate_strings = eina_list_remove_list(
2356                                                 sd->translate_strings, l);
2357              eina_stringshare_del(ts->id);
2358              eina_stringshare_del(ts->domain);
2359              eina_stringshare_del(ts->string);
2360              free(ts);
2361           }
2362         eina_stringshare_del(str);
2363      }
2364
2365 #ifdef HAVE_GETTEXT
2366    if (label && label[0])
2367      label = dgettext(domain, label);
2368 #endif
2369    elm_widget_text_part_set(obj, part, label);
2370 }
2371
2372 EAPI const char *
2373 elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
2374 {
2375    const char *str, *ret = NULL;
2376    Eina_List *l;
2377    Elm_Translate_String_Data *ts;
2378    API_ENTRY return NULL;
2379
2380    str = eina_stringshare_add(part);
2381    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2382       if (ts->id == str)
2383         {
2384            ret = ts->string;
2385            break;
2386         }
2387    eina_stringshare_del(str);
2388    return ret;
2389 }
2390
2391 EAPI void
2392 elm_widget_translate(Evas_Object *obj)
2393 {
2394    const Eina_List *l;
2395    Evas_Object *child;
2396    Elm_Translate_String_Data *ts;
2397
2398    API_ENTRY return;
2399    EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
2400    if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
2401    if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
2402    if (sd->translate_func) sd->translate_func(obj);
2403
2404 #ifdef HAVE_GETTEXT
2405    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2406      {
2407         const char *s = dgettext(ts->domain, ts->string);
2408         elm_widget_text_part_set(obj, ts->id, s);
2409      }
2410 #endif
2411 }
2412
2413 EAPI void
2414 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
2415 {
2416    API_ENTRY return;
2417
2418    if (!sd->on_content_set_func)  return;
2419    sd->on_content_set_func(obj, part, content);
2420 }
2421
2422 EAPI Evas_Object *
2423 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
2424 {
2425    API_ENTRY return NULL;
2426
2427    if (!sd->on_content_get_func) return NULL;
2428    return sd->on_content_get_func(obj, part);
2429 }
2430
2431 EAPI Evas_Object *
2432 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
2433 {
2434    API_ENTRY return NULL;
2435
2436    if (!sd->on_content_unset_func) return NULL;
2437    return sd->on_content_unset_func(obj, part);
2438 }
2439
2440 EAPI void
2441 elm_widget_access_info_set(Evas_Object *obj, const char *txt)
2442 {
2443    API_ENTRY return;
2444    if (sd->access_info) eina_stringshare_del(sd->access_info);
2445    if (!txt) sd->access_info = NULL;
2446    else sd->access_info = eina_stringshare_add(txt);
2447 }
2448
2449 EAPI const char *
2450 elm_widget_access_info_get(Evas_Object *obj)
2451 {
2452    API_ENTRY return NULL;
2453    return sd->access_info;
2454 }
2455
2456 EAPI Elm_Theme *
2457 elm_widget_theme_get(const Evas_Object *obj)
2458 {
2459    API_ENTRY return NULL;
2460    if (!sd->theme)
2461      {
2462         if (sd->parent_obj)
2463           return elm_widget_theme_get(sd->parent_obj);
2464         else
2465           return NULL;
2466      }
2467    return sd->theme;
2468 }
2469
2470 EAPI void
2471 elm_widget_style_set(Evas_Object *obj,
2472                      const char  *style)
2473 {
2474    API_ENTRY return;
2475
2476    if (eina_stringshare_replace(&sd->style, style))
2477      elm_widget_theme(obj);
2478 }
2479
2480 EAPI const char *
2481 elm_widget_style_get(const Evas_Object *obj)
2482 {
2483    API_ENTRY return NULL;
2484    if (sd->style) return sd->style;
2485    return "default";
2486 }
2487
2488 EAPI void
2489 elm_widget_type_set(Evas_Object *obj,
2490                     const char  *type)
2491 {
2492    API_ENTRY return;
2493    eina_stringshare_replace(&sd->type, type);
2494 }
2495
2496 EAPI const char *
2497 elm_widget_type_get(const Evas_Object *obj)
2498 {
2499    API_ENTRY return NULL;
2500    if (sd->type) return sd->type;
2501    return "";
2502 }
2503
2504 EAPI void
2505 elm_widget_tooltip_add(Evas_Object *obj,
2506                        Elm_Tooltip *tt)
2507 {
2508    API_ENTRY return;
2509    sd->tooltips = eina_list_append(sd->tooltips, tt);
2510 }
2511
2512 EAPI void
2513 elm_widget_tooltip_del(Evas_Object *obj,
2514                        Elm_Tooltip *tt)
2515 {
2516    API_ENTRY return;
2517    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2518 }
2519
2520 EAPI void
2521 elm_widget_cursor_add(Evas_Object *obj,
2522                       Elm_Cursor  *cur)
2523 {
2524    API_ENTRY return;
2525    sd->cursors = eina_list_append(sd->cursors, cur);
2526 }
2527
2528 EAPI void
2529 elm_widget_cursor_del(Evas_Object *obj,
2530                       Elm_Cursor  *cur)
2531 {
2532    API_ENTRY return;
2533    sd->cursors = eina_list_remove(sd->cursors, cur);
2534 }
2535
2536 EAPI void
2537 elm_widget_drag_lock_x_set(Evas_Object *obj,
2538                            Eina_Bool    lock)
2539 {
2540    API_ENTRY return;
2541    if (sd->drag_x_locked == lock) return;
2542    sd->drag_x_locked = lock;
2543    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2544    else _propagate_x_drag_lock(obj, -1);
2545 }
2546
2547 EAPI void
2548 elm_widget_drag_lock_y_set(Evas_Object *obj,
2549                            Eina_Bool    lock)
2550 {
2551    API_ENTRY return;
2552    if (sd->drag_y_locked == lock) return;
2553    sd->drag_y_locked = lock;
2554    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2555    else _propagate_y_drag_lock(obj, -1);
2556 }
2557
2558 EAPI Eina_Bool
2559 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2560 {
2561    API_ENTRY return EINA_FALSE;
2562    return sd->drag_x_locked;
2563 }
2564
2565 EAPI Eina_Bool
2566 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2567 {
2568    API_ENTRY return EINA_FALSE;
2569    return sd->drag_y_locked;
2570 }
2571
2572 EAPI int
2573 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2574 {
2575    API_ENTRY return 0;
2576    return sd->child_drag_x_locked;
2577 }
2578
2579 EAPI int
2580 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2581 {
2582    API_ENTRY return 0;
2583    return sd->child_drag_y_locked;
2584 }
2585
2586 EAPI Eina_Bool
2587 elm_widget_theme_object_set(Evas_Object *obj,
2588                             Evas_Object *edj,
2589                             const char  *wname,
2590                             const char  *welement,
2591                             const char  *wstyle)
2592 {
2593    API_ENTRY return EINA_FALSE;
2594    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2595 }
2596
2597 EAPI Eina_Bool
2598 elm_widget_is_check(const Evas_Object *obj)
2599 {
2600    static int abort_on_warn = -1;
2601    if (elm_widget_is(obj))
2602       return EINA_TRUE;
2603
2604    ERR("Passing Object: %p.", obj);
2605    if (abort_on_warn == -1)
2606      {
2607         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2608         else abort_on_warn = 0;
2609      }
2610    if (abort_on_warn == 1) abort();
2611    return EINA_FALSE;
2612 }
2613
2614 EAPI Eina_Bool
2615 elm_widget_type_check(const Evas_Object *obj,
2616                       const char        *type,
2617                       const char        *func)
2618 {
2619    const char *provided, *expected = "(unknown)";
2620    static int abort_on_warn = -1;
2621    provided = elm_widget_type_get(obj);
2622    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2623    if (type) expected = type;
2624    if ((!provided) || (!provided[0]))
2625      {
2626         provided = evas_object_type_get(obj);
2627         if ((!provided) || (!provided[0]))
2628           provided = "(unknown)";
2629      }
2630    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
2631    if (abort_on_warn == -1)
2632      {
2633         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2634         else abort_on_warn = 0;
2635      }
2636    if (abort_on_warn == 1) abort();
2637    return EINA_FALSE;
2638 }
2639
2640 /**
2641  * @internal
2642  *
2643  * Split string in words
2644  *
2645  * @param str Source string
2646  * @return List of const words
2647  *
2648  * @see elm_widget_stringlist_free()
2649  * @ingroup Widget
2650  */
2651 EAPI Eina_List *
2652 elm_widget_stringlist_get(const char *str)
2653 {
2654    Eina_List *list = NULL;
2655    const char *s, *b;
2656    if (!str) return NULL;
2657    for (b = s = str; 1; s++)
2658      {
2659         if ((*s == ' ') || (!*s))
2660           {
2661              char *t = malloc(s - b + 1);
2662              if (t)
2663                {
2664                   strncpy(t, b, s - b);
2665                   t[s - b] = 0;
2666                   list = eina_list_append(list, eina_stringshare_add(t));
2667                   free(t);
2668                }
2669              b = s + 1;
2670           }
2671         if (!*s) break;
2672      }
2673    return list;
2674 }
2675
2676 EAPI void
2677 elm_widget_stringlist_free(Eina_List *list)
2678 {
2679    const char *s;
2680    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2681 }
2682
2683 EAPI void
2684 elm_widget_focus_hide_handle(Evas_Object *obj)
2685 {
2686    _if_focused_revert(obj, EINA_TRUE);
2687 }
2688
2689 EAPI void
2690 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2691 {
2692    Evas_Object *o = obj;
2693    do
2694      {
2695         if (_elm_widget_is(o)) break;
2696         o = evas_object_smart_parent_get(o);
2697      }
2698    while (o);
2699    if (!o) return;
2700    if (!_is_focusable(o)) return;
2701    elm_widget_focus_steal(o);
2702 }
2703
2704 EAPI void
2705 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2706 {
2707    API_ENTRY return;
2708
2709    if (!elm_widget_parent_get(obj))
2710      elm_widget_focused_object_clear(obj);
2711    else
2712      _if_focused_revert(obj, EINA_TRUE);
2713 }
2714
2715 EAPI void
2716 elm_widget_focus_disabled_handle(Evas_Object *obj)
2717 {
2718    API_ENTRY return;
2719
2720    elm_widget_focus_tree_unfocusable_handle(obj);
2721 }
2722
2723 /**
2724  * @internal
2725  *
2726  * Allocate a new Elm_Widget_Item-derived structure.
2727  *
2728  * The goal of this structure is to provide common ground for actions
2729  * that a widget item have, such as the owner widget, callback to
2730  * notify deletion, data pointer and maybe more.
2731  *
2732  * @param widget the owner widget that holds this item, must be an elm_widget!
2733  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2734  *        be used to allocate memory.
2735  *
2736  * @return allocated memory that is already zeroed out, or NULL on errors.
2737  *
2738  * @see elm_widget_item_new() convenience macro.
2739  * @see elm_widget_item_del() to release memory.
2740  * @ingroup Widget
2741  */
2742 EAPI Elm_Widget_Item *
2743 _elm_widget_item_new(Evas_Object *widget,
2744                      size_t       alloc_size)
2745 {
2746    if (!_elm_widget_is(widget))
2747      return NULL;
2748
2749    Elm_Widget_Item *item;
2750
2751    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2752    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2753
2754    item = calloc(1, alloc_size);
2755    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2756
2757    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2758    item->widget = widget;
2759    return item;
2760 }
2761
2762 /**
2763  * @internal
2764  *
2765  * Releases widget item memory, calling back del_cb() if it exists.
2766  *
2767  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2768  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2769  * this function and then unset it, thus being useful for 2 step
2770  * cleanup whenever the del_cb may use any of the data that must be
2771  * deleted from item.
2772  *
2773  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2774  * is presented!
2775  *
2776  * @param item a valid #Elm_Widget_Item to be deleted.
2777  * @see elm_widget_item_del() convenience macro.
2778  * @ingroup Widget
2779  */
2780 EAPI void
2781 _elm_widget_item_del(Elm_Widget_Item *item)
2782 {
2783    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2784
2785    if (item->del_cb)
2786      item->del_cb((void *)item->data, item->widget, item);
2787
2788    if (item->view)
2789      evas_object_del(item->view);
2790
2791    if (item->access)
2792      {
2793         _elm_access_clear(item->access);
2794         free(item->access);
2795         item->access = NULL;
2796      }
2797    if (item->access_info)
2798      {
2799         eina_stringshare_del(item->access_info);
2800         item->access_info = NULL;
2801      }
2802
2803    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2804    free(item);
2805 }
2806
2807 /**
2808  * @internal
2809  *
2810  * Notify object will be deleted without actually deleting it.
2811  *
2812  * This function will callback Elm_Widget_Item::del_cb if it is set
2813  * and then unset it so it is not called twice (ie: from
2814  * elm_widget_item_del()).
2815  *
2816  * @param item a valid #Elm_Widget_Item to be notified
2817  * @see elm_widget_item_pre_notify_del() convenience macro.
2818  * @ingroup Widget
2819  */
2820 EAPI void
2821 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2822 {
2823    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2824    if (!item->del_cb) return;
2825    item->del_cb((void *)item->data, item->widget, item);
2826    item->del_cb = NULL;
2827 }
2828
2829 /**
2830  * @internal
2831  *
2832  * Set the function to notify when item is being deleted.
2833  *
2834  * This function will complain if there was a callback set already,
2835  * however it will set the new one.
2836  *
2837  * The callback will be called from elm_widget_item_pre_notify_del()
2838  * or elm_widget_item_del() will be called with:
2839  *   - data: the Elm_Widget_Item::data value.
2840  *   - obj: the Elm_Widget_Item::widget evas object.
2841  *   - event_info: the item being deleted.
2842  *
2843  * @param item a valid #Elm_Widget_Item to be notified
2844  * @see elm_widget_item_del_cb_set() convenience macro.
2845  * @ingroup Widget
2846  */
2847 EAPI void
2848 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2849                             Evas_Smart_Cb    del_cb)
2850 {
2851    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2852
2853    if ((item->del_cb) && (item->del_cb != del_cb))
2854      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2855          item->del_cb, item, del_cb);
2856
2857    item->del_cb = del_cb;
2858 }
2859
2860 /**
2861  * @internal
2862  *
2863  * Set user-data in this item.
2864  *
2865  * User data may be used to identify this item or just store any
2866  * application data. It is automatically given as the first parameter
2867  * of the deletion notify callback.
2868  *
2869  * @param item a valid #Elm_Widget_Item to store data in.
2870  * @param data user data to store.
2871  * @see elm_widget_item_del_cb_set() convenience macro.
2872  * @ingroup Widget
2873  */
2874 EAPI void
2875 _elm_widget_item_data_set(Elm_Widget_Item *item,
2876                           const void      *data)
2877 {
2878    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2879    if ((item->data) && (item->data != data))
2880      DBG("Replacing item %p data %p with %p", item, item->data, data);
2881    item->data = data;
2882 }
2883
2884 /**
2885  * @internal
2886  *
2887  * Retrieves user-data of this item.
2888  *
2889  * @param item a valid #Elm_Widget_Item to get data from.
2890  * @see elm_widget_item_data_set()
2891  * @ingroup Widget
2892  */
2893 EAPI void *
2894 _elm_widget_item_data_get(const Elm_Widget_Item *item)
2895 {
2896    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2897    return (void *)item->data;
2898 }
2899
2900 EAPI void
2901 _elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_Bool disabled)
2902 {
2903    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2904
2905    if (item->disabled == disabled) return;
2906    item->disabled = !!disabled;
2907    if (item->disable_func) item->disable_func(item);
2908 }
2909
2910 EAPI Eina_Bool
2911 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
2912 {
2913    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2914    return item->disabled;
2915 }
2916
2917 EAPI void
2918 _elm_widget_item_disable_set_hook_set(Elm_Widget_Item *item,
2919                                       Elm_Widget_On_Disable_Set_Cb func)
2920 {
2921    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2922    item->disable_func = func;
2923 }
2924
2925 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
2926
2927 struct _Elm_Widget_Item_Tooltip
2928 {
2929    Elm_Widget_Item            *item;
2930    Elm_Tooltip_Item_Content_Cb func;
2931    Evas_Smart_Cb               del_cb;
2932    const void                 *data;
2933 };
2934
2935 static Evas_Object *
2936 _elm_widget_item_tooltip_label_create(void        *data,
2937                                       Evas_Object *obj __UNUSED__,
2938                                       Evas_Object *tooltip,
2939                                       void        *item __UNUSED__)
2940 {
2941    Evas_Object *label = elm_label_add(tooltip);
2942    if (!label)
2943      return NULL;
2944    elm_object_style_set(label, "tooltip");
2945    elm_object_text_set(label, data);
2946    return label;
2947 }
2948
2949 static Evas_Object *
2950 _elm_widget_item_tooltip_trans_label_create(void        *data,
2951                                             Evas_Object *obj __UNUSED__,
2952                                             Evas_Object *tooltip,
2953                                             void        *item __UNUSED__)
2954 {
2955    Evas_Object *label = elm_label_add(tooltip);
2956    if (!label)
2957      return NULL;
2958    elm_object_style_set(label, "tooltip");
2959    elm_object_translatable_text_set(label, data);
2960    return label;
2961 }
2962
2963 static void
2964 _elm_widget_item_tooltip_label_del_cb(void        *data,
2965                                       Evas_Object *obj __UNUSED__,
2966                                       void        *event_info __UNUSED__)
2967 {
2968    eina_stringshare_del(data);
2969 }
2970
2971 /**
2972  * @internal
2973  *
2974  * Set the text to be shown in the widget item.
2975  *
2976  * @param item Target item
2977  * @param text The text to set in the content
2978  *
2979  * Setup the text as tooltip to object. The item can have only one tooltip,
2980  * so any previous tooltip data is removed.
2981  *
2982  * @ingroup Widget
2983  */
2984 EAPI void
2985 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
2986                                   const char      *text)
2987 {
2988    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2989    EINA_SAFETY_ON_NULL_RETURN(text);
2990
2991    text = eina_stringshare_add(text);
2992    _elm_widget_item_tooltip_content_cb_set
2993      (item, _elm_widget_item_tooltip_label_create, text,
2994      _elm_widget_item_tooltip_label_del_cb);
2995 }
2996
2997 EAPI void
2998 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
2999                                                const char      *text)
3000 {
3001    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3002    EINA_SAFETY_ON_NULL_RETURN(text);
3003
3004    text = eina_stringshare_add(text);
3005    _elm_widget_item_tooltip_content_cb_set
3006      (item, _elm_widget_item_tooltip_trans_label_create, text,
3007      _elm_widget_item_tooltip_label_del_cb);
3008 }
3009
3010 static Evas_Object *
3011 _elm_widget_item_tooltip_create(void        *data,
3012                                 Evas_Object *obj,
3013                                 Evas_Object *tooltip)
3014 {
3015    Elm_Widget_Item_Tooltip *wit = data;
3016    return wit->func((void *)wit->data, obj, tooltip, wit->item);
3017 }
3018
3019 static void
3020 _elm_widget_item_tooltip_del_cb(void        *data,
3021                                 Evas_Object *obj,
3022                                 void        *event_info __UNUSED__)
3023 {
3024    Elm_Widget_Item_Tooltip *wit = data;
3025    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
3026    free(wit);
3027 }
3028
3029 /**
3030  * @internal
3031  *
3032  * Set the content to be shown in the tooltip item
3033  *
3034  * Setup the tooltip to item. The item can have only one tooltip,
3035  * so any previous tooltip data is removed. @p func(with @p data) will
3036  * be called every time that need show the tooltip and it should
3037  * return a valid Evas_Object. This object is then managed fully by
3038  * tooltip system and is deleted when the tooltip is gone.
3039  *
3040  * @param item the widget item being attached a tooltip.
3041  * @param func the function used to create the tooltip contents.
3042  * @param data what to provide to @a func as callback data/context.
3043  * @param del_cb called when data is not needed anymore, either when
3044  *        another callback replaces @func, the tooltip is unset with
3045  *        elm_widget_item_tooltip_unset() or the owner @a item
3046  *        dies. This callback receives as the first parameter the
3047  *        given @a data, and @c event_info is the item.
3048  *
3049  * @ingroup Widget
3050  */
3051 EAPI void
3052 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
3053                                         Elm_Tooltip_Item_Content_Cb func,
3054                                         const void                 *data,
3055                                         Evas_Smart_Cb               del_cb)
3056 {
3057    Elm_Widget_Item_Tooltip *wit;
3058
3059    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
3060
3061    if (!func)
3062      {
3063         _elm_widget_item_tooltip_unset(item);
3064         return;
3065      }
3066
3067    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
3068    if (!wit) goto error;
3069    wit->item = item;
3070    wit->func = func;
3071    wit->data = data;
3072    wit->del_cb = del_cb;
3073
3074    elm_object_sub_tooltip_content_cb_set
3075      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
3076      _elm_widget_item_tooltip_del_cb);
3077
3078    return;
3079
3080 error_noitem:
3081    if (del_cb) del_cb((void *)data, NULL, item);
3082    return;
3083 error:
3084    if (del_cb) del_cb((void *)data, item->widget, item);
3085 }
3086
3087 /**
3088  * @internal
3089  *
3090  * Unset tooltip from item
3091  *
3092  * @param item widget item to remove previously set tooltip.
3093  *
3094  * Remove tooltip from item. The callback provided as del_cb to
3095  * elm_widget_item_tooltip_content_cb_set() will be called to notify
3096  * it is not used anymore.
3097  *
3098  * @see elm_widget_item_tooltip_content_cb_set()
3099  *
3100  * @ingroup Widget
3101  */
3102 EAPI void
3103 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
3104 {
3105    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3106    elm_object_tooltip_unset(item->view);
3107 }
3108
3109 /**
3110  * @internal
3111  *
3112  * Sets a different style for this item tooltip.
3113  *
3114  * @note before you set a style you should define a tooltip with
3115  *       elm_widget_item_tooltip_content_cb_set() or
3116  *       elm_widget_item_tooltip_text_set()
3117  *
3118  * @param item widget item with tooltip already set.
3119  * @param style the theme style to use (default, transparent, ...)
3120  *
3121  * @ingroup Widget
3122  */
3123 EAPI void
3124 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
3125                                    const char      *style)
3126 {
3127    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3128    elm_object_tooltip_style_set(item->view, style);
3129 }
3130
3131 EAPI Eina_Bool
3132 _elm_widget_item_tooltip_size_restrict_disable(Elm_Widget_Item *item, Eina_Bool disable)
3133 {
3134    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3135    return elm_tooltip_size_restrict_disable(item->view, disable);
3136 }
3137
3138 EAPI Eina_Bool
3139 _elm_widget_item_tooltip_size_restrict_disabled_get(const Elm_Widget_Item *item)
3140 {
3141    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3142    return elm_tooltip_size_restrict_disabled_get(item->view);
3143 }
3144
3145 /**
3146  * @internal
3147  *
3148  * Get the style for this item tooltip.
3149  *
3150  * @param item widget item with tooltip already set.
3151  * @return style the theme style in use, defaults to "default". If the
3152  *         object does not have a tooltip set, then NULL is returned.
3153  *
3154  * @ingroup Widget
3155  */
3156 EAPI const char *
3157 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
3158 {
3159    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3160    return elm_object_tooltip_style_get(item->view);
3161 }
3162
3163 EAPI void
3164 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
3165                             const char      *cursor)
3166 {
3167    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3168    elm_object_sub_cursor_set(item->view, item->widget, cursor);
3169 }
3170
3171 EAPI const char *
3172 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
3173 {
3174    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3175    return elm_object_cursor_get(item->view);
3176 }
3177
3178 EAPI void
3179 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
3180 {
3181    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3182    elm_object_cursor_unset(item->view);
3183 }
3184
3185 /**
3186  * @internal
3187  *
3188  * Sets a different style for this item cursor.
3189  *
3190  * @note before you set a style you should define a cursor with
3191  *       elm_widget_item_cursor_set()
3192  *
3193  * @param item widget item with cursor already set.
3194  * @param style the theme style to use (default, transparent, ...)
3195  *
3196  * @ingroup Widget
3197  */
3198 EAPI void
3199 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
3200                                   const char      *style)
3201 {
3202    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3203    elm_object_cursor_style_set(item->view, style);
3204 }
3205
3206 /**
3207  * @internal
3208  *
3209  * Get the style for this item cursor.
3210  *
3211  * @param item widget item with cursor already set.
3212  * @return style the theme style in use, defaults to "default". If the
3213  *         object does not have a cursor set, then NULL is returned.
3214  *
3215  * @ingroup Widget
3216  */
3217 EAPI const char *
3218 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
3219 {
3220    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3221    return elm_object_cursor_style_get(item->view);
3222 }
3223
3224 /**
3225  * @internal
3226  *
3227  * Set if the cursor set should be searched on the theme or should use
3228  * the provided by the engine, only.
3229  *
3230  * @note before you set if should look on theme you should define a cursor
3231  * with elm_object_cursor_set(). By default it will only look for cursors
3232  * provided by the engine.
3233  *
3234  * @param item widget item with cursor already set.
3235  * @param engine_only boolean to define it cursors should be looked only
3236  * between the provided by the engine or searched on widget's theme as well.
3237  *
3238  * @ingroup Widget
3239  */
3240 EAPI void
3241 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
3242                                         Eina_Bool        engine_only)
3243 {
3244    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3245    elm_object_cursor_engine_only_set(item->view, engine_only);
3246 }
3247
3248 /**
3249  * @internal
3250  *
3251  * Get the cursor engine only usage for this item cursor.
3252  *
3253  * @param item widget item with cursor already set.
3254  * @return engine_only boolean to define it cursors should be looked only
3255  * between the provided by the engine or searched on widget's theme as well. If
3256  *         the object does not have a cursor set, then EINA_FALSE is returned.
3257  *
3258  * @ingroup Widget
3259  */
3260 EAPI Eina_Bool
3261 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
3262 {
3263    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3264    return elm_object_cursor_engine_only_get(item->view);
3265 }
3266
3267 // smart object funcs
3268 static void
3269 _smart_reconfigure(Smart_Data *sd)
3270 {
3271    if (sd->resize_obj)
3272      {
3273         evas_object_move(sd->resize_obj, sd->x, sd->y);
3274         evas_object_resize(sd->resize_obj, sd->w, sd->h);
3275      }
3276    if (sd->hover_obj)
3277      {
3278         evas_object_move(sd->hover_obj, sd->x, sd->y);
3279         evas_object_resize(sd->hover_obj, sd->w, sd->h);
3280      }
3281 }
3282
3283 EAPI void
3284 _elm_widget_item_content_part_set(Elm_Widget_Item *item,
3285                                  const char *part,
3286                                  Evas_Object *content)
3287 {
3288    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3289    if (!item->on_content_set_func) return;
3290    item->on_content_set_func((Elm_Object_Item *) item, part, content);
3291 }
3292
3293 EAPI Evas_Object *
3294 _elm_widget_item_content_part_get(const Elm_Widget_Item *item,
3295                                   const char *part)
3296 {
3297    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3298    if (!item->on_content_get_func) return NULL;
3299    return item->on_content_get_func((Elm_Object_Item *) item, part);
3300 }
3301
3302 EAPI Evas_Object *
3303 _elm_widget_item_content_part_unset(Elm_Widget_Item *item,
3304                                     const char *part)
3305 {
3306    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3307    if (!item->on_content_unset_func) return NULL;
3308    return item->on_content_unset_func((Elm_Object_Item *) item, part);
3309 }
3310
3311 EAPI void
3312 _elm_widget_item_text_part_set(Elm_Widget_Item *item,
3313                               const char *part,
3314                               const char *label)
3315 {
3316    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3317    if (!item->on_text_set_func) return;
3318    item->on_text_set_func((Elm_Object_Item *) item, part, label);
3319 }
3320
3321 EAPI void
3322 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
3323                              const char *emission,
3324                              const char *source)
3325 {
3326    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3327    if (item->on_signal_emit_func)
3328      item->on_signal_emit_func((Elm_Object_Item *) item, emission, source);
3329 }
3330
3331 EAPI const char *
3332 _elm_widget_item_text_part_get(const Elm_Widget_Item *item,
3333                                const char *part)
3334 {
3335    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3336    if (!item->on_text_get_func) return NULL;
3337    return item->on_text_get_func((Elm_Object_Item *) item, part);
3338 }
3339
3340 EAPI void
3341 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3342                                       Elm_Widget_On_Content_Set_Cb func)
3343 {
3344    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3345    item->on_content_set_func = func;
3346 }
3347
3348 EAPI void
3349 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3350                                       Elm_Widget_On_Content_Get_Cb func)
3351 {
3352    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3353    item->on_content_get_func = func;
3354 }
3355
3356 EAPI void
3357 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3358                                         Elm_Widget_On_Content_Unset_Cb func)
3359 {
3360    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3361    item->on_content_unset_func = func;
3362 }
3363
3364 EAPI void
3365 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3366                                    Elm_Widget_On_Text_Set_Cb func)
3367 {
3368    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3369    item->on_text_set_func = func;
3370 }
3371
3372 EAPI void
3373 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3374                                    Elm_Widget_On_Text_Get_Cb func)
3375 {
3376    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3377    item->on_text_get_func = func;
3378 }
3379
3380 EAPI void
3381 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
3382                                       Elm_Widget_On_Signal_Emit_Cb func)
3383 {
3384    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3385    item->on_signal_emit_func = func;
3386 }
3387
3388 EAPI void
3389 _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
3390 {
3391    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3392    if (item->access_info) eina_stringshare_del(item->access_info);
3393    if (!txt) item->access_info = NULL;
3394    else item->access_info = eina_stringshare_add(txt);
3395 }
3396
3397
3398 static void
3399 _smart_add(Evas_Object *obj)
3400 {
3401    Smart_Data *sd;
3402
3403    sd = calloc(1, sizeof(Smart_Data));
3404    if (!sd) return;
3405    sd->obj = obj;
3406    sd->x = sd->y = sd->w = sd->h = 0;
3407    sd->can_focus = 1;
3408    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3409    evas_object_smart_data_set(obj, sd);
3410 }
3411
3412 static Evas_Object *
3413 _newest_focus_order_get(Evas_Object  *obj,
3414                         unsigned int *newest_focus_order,
3415                         Eina_Bool     can_focus_only)
3416 {
3417    const Eina_List *l;
3418    Evas_Object *child, *ret, *best;
3419
3420    API_ENTRY return NULL;
3421
3422    if (!evas_object_visible_get(obj)
3423        || (elm_widget_disabled_get(obj))
3424        || (elm_widget_tree_unfocusable_get(obj)))
3425      return NULL;
3426
3427    best = NULL;
3428    if (*newest_focus_order < sd->focus_order)
3429      {
3430         *newest_focus_order = sd->focus_order;
3431         best = obj;
3432      }
3433    EINA_LIST_FOREACH(sd->subobjs, l, child)
3434      {
3435         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3436         if (!ret) continue;
3437         best = ret;
3438      }
3439    if (can_focus_only)
3440      {
3441         if ((!best) || (!elm_widget_can_focus_get(best)))
3442           return NULL;
3443      }
3444    return best;
3445 }
3446
3447 static void
3448 _if_focused_revert(Evas_Object *obj,
3449                    Eina_Bool    can_focus_only)
3450 {
3451    Evas_Object *top;
3452    Evas_Object *newest = NULL;
3453    unsigned int newest_focus_order = 0;
3454
3455    INTERNAL_ENTRY
3456
3457    if (!sd->focused) return;
3458    if (!sd->parent_obj) return;
3459
3460    top = elm_widget_top_get(sd->parent_obj);
3461    if (top)
3462      {
3463         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3464         if (newest)
3465           {
3466              elm_object_focus_set(newest, EINA_FALSE);
3467              elm_object_focus_set(newest, EINA_TRUE);
3468           }
3469      }
3470 }
3471
3472 static void
3473 _smart_del(Evas_Object *obj)
3474 {
3475    Evas_Object *sobj;
3476    Edje_Signal_Data *esd;
3477    Elm_Translate_String_Data *ts;
3478
3479    INTERNAL_ENTRY
3480
3481    if (sd->del_pre_func) sd->del_pre_func(obj);
3482    if (sd->resize_obj)
3483      {
3484         sobj = sd->resize_obj;
3485         sd->resize_obj = NULL;
3486         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3487         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3488         evas_object_del(sobj);
3489         sd->resize_obj = NULL;
3490      }
3491    if (sd->hover_obj)
3492      {
3493         sobj = sd->hover_obj;
3494         sd->hover_obj = NULL;
3495         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3496         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3497         evas_object_del(sobj);
3498         sd->hover_obj = NULL;
3499      }
3500    EINA_LIST_FREE(sd->subobjs, sobj)
3501      {
3502         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3503         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3504         evas_object_del(sobj);
3505      }
3506    eina_list_free(sd->tooltips); /* should be empty anyway */
3507    eina_list_free(sd->cursors); /* should be empty anyway */
3508    EINA_LIST_FREE(sd->edje_signals, esd)
3509      {
3510         eina_stringshare_del(esd->emission);
3511         eina_stringshare_del(esd->source);
3512         free(esd);
3513      }
3514    EINA_LIST_FREE(sd->translate_strings, ts)
3515      {
3516         eina_stringshare_del(ts->id);
3517         eina_stringshare_del(ts->domain);
3518         eina_stringshare_del(ts->string);
3519         free(ts);
3520      }
3521    eina_list_free(sd->event_cb); /* should be empty anyway */
3522    if (sd->del_func) sd->del_func(obj);
3523    if (sd->style) eina_stringshare_del(sd->style);
3524    if (sd->type) eina_stringshare_del(sd->type);
3525    if (sd->theme) elm_theme_free(sd->theme);
3526    _if_focused_revert(obj, EINA_TRUE);
3527    if (sd->access_info) eina_stringshare_del(sd->access_info);
3528    free(sd);
3529 }
3530
3531 static void
3532 _smart_move(Evas_Object *obj,
3533             Evas_Coord   x,
3534             Evas_Coord   y)
3535 {
3536    INTERNAL_ENTRY
3537    sd->x = x;
3538    sd->y = y;
3539    _smart_reconfigure(sd);
3540 }
3541
3542 static void
3543 _smart_resize(Evas_Object *obj,
3544               Evas_Coord   w,
3545               Evas_Coord   h)
3546 {
3547    INTERNAL_ENTRY
3548    sd->w = w;
3549    sd->h = h;
3550    _smart_reconfigure(sd);
3551 }
3552
3553 static void
3554 _smart_show(Evas_Object *obj)
3555 {
3556    Eina_List *list;
3557    Evas_Object *o;
3558    INTERNAL_ENTRY
3559    if ((list = evas_object_smart_members_get(obj)))
3560      {
3561         EINA_LIST_FREE(list, o)
3562           {
3563              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3564              evas_object_show(o);
3565           }
3566      }
3567 }
3568
3569 static void
3570 _smart_hide(Evas_Object *obj)
3571 {
3572    Eina_List *list;
3573    Evas_Object *o;
3574    INTERNAL_ENTRY
3575
3576    list = evas_object_smart_members_get(obj);
3577    EINA_LIST_FREE(list, o)
3578      {
3579         if (evas_object_data_get(o, "_elm_leaveme")) continue;
3580         evas_object_hide(o);
3581      }
3582 }
3583
3584 static void
3585 _smart_color_set(Evas_Object *obj,
3586                  int          r,
3587                  int          g,
3588                  int          b,
3589                  int          a)
3590 {
3591    Eina_List *list;
3592    Evas_Object *o;
3593    INTERNAL_ENTRY
3594    if ((list = evas_object_smart_members_get(obj)))
3595      {
3596         EINA_LIST_FREE(list, o)
3597           {
3598              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3599              evas_object_color_set(o, r, g, b, a);
3600           }
3601      }
3602 }
3603
3604 static void
3605 _smart_clip_set(Evas_Object *obj,
3606                 Evas_Object *clip)
3607 {
3608    Eina_List *list;
3609    Evas_Object *o;
3610    INTERNAL_ENTRY
3611    if ((list = evas_object_smart_members_get(obj)))
3612      {
3613         EINA_LIST_FREE(list, o)
3614           {
3615              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3616              evas_object_clip_set(o, clip);
3617           }
3618      }
3619 }
3620
3621 static void
3622 _smart_clip_unset(Evas_Object *obj)
3623 {
3624    Eina_List *list;
3625    Evas_Object *o;
3626    INTERNAL_ENTRY
3627    if ((list = evas_object_smart_members_get(obj)))
3628      {
3629         EINA_LIST_FREE(list, o)
3630           {
3631              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3632              evas_object_clip_unset(o);
3633           }
3634      }
3635 }
3636
3637 static void
3638 _smart_calculate(Evas_Object *obj)
3639 {
3640    INTERNAL_ENTRY
3641    if (sd->changed_func) sd->changed_func(obj);
3642 }
3643
3644 /* never need to touch this */
3645 static void
3646 _smart_init(void)
3647 {
3648    if (_e_smart) return;
3649      {
3650         static const Evas_Smart_Class sc =
3651           {
3652              SMART_NAME,
3653              EVAS_SMART_CLASS_VERSION,
3654              _smart_add,
3655              _smart_del,
3656              _smart_move,
3657              _smart_resize,
3658              _smart_show,
3659              _smart_hide,
3660              _smart_color_set,
3661              _smart_clip_set,
3662              _smart_clip_unset,
3663              _smart_calculate,
3664              NULL,
3665              NULL,
3666              NULL,
3667              NULL,
3668              NULL,
3669              NULL
3670           };
3671         _e_smart = evas_smart_class_new(&sc);
3672      }
3673 }
3674
3675 /* happy debug functions */
3676 #ifdef ELM_DEBUG
3677 static void
3678 _sub_obj_tree_dump(const Evas_Object *obj,
3679                    int                lvl)
3680 {
3681    int i;
3682
3683    for (i = 0; i < lvl * 3; i++)
3684      putchar(' ');
3685
3686    if (_elm_widget_is(obj))
3687      {
3688         Eina_List *l;
3689         INTERNAL_ENTRY
3690         printf("+ %s(%p)\n",
3691                sd->type,
3692                obj);
3693         if (sd->resize_obj)
3694           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3695         EINA_LIST_FOREACH(sd->subobjs, l, obj)
3696           {
3697              if (obj != sd->resize_obj)
3698                _sub_obj_tree_dump(obj, lvl + 1);
3699           }
3700      }
3701    else
3702      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3703 }
3704
3705 static void
3706 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3707                        FILE              *output)
3708 {
3709    if (!_elm_widget_is(obj))
3710      return;
3711    INTERNAL_ENTRY
3712
3713    Eina_Bool visible = evas_object_visible_get(obj);
3714    Eina_Bool disabled = elm_widget_disabled_get(obj);
3715    Eina_Bool focused = elm_widget_focus_get(obj);
3716    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3717
3718    if (sd->parent_obj)
3719      {
3720         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3721
3722         if (focused)
3723           fprintf(output, ", style=bold");
3724
3725         if (!visible)
3726           fprintf(output, ", color=gray28");
3727
3728         fprintf(output, " ];\n");
3729      }
3730
3731    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3732                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3733            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3734            sd->focus_order);
3735
3736    if (focused)
3737      fprintf(output, ", style=bold");
3738
3739    if (!visible)
3740      fprintf(output, ", fontcolor=gray28");
3741
3742    if ((disabled) || (!visible))
3743      fprintf(output, ", color=gray");
3744
3745    fprintf(output, " ];\n");
3746
3747    Eina_List *l;
3748    Evas_Object *o;
3749    EINA_LIST_FOREACH(sd->subobjs, l, o)
3750      _sub_obj_tree_dot_dump(o, output);
3751 }
3752 #endif
3753
3754 EAPI void
3755 elm_widget_tree_dump(const Evas_Object *top)
3756 {
3757 #ifdef ELM_DEBUG
3758    _sub_obj_tree_dump(top, 0);
3759 #else
3760    return;
3761    (void)top;
3762 #endif
3763 }
3764
3765 EAPI void
3766 elm_widget_tree_dot_dump(const Evas_Object *top,
3767                          FILE              *output)
3768 {
3769 #ifdef ELM_DEBUG
3770    if (!_elm_widget_is(top))
3771      return;
3772    fprintf(output, "graph " " { node [shape=record];\n");
3773    _sub_obj_tree_dot_dump(top, output);
3774    fprintf(output, "}\n");
3775 #else
3776    return;
3777    (void)top;
3778    (void)output;
3779 #endif
3780 }