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