[focus] update child_can_focus on parents, when an widget becomes focusable
[framework/uifw/elementary.git] / src / lib / elm_widget.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_container.h"
4 #include "elm_interface_scrollable.h"
5
6 static const char ELM_WIDGET_SMART_NAME[] = "elm_widget";
7
8 #define API_ENTRY                                               \
9   Elm_Widget_Smart_Data * sd = evas_object_smart_data_get(obj); \
10   if ((!sd) || (!_elm_widget_is(obj)))
11 #define INTERNAL_ENTRY                                          \
12   Elm_Widget_Smart_Data * sd = evas_object_smart_data_get(obj); \
13   if (!sd)                                                      \
14     return
15
16 #define ELM_WIDGET_FOCUS_GET(obj)                                    \
17   ((_elm_access_read_mode_get()) ? (elm_widget_highlight_get(obj)) : \
18                                   (elm_widget_focus_get(obj)))
19 typedef struct _Elm_Event_Cb_Data         Elm_Event_Cb_Data;
20 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
21
22 struct _Elm_Event_Cb_Data
23 {
24    Elm_Event_Cb func;
25    const void  *data;
26 };
27
28 struct _Elm_Translate_String_Data
29 {
30    Eina_Stringshare *id;
31    Eina_Stringshare *domain;
32    Eina_Stringshare *string;
33 };
34
35 /* local subsystem globals */
36 static unsigned int focus_order = 0;
37
38 static inline Eina_Bool
39 _elm_widget_is(const Evas_Object *obj)
40 {
41    return evas_object_smart_type_check_ptr(obj, ELM_WIDGET_SMART_NAME);
42 }
43
44 static inline Eina_Bool
45 _is_focusable(Evas_Object *obj)
46 {
47    API_ENTRY return EINA_FALSE;
48    return sd->can_focus || (sd->child_can_focus);
49 }
50
51 static inline Eina_Bool
52 _elm_scrollable_is(const Evas_Object *obj)
53 {
54    INTERNAL_ENTRY EINA_FALSE;
55    return !!evas_object_smart_interface_get(obj, ELM_SCROLLABLE_IFACE_NAME);
56 }
57
58 /* what follows are basic (unimplemented) smart class functions */
59 #define UNIMPLEMENTED_MAKE(_prefix)                                         \
60   static Eina_Bool                                                          \
61   _elm_widget_##_prefix##_func_unimplemented(Evas_Object * obj)             \
62   {                                                                         \
63      WRN("The %s widget does not implement the \"" #_prefix "\" function.", \
64          elm_widget_type_get(obj));                                         \
65      return EINA_FALSE;                                                     \
66   }
67
68 UNIMPLEMENTED_MAKE(disable);
69 UNIMPLEMENTED_MAKE(translate);
70
71 #undef UNIMPLEMENTED_MAKE
72
73 /**
74  * @internal
75  * Resets the mirrored mode from the system mirror mode for widgets that are in
76  * automatic mirroring mode. This function does not call elm_widget_theme.
77  *
78  * @param obj The widget.
79  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
80  */
81 static void
82 _elm_widget_mirrored_reload(Evas_Object *obj)
83 {
84    API_ENTRY return;
85    Eina_Bool mirrored = elm_config_mirrored_get();
86
87    if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
88      {
89         sd->is_mirrored = mirrored;
90      }
91 }
92
93 static Eina_Bool
94 _elm_widget_theme_func(Evas_Object *obj)
95 {
96    _elm_widget_mirrored_reload(obj);
97
98    elm_widget_disabled_set(obj, elm_widget_disabled_get(obj));
99
100    return EINA_TRUE;
101 }
102
103 static Eina_Bool
104 _elm_widget_on_focus_region_func_unimplemented(const Evas_Object *obj __UNUSED__,
105                                                Evas_Coord *x __UNUSED__,
106                                                Evas_Coord *y __UNUSED__,
107                                                Evas_Coord *w __UNUSED__,
108                                                Evas_Coord *h __UNUSED__)
109 {
110    WRN("The %s widget does not implement the \"on_focus_region\" function.",
111        elm_widget_type_get(obj));
112    return EINA_FALSE;
113 }
114
115 static Eina_Bool
116 _elm_widget_on_focus_func_unimplemented(Evas_Object *obj)
117 {
118    WRN("The %s widget does not implement the \"on_focus\" function.",
119        elm_widget_type_get(obj));
120    return EINA_FALSE;
121 }
122
123 static Eina_Bool
124 _elm_widget_event_func_unimplemented(Evas_Object *obj,
125                                      Evas_Object *source __UNUSED__,
126                                      Evas_Callback_Type type __UNUSED__,
127                                      void *event_info __UNUSED__)
128 {
129    WRN("The %s widget does not implement the \"event\" function.",
130        elm_widget_type_get(obj));
131    return EINA_FALSE;
132 }
133
134 static Eina_Bool
135 _elm_widget_focus_next_func_unimplemented(const Evas_Object *obj,
136                                           Elm_Focus_Direction dir __UNUSED__,
137                                           Evas_Object **next __UNUSED__)
138 {
139    WRN("The %s widget does not implement the \"focus_next\" function.",
140        elm_widget_type_get(obj));
141    return EINA_FALSE;
142 }
143
144 static Eina_Bool
145 _elm_widget_focus_direction_func_unimplemented(const Evas_Object *obj,
146                                                const Evas_Object *b __UNUSED__,
147                                                double degree __UNUSED__,
148                                                Evas_Object **target __UNUSED__,
149                                                double *weight __UNUSED__)
150 {
151    WRN("The %s widget does not implement the \"focus_direction\" function.",
152        elm_widget_type_get(obj));
153    return EINA_FALSE;
154 }
155
156 static void
157 _parents_focus(Evas_Object *obj)
158 {
159    for (; obj; obj = elm_widget_parent_get(obj))
160      {
161         INTERNAL_ENTRY;
162         if (sd->focused) return;
163         sd->focused = 1;
164      }
165 }
166
167 static void
168 _parents_unfocus(Evas_Object *obj)
169 {
170    for (; obj; obj = elm_widget_parent_get(obj))
171      {
172         INTERNAL_ENTRY;
173         if (!sd->focused) return;
174         sd->focused = 0;
175      }
176 }
177
178 static void
179 _on_sub_obj_hide(void *data __UNUSED__,
180               Evas *e __UNUSED__,
181               Evas_Object *obj,
182               void *event_info __UNUSED__)
183 {
184    elm_widget_focus_hide_handle(obj);
185 }
186
187 static void
188 _on_sub_obj_del(void *data,
189              Evas *e __UNUSED__,
190              Evas_Object *obj,
191              void *event_info __UNUSED__)
192 {
193    Elm_Widget_Smart_Data *sd = data;
194
195    if (_elm_widget_is(obj))
196      {
197         if (elm_widget_focus_get(obj)) _parents_unfocus(sd->obj);
198      }
199    if (obj == sd->resize_obj)
200      {
201         /* already dels sub object */
202         elm_widget_resize_object_set(sd->obj, NULL);
203         return;
204      }
205    else if (obj == sd->hover_obj)
206      {
207         sd->hover_obj = NULL;
208         return;
209      }
210    else
211      {
212         if (!elm_widget_sub_object_del(sd->obj, obj))
213           ERR("failed to remove sub object %p from %p\n", obj, sd->obj);
214      }
215 }
216
217 static Eina_Bool
218 _elm_widget_sub_object_add_func(Evas_Object *obj,
219                                 Evas_Object *sobj)
220 {
221    double scale, pscale = elm_widget_scale_get(sobj);
222    Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
223    Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
224
225    ELM_WIDGET_DATA_GET(obj, sd);
226    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
227
228    if (sobj == sd->parent_obj)
229      {
230         /* in this case, sobj must be an elm widget, or something
231          * very wrong is happening */
232         if (!_elm_widget_is(sobj)) return EINA_FALSE;
233
234         if (!elm_widget_sub_object_del(sobj, obj)) return EINA_FALSE;
235         WRN("You passed a parent object of obj = %p as the sub object = %p!",
236             obj, sobj);
237      }
238
239    if (_elm_widget_is(sobj))
240      {
241         ELM_WIDGET_DATA_GET(sobj, sdc);
242
243         if (sdc->parent_obj == obj) return EINA_TRUE;
244         if (sdc->parent_obj)
245           {
246              if (!elm_widget_sub_object_del(sdc->parent_obj, sobj))
247                return EINA_FALSE;
248           }
249         sdc->parent_obj = obj;
250         sdc->orient_mode = sd->orient_mode;
251         _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
252
253         /* update child focusable-ness on self and parents, now that a
254          * focusable child got in */
255         if (!sd->child_can_focus && (_is_focusable(sobj)))
256           {
257              Elm_Widget_Smart_Data *sdp = sd;
258
259              sdp->child_can_focus = EINA_TRUE;
260              while (sdp->parent_obj)
261                {
262                   sdp = evas_object_smart_data_get(sdp->parent_obj);
263
264                   if (sdp->child_can_focus) break;
265
266                   sdp->child_can_focus = EINA_TRUE;
267                }
268           }
269      }
270    else
271      {
272         void *data = evas_object_data_get(sobj, "elm-parent");
273
274         if (data)
275           {
276              if (data == obj) return EINA_TRUE;
277              if (!elm_widget_sub_object_del(data, sobj)) return EINA_FALSE;
278           }
279      }
280
281    sd->subobjs = eina_list_append(sd->subobjs, sobj);
282    evas_object_data_set(sobj, "elm-parent", obj);
283    evas_object_event_callback_add
284      (sobj, EVAS_CALLBACK_DEL, _on_sub_obj_del, sd);
285    if (_elm_widget_is(sobj))
286      {
287         evas_object_event_callback_add
288           (sobj, EVAS_CALLBACK_HIDE, _on_sub_obj_hide, sd);
289
290         scale = elm_widget_scale_get(sobj);
291         th = elm_widget_theme_get(sobj);
292         mirrored = elm_widget_mirrored_get(sobj);
293
294         if ((scale != pscale) || (th != pth) || (pmirrored != mirrored))
295           elm_widget_theme(sobj);
296
297         if (elm_widget_focus_get(sobj)) _parents_focus(obj);
298      }
299
300    return EINA_TRUE;
301 }
302
303 static Eina_Bool
304 _elm_widget_sub_object_del_func(Evas_Object *obj,
305                                 Evas_Object *sobj)
306 {
307    Evas_Object *sobj_parent;
308
309    if (!sobj) return EINA_FALSE;
310
311    ELM_WIDGET_DATA_GET(obj, sd);
312    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
313
314    sobj_parent = evas_object_data_del(sobj, "elm-parent");
315    if (sobj_parent != obj)
316      {
317         static int abort_on_warn = -1;
318
319         ERR("removing sub object %p (%s) from parent %p (%s), "
320             "but elm-parent is different %p (%s)!",
321             sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
322             sobj_parent, elm_widget_type_get(sobj_parent));
323
324         if (EINA_UNLIKELY(abort_on_warn == -1))
325           {
326              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
327              else abort_on_warn = 0;
328           }
329         if (abort_on_warn == 1) abort();
330
331         return EINA_FALSE;
332      }
333
334    if (_elm_widget_is(sobj))
335      {
336         if (elm_widget_focus_get(sobj))
337           {
338              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
339              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
340           }
341         if ((sd->child_can_focus) && (_is_focusable(sobj)))
342           {
343              Evas_Object *parent = obj;
344
345              /* update child focusable-ness on self and parents, now that a
346               * focusable child is gone */
347              while (parent)
348                {
349                   const Eina_List *l;
350                   Evas_Object *subobj;
351
352                   ELM_WIDGET_DATA_GET(parent, sdp);
353
354                   sdp->child_can_focus = EINA_FALSE;
355                   EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
356                     {
357                        if ((subobj != sobj) && (_is_focusable(subobj)))
358                          {
359                             sdp->child_can_focus = EINA_TRUE;
360                             break;
361                          }
362                     }
363
364                   /* break again, child_can_focus went back to
365                    * original value */
366                   if (sdp->child_can_focus) break;
367                   parent = sdp->parent_obj;
368                }
369           }
370
371         ELM_WIDGET_DATA_GET(sobj, sdc);
372         sdc->parent_obj = NULL;
373      }
374
375    if (sd->resize_obj == sobj) sd->resize_obj = NULL;
376
377    sd->subobjs = eina_list_remove(sd->subobjs, sobj);
378
379    evas_object_event_callback_del_full
380      (sobj, EVAS_CALLBACK_DEL, _on_sub_obj_del, sd);
381    if (_elm_widget_is(sobj))
382      evas_object_event_callback_del_full
383        (sobj, EVAS_CALLBACK_HIDE, _on_sub_obj_hide, sd);
384
385    return EINA_TRUE;
386 }
387
388 static const Evas_Smart_Cb_Description _smart_callbacks[] =
389 {
390    /* FIXME: complete later */
391    {NULL, NULL}
392 };
393
394 static void
395 _smart_add(Evas_Object *obj)
396 {
397    const Evas_Smart_Class *sc;
398    const Evas_Smart *smart;
399
400    EVAS_SMART_DATA_ALLOC(obj, Elm_Widget_Smart_Data);
401
402    smart = evas_object_smart_smart_get(obj);
403    sc = evas_smart_class_get(smart);
404    priv->api = (const Elm_Widget_Smart_Class *)sc;
405    priv->obj = obj;
406    priv->x = priv->y = priv->w = priv->h = 0;
407    priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale
408                                           * settings */
409    elm_widget_can_focus_set(obj, EINA_TRUE);
410    elm_widget_mirrored_set(obj, elm_config_mirrored_get());
411
412    /* just a helper for inheriting classes */
413    if (priv->resize_obj)
414      {
415         Evas_Object *r_obj = priv->resize_obj;
416         priv->resize_obj = NULL;
417
418         elm_widget_resize_object_set(obj, r_obj);
419      }
420 }
421
422
423 static void
424 _if_focused_revert(Evas_Object *obj,
425                    Eina_Bool can_focus_only)
426 {
427    Evas_Object *top;
428    Evas_Object *newest = NULL;
429    unsigned int newest_focus_order = 0;
430
431    INTERNAL_ENTRY;
432
433    if (!sd->focused) return;
434    if (!sd->parent_obj) return;
435
436    top = elm_widget_top_get(sd->parent_obj);
437    if (top)
438      {
439         newest = elm_widget_newest_focus_order_get
440            (top, &newest_focus_order, can_focus_only);
441         if (newest)
442           {
443              elm_object_focus_set(newest, EINA_FALSE);
444              elm_object_focus_set(newest, EINA_TRUE);
445           }
446      }
447 }
448
449 static void
450 _smart_del(Evas_Object *obj)
451 {
452    Evas_Object *sobj;
453    Elm_Translate_String_Data *ts;
454    Elm_Event_Cb_Data *ecb;
455
456    ELM_WIDGET_DATA_GET(obj, sd);
457
458    if (sd->hover_obj)
459      {
460         /* detach it from us */
461         evas_object_event_callback_del_full
462           (sd->hover_obj, EVAS_CALLBACK_DEL, _on_sub_obj_del, sd);
463         sd->hover_obj = NULL;
464      }
465
466    while (sd->subobjs)
467      {
468         sobj = eina_list_data_get(sd->subobjs);
469
470         /* let the objects clean-up themselves and get rid of this list */
471         if (!elm_widget_sub_object_del(obj, sobj))
472           {
473              ERR("failed to remove sub object %p from %p\n", sobj, obj);
474              sd->subobjs = eina_list_remove_list
475                  (sd->subobjs, sd->subobjs);
476           }
477         evas_object_del(sobj);
478      }
479    sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
480    sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
481    EINA_LIST_FREE (sd->translate_strings, ts)
482      {
483         eina_stringshare_del(ts->id);
484         eina_stringshare_del(ts->domain);
485         eina_stringshare_del(ts->string);
486         free(ts);
487      }
488
489    EINA_LIST_FREE (sd->event_cb, ecb)
490      free(ecb);
491
492    if (sd->style) eina_stringshare_del(sd->style);
493    if (sd->theme) elm_theme_free(sd->theme);
494    _if_focused_revert(obj, EINA_TRUE);
495    if (sd->access_info) eina_stringshare_del(sd->access_info);
496    free(sd);
497    evas_object_smart_data_set(obj, NULL);
498 }
499
500 static void
501 _smart_reconfigure(Elm_Widget_Smart_Data *sd)
502 {
503    if (sd->resize_obj)
504      {
505         evas_object_move(sd->resize_obj, sd->x, sd->y);
506         evas_object_resize(sd->resize_obj, sd->w, sd->h);
507      }
508    if (sd->hover_obj)
509      {
510         evas_object_move(sd->hover_obj, sd->x, sd->y);
511         evas_object_resize(sd->hover_obj, sd->w, sd->h);
512      }
513 }
514
515 static void
516 _smart_move(Evas_Object *obj,
517             Evas_Coord x,
518             Evas_Coord y)
519 {
520    ELM_WIDGET_DATA_GET(obj, sd);
521
522    sd->x = x;
523    sd->y = y;
524
525    _smart_reconfigure(sd);
526 }
527
528 static void
529 _smart_resize(Evas_Object *obj,
530               Evas_Coord w,
531               Evas_Coord h)
532 {
533    ELM_WIDGET_DATA_GET(obj, sd);
534
535    sd->w = w;
536    sd->h = h;
537
538    _smart_reconfigure(sd);
539 }
540
541 static void
542 _smart_show(Evas_Object *obj)
543 {
544    Eina_List *list;
545    Evas_Object *o;
546
547    if ((list = evas_object_smart_members_get(obj)))
548      {
549         EINA_LIST_FREE (list, o)
550           {
551              if (evas_object_data_get(o, "_elm_leaveme")) continue;
552              evas_object_show(o);
553           }
554      }
555 }
556
557 static void
558 _smart_hide(Evas_Object *obj)
559 {
560    Eina_List *list;
561    Evas_Object *o;
562
563    list = evas_object_smart_members_get(obj);
564    EINA_LIST_FREE (list, o)
565      {
566         if (evas_object_data_get(o, "_elm_leaveme")) continue;
567         evas_object_hide(o);
568      }
569 }
570
571 static void
572 _smart_color_set(Evas_Object *obj,
573                  int r,
574                  int g,
575                  int b,
576                  int a)
577 {
578    Eina_List *list;
579    Evas_Object *o;
580
581    if ((list = evas_object_smart_members_get(obj)))
582      {
583         EINA_LIST_FREE (list, o)
584           {
585              if (evas_object_data_get(o, "_elm_leaveme")) continue;
586              evas_object_color_set(o, r, g, b, a);
587           }
588      }
589 }
590
591 static void
592 _smart_clip_set(Evas_Object *obj,
593                 Evas_Object *clip)
594 {
595    Eina_List *list;
596    Evas_Object *o;
597
598    if ((list = evas_object_smart_members_get(obj)))
599      {
600         EINA_LIST_FREE (list, o)
601           {
602              if (evas_object_data_get(o, "_elm_leaveme")) continue;
603              evas_object_clip_set(o, clip);
604           }
605      }
606 }
607
608 static void
609 _smart_clip_unset(Evas_Object *obj)
610 {
611    Eina_List *list;
612    Evas_Object *o;
613
614    if ((list = evas_object_smart_members_get(obj)))
615      {
616         EINA_LIST_FREE (list, o)
617           {
618              if (evas_object_data_get(o, "_elm_leaveme")) continue;
619              evas_object_clip_unset(o);
620           }
621      }
622 }
623
624 static void
625 _smart_calculate(Evas_Object *obj __UNUSED__)
626 {
627    /* a NO-OP, on the base */
628 }
629
630 static void
631 _smart_member_add(Evas_Object *obj,
632                   Evas_Object *child)
633 {
634    int r, g, b, a;
635
636    if (evas_object_data_get(child, "_elm_leaveme")) return;
637
638    evas_object_color_get(obj, &r, &g, &b, &a);
639    evas_object_color_set(child, r, g, b, a);
640
641    evas_object_clip_set(child, evas_object_clip_get(obj));
642
643    if (evas_object_visible_get(obj))
644      evas_object_show(child);
645    else
646      evas_object_hide(child);
647 }
648
649 static void
650 _smart_member_del(Evas_Object *obj __UNUSED__,
651                   Evas_Object *child)
652 {
653    if (evas_object_data_get(child, "_elm_leaveme")) return;
654    evas_object_clip_unset(child);
655 }
656
657 static void
658 _elm_widget_smart_set(Elm_Widget_Smart_Class *api)
659 {
660    Evas_Smart_Class *sc;
661
662    if (!(sc = (Evas_Smart_Class *)api))
663      return;
664
665    sc->add = _smart_add;
666    sc->del = _smart_del;
667    sc->move = _smart_move;
668    sc->resize = _smart_resize;
669    sc->show = _smart_show;
670    sc->hide = _smart_hide;
671    sc->color_set = _smart_color_set;
672    sc->clip_set = _smart_clip_set;
673    sc->clip_unset = _smart_clip_unset;
674    sc->calculate = _smart_calculate;
675    sc->member_add = _smart_member_add;
676    sc->member_del = _smart_member_del;
677
678 #define API_DEFAULT_SET_UNIMPLEMENTED(_prefix) \
679   api->_prefix = _elm_widget_##_prefix##_func_unimplemented;
680
681    /* NB: always remember to call these parent versions on children,
682     * except for the unimplemented ones and calculate, which is moot */
683
684 #define API_DEFAULT_SET(_prefix) \
685   api->_prefix = _elm_widget_##_prefix##_func;
686
687    /* base api */
688    API_DEFAULT_SET_UNIMPLEMENTED(on_focus);
689    API_DEFAULT_SET_UNIMPLEMENTED(disable);
690
691    API_DEFAULT_SET(theme);
692    API_DEFAULT_SET_UNIMPLEMENTED(on_focus_region);
693
694    API_DEFAULT_SET_UNIMPLEMENTED(translate);
695    API_DEFAULT_SET_UNIMPLEMENTED(event);
696    API_DEFAULT_SET_UNIMPLEMENTED(focus_next);
697    API_DEFAULT_SET_UNIMPLEMENTED(focus_direction);
698
699    /* NB: because those two weren't hooks before, translate the
700     * individual calls to them on the widgets as we bring them to the
701     * new class hierarchy. also, sub_object_{add,del} must be
702     * different than member_{add,del} here, because widget parenting
703     * on elm does not always imply parent and child will live on the
704     * same Evas layer */
705    API_DEFAULT_SET(sub_object_add);
706    API_DEFAULT_SET(sub_object_del);
707
708 #undef API_DEFAULT_SET
709 #undef API_DEFAULT_SET_UNIMPLEMENTED
710
711    sc->callbacks = _smart_callbacks;
712 }
713
714 // internal funcs
715 static inline Eina_Bool
716 _elm_widget_focus_chain_manager_is(const Evas_Object *obj)
717 {
718    API_ENTRY return EINA_FALSE;
719
720    if (!sd->api) return EINA_FALSE;
721    return sd->api->focus_next &&
722           (sd->api->focus_next != _elm_widget_focus_next_func_unimplemented);
723 }
724
725 static inline Eina_Bool
726 _elm_widget_focus_direction_manager_is(const Evas_Object *obj)
727 {
728    API_ENTRY return EINA_FALSE;
729
730    if (!sd->api) return EINA_FALSE;
731    return sd->api->focus_direction &&
732           (sd->api->focus_direction !=
733            _elm_widget_focus_direction_func_unimplemented);
734 }
735
736 static void
737 _obj_mouse_down(void *data,
738                 Evas *e __UNUSED__,
739                 Evas_Object *obj __UNUSED__,
740                 void *event_info)
741 {
742    Elm_Widget_Smart_Data *sd = data;
743    Evas_Event_Mouse_Down *ev = event_info;
744    if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
745      sd->still_in = EINA_TRUE;
746 }
747
748 static void
749 _obj_mouse_move(void *data,
750                 Evas *e __UNUSED__,
751                 Evas_Object *obj,
752                 void *event_info)
753 {
754    Elm_Widget_Smart_Data *sd = data;
755    Evas_Event_Mouse_Move *ev = event_info;
756    if (sd->still_in)
757      {
758         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
759           sd->still_in = EINA_FALSE;
760         else
761           {
762              Evas_Coord x, y, w, h;
763              evas_object_geometry_get(obj, &x, &y, &w, &h);
764              if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
765                  (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
766                sd->still_in = EINA_FALSE;
767           }
768      }
769 }
770
771 static void
772 _obj_mouse_up(void *data,
773               Evas *e __UNUSED__,
774               Evas_Object *obj,
775               void *event_info __UNUSED__)
776 {
777    Elm_Widget_Smart_Data *sd = data;
778    if (sd->still_in)
779      elm_widget_focus_mouse_up_handle(obj);
780    sd->still_in = EINA_FALSE;
781 }
782
783 static void
784 _propagate_x_drag_lock(Evas_Object *obj,
785                        int dir)
786 {
787    INTERNAL_ENTRY;
788    if (sd->parent_obj)
789      {
790         Elm_Widget_Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
791         if (sd2)
792           {
793              sd2->child_drag_x_locked += dir;
794              _propagate_x_drag_lock(sd->parent_obj, dir);
795           }
796      }
797 }
798
799 static void
800 _propagate_y_drag_lock(Evas_Object *obj,
801                        int dir)
802 {
803    INTERNAL_ENTRY;
804    if (sd->parent_obj)
805      {
806         Elm_Widget_Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
807         if (sd2)
808           {
809              sd2->child_drag_y_locked += dir;
810              _propagate_y_drag_lock(sd->parent_obj, dir);
811           }
812      }
813 }
814
815 static void
816 _propagate_event(void *data,
817                  Evas *e __UNUSED__,
818                  Evas_Object *obj,
819                  void *event_info)
820 {
821    INTERNAL_ENTRY;
822    Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
823    Evas_Event_Flags *event_flags = NULL;
824
825    switch (type)
826      {
827       case EVAS_CALLBACK_KEY_DOWN:
828       {
829          Evas_Event_Key_Down *ev = event_info;
830          event_flags = &(ev->event_flags);
831       }
832       break;
833
834       case EVAS_CALLBACK_KEY_UP:
835       {
836          Evas_Event_Key_Up *ev = event_info;
837          event_flags = &(ev->event_flags);
838       }
839       break;
840
841       case EVAS_CALLBACK_MOUSE_WHEEL:
842       {
843          Evas_Event_Mouse_Wheel *ev = event_info;
844          event_flags = &(ev->event_flags);
845       }
846       break;
847
848       default:
849         break;
850      }
851
852    elm_widget_event_propagate(obj, type, event_info, event_flags);
853 }
854
855 /**
856  * If elm_widget_focus_region_get() returns EINA_FALSE, this function will
857  * ignore region show action.
858  */
859 static void
860 _elm_widget_focus_region_show(const Evas_Object *obj)
861 {
862    Evas_Coord x, y, ox, oy, w, h;
863    Evas_Object *o;
864
865    API_ENTRY return;
866
867    o = elm_widget_parent_get(obj);
868    if (!o) return;
869
870    if (!elm_widget_focus_region_get(obj, &x, &y, NULL, NULL))
871      return;
872
873    evas_object_geometry_get(obj, &ox, &oy, &w, &h);
874    if (w == 0 && h == 0) return;
875
876    while (o)
877      {
878         if (_elm_scrollable_is(o))
879           {
880              Evas_Coord px, py, pw, ph;
881              Evas_Coord rx, ry;
882
883              evas_object_geometry_get(o, &px, &py, &pw, &ph);
884
885              if ((px <= ox) && (px + pw) >= (ox + w) &&
886                  (py <= oy) && (py + ph) >= (oy + h))
887                {
888                   // if object is already shown
889                   o = elm_widget_parent_get(o);
890                   continue;
891                }
892              else if ((px < ox) && ((px + pw) < (ox + w)))
893                {
894                   // if object is over the viewport to the x axis.
895                   x += w - pw;
896                }
897              else if ((py < oy) && ((py + ph) < (oy + h)))
898                {
899                   // if object is over the viewport to the y axis.
900                   y += h - ph;
901                }
902
903              ELM_SCROLLABLE_IFACE_GET(o, s_iface);
904              s_iface->content_pos_get(o, &rx, &ry);
905              s_iface->content_viewport_size_get(o, &w, &h);
906
907              x += rx + ox - px;
908              y += ry + oy - py;
909
910              s_iface->content_region_show(o, x, y, w, h);
911              x = 0;
912              y = 0;
913           }
914         o = elm_widget_parent_get(o);
915      }
916 }
917
918 static void
919 _parent_focus(Evas_Object *obj)
920 {
921    API_ENTRY return;
922
923    if (sd->focused) return;
924
925    Evas_Object *o = elm_widget_parent_get(obj);
926    sd->focus_order_on_calc = EINA_TRUE;
927
928    if (o) _parent_focus(o);
929
930    if (!sd->focus_order_on_calc)
931      return;  /* we don't want to override it if by means of any of the
932                  callbacks below one gets to calculate our order
933                  first. */
934
935    focus_order++;
936    sd->focus_order = focus_order;
937    if (!sd->api) return;
938    if (sd->top_win_focused)
939      {
940         sd->focused = EINA_TRUE;
941         sd->api->on_focus(obj);
942      }
943    sd->focus_order_on_calc = EINA_FALSE;
944
945    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
946      _elm_access_highlight_set(obj);
947 }
948
949 static void
950 _elm_object_focus_chain_del_cb(void *data,
951                                Evas *e __UNUSED__,
952                                Evas_Object *obj,
953                                void *event_info __UNUSED__)
954 {
955    Elm_Widget_Smart_Data *sd = data;
956
957    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
958 }
959
960 EAPI const Elm_Widget_Smart_Class *
961 elm_widget_smart_class_get(void)
962 {
963    static Elm_Widget_Smart_Class _sc =
964      ELM_WIDGET_SMART_CLASS_INIT_NAME_VERSION(ELM_WIDGET_SMART_NAME);
965    static const Elm_Widget_Smart_Class *class = NULL;
966
967    if (class)
968      return class;
969
970    _elm_widget_smart_set(&_sc);
971    class = &_sc;
972
973    return class;
974 }
975
976 EAPI Evas_Object *
977 elm_widget_add(Evas_Smart *smart,
978                Evas_Object *parent)
979 {
980    Evas *e;
981    Evas_Object *o;
982
983    e = evas_object_evas_get(parent);
984    if (!e) return NULL;
985
986    o = evas_object_smart_add(e, smart);
987    elm_widget_parent_set(o, parent);
988
989    return o;
990 }
991
992 EAPI void
993 elm_widget_parent_set(Evas_Object *obj,
994                       Evas_Object *parent)
995 {
996    ELM_WIDGET_DATA_GET(obj, sd);
997
998    if (!sd->api->parent_set) return;
999
1000    sd->api->parent_set(obj, parent);
1001 }
1002
1003 EAPI Eina_Bool
1004 elm_widget_api_check(int ver)
1005 {
1006    if (ver != ELM_INTERNAL_API_VERSION)
1007      {
1008         CRITICAL("Elementary widget api versions do not match");
1009         return EINA_FALSE;
1010      }
1011    return EINA_TRUE;
1012 }
1013
1014 EAPI Eina_Bool
1015 elm_widget_access(Evas_Object *obj,
1016                   Eina_Bool is_access)
1017 {
1018    const Eina_List *l;
1019    Evas_Object *child;
1020    Eina_Bool ret = EINA_TRUE;
1021
1022    API_ENTRY return EINA_FALSE;
1023    EINA_LIST_FOREACH(sd->subobjs, l, child)
1024      ret &= elm_widget_access(child, is_access);
1025
1026    if (sd->api && sd->api->access)
1027      sd->api->access(obj, is_access);
1028    else
1029      return EINA_FALSE;
1030
1031    return ret;
1032 }
1033
1034 EAPI Eina_Bool
1035 elm_widget_theme(Evas_Object *obj)
1036 {
1037    const Eina_List *l;
1038    Evas_Object *child;
1039    Elm_Tooltip *tt;
1040    Elm_Cursor *cur;
1041    Eina_Bool ret = EINA_TRUE;
1042
1043    API_ENTRY return EINA_FALSE;
1044
1045    EINA_LIST_FOREACH(sd->subobjs, l, child)
1046      if (_elm_widget_is(child)) ret &= elm_widget_theme(child);
1047    if (sd->resize_obj && _elm_widget_is(sd->resize_obj))
1048      ret &= elm_widget_theme(sd->resize_obj);
1049    if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
1050
1051    EINA_LIST_FOREACH(sd->tooltips, l, tt)
1052      elm_tooltip_theme(tt);
1053    EINA_LIST_FOREACH(sd->cursors, l, cur)
1054      elm_cursor_theme(cur);
1055
1056    if (!sd->api) return EINA_FALSE;
1057
1058    ret &= sd->api->theme(obj);
1059
1060    return ret;
1061 }
1062
1063 EAPI void
1064 elm_widget_theme_specific(Evas_Object *obj,
1065                           Elm_Theme *th,
1066                           Eina_Bool force)
1067 {
1068    const Eina_List *l;
1069    Evas_Object *child;
1070    Elm_Tooltip *tt;
1071    Elm_Cursor *cur;
1072    Elm_Theme *th2, *thdef;
1073
1074    API_ENTRY return;
1075
1076    thdef = elm_theme_default_get();
1077    if (!th) th = thdef;
1078    if (!force)
1079      {
1080         th2 = sd->theme;
1081         if (!th2) th2 = thdef;
1082         while (th2)
1083           {
1084              if (th2 == th)
1085                {
1086                   force = EINA_TRUE;
1087                   break;
1088                }
1089              if (th2 == thdef) break;
1090              th2 = th2->ref_theme;
1091              if (!th2) th2 = thdef;
1092           }
1093      }
1094    if (!force) return;
1095    EINA_LIST_FOREACH(sd->subobjs, l, child)
1096      elm_widget_theme_specific(child, th, force);
1097    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
1098    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
1099    EINA_LIST_FOREACH(sd->tooltips, l, tt)
1100      elm_tooltip_theme(tt);
1101    EINA_LIST_FOREACH(sd->cursors, l, cur)
1102      elm_cursor_theme(cur);
1103    if (!sd->api) return;
1104    sd->api->theme(obj);
1105 }
1106
1107 /**
1108  * Returns the widget's mirrored mode.
1109  *
1110  * @param obj The widget.
1111  * @return mirrored mode of the object.
1112  *
1113  **/
1114 EAPI Eina_Bool
1115 elm_widget_mirrored_get(const Evas_Object *obj)
1116 {
1117    API_ENTRY return EINA_FALSE;
1118    return sd->is_mirrored;
1119 }
1120
1121 /**
1122  * Sets the widget's mirrored mode.
1123  *
1124  * @param obj The widget.
1125  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
1126  */
1127 EAPI void
1128 elm_widget_mirrored_set(Evas_Object *obj,
1129                         Eina_Bool mirrored)
1130 {
1131    API_ENTRY return;
1132
1133    mirrored = !!mirrored;
1134
1135    if (sd->is_mirrored == mirrored) return;
1136
1137    sd->is_mirrored = mirrored;
1138    elm_widget_theme(obj);
1139 }
1140
1141 /**
1142  * Returns the widget's mirrored mode setting.
1143  *
1144  * @param obj The widget.
1145  * @return mirrored mode setting of the object.
1146  *
1147  **/
1148 EAPI Eina_Bool
1149 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
1150 {
1151    API_ENTRY return EINA_FALSE;
1152    return sd->mirrored_auto_mode;
1153 }
1154
1155 /**
1156  * Sets the widget's mirrored mode setting.
1157  * When widget in automatic mode, it follows the system mirrored mode set by
1158  * elm_mirrored_set().
1159  * @param obj The widget.
1160  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
1161  */
1162 EAPI void
1163 elm_widget_mirrored_automatic_set(Evas_Object *obj,
1164                                   Eina_Bool automatic)
1165 {
1166    API_ENTRY return;
1167    if (sd->mirrored_auto_mode != automatic)
1168      {
1169         sd->mirrored_auto_mode = automatic;
1170
1171         if (automatic)
1172           {
1173              elm_widget_mirrored_set(obj, elm_config_mirrored_get());
1174           }
1175      }
1176 }
1177
1178 EAPI void
1179 elm_widget_on_show_region_hook_set(Evas_Object *obj,
1180                                    void (*func)(void *data,
1181                                                 Evas_Object *obj),
1182                                    void *data)
1183 {
1184    API_ENTRY return;
1185
1186    sd->on_show_region = func;
1187    sd->on_show_region_data = data;
1188 }
1189
1190 EAPI Eina_Bool
1191 elm_widget_sub_object_add(Evas_Object *obj,
1192                           Evas_Object *sobj)
1193 {
1194    API_ENTRY return EINA_FALSE;
1195    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1196
1197    if (!sd->api) return EINA_FALSE;
1198    return sd->api->sub_object_add(obj, sobj);
1199 }
1200
1201 EAPI Eina_Bool
1202 elm_widget_sub_object_del(Evas_Object *obj,
1203                           Evas_Object *sobj)
1204 {
1205    API_ENTRY return EINA_FALSE;
1206    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1207
1208    if (!sobj) return EINA_FALSE;
1209
1210    if (!sd->api) return EINA_FALSE;
1211    return sd->api->sub_object_del(obj, sobj);
1212 }
1213
1214 //SHKWAK : Temp Function for Indicator Issue
1215 // THIS MUST BE REMOVED
1216
1217 EAPI const Eina_List *
1218 elm_widget_sub_object_list_get(const Evas_Object *obj)
1219 {
1220    API_ENTRY return NULL;
1221    return (const Eina_List *)sd->subobjs;
1222 }
1223
1224 //SHKWAK : END
1225
1226
1227 /* a resize object is a sub object with some more callbacks on it and
1228  * a smart member of the parent
1229  */
1230 EAPI void
1231 elm_widget_resize_object_set(Evas_Object *obj,
1232                              Evas_Object *sobj)
1233 {
1234    Evas_Object *parent;
1235
1236    API_ENTRY return;
1237
1238    if (sd->resize_obj == sobj) return;
1239
1240    // orphan previous resize obj
1241    if (sd->resize_obj)
1242      {
1243         evas_object_clip_unset(sd->resize_obj);
1244         evas_object_smart_member_del(sd->resize_obj);
1245
1246         if (_elm_widget_is(sd->resize_obj))
1247           {
1248              if (elm_widget_focus_get(sd->resize_obj)) _parents_unfocus(obj);
1249           }
1250
1251         elm_widget_sub_object_del(obj, sd->resize_obj);
1252      }
1253
1254    sd->resize_obj = sobj;
1255    if (!sobj)
1256      {
1257         evas_object_event_callback_del_full(obj,
1258                                             EVAS_CALLBACK_MOUSE_DOWN,
1259                                             _obj_mouse_down, sd);
1260         evas_object_event_callback_del_full(obj,
1261                                             EVAS_CALLBACK_MOUSE_MOVE,
1262                                             _obj_mouse_move, sd);
1263         evas_object_event_callback_del_full(obj,
1264                                             EVAS_CALLBACK_MOUSE_UP,
1265                                             _obj_mouse_up, sd);
1266         return;
1267      }
1268
1269    // orphan new resize obj
1270    parent = evas_object_data_get(sobj, "elm-parent");
1271    if (parent && parent != obj)
1272      {
1273         ELM_WIDGET_DATA_GET(parent, sdp);
1274
1275         /* should be there, just being paranoid */
1276         if (sdp)
1277           {
1278              if (sdp->resize_obj == sobj)
1279                elm_widget_resize_object_set(parent, NULL);
1280              else
1281                elm_widget_sub_object_del(parent, sobj);
1282           }
1283      }
1284
1285    elm_widget_sub_object_add(obj, sobj);
1286
1287    evas_object_smart_member_add(sobj, obj);
1288
1289    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1290                                   _obj_mouse_down, sd);
1291    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1292                                   _obj_mouse_move, sd);
1293    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1294                                   _obj_mouse_up, sd);
1295    _smart_reconfigure(sd);
1296 }
1297
1298 /* WARNING: the programmer is responsible, in the scenario of
1299  * exchanging a hover object, of cleaning the old hover "target"
1300  * before
1301  */
1302 EAPI void
1303 elm_widget_hover_object_set(Evas_Object *obj,
1304                             Evas_Object *sobj)
1305 {
1306    API_ENTRY return;
1307    if (sd->hover_obj)
1308      {
1309         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1310                                             _on_sub_obj_del, sd);
1311      }
1312    sd->hover_obj = sobj;
1313    if (sd->hover_obj)
1314      {
1315         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1316                                        _on_sub_obj_del, sd);
1317         _smart_reconfigure(sd);
1318      }
1319 }
1320
1321 EAPI void
1322 elm_widget_can_focus_set(Evas_Object *obj,
1323                          Eina_Bool can_focus)
1324 {
1325    API_ENTRY return;
1326
1327    can_focus = !!can_focus;
1328
1329    if (sd->can_focus == can_focus) return;
1330    sd->can_focus = can_focus;
1331    if (sd->can_focus)
1332      {
1333         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1334                                        _propagate_event,
1335                                        (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1336         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1337                                        _propagate_event,
1338                                        (void *)(long)EVAS_CALLBACK_KEY_UP);
1339         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1340                                        _propagate_event,
1341                                        (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1342
1343         /* update child focusable-ness on parents, now that a
1344          * focusable child got in */
1345         Elm_Widget_Smart_Data *sdp = sd;
1346         if (!sd->child_can_focus)
1347           {
1348              sdp->child_can_focus = EINA_TRUE;
1349              while (sdp->parent_obj)
1350                {
1351                   if (sdp->child_can_focus) break;
1352
1353                   sdp->child_can_focus = EINA_TRUE;
1354                   sdp = evas_object_smart_data_get(sdp->parent_obj);
1355                }
1356           }
1357      }
1358    else
1359      {
1360         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1361                                        _propagate_event);
1362         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1363                                        _propagate_event);
1364         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1365                                        _propagate_event);
1366      }
1367 }
1368
1369 EAPI Eina_Bool
1370 elm_widget_can_focus_get(const Evas_Object *obj)
1371 {
1372    API_ENTRY return EINA_FALSE;
1373    return sd->can_focus;
1374 }
1375
1376 EAPI Eina_Bool
1377 elm_widget_child_can_focus_get(const Evas_Object *obj)
1378 {
1379    API_ENTRY return EINA_FALSE;
1380    return sd->child_can_focus;
1381 }
1382
1383 /**
1384  * @internal
1385  *
1386  * This API makes the widget object and its children to be unfocusable.
1387  *
1388  * This API can be helpful for an object to be deleted.
1389  * When an object will be deleted soon, it and its children may not
1390  * want to get focus (by focus reverting or by other focus controls).
1391  * Then, just use this API before deleting.
1392  *
1393  * @param obj The widget root of sub-tree
1394  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1395  *
1396  * @ingroup Widget
1397  */
1398 EAPI void
1399 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1400                                 Eina_Bool tree_unfocusable)
1401 {
1402    API_ENTRY return;
1403
1404    tree_unfocusable = !!tree_unfocusable;
1405    if (sd->tree_unfocusable == tree_unfocusable) return;
1406    sd->tree_unfocusable = tree_unfocusable;
1407    elm_widget_focus_tree_unfocusable_handle(obj);
1408 }
1409
1410 /**
1411  * @internal
1412  *
1413  * This returns true, if the object sub-tree is unfocusable.
1414  *
1415  * @param obj The widget root of sub-tree
1416  * @return EINA_TRUE if the object sub-tree is unfocusable
1417  *
1418  * @ingroup Widget
1419  */
1420 EAPI Eina_Bool
1421 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1422 {
1423    API_ENTRY return EINA_FALSE;
1424    return sd->tree_unfocusable;
1425 }
1426
1427 /**
1428  * @internal
1429  *
1430  * Get the list of focusable child objects.
1431  *
1432  * This function retruns list of child objects which can get focus.
1433  *
1434  * @param obj The parent widget
1435  * @retrun list of focusable child objects.
1436  *
1437  * @ingroup Widget
1438  */
1439 EAPI Eina_List *
1440 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1441 {
1442    API_ENTRY return NULL;
1443
1444    const Eina_List *l;
1445    Eina_List *child_list = NULL;
1446    Evas_Object *child;
1447
1448    if (sd->subobjs)
1449      {
1450         EINA_LIST_FOREACH(sd->subobjs, l, child)
1451           {
1452              if ((elm_widget_can_focus_get(child)) &&
1453                  (evas_object_visible_get(child)) &&
1454                  (!elm_widget_disabled_get(child)))
1455                child_list = eina_list_append(child_list, child);
1456              else if (elm_widget_is(child))
1457                {
1458                   Eina_List *can_focus_list;
1459                   can_focus_list = elm_widget_can_focus_child_list_get(child);
1460                   if (can_focus_list)
1461                     child_list = eina_list_merge(child_list, can_focus_list);
1462                }
1463           }
1464      }
1465    return child_list;
1466 }
1467
1468 EAPI void
1469 elm_widget_highlight_ignore_set(Evas_Object *obj,
1470                                 Eina_Bool ignore)
1471 {
1472    API_ENTRY return;
1473    sd->highlight_ignore = !!ignore;
1474 }
1475
1476 EAPI Eina_Bool
1477 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1478 {
1479    API_ENTRY return EINA_FALSE;
1480    return sd->highlight_ignore;
1481 }
1482
1483 EAPI void
1484 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1485                                   Eina_Bool highlight)
1486 {
1487    API_ENTRY return;
1488    sd->highlight_in_theme = !!highlight;
1489    /* FIXME: if focused, it should switch from one mode to the other */
1490 }
1491
1492 EAPI Eina_Bool
1493 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1494 {
1495    API_ENTRY return EINA_FALSE;
1496    return sd->highlight_in_theme;
1497 }
1498
1499 EAPI Eina_Bool
1500 elm_widget_focus_get(const Evas_Object *obj)
1501 {
1502    API_ENTRY return EINA_FALSE;
1503    return sd->focused;
1504 }
1505
1506 EAPI Evas_Object *
1507 elm_widget_focused_object_get(const Evas_Object *obj)
1508 {
1509    const Evas_Object *subobj;
1510    const Eina_List *l;
1511    API_ENTRY return NULL;
1512
1513    if (!sd->focused) return NULL;
1514    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1515      {
1516         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1517         if (fobj) return fobj;
1518      }
1519    return (Evas_Object *)obj;
1520 }
1521
1522 EAPI Evas_Object *
1523 elm_widget_top_get(const Evas_Object *obj)
1524 {
1525    API_ENTRY return NULL;
1526    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1527    return (Evas_Object *)obj;
1528 }
1529
1530 EAPI Eina_Bool
1531 elm_widget_is(const Evas_Object *obj)
1532 {
1533    return _elm_widget_is(obj);
1534 }
1535
1536 EAPI Evas_Object *
1537 elm_widget_parent_widget_get(const Evas_Object *obj)
1538 {
1539    Evas_Object *parent;
1540
1541    if (_elm_widget_is(obj))
1542      {
1543         Elm_Widget_Smart_Data *sd = evas_object_smart_data_get(obj);
1544         if (!sd) return NULL;
1545         parent = sd->parent_obj;
1546      }
1547    else
1548      {
1549         parent = evas_object_data_get(obj, "elm-parent");
1550         if (!parent) parent = evas_object_smart_parent_get(obj);
1551      }
1552
1553    while (parent)
1554      {
1555         Evas_Object *elm_parent;
1556         if (_elm_widget_is(parent)) break;
1557         elm_parent = evas_object_data_get(parent, "elm-parent");
1558         if (elm_parent) parent = elm_parent;
1559         else parent = evas_object_smart_parent_get(parent);
1560      }
1561    return parent;
1562 }
1563
1564 EAPI Evas_Object *
1565 elm_widget_parent2_get(const Evas_Object *obj)
1566 {
1567    if (_elm_widget_is(obj))
1568      {
1569         Elm_Widget_Smart_Data *sd = evas_object_smart_data_get(obj);
1570         if (sd) return sd->parent2;
1571      }
1572    return NULL;
1573 }
1574
1575 EAPI void
1576 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1577 {
1578    API_ENTRY return;
1579    sd->parent2 = parent;
1580 }
1581
1582 EAPI void
1583 elm_widget_event_callback_add(Evas_Object *obj,
1584                               Elm_Event_Cb func,
1585                               const void *data)
1586 {
1587    API_ENTRY return;
1588    EINA_SAFETY_ON_NULL_RETURN(func);
1589    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1590    ecb->func = func;
1591    ecb->data = data;
1592    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1593 }
1594
1595 EAPI void *
1596 elm_widget_event_callback_del(Evas_Object *obj,
1597                               Elm_Event_Cb func,
1598                               const void *data)
1599 {
1600    API_ENTRY return NULL;
1601    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1602    Eina_List *l;
1603    Elm_Event_Cb_Data *ecd;
1604    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1605      if ((ecd->func == func) && (ecd->data == data))
1606        {
1607           free(ecd);
1608           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1609           return (void *)data;
1610        }
1611    return NULL;
1612 }
1613
1614 EAPI Eina_Bool
1615 elm_widget_event_propagate(Evas_Object *obj,
1616                            Evas_Callback_Type type,
1617                            void *event_info,
1618                            Evas_Event_Flags *event_flags)
1619 {
1620    API_ENTRY return EINA_FALSE; //TODO reduce.
1621
1622    if (!_elm_widget_is(obj)) return EINA_FALSE;
1623    Evas_Object *parent = obj;
1624    Elm_Event_Cb_Data *ecd;
1625    Eina_List *l, *l_prev;
1626
1627    while (parent &&
1628           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1629      {
1630         sd = evas_object_smart_data_get(parent);
1631         if ((!sd) || (!_elm_widget_is(obj)))
1632           return EINA_FALSE;  //Not Elm Widget
1633         if (!sd->api) return EINA_FALSE;
1634
1635         if (sd->api->event(parent, obj, type, event_info))
1636           return EINA_TRUE;
1637
1638         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1639           {
1640              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1641                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1642                return EINA_TRUE;
1643           }
1644         parent = sd->parent_obj;
1645      }
1646
1647    return EINA_FALSE;
1648 }
1649
1650 /**
1651  * @internal
1652  *
1653  * Set custom focus chain.
1654  *
1655  * This function i set one new and overwrite any previous custom focus chain
1656  * with the list of objects. The previous list will be deleted and this list
1657  * will be managed. After setted, don't modity it.
1658  *
1659  * @note On focus cycle, only will be evaluated children of this container.
1660  *
1661  * @param obj The container widget
1662  * @param objs Chain of objects to pass focus
1663  * @ingroup Widget
1664  */
1665 EAPI void
1666 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1667                                   Eina_List *objs)
1668 {
1669    API_ENTRY return;
1670
1671    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1672
1673    elm_widget_focus_custom_chain_unset(obj);
1674
1675    Eina_List *l;
1676    Evas_Object *o;
1677
1678    EINA_LIST_FOREACH(objs, l, o)
1679      {
1680         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1681                                        _elm_object_focus_chain_del_cb, sd);
1682      }
1683
1684    sd->focus_chain = objs;
1685 }
1686
1687 /**
1688  * @internal
1689  *
1690  * Get custom focus chain
1691  *
1692  * @param obj The container widget
1693  * @ingroup Widget
1694  */
1695 EAPI const Eina_List *
1696 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1697 {
1698    API_ENTRY return NULL;
1699    return (const Eina_List *)sd->focus_chain;
1700 }
1701
1702 /**
1703  * @internal
1704  *
1705  * Unset custom focus chain
1706  *
1707  * @param obj The container widget
1708  * @ingroup Widget
1709  */
1710 EAPI void
1711 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1712 {
1713    API_ENTRY return;
1714    Eina_List *l, *l_next;
1715    Evas_Object *o;
1716
1717    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1718      {
1719         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1720                                             _elm_object_focus_chain_del_cb, sd);
1721         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1722      }
1723 }
1724
1725 /**
1726  * @internal
1727  *
1728  * Append object to custom focus chain.
1729  *
1730  * @note If relative_child equal to NULL or not in custom chain, the object
1731  * will be added in end.
1732  *
1733  * @note On focus cycle, only will be evaluated children of this container.
1734  *
1735  * @param obj The container widget
1736  * @param child The child to be added in custom chain
1737  * @param relative_child The relative object to position the child
1738  * @ingroup Widget
1739  */
1740 EAPI void
1741 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1742                                      Evas_Object *child,
1743                                      Evas_Object *relative_child)
1744 {
1745    API_ENTRY return;
1746    EINA_SAFETY_ON_NULL_RETURN(child);
1747
1748    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1749
1750    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1751                                        _elm_object_focus_chain_del_cb, sd);
1752
1753    if (!relative_child)
1754      sd->focus_chain = eina_list_append(sd->focus_chain, child);
1755    else
1756      sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1757                                                  child, relative_child);
1758 }
1759
1760 /**
1761  * @internal
1762  *
1763  * Prepend object to custom focus chain.
1764  *
1765  * @note If relative_child equal to NULL or not in custom chain, the object
1766  * will be added in begin.
1767  *
1768  * @note On focus cycle, only will be evaluated children of this container.
1769  *
1770  * @param obj The container widget
1771  * @param child The child to be added in custom chain
1772  * @param relative_child The relative object to position the child
1773  * @ingroup Widget
1774  */
1775 EAPI void
1776 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1777                                       Evas_Object *child,
1778                                       Evas_Object *relative_child)
1779 {
1780    API_ENTRY return;
1781    EINA_SAFETY_ON_NULL_RETURN(child);
1782
1783    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1784
1785    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1786                                        _elm_object_focus_chain_del_cb, sd);
1787
1788    if (!relative_child)
1789      sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1790    else
1791      sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1792                                                   child, relative_child);
1793 }
1794
1795 /**
1796  * @internal
1797  *
1798  * Give focus to next object in object tree.
1799  *
1800  * Give focus to next object in focus chain of one object sub-tree.
1801  * If the last object of chain already have focus, the focus will go to the
1802  * first object of chain.
1803  *
1804  * @param obj The widget root of sub-tree
1805  * @param dir Direction to cycle the focus
1806  *
1807  * @ingroup Widget
1808  */
1809 EAPI void
1810 elm_widget_focus_cycle(Evas_Object *obj,
1811                        Elm_Focus_Direction dir)
1812 {
1813    Evas_Object *target = NULL;
1814    if (!_elm_widget_is(obj))
1815      return;
1816    elm_widget_focus_next_get(obj, dir, &target);
1817    if (target)
1818      {
1819         /* access */
1820         if (_elm_config->access_mode && _elm_access_read_mode_get())
1821           {
1822              _elm_access_highlight_set(target);
1823              _elm_widget_focus_region_show(target);
1824           }
1825         else elm_widget_focus_steal(target);
1826      }
1827 }
1828
1829 /**
1830  * @internal
1831  *
1832  * Give focus to near object(in object tree) in one direction.
1833  *
1834  * Give focus to near object(in object tree) in direction of current
1835  * focused object.  If none focusable object in given direction or
1836  * none focused object in object tree, the focus will not change.
1837  *
1838  * @param obj The reference widget
1839  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
1840  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
1841  * @return EINA_TRUE if focus is moved.
1842  *
1843  * @ingroup Widget
1844  */
1845 EAPI Eina_Bool
1846 elm_widget_focus_direction_go(Evas_Object *obj,
1847                               double degree)
1848 {
1849    Evas_Object *target = NULL;
1850    Evas_Object *current_focused = NULL;
1851    double weight = 0.0;
1852
1853    if (!_elm_widget_is(obj)) return EINA_FALSE;
1854    if (!elm_widget_focus_get(obj)) return EINA_FALSE;
1855
1856    current_focused = elm_widget_focused_object_get(obj);
1857
1858    if (elm_widget_focus_direction_get
1859          (obj, current_focused, degree, &target, &weight))
1860      {
1861         elm_widget_focus_steal(target);
1862         return EINA_TRUE;
1863      }
1864    return EINA_FALSE;
1865 }
1866
1867 static double
1868 _direction_weight_get(const Evas_Object *obj1,
1869                       const Evas_Object *obj2,
1870                       double degree)
1871 {
1872    Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
1873    double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
1874    double ax, ay, cx, cy;
1875    double weight = -1.0, g = 0.0;
1876
1877    if (obj1 == obj2) return 0.0;
1878
1879    degree -= 90.0;
1880    while (degree >= 360.0)
1881      degree -= 360.0;
1882    while (degree < 0.0)
1883      degree += 360.0;
1884
1885    evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
1886    cx = obj_x1 + (w1 / 2.0);
1887    cy = obj_y1 + (h1 / 2.0);
1888    evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
1889
1890    /* For overlapping cases. */
1891    if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2))
1892      return 0.0;
1893
1894    /* Change all points to relative one. */
1895    x1 = obj_x1 - cx;
1896    xx1 = x1 + w1;
1897    yy1 = obj_y1 - cy;
1898    yyy1 = yy1 + h1;
1899    x2 = obj_x2 - cx;
1900    xx2 = x2 + w2;
1901    yy2 = obj_y2 - cy;
1902    yyy2 = yy2 + h2;
1903
1904    /* Get crossing points (ax, ay) between obj1 and a line extending
1905     * to the direction of current degree. */
1906    if (degree == 0.0)
1907      {
1908         ax = xx1;
1909         ay = 0.0;
1910      }
1911    else if (degree == 90.0)
1912      {
1913         ax = 0.0;
1914         ay = yyy1;
1915      }
1916    else if (degree == 180.0)
1917      {
1918         ax = x1;
1919         ay = 0.0;
1920      }
1921    else if (degree == 270.0)
1922      {
1923         ax = 0.0;
1924         ay = yy1;
1925      }
1926    else
1927      {
1928         g = tan(degree * (M_PI / 180.0));
1929         if ((degree > 0.0) && (degree < 90.0))
1930           {
1931              ay = g * xx1;
1932              if (ay <= yyy1) ax = xx1;
1933              else
1934                {
1935                   ax = yyy1 / g;
1936                   ay = yyy1;
1937                }
1938           }
1939         else if ((degree > 90.0) && (degree < 180.0))
1940           {
1941              ay = g * x1;
1942              if (ay <= yyy1) ax = x1;
1943              else
1944                {
1945                   ax = yyy1 / g;
1946                   ay = yyy1;
1947                }
1948           }
1949         else if ((degree > 180.0) && (degree < 270.0))
1950           {
1951              ay = g * x1;
1952              if (ay >= yy1) ax = x1;
1953              else
1954                {
1955                   ax = yy1 / g;
1956                   ay = yy1;
1957                }
1958           }
1959         else
1960           {
1961              ay = g * xx1;
1962              if (ay >= yy1) ax = xx1;
1963              else
1964                {
1965                   ax = yy1 / g;
1966                   ay = yy1;
1967                }
1968           }
1969      }
1970
1971    /* Filter obj2, if it is not in the specific derection. */
1972    int i = 0;
1973    double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
1974    double t1, t2, u1, v1, u2, v2;
1975
1976    if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) ||
1977        (degree == 315.0))
1978      {
1979         u1 = 1.0;
1980         v1 = 0.0;
1981         u2 = 0.0;
1982         v2 = 1.0;
1983      }
1984    else
1985      {
1986         double g2 = tan((degree + 45.0) * (M_PI / 180.0));
1987         u1 = (-1.0 * g2);
1988         u2 = (1.0 / g2);
1989         v1 = v2 = 1.0;
1990      }
1991    t1 = (u1 * ax) + (v1 * ay);
1992    t2 = (u2 * ax) + (v2 * ay);
1993
1994 #define _R(x) (int)((x + 0.05) * 10.0)
1995
1996    if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) +
1997                                                             (v2 * yy2))) > 0))
1998      {
1999         rx[i] = x2;
2000         ry[i++] = yy2;
2001      }
2002    if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) +
2003                                                              (v2 * yyy2))) > 0))
2004      {
2005         rx[i] = x2;
2006         ry[i++] = yyy2;
2007      }
2008    if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) +
2009                                                              (v2 * yy2))) > 0))
2010      {
2011         rx[i] = xx2;
2012         ry[i++] = yy2;
2013      }
2014    if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) &&
2015        (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
2016      {
2017         rx[i] = xx2;
2018         ry[i++] = yyy2;
2019      }
2020    if (i == 0)
2021      {
2022         if (degree == 0.0)
2023           {
2024              if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2025           }
2026         else if (degree == 90.0)
2027           {
2028              if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2029           }
2030         else if (degree == 180.0)
2031           {
2032              if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2033           }
2034         else if (degree == 270.0)
2035           {
2036              if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2037           }
2038         else
2039           {
2040              if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
2041                {
2042                   if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0)))
2043                     return 0.0;
2044                }
2045              else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
2046                {
2047                   if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0)))
2048                     return 0.0;
2049                }
2050              else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2)
2051                                                            <= _R(xx2)))
2052                {
2053                   if (!((_R(ax * ((1.0 / g) * yy2)) > 0)
2054                         && (_R(ay * yy2) > 0)))
2055                     return 0.0;
2056                }
2057              else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) &&
2058                       (_R((1.0 / g) * yyy2) <= _R(xx2)))
2059                {
2060                   if (!((_R(ax * ((1.0 / g) * yyy2)) > 0)
2061                         && (_R(ay * yyy2) > 0))) return 0.0;
2062                }
2063              else return 0.0;
2064           }
2065      }
2066
2067    /* Calculate the weight for obj2. */
2068    if (degree == 0.0)
2069      {
2070         if (_R(xx1) > _R(x2)) weight = -1.0;
2071         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2072           weight = (x2 - xx1) * (x2 - xx1);
2073         else if (_R(yy2) > 0)
2074           weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
2075         else if (_R(yyy2) < 0)
2076           weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
2077         else weight = (x2 - xx1) * (x2 - xx1);
2078      }
2079    else if (degree == 90.0)
2080      {
2081         if (_R(yyy1) > _R(yy2)) weight = -1.0;
2082         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2083           weight = (yy2 - yyy1) * (yy2 - yyy1);
2084         else if (_R(x2) > 0)
2085           weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
2086         else if (_R(xx2) < 0)
2087           weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
2088         else weight = (yy2 - yyy1) * (yy2 - yyy1);
2089      }
2090    else if (degree == 180.0)
2091      {
2092         if (_R(x1) < _R(xx2)) weight = -1.0;
2093         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2094           weight = (x1 - xx2) * (x1 - xx2);
2095         else if (_R(yy2) > 0)
2096           weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
2097         else if (_R(yyy2) < 0)
2098           weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
2099         else weight = (x1 - xx2) * (x1 - xx2);
2100      }
2101    else if (degree == 270.0)
2102      {
2103         if (_R(yy1) < _R(yyy2)) weight = -1.0;
2104         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2105           weight = (yy1 - yyy2) * (yy1 - yyy2);
2106         else if (_R(x2) > 0)
2107           weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
2108         else if (_R(xx2) < 0)
2109           weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
2110         else weight = (yy1 - yyy2) * (yy1 - yyy2);
2111      }
2112    else
2113      {
2114         int j = 0, k = 0;
2115         double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
2116         double t_weight[4] = {-1.0, -1.0, -1.0, -1.0};
2117         if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
2118           {
2119              sx[j] = x2;
2120              sy[j] = g * x2;
2121              t_weight[j++] = ((ax - x2) * (ax - x2)) +
2122                ((ay - (g * x2)) * (ay - (g * x2)));
2123           }
2124         if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
2125           {
2126              sx[j] = xx2;
2127              sy[j] = g * xx2;
2128              t_weight[j++] = ((ax - xx2) * (ax - xx2)) +
2129                ((ay - (g * xx2)) * (ay - (g * xx2)));
2130           }
2131         if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
2132           {
2133              sx[j] = (1.0 / g) * yy2;
2134              sy[j] = yy2;
2135              t_weight[j++] =
2136                ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) +
2137                ((ay - yy2) * (ay - yy2));
2138           }
2139         if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2)
2140                                                  <= _R(xx2)))
2141           {
2142              sx[j] = (1.0 / g) * yyy2;
2143              sy[j] = yyy2;
2144              t_weight[j++] =
2145                ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) +
2146                ((ay - yyy2) * (ay - yyy2));
2147           }
2148
2149         if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) ||
2150                                      (_R(sy[0]) != _R(sy[1])))))
2151           {
2152              for (; k < j; k++)
2153                {
2154                   if (_R(t_weight[k]) == 0) return -1.0;
2155                   if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
2156                }
2157           }
2158         else
2159           {
2160              for (; k < i; k++)
2161                {
2162                   double ccx, ccy, t1_weight, x_diff, y_diff;
2163                   ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
2164                   ccy = g * ccx;
2165                   x_diff = rx[k] - ccx;
2166                   if (x_diff < 0) x_diff *= -1.0;
2167                   y_diff = ry[k] - ccy;
2168                   if (y_diff < 0) y_diff *= -1.0;
2169                   t1_weight =
2170                     (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
2171                     ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
2172                   if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
2173                     weight = t1_weight;
2174                }
2175           }
2176      }
2177    /* Return the current object's weight. */
2178    if (weight == -1.0) return 0.0;
2179    if (_R(weight) == 0) return -1.0;
2180
2181 #undef _R
2182
2183    return 1.0 / weight;
2184 }
2185
2186 /**
2187  * @internal
2188  *
2189  * Get near object in one direction of base object.
2190  *
2191  * Get near object(in the object sub-tree) in one direction of
2192  * base object. Return the near object by reference.
2193  * By initializing weight, you can filter objects locating far
2194  * from base object. If object is in the specific direction,
2195  * weight is (1/(distance^2)). If object is not exactly in one
2196  * direction, some penalty will be added.
2197  *
2198  * @param obj The widget root of sub-tree
2199  * @param base The base object of the direction
2200  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2201  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2202  * @param direction The near object in one direction
2203  * @param weight The weight is bigger when the object is located near
2204  * @return EINA_TRUE if near object is updated.
2205  *
2206  * @ingroup Widget
2207  */
2208 EAPI Eina_Bool
2209 elm_widget_focus_direction_get(const Evas_Object *obj,
2210                                const Evas_Object *base,
2211                                double degree,
2212                                Evas_Object **direction,
2213                                double *weight)
2214 {
2215    double c_weight;
2216
2217    API_ENTRY return EINA_FALSE;
2218
2219    /* -1 means the best was already decided. Don't need any more searching. */
2220    if (!direction || !weight || !base || (obj == base))
2221      return EINA_FALSE;
2222
2223    /* Ignore if disabled */
2224    if ((!evas_object_visible_get(obj))
2225        || (elm_widget_disabled_get(obj))
2226        || (elm_widget_tree_unfocusable_get(obj)))
2227      return EINA_FALSE;
2228
2229    if (!sd->api) return EINA_FALSE;
2230
2231    /* Try use hook */
2232    if (_elm_widget_focus_direction_manager_is(obj))
2233      return sd->api->focus_direction(obj, base, degree, direction, weight);
2234
2235    if (!elm_widget_can_focus_get(obj) || elm_widget_focus_get(obj))
2236      return EINA_FALSE;
2237
2238    c_weight = _direction_weight_get(base, obj, degree);
2239    if ((c_weight == -1.0) ||
2240        ((c_weight != 0.0) && (*weight != -1.0) &&
2241         ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
2242      {
2243         if ((int)(*weight * 1000000) == (int)(c_weight * 1000000))
2244           {
2245              Elm_Widget_Smart_Data *sd1 =
2246                evas_object_smart_data_get(*direction);
2247              if (sd1)
2248                {
2249                   if (sd->focus_order <= sd1->focus_order)
2250                     return EINA_FALSE;
2251                }
2252           }
2253         *direction = (Evas_Object *)obj;
2254         *weight = c_weight;
2255         return EINA_TRUE;
2256      }
2257    return EINA_FALSE;
2258 }
2259
2260 /**
2261  * @internal
2262  *
2263  * Get near object in one direction of base object in list.
2264  *
2265  * Get near object in one direction of base object in the specific
2266  * object list. Return the near object by reference.
2267  * By initializing weight, you can filter objects locating far
2268  * from base object. If object is in the specific direction,
2269  * weight is (1/(distance^2)). If object is not exactly in one
2270  * direction, some penalty will be added.
2271  *
2272  * @param obj The widget root of sub-tree
2273  * @param base The base object of the direction
2274  * @param items list with ordered objects
2275  * @param list_data_get function to get the object from one item of list
2276  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2277  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2278  * @param direction The near object in one direction
2279  * @param weight The weight is bigger when the object is located near
2280  * @return EINA_TRUE if near object is updated.
2281  *
2282  * @ingroup Widget
2283  */
2284 EAPI Eina_Bool
2285 elm_widget_focus_list_direction_get(const Evas_Object *obj,
2286                                     const Evas_Object *base,
2287                                     const Eina_List *items,
2288                                     void *(*list_data_get)(const Eina_List *l),
2289                                     double degree,
2290                                     Evas_Object **direction,
2291                                     double *weight)
2292 {
2293    API_ENTRY return EINA_FALSE;
2294    if (!direction || !weight || !base || !items)
2295      return EINA_FALSE;
2296
2297    const Eina_List *l = items;
2298    Evas_Object *current_best = *direction;
2299
2300    for (; l; l = eina_list_next(l))
2301      {
2302         Evas_Object *cur = list_data_get(l);
2303         elm_widget_focus_direction_get(cur, base, degree, direction, weight);
2304      }
2305    if (current_best != *direction)
2306      return EINA_TRUE;
2307    else
2308      return EINA_FALSE;
2309 }
2310
2311 /**
2312  * @internal
2313  *
2314  * Get next object in focus chain of object tree.
2315  *
2316  * Get next object in focus chain of one object sub-tree.
2317  * Return the next object by reference. If don't have any candidate to receive
2318  * focus before chain end, the first candidate will be returned.
2319  *
2320  * @param obj The widget root of sub-tree
2321  * @param dir Direction os focus chain
2322  * @param next The next object in focus chain
2323  * @return EINA_TRUE if don't need focus chain restart/loop back
2324  *         to use 'next' obj.
2325  *
2326  * @ingroup Widget
2327  */
2328 EAPI Eina_Bool
2329 elm_widget_focus_next_get(const Evas_Object *obj,
2330                           Elm_Focus_Direction dir,
2331                           Evas_Object **next)
2332 {
2333    if (!next)
2334      return EINA_FALSE;
2335    *next = NULL;
2336
2337    API_ENTRY return EINA_FALSE;
2338
2339    /* Ignore if disabled */
2340    if ((!evas_object_visible_get(obj))
2341        || (elm_widget_disabled_get(obj))
2342        || (elm_widget_tree_unfocusable_get(obj)))
2343      return EINA_FALSE;
2344
2345    if (!sd->api) return EINA_FALSE;
2346
2347    /* Try use hook */
2348    if (_elm_widget_focus_chain_manager_is(obj))
2349      {
2350         Eina_Bool ret;
2351         ret = sd->api->focus_next(obj, dir, next);
2352         if (!ret && elm_widget_focus_get(obj))
2353           {
2354              Evas_Object *o = NULL;
2355              if (dir == ELM_FOCUS_PREVIOUS)
2356                o = sd->focus_previous;
2357              else if (dir == ELM_FOCUS_NEXT)
2358                o = sd->focus_next;
2359              else if (dir == ELM_FOCUS_UP)
2360                o = sd->focus_up;
2361              else if (dir == ELM_FOCUS_DOWN)
2362                o = sd->focus_down;
2363              else if (dir == ELM_FOCUS_RIGHT)
2364                o = sd->focus_right;
2365              else if (dir == ELM_FOCUS_LEFT)
2366                o = sd->focus_left;
2367
2368              if (o)
2369                {
2370                   *next = o;
2371                   return EINA_TRUE;
2372                }
2373           }
2374         return ret;
2375      }
2376
2377    if (!elm_widget_can_focus_get(obj))
2378      return EINA_FALSE;
2379
2380    /* focusable object but does not have access info */
2381    if (_elm_config->access_mode)
2382      {
2383         if (!_elm_access_object_get(obj)) return EINA_FALSE;
2384      }
2385
2386    if (elm_widget_focus_get(obj))
2387      {
2388         if (dir == ELM_FOCUS_PREVIOUS)
2389           *next = sd->focus_previous;
2390         else if (dir == ELM_FOCUS_NEXT)
2391           *next = sd->focus_next;
2392         else if (dir == ELM_FOCUS_UP)
2393           *next = sd->focus_up;
2394         else if (dir == ELM_FOCUS_DOWN)
2395           *next = sd->focus_down;
2396         else if (dir == ELM_FOCUS_RIGHT)
2397           *next = sd->focus_right;
2398         else if (dir == ELM_FOCUS_LEFT)
2399           *next = sd->focus_left;
2400
2401         if (*next)
2402           return EINA_TRUE;
2403      }
2404    /* Return */
2405    *next = (Evas_Object *)obj;
2406    return !ELM_WIDGET_FOCUS_GET(obj);
2407 }
2408
2409 /**
2410  * @internal
2411  *
2412  * Get next object in focus chain of object tree in list.
2413  *
2414  * Get next object in focus chain of one object sub-tree ordered by one list.
2415  * Return the next object by reference. If don't have any candidate to receive
2416  * focus before list end, the first candidate will be returned.
2417  *
2418  * @param obj The widget root of sub-tree
2419  * @param dir Direction os focus chain
2420  * @param items list with ordered objects
2421  * @param list_data_get function to get the object from one item of list
2422  * @param next The next object in focus chain
2423  * @return EINA_TRUE if don't need focus chain restart/loop back
2424  *         to use 'next' obj.
2425  *
2426  * @ingroup Widget
2427  */
2428 EAPI Eina_Bool
2429 elm_widget_focus_list_next_get(const Evas_Object *obj,
2430                                const Eina_List *items,
2431                                void *(*list_data_get)(const Eina_List *list),
2432                                Elm_Focus_Direction dir,
2433                                Evas_Object **next)
2434 {
2435    Eina_List *(*list_next)(const Eina_List *list) = NULL;
2436    Evas_Object *focused_object = NULL;
2437
2438    if (!next)
2439      return EINA_FALSE;
2440    *next = NULL;
2441
2442    if (!_elm_widget_is(obj))
2443      return EINA_FALSE;
2444
2445    if (!items)
2446      return EINA_FALSE;
2447
2448    /* When Up, Down, Right, or Left, try direction_get first. */
2449    focused_object = elm_widget_focused_object_get(obj);
2450    if (focused_object)
2451      {
2452         if((dir == ELM_FOCUS_UP)
2453            || (dir == ELM_FOCUS_DOWN)
2454            || (dir == ELM_FOCUS_RIGHT)
2455            || (dir == ELM_FOCUS_LEFT))
2456           {
2457              *next = elm_widget_focus_next_object_get(focused_object, dir);
2458              if (*next)
2459                return EINA_TRUE;
2460              else
2461                {
2462                   Evas_Object *n = NULL;
2463                   double degree;
2464                   double weight;
2465
2466                   if (dir == ELM_FOCUS_UP) degree = 0.0;
2467                   else if (dir == ELM_FOCUS_DOWN) degree = 180.0;
2468                   else if (dir == ELM_FOCUS_RIGHT) degree = 90.0;
2469                   else if (dir == ELM_FOCUS_LEFT) degree = 270.0;
2470
2471                   if (elm_widget_focus_list_direction_get(obj, focused_object,
2472                                                           items, list_data_get,
2473                                                           degree, &n, &weight))
2474                     {
2475                        *next = n;
2476                        return EINA_TRUE;
2477                     }
2478                }
2479           }
2480      }
2481
2482    /* Direction */
2483    if (dir == ELM_FOCUS_PREVIOUS)
2484      {
2485         items = eina_list_last(items);
2486         list_next = eina_list_prev;
2487      }
2488    else if ((dir == ELM_FOCUS_NEXT)
2489             || (dir == ELM_FOCUS_UP)
2490             || (dir == ELM_FOCUS_DOWN)
2491             || (dir == ELM_FOCUS_RIGHT)
2492             || (dir == ELM_FOCUS_LEFT))
2493      list_next = eina_list_next;
2494    else
2495      return EINA_FALSE;
2496
2497    const Eina_List *l = items;
2498
2499    /* Recovery last focused sub item */
2500    if (ELM_WIDGET_FOCUS_GET(obj))
2501      {
2502         for (; l; l = list_next(l))
2503           {
2504              Evas_Object *cur = list_data_get(l);
2505              if (ELM_WIDGET_FOCUS_GET(cur)) break;
2506           }
2507
2508          /* Focused object, but no focused sub item */
2509          if (!l) l = items;
2510      }
2511
2512    const Eina_List *start = l;
2513    Evas_Object *to_focus = NULL;
2514
2515    /* Interate sub items */
2516    /* Go to end of list */
2517    for (; l; l = list_next(l))
2518      {
2519         Evas_Object *tmp = NULL;
2520         Evas_Object *cur = list_data_get(l);
2521
2522         if (elm_widget_parent_get(cur) != obj)
2523           continue;
2524
2525         /* Try Focus cycle in subitem */
2526         if (elm_widget_focus_next_get(cur, dir, &tmp))
2527           {
2528              *next = tmp;
2529              return EINA_TRUE;
2530           }
2531         else if ((dir == ELM_FOCUS_UP)
2532                  || (dir == ELM_FOCUS_DOWN)
2533                  || (dir == ELM_FOCUS_RIGHT)
2534                  || (dir == ELM_FOCUS_LEFT))
2535           {
2536              if (tmp && elm_widget_focus_get(cur))
2537                {
2538                   *next = tmp;
2539                   return EINA_FALSE;
2540                }
2541           }
2542         else if ((tmp) && (!to_focus))
2543           to_focus = tmp;
2544      }
2545
2546    l = items;
2547
2548    /* Get First possible */
2549    for (; l != start; l = list_next(l))
2550      {
2551         Evas_Object *tmp = NULL;
2552         Evas_Object *cur = list_data_get(l);
2553
2554         if (elm_widget_parent_get(cur) != obj)
2555           continue;
2556
2557         /* Try Focus cycle in subitem */
2558         elm_widget_focus_next_get(cur, dir, &tmp);
2559         if (tmp)
2560           {
2561              *next = tmp;
2562              return EINA_FALSE;
2563           }
2564      }
2565
2566    *next = to_focus;
2567    return EINA_FALSE;
2568 }
2569
2570
2571 /**
2572  * @internal
2573  *
2574  * Get next object which was set with specific focus direction.
2575  *
2576  * Get next object which was set by elm_widget_focus_next_object_set
2577  * with specific focus directioin.
2578  *
2579  * @param obj The widget
2580  * @param dir Direction of focus
2581  * @return Widget which was registered with sepecific focus direction.
2582  *
2583  * @ingroup Widget
2584  */
2585 EAPI Evas_Object *
2586 elm_widget_focus_next_object_get(const Evas_Object *obj, Elm_Focus_Direction dir)
2587 {
2588    API_ENTRY return NULL;
2589
2590    if (dir == ELM_FOCUS_PREVIOUS)
2591      return sd->focus_previous;
2592    else if (dir == ELM_FOCUS_NEXT)
2593      return sd->focus_next;
2594    else if (dir == ELM_FOCUS_UP)
2595      return sd->focus_up;
2596    else if (dir == ELM_FOCUS_DOWN)
2597      return sd->focus_down;
2598    else if (dir == ELM_FOCUS_RIGHT)
2599      return sd->focus_right;
2600    else if (dir == ELM_FOCUS_LEFT)
2601      return sd->focus_left;
2602
2603    return NULL;
2604 }
2605
2606 /**
2607  * @internal
2608  *
2609  * Set next object with specific focus direction.
2610  *
2611  * When a widget is set with specific focus direction, this widget will be
2612  * the first candidate when finding the next focus object.
2613  * Focus next object can be registered with six directions that are previous,
2614  * next, up, down, right, and left.
2615  *
2616  * @param obj The widget
2617  * @param next Next focus object
2618  * @param dir Direction of focus
2619  *
2620  * @ingroup Widget
2621  */
2622 EAPI void
2623 elm_widget_focus_next_object_set(Evas_Object *obj, Evas_Object *next, Elm_Focus_Direction dir)
2624 {
2625    API_ENTRY return;
2626
2627    if (dir == ELM_FOCUS_PREVIOUS)
2628      sd->focus_previous = next;
2629    else if (dir == ELM_FOCUS_NEXT)
2630      sd->focus_next = next;
2631    else if (dir == ELM_FOCUS_UP)
2632      sd->focus_up = next;
2633    else if (dir == ELM_FOCUS_DOWN)
2634      sd->focus_down = next;
2635    else if (dir == ELM_FOCUS_RIGHT)
2636      sd->focus_right = next;
2637    else if (dir == ELM_FOCUS_LEFT)
2638      sd->focus_left = next;
2639 }
2640
2641
2642 EAPI Eina_Bool
2643 elm_widget_highlight_get(const Evas_Object *obj)
2644 {
2645    API_ENTRY return EINA_FALSE;
2646    return sd->highlighted;
2647 }
2648
2649 EAPI void
2650 elm_widget_parent_highlight_set(Evas_Object *obj,
2651                                 Eina_Bool highlighted)
2652 {
2653    API_ENTRY return;
2654
2655    highlighted = !!highlighted;
2656
2657    Evas_Object *o = elm_widget_parent_get(obj);
2658
2659    if (o) elm_widget_parent_highlight_set(o, highlighted);
2660
2661    sd->highlighted = highlighted;
2662 }
2663
2664 EAPI void
2665 elm_widget_signal_emit(Evas_Object *obj,
2666                        const char *emission,
2667                        const char *source)
2668 {
2669    API_ENTRY return;
2670
2671    if (evas_object_smart_type_check(obj, "elm_layout"))
2672      elm_layout_signal_emit(obj, emission, source);
2673    else if (evas_object_smart_type_check(obj, "elm_icon"))
2674      {
2675         WRN("Deprecated function. This functionality on icon objects"
2676             " will be dropped on a next release.");
2677         _elm_icon_signal_emit(obj, emission, source);
2678      }
2679 }
2680
2681 EAPI void
2682 elm_widget_signal_callback_add(Evas_Object *obj,
2683                                const char *emission,
2684                                const char *source,
2685                                Edje_Signal_Cb func,
2686                                void *data)
2687 {
2688    API_ENTRY return;
2689
2690    EINA_SAFETY_ON_NULL_RETURN(func);
2691
2692    if (evas_object_smart_type_check(obj, "elm_layout"))
2693      elm_layout_signal_callback_add(obj, emission, source, func, data);
2694    else if (evas_object_smart_type_check(obj, "elm_icon"))
2695      {
2696         WRN("Deprecated function. This functionality on icon objects"
2697             " will be dropped on a next release.");
2698
2699         _elm_icon_signal_callback_add(obj, emission, source, func, data);
2700      }
2701 }
2702
2703 EAPI void *
2704 elm_widget_signal_callback_del(Evas_Object *obj,
2705                                const char *emission,
2706                                const char *source,
2707                                Edje_Signal_Cb func)
2708 {
2709    void *data = NULL;
2710
2711    API_ENTRY return NULL;
2712
2713    if (evas_object_smart_type_check(obj, "elm_layout"))
2714      data = elm_layout_signal_callback_del(obj, emission, source, func);
2715    else if (evas_object_smart_type_check(obj, "elm_icon"))
2716      {
2717         WRN("Deprecated function. This functionality on icon objects"
2718             " will be dropped on a next release.");
2719
2720         data = _elm_icon_signal_callback_del(obj, emission, source, func);
2721      }
2722
2723    return data;
2724 }
2725
2726 EAPI void
2727 elm_widget_focus_set(Evas_Object *obj,
2728                      int first)
2729 {
2730    API_ENTRY return;
2731
2732    if (!sd->api) return;
2733
2734    if (!sd->focused)
2735      {
2736         focus_order++;
2737         sd->focus_order = focus_order;
2738         sd->focused = EINA_TRUE;
2739         sd->api->on_focus(obj);
2740      }
2741
2742    if (first)
2743      {
2744         if ((_is_focusable(sd->resize_obj)) &&
2745             (!elm_widget_disabled_get(sd->resize_obj)))
2746           {
2747              elm_widget_focus_set(sd->resize_obj, first);
2748           }
2749         else
2750           {
2751              const Eina_List *l;
2752              Evas_Object *child;
2753
2754              EINA_LIST_FOREACH(sd->subobjs, l, child)
2755                {
2756                   if ((_is_focusable(child)) &&
2757                       (!elm_widget_disabled_get(child)))
2758                     {
2759                        elm_widget_focus_set(child, first);
2760                        break;
2761                     }
2762                }
2763           }
2764      }
2765    else
2766      {
2767         const Eina_List *l;
2768         Evas_Object *child;
2769
2770         EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
2771           {
2772              if ((_is_focusable(child)) &&
2773                  (!elm_widget_disabled_get(child)))
2774                {
2775                   elm_widget_focus_set(child, first);
2776                   break;
2777                }
2778           }
2779         if (!l)
2780           {
2781              if ((_is_focusable(sd->resize_obj)) &&
2782                  (!elm_widget_disabled_get(sd->resize_obj)))
2783                {
2784                   elm_widget_focus_set(sd->resize_obj, first);
2785                }
2786           }
2787      }
2788 }
2789
2790 EAPI Evas_Object *
2791 elm_widget_parent_get(const Evas_Object *obj)
2792 {
2793    API_ENTRY return NULL;
2794    return sd->parent_obj;
2795 }
2796
2797 EAPI void
2798 elm_widget_focused_object_clear(Evas_Object *obj)
2799 {
2800    API_ENTRY return;
2801
2802    if (!sd->api) return;
2803
2804    if (!sd->focused) return;
2805
2806    // FIXME: evas_object_ref/unref is temporary code to fix logical issue.
2807    // After Eo is applied to elementary, remove these.
2808    evas_object_ref(obj);
2809    if (sd->resize_obj && elm_widget_focus_get(sd->resize_obj))
2810      elm_widget_focused_object_clear(sd->resize_obj);
2811    else
2812      {
2813         const Eina_List *l;
2814         Evas_Object *child;
2815         EINA_LIST_FOREACH(sd->subobjs, l, child)
2816           {
2817              if (elm_widget_focus_get(child))
2818                {
2819                   elm_widget_focused_object_clear(child);
2820                   break;
2821                }
2822           }
2823      }
2824    sd->focused = EINA_FALSE;
2825    sd->api->on_focus(obj);
2826    evas_object_unref(obj);
2827 }
2828
2829 EAPI void
2830 elm_widget_focus_steal(Evas_Object *obj)
2831 {
2832    Evas_Object *parent, *parent2, *o;
2833    API_ENTRY return;
2834
2835    if (sd->focused) return;
2836    if (sd->disabled) return;
2837    if (!sd->can_focus) return;
2838    if (sd->tree_unfocusable) return;
2839    parent = obj;
2840    for (;; )
2841      {
2842         o = elm_widget_parent_get(parent);
2843         if (!o) break;
2844         sd = evas_object_smart_data_get(o);
2845         if (sd->disabled || sd->tree_unfocusable) return;
2846         if (sd->focused) break;
2847         parent = o;
2848      }
2849    if ((!elm_widget_parent_get(parent)) &&
2850        (!elm_widget_parent2_get(parent)))
2851      elm_widget_focused_object_clear(parent);
2852    else
2853      {
2854         parent2 = elm_widget_parent_get(parent);
2855         if (!parent2) parent2 = elm_widget_parent2_get(parent);
2856         parent = parent2;
2857         sd = evas_object_smart_data_get(parent);
2858         if (sd)
2859           {
2860              if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
2861                elm_widget_focused_object_clear(sd->resize_obj);
2862              else
2863                {
2864                   const Eina_List *l;
2865                   Evas_Object *child;
2866                   EINA_LIST_FOREACH(sd->subobjs, l, child)
2867                     {
2868                        if (elm_widget_focus_get(child))
2869                          {
2870                             elm_widget_focused_object_clear(child);
2871                             break;
2872                          }
2873                     }
2874                }
2875           }
2876      }
2877    _parent_focus(obj);
2878    _elm_widget_focus_region_show(obj);
2879    return;
2880 }
2881
2882 EAPI void
2883 elm_widget_focus_restore(Evas_Object *obj)
2884 {
2885    Evas_Object *newest = NULL;
2886    unsigned int newest_focus_order = 0;
2887    API_ENTRY return;
2888
2889    newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2890    if (newest)
2891      {
2892         elm_object_focus_set(newest, EINA_FALSE);
2893         elm_object_focus_set(newest, EINA_TRUE);
2894      }
2895 }
2896
2897 void
2898 _elm_widget_top_win_focused_set(Evas_Object *obj,
2899                                 Eina_Bool top_win_focused)
2900 {
2901    const Eina_List *l;
2902    Evas_Object *child;
2903    API_ENTRY return;
2904
2905    if (sd->top_win_focused == top_win_focused) return;
2906    if (sd->resize_obj)
2907      _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2908    EINA_LIST_FOREACH(sd->subobjs, l, child)
2909      {
2910         _elm_widget_top_win_focused_set(child, top_win_focused);
2911      }
2912    sd->top_win_focused = top_win_focused;
2913 }
2914
2915 Eina_Bool
2916 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2917 {
2918    API_ENTRY return EINA_FALSE;
2919    return sd->top_win_focused;
2920 }
2921
2922 EAPI void
2923 elm_widget_disabled_set(Evas_Object *obj,
2924                         Eina_Bool disabled)
2925 {
2926    API_ENTRY return;
2927
2928    if (sd->disabled == disabled) return;
2929    sd->disabled = !!disabled;
2930    elm_widget_focus_disabled_handle(obj);
2931    if (!sd->api) return;
2932    sd->api->disable(obj);
2933 }
2934
2935 EAPI Eina_Bool
2936 elm_widget_disabled_get(const Evas_Object *obj)
2937 {
2938    API_ENTRY return 0;
2939    return sd->disabled;
2940 }
2941
2942 EAPI void
2943 elm_widget_show_region_set(Evas_Object *obj,
2944                            Evas_Coord x,
2945                            Evas_Coord y,
2946                            Evas_Coord w,
2947                            Evas_Coord h,
2948                            Eina_Bool forceshow)
2949 {
2950    Evas_Object *parent_obj, *child_obj;
2951    Evas_Coord px, py, cx, cy;
2952
2953    API_ENTRY return;
2954
2955    evas_smart_objects_calculate(evas_object_evas_get(obj));
2956    ELM_WIDGET_CHECK_OR_RETURN(obj);
2957
2958    if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
2959        (w == sd->rw) && (h == sd->rh)) return;
2960
2961    sd->rx = x;
2962    sd->ry = y;
2963    sd->rw = w;
2964    sd->rh = h;
2965    if (sd->on_show_region)
2966      sd->on_show_region
2967        (sd->on_show_region_data, obj);
2968
2969    do
2970      {
2971         parent_obj = sd->parent_obj;
2972         child_obj = sd->obj;
2973         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2974         sd = evas_object_smart_data_get(parent_obj);
2975         if (!sd) break;
2976
2977         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2978         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2979
2980         x += (cx - px);
2981         y += (cy - py);
2982         sd->rx = x;
2983         sd->ry = y;
2984         sd->rw = w;
2985         sd->rh = h;
2986
2987         if (sd->on_show_region)
2988           {
2989              sd->on_show_region
2990                (sd->on_show_region_data, parent_obj);
2991           }
2992      }
2993    while (parent_obj);
2994 }
2995
2996 EAPI void
2997 elm_widget_show_region_get(const Evas_Object *obj,
2998                            Evas_Coord *x,
2999                            Evas_Coord *y,
3000                            Evas_Coord *w,
3001                            Evas_Coord *h)
3002 {
3003    API_ENTRY return;
3004    if (x) *x = sd->rx;
3005    if (y) *y = sd->ry;
3006    if (w) *w = sd->rw;
3007    if (h) *h = sd->rh;
3008 }
3009
3010 /**
3011  * @internal
3012  *
3013  * Get the focus region of the given widget.
3014  *
3015  * @return show region or not
3016  * (@c EINA_TRUE = show region/@c EINA_FALSE = do not show region). Default is @c EINA_FALSE.
3017  *
3018  * The focus region is the area of a widget that should brought into the
3019  * visible area when the widget is focused. Mostly used to show the part of
3020  * an entry where the cursor is, for example. The area returned is relative
3021  * to the object @p obj.
3022  *
3023  * @param obj The widget object
3024  * @param x Where to store the x coordinate of the area
3025  * @param y Where to store the y coordinate of the area
3026  * @param w Where to store the width of the area
3027  * @param h Where to store the height of the area
3028  *
3029  * @ingroup Widget
3030  */
3031 EAPI Eina_Bool
3032 elm_widget_focus_region_get(const Evas_Object *obj,
3033                             Evas_Coord *x,
3034                             Evas_Coord *y,
3035                             Evas_Coord *w,
3036                             Evas_Coord *h)
3037 {
3038    API_ENTRY return EINA_FALSE;
3039    if (!sd->api->on_focus_region(obj, x, y, w, h))
3040      {
3041         evas_object_geometry_get(obj, NULL, NULL, w, h);
3042         if (x) *x = 0;
3043         if (y) *y = 0;
3044      }
3045    return EINA_TRUE;
3046 }
3047
3048 EAPI Eina_List *
3049 elm_widget_scrollable_children_get(Evas_Object *obj)
3050 {
3051    Eina_List *l, *ret = NULL;
3052    Evas_Object *child;
3053
3054    API_ENTRY return NULL;
3055
3056    EINA_LIST_FOREACH(sd->subobjs, l, child)
3057      {
3058         if (_elm_scrollable_is(child))
3059           ret = eina_list_append(ret, child);
3060      }
3061
3062    return ret;
3063 }
3064
3065 EAPI void
3066 elm_widget_scroll_hold_push(Evas_Object *obj)
3067 {
3068    API_ENTRY return;
3069    sd->scroll_hold++;
3070    if (sd->scroll_hold == 1)
3071      {
3072         if (_elm_scrollable_is(obj))
3073           {
3074              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3075              s_iface->hold_set(obj, EINA_TRUE);
3076           }
3077         else
3078           {
3079              Eina_List *scr_children, *l;
3080              Evas_Object *child;
3081
3082              scr_children = elm_widget_scrollable_children_get(obj);
3083              EINA_LIST_FOREACH(scr_children, l, child)
3084                {
3085                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3086                   s_iface->hold_set(child, EINA_TRUE);
3087                }
3088              eina_list_free(scr_children);
3089           }
3090      }
3091    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
3092    // FIXME: on delete/reparent hold pop
3093 }
3094
3095 EAPI void
3096 elm_widget_scroll_hold_pop(Evas_Object *obj)
3097 {
3098    API_ENTRY return;
3099    sd->scroll_hold--;
3100    if (!sd->scroll_hold)
3101      {
3102         if (_elm_scrollable_is(obj))
3103           {
3104              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3105              s_iface->hold_set(obj, EINA_FALSE);
3106           }
3107         else
3108           {
3109              Eina_List *scr_children, *l;
3110              Evas_Object *child;
3111
3112              scr_children = elm_widget_scrollable_children_get(obj);
3113              EINA_LIST_FOREACH(scr_children, l, child)
3114                {
3115                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3116                   s_iface->hold_set(child, EINA_FALSE);
3117                }
3118              eina_list_free(scr_children);
3119           }
3120      }
3121    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
3122    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
3123 }
3124
3125 EAPI int
3126 elm_widget_scroll_hold_get(const Evas_Object *obj)
3127 {
3128    API_ENTRY return 0;
3129    return sd->scroll_hold;
3130 }
3131
3132 EAPI void
3133 elm_widget_scroll_freeze_push(Evas_Object *obj)
3134 {
3135    API_ENTRY return;
3136    sd->scroll_freeze++;
3137    if (sd->scroll_freeze == 1)
3138      {
3139         if (_elm_scrollable_is(obj))
3140           {
3141              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3142              s_iface->freeze_set(obj, EINA_TRUE);
3143           }
3144         else
3145           {
3146              Eina_List *scr_children, *l;
3147              Evas_Object *child;
3148
3149              scr_children = elm_widget_scrollable_children_get(obj);
3150              EINA_LIST_FOREACH(scr_children, l, child)
3151                {
3152                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3153                   s_iface->freeze_set(child, EINA_TRUE);
3154                }
3155              eina_list_free(scr_children);
3156           }
3157      }
3158    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
3159    // FIXME: on delete/reparent freeze pop
3160 }
3161
3162 EAPI void
3163 elm_widget_scroll_freeze_pop(Evas_Object *obj)
3164 {
3165    API_ENTRY return;
3166    sd->scroll_freeze--;
3167    if (!sd->scroll_freeze)
3168      {
3169         if (_elm_scrollable_is(obj))
3170           {
3171              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3172              s_iface->freeze_set(obj, EINA_FALSE);
3173           }
3174         else
3175           {
3176              Eina_List *scr_children, *l;
3177              Evas_Object *child;
3178
3179              scr_children = elm_widget_scrollable_children_get(obj);
3180              EINA_LIST_FOREACH(scr_children, l, child)
3181                {
3182                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3183                   s_iface->freeze_set(child, EINA_FALSE);
3184                }
3185              eina_list_free(scr_children);
3186           }
3187      }
3188    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
3189    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
3190 }
3191
3192 EAPI int
3193 elm_widget_scroll_freeze_get(const Evas_Object *obj)
3194 {
3195    API_ENTRY return 0;
3196    return sd->scroll_freeze;
3197 }
3198
3199 EAPI void
3200 elm_widget_scale_set(Evas_Object *obj,
3201                      double scale)
3202 {
3203    API_ENTRY return;
3204    if (scale <= 0.0) scale = 0.0;
3205    if (sd->scale != scale)
3206      {
3207         sd->scale = scale;
3208         elm_widget_theme(obj);
3209      }
3210 }
3211
3212 EAPI double
3213 elm_widget_scale_get(const Evas_Object *obj)
3214 {
3215    API_ENTRY return 1.0;
3216    // FIXME: save walking up the tree by storing/caching parent scale
3217    if (sd->scale == 0.0)
3218      {
3219         if (sd->parent_obj)
3220           return elm_widget_scale_get(sd->parent_obj);
3221         else
3222           return 1.0;
3223      }
3224    return sd->scale;
3225 }
3226
3227 EAPI void
3228 elm_widget_theme_set(Evas_Object *obj,
3229                      Elm_Theme *th)
3230 {
3231    API_ENTRY return;
3232    if (sd->theme != th)
3233      {
3234         if (sd->theme) elm_theme_free(sd->theme);
3235         sd->theme = th;
3236         if (th) th->ref++;
3237         elm_widget_theme(obj);
3238      }
3239 }
3240
3241 EAPI void
3242 elm_widget_text_part_set(Evas_Object *obj,
3243                          const char *part,
3244                          const char *label)
3245 {
3246    API_ENTRY return;
3247
3248    if (evas_object_smart_type_check(obj, "elm_layout"))
3249      elm_layout_text_set(obj, part, label);
3250 }
3251
3252 EAPI const char *
3253 elm_widget_text_part_get(const Evas_Object *obj,
3254                          const char *part)
3255 {
3256    API_ENTRY return NULL;
3257
3258    if (evas_object_smart_type_check(obj, "elm_layout"))
3259      return elm_layout_text_get(obj, part);
3260
3261    return NULL;
3262 }
3263
3264 static Eina_Bool
3265 _translatable_part_text_set(Eina_List **translate_strings, const char *part, const char *domain, const char *label)
3266 {
3267    const char *str;
3268    Eina_List *t, *l;
3269    Elm_Translate_String_Data *ts = NULL;
3270
3271    t = *translate_strings;
3272    str = eina_stringshare_add(part);
3273    EINA_LIST_FOREACH(t, l, ts)
3274      {
3275         if (ts->id == str) break;
3276         else ts = NULL;
3277      }
3278
3279    if (!ts && !label)
3280      eina_stringshare_del(str);
3281    else if (!ts)
3282      {
3283         ts = malloc(sizeof(Elm_Translate_String_Data));
3284         if (!ts) return EINA_FALSE;
3285
3286         ts->id = str;
3287         ts->domain = eina_stringshare_add(domain);
3288         ts->string = eina_stringshare_add(label);
3289         t = eina_list_append(t, ts);
3290      }
3291    else
3292      {
3293         if (label)
3294           {
3295              eina_stringshare_replace(&ts->domain, domain);
3296              eina_stringshare_replace(&ts->string, label);
3297           }
3298         else
3299           {
3300              t = eina_list_remove_list(t, l);
3301              eina_stringshare_del(ts->id);
3302              eina_stringshare_del(ts->domain);
3303              eina_stringshare_del(ts->string);
3304              free(ts);
3305           }
3306         eina_stringshare_del(str);
3307      }
3308
3309    *translate_strings = t;
3310    return EINA_TRUE;
3311 }
3312
3313 EAPI void
3314 elm_widget_domain_translatable_part_text_set(Evas_Object *obj,
3315                                              const char *part,
3316                                              const char *domain,
3317                                              const char *label)
3318 {
3319    API_ENTRY return;
3320
3321    if (!_translatable_part_text_set(&sd->translate_strings, part, domain,
3322                                     label)) return;
3323 #ifdef HAVE_GETTEXT
3324    if (label && label[0])
3325      label = dgettext(domain, label);
3326 #endif
3327    elm_widget_text_part_set(obj, part, label);
3328 }
3329
3330 static const char *
3331 _translatable_part_text_get(Eina_List *translate_strings, const char *part)
3332 {
3333    Elm_Translate_String_Data *ts;
3334    const char*ret = NULL, *str;
3335    Eina_List *l;
3336
3337    str = eina_stringshare_add(part);
3338    EINA_LIST_FOREACH(translate_strings, l, ts)
3339      if (ts->id == str)
3340        {
3341           ret = ts->string;
3342           break;
3343        }
3344    eina_stringshare_del(str);
3345
3346    return ret;
3347 }
3348
3349 EAPI const char *
3350 elm_widget_translatable_part_text_get(const Evas_Object *obj,
3351                                       const char *part)
3352 {
3353    API_ENTRY return NULL;
3354    return _translatable_part_text_get(sd->translate_strings, part);
3355 }
3356
3357 EAPI void
3358 elm_widget_translate(Evas_Object *obj)
3359 {
3360    const Eina_List *l;
3361    Evas_Object *child;
3362 #ifdef HAVE_GETTEXT
3363    Elm_Translate_String_Data *ts;
3364 #endif
3365
3366    API_ENTRY return;
3367
3368    EINA_LIST_FOREACH(sd->subobjs, l, child)
3369      elm_widget_translate(child);
3370    if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
3371    if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
3372    if (!sd->api) return;
3373    sd->api->translate(obj);
3374
3375 #ifdef HAVE_GETTEXT
3376    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
3377      {
3378         const char *s = dgettext(ts->domain, ts->string);
3379         elm_widget_text_part_set(obj, ts->id, s);
3380      }
3381 #endif
3382 }
3383
3384 EAPI void
3385 elm_widget_content_part_set(Evas_Object *obj,
3386                             const char *part,
3387                             Evas_Object *content)
3388 {
3389    API_ENTRY return;
3390
3391    if (!sd->api) return;
3392    if (evas_object_smart_type_check(obj, "elm_container"))
3393      ELM_CONTAINER_CLASS(sd->api)->content_set(obj, part, content);
3394 }
3395
3396 EAPI Evas_Object *
3397 elm_widget_content_part_get(const Evas_Object *obj,
3398                             const char *part)
3399 {
3400    API_ENTRY return NULL;
3401
3402    if (!sd->api) return NULL;
3403
3404    if (evas_object_smart_type_check(obj, "elm_container"))
3405      return ELM_CONTAINER_CLASS(sd->api)->content_get(obj, part);
3406
3407    return NULL;
3408 }
3409
3410 EAPI Evas_Object *
3411 elm_widget_content_part_unset(Evas_Object *obj,
3412                               const char *part)
3413 {
3414    API_ENTRY return NULL;
3415
3416    if (!sd->api) return NULL;
3417    if (evas_object_smart_type_check(obj, "elm_container"))
3418      return ELM_CONTAINER_CLASS(sd->api)->content_unset(obj, part);
3419
3420    return NULL;
3421 }
3422
3423 EAPI void
3424 elm_widget_access_info_set(Evas_Object *obj,
3425                            const char *txt)
3426 {
3427    API_ENTRY return;
3428    if (sd->access_info) eina_stringshare_del(sd->access_info);
3429    if (!txt) sd->access_info = NULL;
3430    else sd->access_info = eina_stringshare_add(txt);
3431 }
3432
3433 EAPI const char *
3434 elm_widget_access_info_get(const Evas_Object *obj)
3435 {
3436    API_ENTRY return NULL;
3437    return sd->access_info;
3438 }
3439
3440 EAPI Elm_Theme *
3441 elm_widget_theme_get(const Evas_Object *obj)
3442 {
3443    API_ENTRY return NULL;
3444    if (!sd->theme)
3445      {
3446         if (sd->parent_obj)
3447           return elm_widget_theme_get(sd->parent_obj);
3448         else
3449           return NULL;
3450      }
3451    return sd->theme;
3452 }
3453
3454 EAPI Eina_Bool
3455 elm_widget_style_set(Evas_Object *obj,
3456                      const char *style)
3457 {
3458    API_ENTRY return EINA_FALSE;
3459
3460    if (eina_stringshare_replace(&sd->style, style))
3461      return elm_widget_theme(obj);
3462
3463    return EINA_TRUE;
3464 }
3465
3466 EAPI const char *
3467 elm_widget_style_get(const Evas_Object *obj)
3468 {
3469    API_ENTRY return NULL;
3470    if (sd->style) return sd->style;
3471    return "default";
3472 }
3473
3474 EAPI void
3475 elm_widget_tooltip_add(Evas_Object *obj,
3476                        Elm_Tooltip *tt)
3477 {
3478    API_ENTRY return;
3479    sd->tooltips = eina_list_append(sd->tooltips, tt);
3480 }
3481
3482 EAPI void
3483 elm_widget_tooltip_del(Evas_Object *obj,
3484                        Elm_Tooltip *tt)
3485 {
3486    API_ENTRY return;
3487    sd->tooltips = eina_list_remove(sd->tooltips, tt);
3488 }
3489
3490 EAPI void
3491 elm_widget_cursor_add(Evas_Object *obj,
3492                       Elm_Cursor *cur)
3493 {
3494    API_ENTRY return;
3495    sd->cursors = eina_list_append(sd->cursors, cur);
3496 }
3497
3498 EAPI void
3499 elm_widget_cursor_del(Evas_Object *obj,
3500                       Elm_Cursor *cur)
3501 {
3502    API_ENTRY return;
3503    sd->cursors = eina_list_remove(sd->cursors, cur);
3504 }
3505
3506 EAPI void
3507 elm_widget_drag_lock_x_set(Evas_Object *obj,
3508                            Eina_Bool lock)
3509 {
3510    API_ENTRY return;
3511    if (sd->drag_x_locked == lock) return;
3512    sd->drag_x_locked = lock;
3513    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
3514    else _propagate_x_drag_lock(obj, -1);
3515 }
3516
3517 EAPI void
3518 elm_widget_drag_lock_y_set(Evas_Object *obj,
3519                            Eina_Bool lock)
3520 {
3521    API_ENTRY return;
3522    if (sd->drag_y_locked == lock) return;
3523    sd->drag_y_locked = lock;
3524    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
3525    else _propagate_y_drag_lock(obj, -1);
3526 }
3527
3528 EAPI Eina_Bool
3529 elm_widget_drag_lock_x_get(const Evas_Object *obj)
3530 {
3531    API_ENTRY return EINA_FALSE;
3532    return sd->drag_x_locked;
3533 }
3534
3535 EAPI Eina_Bool
3536 elm_widget_drag_lock_y_get(const Evas_Object *obj)
3537 {
3538    API_ENTRY return EINA_FALSE;
3539    return sd->drag_y_locked;
3540 }
3541
3542 EAPI int
3543 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
3544 {
3545    API_ENTRY return 0;
3546    return sd->child_drag_x_locked;
3547 }
3548
3549 EAPI int
3550 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
3551 {
3552    API_ENTRY return 0;
3553    return sd->child_drag_y_locked;
3554 }
3555
3556 EAPI Eina_Bool
3557 elm_widget_theme_object_set(Evas_Object *obj,
3558                             Evas_Object *edj,
3559                             const char *wname,
3560                             const char *welement,
3561                             const char *wstyle)
3562 {
3563    API_ENTRY return EINA_FALSE;
3564    char buf[128];
3565
3566    if (!_elm_theme_object_set(obj, edj, wname, welement, wstyle))
3567      return EINA_FALSE;
3568
3569    if (sd->orient_mode != -1)
3570      {
3571
3572         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
3573         elm_widget_signal_emit(obj, buf, "elm");
3574
3575      }
3576    return EINA_TRUE;
3577 }
3578
3579 EAPI Eina_Bool
3580 elm_widget_is_check(const Evas_Object *obj)
3581 {
3582    static int abort_on_warn = -1;
3583    if (elm_widget_is(obj))
3584      return EINA_TRUE;
3585
3586    ERR("Passing Object: %p.", obj);
3587    if (abort_on_warn == -1)
3588      {
3589         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3590         else abort_on_warn = 0;
3591      }
3592    if (abort_on_warn == 1) abort();
3593    return EINA_FALSE;
3594 }
3595
3596 EAPI const char *
3597 elm_widget_type_get(const Evas_Object *obj)
3598 {
3599    API_ENTRY return NULL;
3600
3601    return evas_object_type_get(obj);
3602 }
3603
3604 EAPI Eina_Bool
3605 elm_widget_type_check(const Evas_Object *obj,
3606                       const char *type,
3607                       const char *func)
3608 {
3609    const char *provided, *expected = "(unknown)";
3610    static int abort_on_warn = -1;
3611
3612    provided = elm_widget_type_get(obj);
3613    /* TODO: eventually migrate to check_ptr version */
3614    if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
3615    if (type) expected = type;
3616    if ((!provided) || (!provided[0]))
3617      {
3618         provided = evas_object_type_get(obj);
3619         if ((!provided) || (!provided[0]))
3620           provided = "(unknown)";
3621      }
3622    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
3623        " type: '%s'", obj, func, provided, expected);
3624    if (abort_on_warn == -1)
3625      {
3626         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3627         else abort_on_warn = 0;
3628      }
3629    if (abort_on_warn == 1) abort();
3630    return EINA_FALSE;
3631 }
3632
3633 static Evas_Object *
3634 _widget_name_find(const Evas_Object *obj,
3635                   const char *name,
3636                   int recurse)
3637 {
3638    Eina_List *l;
3639    Evas_Object *child;
3640    const char *s;
3641    INTERNAL_ENTRY NULL;
3642
3643    if (!_elm_widget_is(obj)) return NULL;
3644    if (sd->resize_obj)
3645      {
3646         s = evas_object_name_get(sd->resize_obj);
3647         if ((s) && (!strcmp(s, name))) return sd->resize_obj;
3648         if ((recurse != 0) &&
3649             ((child = _widget_name_find(sd->resize_obj, name, recurse - 1))))
3650           return child;
3651      }
3652    EINA_LIST_FOREACH(sd->subobjs, l, child)
3653      {
3654         s = evas_object_name_get(child);
3655         if ((s) && (!strcmp(s, name))) return child;
3656         if ((recurse != 0) &&
3657             ((child = _widget_name_find(child, name, recurse - 1))))
3658           return child;
3659      }
3660    if (sd->hover_obj)
3661      {
3662         s = evas_object_name_get(sd->hover_obj);
3663         if ((s) && (!strcmp(s, name))) return sd->hover_obj;
3664         if ((recurse != 0) &&
3665             ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
3666           return child;
3667      }
3668    return NULL;
3669 }
3670
3671 EAPI Evas_Object *
3672 elm_widget_name_find(const Evas_Object *obj,
3673                      const char *name,
3674                      int recurse)
3675 {
3676    API_ENTRY return NULL;
3677    if (!name) return NULL;
3678    return _widget_name_find(obj, name, recurse);
3679 }
3680
3681 EAPI void
3682 elm_widget_orientation_mode_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3683 {
3684    int orient_mode = -1;
3685
3686    API_ENTRY return;
3687
3688    if (disabled && (sd->orient_mode == -1)) return;
3689    if (!disabled && (sd->orient_mode != -1)) return;
3690
3691    if (!disabled)
3692      {
3693         //Get current orient mode from it's parent otherwise, 0.
3694         sd->orient_mode = 0;
3695         ELM_WIDGET_DATA_GET(sd->parent_obj, sd_parent);
3696         if (!sd_parent) orient_mode = 0;
3697         else orient_mode = sd_parent->orient_mode;
3698      }
3699    elm_widget_orientation_set(obj, orient_mode);
3700 }
3701
3702 EAPI Eina_Bool
3703 elm_widget_orientation_mode_disabled_get(const Evas_Object *obj)
3704 {
3705    Eina_Bool ret;
3706
3707    API_ENTRY return EINA_FALSE;
3708
3709    if (sd->orient_mode == -1) ret = EINA_TRUE;
3710    else ret = EINA_FALSE;
3711    return ret;
3712 }
3713
3714 EAPI void
3715 elm_widget_orientation_set(Evas_Object *obj, int rotation)
3716 {
3717    Evas_Object *child;
3718    Eina_List *l;
3719
3720    API_ENTRY return;
3721
3722    if ((sd->orient_mode == rotation) || (sd->orient_mode == -1)) return;
3723
3724    sd->orient_mode = rotation;
3725
3726    EINA_LIST_FOREACH (sd->subobjs, l, child)
3727      elm_widget_orientation_set(child, rotation);
3728
3729    if (rotation != -1)
3730      {
3731         char buf[128];
3732         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
3733         elm_widget_signal_emit(obj, buf, "elm");
3734      }
3735 }
3736
3737 /**
3738  * @internal
3739  *
3740  * Split string in words
3741  *
3742  * @param str Source string
3743  * @return List of const words
3744  *
3745  * @see elm_widget_stringlist_free()
3746  * @ingroup Widget
3747  */
3748 EAPI Eina_List *
3749 elm_widget_stringlist_get(const char *str)
3750 {
3751    Eina_List *list = NULL;
3752    const char *s, *b;
3753    if (!str) return NULL;
3754    for (b = s = str; 1; s++)
3755      {
3756         if ((*s == ' ') || (!*s))
3757           {
3758              char *t = malloc(s - b + 1);
3759              if (t)
3760                {
3761                   strncpy(t, b, s - b);
3762                   t[s - b] = 0;
3763                   list = eina_list_append(list, eina_stringshare_add(t));
3764                   free(t);
3765                }
3766              b = s + 1;
3767           }
3768         if (!*s) break;
3769      }
3770    return list;
3771 }
3772
3773 EAPI void
3774 elm_widget_stringlist_free(Eina_List *list)
3775 {
3776    const char *s;
3777    EINA_LIST_FREE (list, s)
3778      eina_stringshare_del(s);
3779 }
3780
3781 EAPI void
3782 elm_widget_focus_hide_handle(Evas_Object *obj)
3783 {
3784    if (!_elm_widget_is(obj))
3785      return;
3786    _if_focused_revert(obj, EINA_TRUE);
3787 }
3788
3789 EAPI void
3790 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
3791 {
3792    Evas_Object *o = obj;
3793    do
3794      {
3795         if (_elm_widget_is(o)) break;
3796         o = evas_object_smart_parent_get(o);
3797      }
3798    while (o);
3799    if (!o) return;
3800    if (!_is_focusable(o)) return;
3801    elm_widget_focus_steal(o);
3802 }
3803
3804 EAPI void
3805 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
3806 {
3807    API_ENTRY return;
3808
3809    //FIXME: Need to check whether the object is unfocusable or not.
3810
3811    if (!elm_widget_parent_get(obj))
3812      elm_widget_focused_object_clear(obj);
3813    else
3814      _if_focused_revert(obj, EINA_TRUE);
3815 }
3816
3817 EAPI void
3818 elm_widget_focus_disabled_handle(Evas_Object *obj)
3819 {
3820    API_ENTRY return;
3821
3822    elm_widget_focus_tree_unfocusable_handle(obj);
3823 }
3824
3825 EAPI unsigned int
3826 elm_widget_focus_order_get(const Evas_Object *obj)
3827 {
3828    API_ENTRY return 0;
3829    return sd->focus_order;
3830 }
3831
3832 EAPI Evas_Object *
3833 elm_widget_newest_focus_order_get(const Evas_Object *obj,
3834                                   unsigned int *newest_focus_order,
3835                                   Eina_Bool can_focus_only)
3836 {
3837    const Eina_List *l;
3838    Evas_Object *child, *ret, *best;
3839
3840    API_ENTRY return NULL;
3841
3842    if (!evas_object_visible_get(obj)
3843        || (elm_widget_disabled_get(obj))
3844        || (elm_widget_tree_unfocusable_get(obj)))
3845      return NULL;
3846
3847    best = NULL;
3848    if (*newest_focus_order < sd->focus_order)
3849      {
3850         *newest_focus_order = sd->focus_order;
3851         best = (Evas_Object *)obj;
3852      }
3853    EINA_LIST_FOREACH(sd->subobjs, l, child)
3854      {
3855         ret = elm_widget_newest_focus_order_get
3856            (child, newest_focus_order, can_focus_only);
3857         if (!ret) continue;
3858         best = ret;
3859      }
3860    if (can_focus_only)
3861      {
3862         if ((!best) || (!elm_widget_can_focus_get(best)))
3863           return NULL;
3864      }
3865    return best;
3866 }
3867
3868 EAPI void
3869 elm_widget_activate(Evas_Object *obj, Elm_Activate act)
3870 {
3871    Evas_Object *parent;
3872    Eina_Bool ret;
3873
3874    API_ENTRY return;
3875
3876    ret = EINA_FALSE;
3877    if (sd->api->activate)
3878      ret = sd->api->activate(obj, act);
3879
3880    if (ret) return;
3881
3882    parent = elm_widget_parent_get(obj);
3883    if (parent)
3884      elm_widget_activate(parent, act);
3885
3886    return;
3887 }
3888
3889 /**
3890  * @internal
3891  *
3892  * Returns the widget's Evas_Display_Mode
3893  *
3894  * @param obj The widget.
3895  * @return Evas_Display_Mode of the object.
3896  *
3897  * @see elm_widget_display_mode_set().
3898  * @ingroup Widget
3899  **/
3900 EAPI Evas_Display_Mode
3901 elm_widget_display_mode_get(const Evas_Object *obj)
3902 {
3903    Evas_Display_Mode new_mode;
3904    Evas_Object *parent;
3905
3906    API_ENTRY return EVAS_DISPLAY_MODE_NONE;
3907
3908    new_mode = evas_object_size_hint_display_mode_get(obj);
3909    parent = elm_widget_parent_get(obj);
3910
3911    if ((new_mode == EVAS_DISPLAY_MODE_INHERIT) && parent)
3912      return elm_widget_display_mode_get(parent);
3913    return new_mode;
3914
3915 }
3916
3917 /**
3918  * @internal
3919  *
3920  * Sets the widget and child widget's Evas_Display_Mode.
3921  *
3922  * @param obj The widget.
3923  * @param dispmode Evas_Display_Mode to set widget's mode.
3924  *
3925  * Widgets are resized by several reasons.
3926  * Evas_Display_Mode can help for widgets to get one more reason of resize.
3927  * For example, elm conform widget resizes it's contents when keypad state changed.
3928  * After keypad showing, conform widget can change child's Evas_Display_Mode.
3929  * @ingroup Widget
3930  */
3931 EAPI void
3932 elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode)
3933 {
3934    Evas_Display_Mode child_mode;
3935    Evas_Object *child;
3936    Eina_List *l;
3937
3938    API_ENTRY return;
3939
3940    if (elm_widget_display_mode_get(obj) == dispmode) return;
3941    evas_object_size_hint_display_mode_set(obj, dispmode);
3942
3943    //TODO: Need to deal with EVAS_DISPLAY_MODE_INHERIT efficiently.
3944    EINA_LIST_FOREACH (sd->subobjs, l, child)
3945      {
3946         child_mode = evas_object_size_hint_display_mode_get(child);
3947         if (child_mode != EVAS_DISPLAY_MODE_DONT_CHANGE)
3948           {
3949              elm_widget_display_mode_set(child, dispmode);
3950           }
3951      }
3952
3953 }
3954
3955 // TIZEN ONLY: temporary code. should be removed after eo is applied.
3956 EAPI void
3957 _elm_widget_orient_signal_emit(Evas_Object *obj)
3958 {
3959    ELM_WIDGET_DATA_GET(obj, sd);
3960    char buf[128];
3961    if (sd->orient_mode > 0)
3962      {
3963         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
3964         elm_widget_signal_emit(obj, buf, "elm");
3965      }
3966 }
3967
3968 /**
3969  * @internal
3970  *
3971  * Allocate a new Elm_Widget_Item-derived structure.
3972  *
3973  * The goal of this structure is to provide common ground for actions
3974  * that a widget item have, such as the owner widget, callback to
3975  * notify deletion, data pointer and maybe more.
3976  *
3977  * @param widget the owner widget that holds this item, must be an elm_widget!
3978  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
3979  *        be used to allocate memory.
3980  *
3981  * @return allocated memory that is already zeroed out, or NULL on errors.
3982  *
3983  * @see elm_widget_item_new() convenience macro.
3984  * @see elm_widget_item_del() to release memory.
3985  * @ingroup Widget
3986  */
3987 EAPI Elm_Widget_Item *
3988 _elm_widget_item_new(Evas_Object *widget,
3989                      size_t alloc_size)
3990 {
3991    if (!_elm_widget_is(widget))
3992      return NULL;
3993
3994    Elm_Widget_Item *item;
3995
3996    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
3997    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
3998
3999    item = calloc(1, alloc_size);
4000    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
4001
4002    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
4003    item->widget = widget;
4004    return item;
4005 }
4006
4007 EAPI void
4008 _elm_widget_item_free(Elm_Widget_Item *item)
4009 {
4010    Elm_Translate_String_Data *ts;
4011    Elm_Widget_Item_Signal_Data *wisd;
4012
4013    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4014
4015    if (item->del_func)
4016      item->del_func((void *)item->data, item->widget, item);
4017
4018    if (item->view)
4019      evas_object_del(item->view);
4020
4021    if (item->access_info)
4022      eina_stringshare_del(item->access_info);
4023
4024    EINA_LIST_FREE(item->signals, wisd)
4025      {
4026         eina_stringshare_del(wisd->emission);
4027         eina_stringshare_del(wisd->source);
4028         free(wisd);
4029      }
4030
4031    EINA_LIST_FREE(item->translate_strings, ts)
4032      {
4033         eina_stringshare_del(ts->id);
4034         eina_stringshare_del(ts->domain);
4035         eina_stringshare_del(ts->string);
4036         free(ts);
4037      }
4038
4039    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
4040    free(item);
4041 }
4042
4043 /**
4044  * @internal
4045  *
4046  * Releases widget item memory, calling back del_cb() if it exists.
4047  *
4048  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
4049  * to memory release. Note that elm_widget_item_pre_notify_del() calls
4050  * this function and then unset it, thus being useful for 2 step
4051  * cleanup whenever the del_cb may use any of the data that must be
4052  * deleted from item.
4053  *
4054  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
4055  * is presented!
4056  *
4057  * @param item a valid #Elm_Widget_Item to be deleted.
4058  * @see elm_widget_item_del() convenience macro.
4059  * @ingroup Widget
4060  */
4061 EAPI void
4062 _elm_widget_item_del(Elm_Widget_Item *item)
4063 {
4064    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4065    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4066    item->on_deletion = EINA_TRUE;
4067
4068    //Widget item delete callback
4069    if (item->del_pre_func)
4070      {
4071         if (item->del_pre_func((Elm_Object_Item *)item))
4072           _elm_widget_item_free(item);
4073      }
4074    else
4075      _elm_widget_item_free(item);
4076  }
4077
4078 /**
4079  * @internal
4080  *
4081  * Set the function to notify to widgets when item is being deleted by user.
4082  *
4083  * @param item a valid #Elm_Widget_Item to be notified
4084  * @see elm_widget_item_del_pre_hook_set() convenience macro.
4085  * @ingroup Widget
4086  */
4087 EAPI void
4088 _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item,
4089                                   Elm_Widget_Del_Pre_Cb func)
4090 {
4091    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4092    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4093    item->del_pre_func = func;
4094 }
4095
4096 /**
4097  * @internal
4098  *
4099  * Notify object will be deleted without actually deleting it.
4100  *
4101  * This function will callback Elm_Widget_Item::del_cb if it is set
4102  * and then unset it so it is not called twice (ie: from
4103  * elm_widget_item_del()).
4104  *
4105  * @param item a valid #Elm_Widget_Item to be notified
4106  * @see elm_widget_item_pre_notify_del() convenience macro.
4107  * @ingroup Widget
4108  */
4109 EAPI void
4110 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
4111 {
4112    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4113    if (!item->del_func) return;
4114    item->del_func((void *)item->data, item->widget, item);
4115    item->del_func = NULL;
4116 }
4117
4118 /**
4119  * @internal
4120  *
4121  * Set the function to notify when item is being deleted.
4122  *
4123  * This function will complain if there was a callback set already,
4124  * however it will set the new one.
4125  *
4126  * The callback will be called from elm_widget_item_pre_notify_del()
4127  * or elm_widget_item_del() will be called with:
4128  *   - data: the Elm_Widget_Item::data value.
4129  *   - obj: the Elm_Widget_Item::widget evas object.
4130  *   - event_info: the item being deleted.
4131  *
4132  * @param item a valid #Elm_Widget_Item to be notified
4133  * @see elm_widget_item_del_cb_set() convenience macro.
4134  * @ingroup Widget
4135  */
4136 EAPI void
4137 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
4138                             Evas_Smart_Cb func)
4139 {
4140    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4141    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4142
4143    if ((item->del_func) && (item->del_func != func))
4144      WRN("You're replacing a previously set del_cb %p of item %p with %p",
4145          item->del_func, item, func);
4146
4147    item->del_func = func;
4148 }
4149
4150 /**
4151  * @internal
4152  *
4153  * Retrieves owner widget of this item.
4154  *
4155  * @param item a valid #Elm_Widget_Item to get data from.
4156  * @return owner widget of this item.
4157  * @ingroup Widget
4158  */
4159 EAPI Evas_Object *
4160 _elm_widget_item_widget_get(const Elm_Widget_Item *item)
4161 {
4162    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4163    return item->widget;
4164 }
4165
4166 /**
4167  * @internal
4168  *
4169  * Set user-data in this item.
4170  *
4171  * User data may be used to identify this item or just store any
4172  * application data. It is automatically given as the first parameter
4173  * of the deletion notify callback.
4174  *
4175  * @param item a valid #Elm_Widget_Item to store data in.
4176  * @param data user data to store.
4177  * @see elm_widget_item_del_cb_set() convenience macro.
4178  * @ingroup Widget
4179  */
4180 EAPI void
4181 _elm_widget_item_data_set(Elm_Widget_Item *item,
4182                           const void *data)
4183 {
4184    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4185    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4186
4187    if ((item->data) && (item->data != data))
4188      DBG("Replacing item %p data %p with %p", item, item->data, data);
4189    item->data = data;
4190 }
4191
4192 /**
4193  * @internal
4194  *
4195  * Retrieves user-data of this item.
4196  *
4197  * @param item a valid #Elm_Widget_Item to get data from.
4198  * @see elm_widget_item_data_set()
4199  * @ingroup Widget
4200  */
4201 EAPI void *
4202 _elm_widget_item_data_get(const Elm_Widget_Item *item)
4203 {
4204    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4205    return (void *)item->data;
4206 }
4207
4208 EAPI void
4209 _elm_widget_item_disabled_set(Elm_Widget_Item *item,
4210                               Eina_Bool disabled)
4211 {
4212    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4213    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4214
4215    if (item->disabled == disabled) return;
4216    item->disabled = !!disabled;
4217    if (item->disable_func) item->disable_func(item);
4218 }
4219
4220 EAPI Eina_Bool
4221 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
4222 {
4223    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4224    return item->disabled;
4225 }
4226
4227 EAPI void
4228 _elm_widget_item_disable_hook_set(Elm_Widget_Item *item,
4229                                   Elm_Widget_Disable_Cb func)
4230 {
4231    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4232    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4233
4234    item->disable_func = func;
4235 }
4236
4237 EAPI void
4238 _elm_widget_item_domain_translatable_part_text_set(Elm_Widget_Item *item,
4239                                                    const char *part,
4240                                                    const char *domain,
4241                                                    const char *label)
4242 {
4243    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4244
4245    if (!_translatable_part_text_set(&item->translate_strings, part, domain,
4246                                     label)) return;
4247 #ifdef HAVE_GETTEXT
4248    if (label && label[0])
4249      label = dgettext(domain, label);
4250 #endif
4251    _elm_widget_item_part_text_set(item, part, label);
4252 }
4253
4254 EAPI const char *
4255 _elm_widget_item_translatable_part_text_get(const Elm_Widget_Item *item,
4256                                             const char *part)
4257 {
4258    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4259    return _translatable_part_text_get(item->translate_strings, part);
4260 }
4261
4262 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
4263
4264 struct _Elm_Widget_Item_Tooltip
4265 {
4266    Elm_Widget_Item            *item;
4267    Elm_Tooltip_Item_Content_Cb func;
4268    Evas_Smart_Cb               del_cb;
4269    const void                 *data;
4270 };
4271
4272 static Evas_Object *
4273 _elm_widget_item_tooltip_label_create(void *data,
4274                                       Evas_Object *obj __UNUSED__,
4275                                       Evas_Object *tooltip,
4276                                       void *item __UNUSED__)
4277 {
4278    Evas_Object *label = elm_label_add(tooltip);
4279    if (!label)
4280      return NULL;
4281    elm_object_style_set(label, "tooltip");
4282    elm_object_text_set(label, data);
4283    return label;
4284 }
4285
4286 static Evas_Object *
4287 _elm_widget_item_tooltip_trans_label_create(void *data,
4288                                             Evas_Object *obj __UNUSED__,
4289                                             Evas_Object *tooltip,
4290                                             void *item __UNUSED__)
4291 {
4292    Evas_Object *label = elm_label_add(tooltip);
4293    if (!label)
4294      return NULL;
4295    elm_object_style_set(label, "tooltip");
4296    elm_object_translatable_text_set(label, data);
4297    return label;
4298 }
4299
4300 static void
4301 _elm_widget_item_tooltip_label_del_cb(void *data,
4302                                       Evas_Object *obj __UNUSED__,
4303                                       void *event_info __UNUSED__)
4304 {
4305    eina_stringshare_del(data);
4306 }
4307
4308 /**
4309  * @internal
4310  *
4311  * Set the text to be shown in the widget item.
4312  *
4313  * @param item Target item
4314  * @param text The text to set in the content
4315  *
4316  * Setup the text as tooltip to object. The item can have only one tooltip,
4317  * so any previous tooltip data is removed.
4318  *
4319  * @ingroup Widget
4320  */
4321 EAPI void
4322 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
4323                                   const char *text)
4324 {
4325    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4326    EINA_SAFETY_ON_NULL_RETURN(text);
4327    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4328
4329    text = eina_stringshare_add(text);
4330    _elm_widget_item_tooltip_content_cb_set
4331      (item, _elm_widget_item_tooltip_label_create, text,
4332      _elm_widget_item_tooltip_label_del_cb);
4333 }
4334
4335 EAPI void
4336 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
4337                                                const char *text)
4338 {
4339    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4340    EINA_SAFETY_ON_NULL_RETURN(text);
4341    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4342
4343    text = eina_stringshare_add(text);
4344    _elm_widget_item_tooltip_content_cb_set
4345      (item, _elm_widget_item_tooltip_trans_label_create, text,
4346      _elm_widget_item_tooltip_label_del_cb);
4347 }
4348
4349 static Evas_Object *
4350 _elm_widget_item_tooltip_create(void *data,
4351                                 Evas_Object *obj,
4352                                 Evas_Object *tooltip)
4353 {
4354    Elm_Widget_Item_Tooltip *wit = data;
4355    return wit->func((void *)wit->data, obj, tooltip, wit->item);
4356 }
4357
4358 static void
4359 _elm_widget_item_tooltip_del_cb(void *data,
4360                                 Evas_Object *obj,
4361                                 void *event_info __UNUSED__)
4362 {
4363    Elm_Widget_Item_Tooltip *wit = data;
4364    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
4365    free(wit);
4366 }
4367
4368 /**
4369  * @internal
4370  *
4371  * Set the content to be shown in the tooltip item
4372  *
4373  * Setup the tooltip to item. The item can have only one tooltip,
4374  * so any previous tooltip data is removed. @p func(with @p data) will
4375  * be called every time that need show the tooltip and it should
4376  * return a valid Evas_Object. This object is then managed fully by
4377  * tooltip system and is deleted when the tooltip is gone.
4378  *
4379  * @param item the widget item being attached a tooltip.
4380  * @param func the function used to create the tooltip contents.
4381  * @param data what to provide to @a func as callback data/context.
4382  * @param del_cb called when data is not needed anymore, either when
4383  *        another callback replaces @func, the tooltip is unset with
4384  *        elm_widget_item_tooltip_unset() or the owner @a item
4385  *        dies. This callback receives as the first parameter the
4386  *        given @a data, and @c event_info is the item.
4387  *
4388  * @ingroup Widget
4389  */
4390 EAPI void
4391 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item,
4392                                         Elm_Tooltip_Item_Content_Cb func,
4393                                         const void *data,
4394                                         Evas_Smart_Cb del_cb)
4395 {
4396    Elm_Widget_Item_Tooltip *wit;
4397
4398    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
4399    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4400    if (!func)
4401      {
4402         _elm_widget_item_tooltip_unset(item);
4403         return;
4404      }
4405
4406    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
4407    if (!wit) goto error;
4408    wit->item = item;
4409    wit->func = func;
4410    wit->data = data;
4411    wit->del_cb = del_cb;
4412
4413    elm_object_sub_tooltip_content_cb_set
4414      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
4415      _elm_widget_item_tooltip_del_cb);
4416
4417    return;
4418
4419 error_noitem:
4420    if (del_cb) del_cb((void *)data, NULL, item);
4421    return;
4422 error:
4423    if (del_cb) del_cb((void *)data, item->widget, item);
4424 }
4425
4426 /**
4427  * @internal
4428  *
4429  * Unset tooltip from item
4430  *
4431  * @param item widget item to remove previously set tooltip.
4432  *
4433  * Remove tooltip from item. The callback provided as del_cb to
4434  * elm_widget_item_tooltip_content_cb_set() will be called to notify
4435  * it is not used anymore.
4436  *
4437  * @see elm_widget_item_tooltip_content_cb_set()
4438  *
4439  * @ingroup Widget
4440  */
4441 EAPI void
4442 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
4443 {
4444    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4445    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4446
4447    elm_object_tooltip_unset(item->view);
4448 }
4449
4450 /**
4451  * @internal
4452  *
4453  * Sets a different style for this item tooltip.
4454  *
4455  * @note before you set a style you should define a tooltip with
4456  *       elm_widget_item_tooltip_content_cb_set() or
4457  *       elm_widget_item_tooltip_text_set()
4458  *
4459  * @param item widget item with tooltip already set.
4460  * @param style the theme style to use (default, transparent, ...)
4461  *
4462  * @ingroup Widget
4463  */
4464 EAPI void
4465 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
4466                                    const char *style)
4467 {
4468    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4469    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4470
4471    elm_object_tooltip_style_set(item->view, style);
4472 }
4473
4474 EAPI Eina_Bool
4475 _elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item,
4476                                          Eina_Bool disable)
4477 {
4478    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4479    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
4480
4481    return elm_object_tooltip_window_mode_set(item->view, disable);
4482 }
4483
4484 EAPI Eina_Bool
4485 _elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item)
4486 {
4487    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4488    return elm_object_tooltip_window_mode_get(item->view);
4489 }
4490
4491 /**
4492  * @internal
4493  *
4494  * Get the style for this item tooltip.
4495  *
4496  * @param item widget item with tooltip already set.
4497  * @return style the theme style in use, defaults to "default". If the
4498  *         object does not have a tooltip set, then NULL is returned.
4499  *
4500  * @ingroup Widget
4501  */
4502 EAPI const char *
4503 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
4504 {
4505    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4506    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4507
4508    return elm_object_tooltip_style_get(item->view);
4509 }
4510
4511 EAPI void
4512 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
4513                             const char *cursor)
4514 {
4515    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4516    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4517
4518    elm_object_sub_cursor_set(item->view, item->widget, cursor);
4519 }
4520
4521 EAPI const char *
4522 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
4523 {
4524    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4525    return elm_object_cursor_get(item->view);
4526 }
4527
4528 EAPI void
4529 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
4530 {
4531    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4532    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4533
4534    elm_object_cursor_unset(item->view);
4535 }
4536
4537 /**
4538  * @internal
4539  *
4540  * Sets a different style for this item cursor.
4541  *
4542  * @note before you set a style you should define a cursor with
4543  *       elm_widget_item_cursor_set()
4544  *
4545  * @param item widget item with cursor already set.
4546  * @param style the theme style to use (default, transparent, ...)
4547  *
4548  * @ingroup Widget
4549  */
4550 EAPI void
4551 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
4552                                   const char *style)
4553 {
4554    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4555    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4556
4557    elm_object_cursor_style_set(item->view, style);
4558 }
4559
4560 /**
4561  * @internal
4562  *
4563  * Get the style for this item cursor.
4564  *
4565  * @param item widget item with cursor already set.
4566  * @return style the theme style in use, defaults to "default". If the
4567  *         object does not have a cursor set, then NULL is returned.
4568  *
4569  * @ingroup Widget
4570  */
4571 EAPI const char *
4572 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
4573 {
4574    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4575    return elm_object_cursor_style_get(item->view);
4576 }
4577
4578 /**
4579  * @internal
4580  *
4581  * Set if the cursor set should be searched on the theme or should use
4582  * the provided by the engine, only.
4583  *
4584  * @note before you set if should look on theme you should define a cursor
4585  * with elm_object_cursor_set(). By default it will only look for cursors
4586  * provided by the engine.
4587  *
4588  * @param item widget item with cursor already set.
4589  * @param engine_only boolean to define it cursors should be looked only
4590  * between the provided by the engine or searched on widget's theme as well.
4591  *
4592  * @ingroup Widget
4593  */
4594 EAPI void
4595 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
4596                                         Eina_Bool engine_only)
4597 {
4598    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4599    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4600
4601    elm_object_cursor_theme_search_enabled_set(item->view, engine_only);
4602 }
4603
4604 /**
4605  * @internal
4606  *
4607  * Get the cursor engine only usage for this item cursor.
4608  *
4609  * @param item widget item with cursor already set.
4610  * @return engine_only boolean to define it cursors should be looked only
4611  * between the provided by the engine or searched on widget's theme as well. If
4612  *         the object does not have a cursor set, then EINA_FALSE is returned.
4613  *
4614  * @ingroup Widget
4615  */
4616 EAPI Eina_Bool
4617 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
4618 {
4619    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4620    return elm_object_cursor_theme_search_enabled_get(item->view);
4621 }
4622
4623 EAPI void
4624 _elm_widget_item_part_content_set(Elm_Widget_Item *item,
4625                                   const char *part,
4626                                   Evas_Object *content)
4627 {
4628    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4629    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4630    if (!item->content_set_func)
4631      {
4632         ERR("%s does not support elm_object_item_part_content_set() API.",
4633             elm_widget_type_get(item->widget));
4634         return;
4635      }
4636    item->content_set_func((Elm_Object_Item *)item, part, content);
4637 }
4638
4639 EAPI Evas_Object *
4640 _elm_widget_item_part_content_get(const Elm_Widget_Item *item,
4641                                   const char *part)
4642 {
4643    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4644    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4645
4646    return item->content_get_func((Elm_Object_Item *)item, part);
4647 }
4648
4649 EAPI Evas_Object *
4650 _elm_widget_item_part_content_unset(Elm_Widget_Item *item,
4651                                     const char *part)
4652 {
4653    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4654    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4655    if (!item->content_unset_func)
4656      {
4657         ERR("%s does not support elm_object_item_part_content_unset() API.",
4658             elm_widget_type_get(item->widget));
4659         return NULL;
4660      }
4661
4662    return item->content_unset_func((Elm_Object_Item *)item, part);
4663 }
4664
4665 EAPI void
4666 _elm_widget_item_part_text_set(Elm_Widget_Item *item,
4667                                const char *part,
4668                                const char *label)
4669 {
4670    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4671    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4672    if (!item->text_set_func)
4673      {
4674         ERR("%s does not support elm_object_item_part_text_set() API.",
4675             elm_widget_type_get(item->widget));
4676         return;
4677      }
4678
4679    item->text_set_func((Elm_Object_Item *)item, part, label);
4680 }
4681
4682 EAPI const char *
4683 _elm_widget_item_part_text_get(const Elm_Widget_Item *item,
4684                                const char *part)
4685 {
4686    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4687    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4688    if (!item->text_get_func)
4689      {
4690         ERR("%s does not support elm_object_item_part_text_get() API.",
4691             elm_widget_type_get(item->widget));
4692         return NULL;
4693      }
4694
4695    return item->text_get_func((Elm_Object_Item *)item, part);
4696 }
4697
4698 EAPI void
4699 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
4700                                       Elm_Widget_Content_Set_Cb func)
4701 {
4702    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4703    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4704
4705    item->content_set_func = func;
4706 }
4707
4708 EAPI void
4709 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
4710                                       Elm_Widget_Content_Get_Cb func)
4711 {
4712    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4713    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4714
4715    item->content_get_func = func;
4716 }
4717
4718 EAPI void
4719 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
4720                                         Elm_Widget_Content_Unset_Cb func)
4721 {
4722    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4723    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4724
4725    item->content_unset_func = func;
4726 }
4727
4728 EAPI void
4729 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
4730                                    Elm_Widget_Text_Set_Cb func)
4731 {
4732    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4733    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4734
4735    item->text_set_func = func;
4736 }
4737
4738 EAPI void
4739 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
4740                                    Elm_Widget_Text_Get_Cb func)
4741 {
4742    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4743    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4744
4745    item->text_get_func = func;
4746 }
4747
4748 EAPI void
4749 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
4750                              const char *emission,
4751                              const char *source)
4752 {
4753    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4754    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4755
4756    if (item->signal_emit_func)
4757      item->signal_emit_func((Elm_Object_Item *)item, emission, source);
4758 }
4759
4760 EAPI void
4761 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
4762                                       Elm_Widget_Signal_Emit_Cb func)
4763 {
4764    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4765    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4766
4767    item->signal_emit_func = func;
4768 }
4769
4770
4771 static void
4772 _elm_widget_item_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission,
4773                            const char *source)
4774 {
4775    Elm_Widget_Item_Signal_Data *wisd = data;
4776    wisd->func(wisd->data, wisd->item, emission, source);
4777 }
4778
4779 EAPI void
4780 _elm_widget_item_signal_callback_add(Elm_Widget_Item *item,
4781                                      const char *emission,
4782                                      const char *source,
4783                                      Elm_Widget_Item_Signal_Cb func,
4784                                      void *data)
4785 {
4786    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4787    EINA_SAFETY_ON_NULL_RETURN(func);
4788
4789    Elm_Widget_Item_Signal_Data *wisd;
4790
4791    wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
4792    if (!wisd) return;
4793
4794    wisd->item = item;
4795    wisd->func = func;
4796    wisd->data = data;
4797    wisd->emission = eina_stringshare_add(emission);
4798    wisd->source = eina_stringshare_add(source);
4799
4800    if (_elm_widget_is(item->view))
4801      elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
4802    else if (!strcmp(evas_object_type_get(item->view), "edje"))
4803      edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
4804    else
4805      {
4806         WRN("The %s widget item doesn't support signal callback add!",
4807             evas_object_type_get(item->widget));
4808         free(wisd);
4809         return;
4810      }
4811
4812    item->signals = eina_list_append(item->signals, wisd);
4813 }
4814
4815 EAPI void *
4816 _elm_widget_item_signal_callback_del(Elm_Widget_Item *item,
4817                                     const char *emission,
4818                                     const char *source,
4819                                     Elm_Widget_Item_Signal_Cb func)
4820 {
4821    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4822    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
4823
4824    Elm_Widget_Item_Signal_Data *wisd;
4825    Eina_List *l;
4826    void *data = NULL;
4827
4828    EINA_LIST_FOREACH(item->signals, l, wisd)
4829      {
4830         if ((wisd->func == func) && !strcmp(wisd->emission, emission) &&
4831             !strcmp(wisd->source, source))
4832           {
4833              item->signals = eina_list_remove_list(item->signals, l);
4834              eina_stringshare_del(wisd->emission);
4835              eina_stringshare_del(wisd->source);
4836              data = wisd->data;
4837
4838              if (_elm_widget_is(item->view))
4839                elm_object_signal_callback_del(item->view, emission, source,
4840                                               _elm_widget_item_signal_cb);
4841              else if (!strcmp(evas_object_type_get(item->view), "edje"))
4842                edje_object_signal_callback_del_full(item->view, emission,
4843                                                     source,
4844                                                     _elm_widget_item_signal_cb,
4845                                                     data);
4846           }
4847      }
4848
4849    return data;
4850 }
4851
4852 EAPI void
4853 _elm_widget_item_access_info_set(Elm_Widget_Item *item,
4854                                  const char *txt)
4855 {
4856    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4857    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4858
4859    if (item->access_info) eina_stringshare_del(item->access_info);
4860    if (!txt) item->access_info = NULL;
4861    else item->access_info = eina_stringshare_add(txt);
4862 }
4863
4864 /* happy debug functions */
4865 #ifdef ELM_DEBUG
4866 static void
4867 _sub_obj_tree_dump(const Evas_Object *obj,
4868                    int lvl)
4869 {
4870    int i;
4871
4872    for (i = 0; i < lvl * 3; i++)
4873      putchar(' ');
4874
4875    if (_elm_widget_is(obj))
4876      {
4877         Eina_List *l;
4878         INTERNAL_ENTRY;
4879         printf("+ %s(%p)\n",
4880                elm_widget_type_get(obj),
4881                obj);
4882         if (sd->resize_obj)
4883           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
4884         EINA_LIST_FOREACH(sd->subobjs, l, obj)
4885           {
4886              if (obj != sd->resize_obj)
4887                _sub_obj_tree_dump(obj, lvl + 1);
4888           }
4889      }
4890    else
4891      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
4892 }
4893
4894 static void
4895 _sub_obj_tree_dot_dump(const Evas_Object *obj,
4896                        FILE *output)
4897 {
4898    if (!_elm_widget_is(obj))
4899      return;
4900    INTERNAL_ENTRY;
4901
4902    Eina_Bool visible = evas_object_visible_get(obj);
4903    Eina_Bool disabled = elm_widget_disabled_get(obj);
4904    Eina_Bool focused = elm_widget_focus_get(obj);
4905    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
4906
4907    if (sd->parent_obj)
4908      {
4909         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
4910
4911         if (focused)
4912           fprintf(output, ", style=bold");
4913
4914         if (!visible)
4915           fprintf(output, ", color=gray28");
4916
4917         fprintf(output, " ];\n");
4918      }
4919
4920    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
4921                    "disabled: %d|focused: %d/%d|focus order:%d}\"",
4922            obj, obj, elm_widget_type_get(obj),
4923            evas_object_name_get(obj), visible, disabled, focused, can_focus,
4924            sd->focus_order);
4925
4926    if (focused)
4927      fprintf(output, ", style=bold");
4928
4929    if (!visible)
4930      fprintf(output, ", fontcolor=gray28");
4931
4932    if ((disabled) || (!visible))
4933      fprintf(output, ", color=gray");
4934
4935    fprintf(output, " ];\n");
4936
4937    Eina_List *l;
4938    Evas_Object *o;
4939    EINA_LIST_FOREACH(sd->subobjs, l, o)
4940      _sub_obj_tree_dot_dump(o, output);
4941 }
4942
4943 #endif
4944
4945 EAPI void
4946 elm_widget_tree_dump(const Evas_Object *top)
4947 {
4948 #ifdef ELM_DEBUG
4949    if (!_elm_widget_is(top))
4950      return;
4951    _sub_obj_tree_dump(top, 0);
4952 #else
4953    (void)top;
4954    return;
4955 #endif
4956 }
4957
4958 EAPI void
4959 elm_widget_tree_dot_dump(const Evas_Object *top,
4960                          FILE *output)
4961 {
4962 #ifdef ELM_DEBUG
4963    if (!_elm_widget_is(top))
4964      return;
4965    fprintf(output, "graph " " { node [shape=record];\n");
4966    _sub_obj_tree_dot_dump(top, output);
4967    fprintf(output, "}\n");
4968 #else
4969    (void)top;
4970    (void)output;
4971    return;
4972 #endif
4973 }