commit cdceaf5792c82f970d38ad35f5928b1f7bcc8cf8
[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    const char *id;
31    const char *domain;
32    const char *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    else
1344      {
1345         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1346                                        _propagate_event);
1347         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1348                                        _propagate_event);
1349         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1350                                        _propagate_event);
1351      }
1352 }
1353
1354 EAPI Eina_Bool
1355 elm_widget_can_focus_get(const Evas_Object *obj)
1356 {
1357    API_ENTRY return EINA_FALSE;
1358    return sd->can_focus;
1359 }
1360
1361 EAPI Eina_Bool
1362 elm_widget_child_can_focus_get(const Evas_Object *obj)
1363 {
1364    API_ENTRY return EINA_FALSE;
1365    return sd->child_can_focus;
1366 }
1367
1368 /**
1369  * @internal
1370  *
1371  * This API makes the widget object and its children to be unfocusable.
1372  *
1373  * This API can be helpful for an object to be deleted.
1374  * When an object will be deleted soon, it and its children may not
1375  * want to get focus (by focus reverting or by other focus controls).
1376  * Then, just use this API before deleting.
1377  *
1378  * @param obj The widget root of sub-tree
1379  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1380  *
1381  * @ingroup Widget
1382  */
1383 EAPI void
1384 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1385                                 Eina_Bool tree_unfocusable)
1386 {
1387    API_ENTRY return;
1388
1389    tree_unfocusable = !!tree_unfocusable;
1390    if (sd->tree_unfocusable == tree_unfocusable) return;
1391    sd->tree_unfocusable = tree_unfocusable;
1392    elm_widget_focus_tree_unfocusable_handle(obj);
1393 }
1394
1395 /**
1396  * @internal
1397  *
1398  * This returns true, if the object sub-tree is unfocusable.
1399  *
1400  * @param obj The widget root of sub-tree
1401  * @return EINA_TRUE if the object sub-tree is unfocusable
1402  *
1403  * @ingroup Widget
1404  */
1405 EAPI Eina_Bool
1406 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1407 {
1408    API_ENTRY return EINA_FALSE;
1409    return sd->tree_unfocusable;
1410 }
1411
1412 /**
1413  * @internal
1414  *
1415  * Get the list of focusable child objects.
1416  *
1417  * This function retruns list of child objects which can get focus.
1418  *
1419  * @param obj The parent widget
1420  * @retrun list of focusable child objects.
1421  *
1422  * @ingroup Widget
1423  */
1424 EAPI Eina_List *
1425 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1426 {
1427    API_ENTRY return NULL;
1428
1429    const Eina_List *l;
1430    Eina_List *child_list = NULL;
1431    Evas_Object *child;
1432
1433    if (sd->subobjs)
1434      {
1435         EINA_LIST_FOREACH(sd->subobjs, l, child)
1436           {
1437              if ((elm_widget_can_focus_get(child)) &&
1438                  (evas_object_visible_get(child)) &&
1439                  (!elm_widget_disabled_get(child)))
1440                child_list = eina_list_append(child_list, child);
1441              else if (elm_widget_is(child))
1442                {
1443                   Eina_List *can_focus_list;
1444                   can_focus_list = elm_widget_can_focus_child_list_get(child);
1445                   if (can_focus_list)
1446                     child_list = eina_list_merge(child_list, can_focus_list);
1447                }
1448           }
1449      }
1450    return child_list;
1451 }
1452
1453 EAPI void
1454 elm_widget_highlight_ignore_set(Evas_Object *obj,
1455                                 Eina_Bool ignore)
1456 {
1457    API_ENTRY return;
1458    sd->highlight_ignore = !!ignore;
1459 }
1460
1461 EAPI Eina_Bool
1462 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1463 {
1464    API_ENTRY return EINA_FALSE;
1465    return sd->highlight_ignore;
1466 }
1467
1468 EAPI void
1469 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1470                                   Eina_Bool highlight)
1471 {
1472    API_ENTRY return;
1473    sd->highlight_in_theme = !!highlight;
1474    /* FIXME: if focused, it should switch from one mode to the other */
1475 }
1476
1477 EAPI Eina_Bool
1478 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1479 {
1480    API_ENTRY return EINA_FALSE;
1481    return sd->highlight_in_theme;
1482 }
1483
1484 EAPI Eina_Bool
1485 elm_widget_focus_get(const Evas_Object *obj)
1486 {
1487    API_ENTRY return EINA_FALSE;
1488    return sd->focused;
1489 }
1490
1491 EAPI Evas_Object *
1492 elm_widget_focused_object_get(const Evas_Object *obj)
1493 {
1494    const Evas_Object *subobj;
1495    const Eina_List *l;
1496    API_ENTRY return NULL;
1497
1498    if (!sd->focused) return NULL;
1499    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1500      {
1501         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1502         if (fobj) return fobj;
1503      }
1504    return (Evas_Object *)obj;
1505 }
1506
1507 EAPI Evas_Object *
1508 elm_widget_top_get(const Evas_Object *obj)
1509 {
1510    API_ENTRY return NULL;
1511    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1512    return (Evas_Object *)obj;
1513 }
1514
1515 EAPI Eina_Bool
1516 elm_widget_is(const Evas_Object *obj)
1517 {
1518    return _elm_widget_is(obj);
1519 }
1520
1521 EAPI Evas_Object *
1522 elm_widget_parent_widget_get(const Evas_Object *obj)
1523 {
1524    Evas_Object *parent;
1525
1526    if (_elm_widget_is(obj))
1527      {
1528         Elm_Widget_Smart_Data *sd = evas_object_smart_data_get(obj);
1529         if (!sd) return NULL;
1530         parent = sd->parent_obj;
1531      }
1532    else
1533      {
1534         parent = evas_object_data_get(obj, "elm-parent");
1535         if (!parent) parent = evas_object_smart_parent_get(obj);
1536      }
1537
1538    while (parent)
1539      {
1540         Evas_Object *elm_parent;
1541         if (_elm_widget_is(parent)) break;
1542         elm_parent = evas_object_data_get(parent, "elm-parent");
1543         if (elm_parent) parent = elm_parent;
1544         else parent = evas_object_smart_parent_get(parent);
1545      }
1546    return parent;
1547 }
1548
1549 EAPI Evas_Object *
1550 elm_widget_parent2_get(const Evas_Object *obj)
1551 {
1552    if (_elm_widget_is(obj))
1553      {
1554         Elm_Widget_Smart_Data *sd = evas_object_smart_data_get(obj);
1555         if (sd) return sd->parent2;
1556      }
1557    return NULL;
1558 }
1559
1560 EAPI void
1561 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1562 {
1563    API_ENTRY return;
1564    sd->parent2 = parent;
1565 }
1566
1567 EAPI void
1568 elm_widget_event_callback_add(Evas_Object *obj,
1569                               Elm_Event_Cb func,
1570                               const void *data)
1571 {
1572    API_ENTRY return;
1573    EINA_SAFETY_ON_NULL_RETURN(func);
1574    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1575    ecb->func = func;
1576    ecb->data = data;
1577    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1578 }
1579
1580 EAPI void *
1581 elm_widget_event_callback_del(Evas_Object *obj,
1582                               Elm_Event_Cb func,
1583                               const void *data)
1584 {
1585    API_ENTRY return NULL;
1586    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1587    Eina_List *l;
1588    Elm_Event_Cb_Data *ecd;
1589    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1590      if ((ecd->func == func) && (ecd->data == data))
1591        {
1592           free(ecd);
1593           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1594           return (void *)data;
1595        }
1596    return NULL;
1597 }
1598
1599 EAPI Eina_Bool
1600 elm_widget_event_propagate(Evas_Object *obj,
1601                            Evas_Callback_Type type,
1602                            void *event_info,
1603                            Evas_Event_Flags *event_flags)
1604 {
1605    API_ENTRY return EINA_FALSE; //TODO reduce.
1606
1607    if (!_elm_widget_is(obj)) return EINA_FALSE;
1608    Evas_Object *parent = obj;
1609    Elm_Event_Cb_Data *ecd;
1610    Eina_List *l, *l_prev;
1611
1612    while (parent &&
1613           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1614      {
1615         sd = evas_object_smart_data_get(parent);
1616         if ((!sd) || (!_elm_widget_is(obj)))
1617           return EINA_FALSE;  //Not Elm Widget
1618         if (!sd->api) return EINA_FALSE;
1619
1620         if (sd->api->event(parent, obj, type, event_info))
1621           return EINA_TRUE;
1622
1623         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1624           {
1625              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1626                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1627                return EINA_TRUE;
1628           }
1629         parent = sd->parent_obj;
1630      }
1631
1632    return EINA_FALSE;
1633 }
1634
1635 /**
1636  * @internal
1637  *
1638  * Set custom focus chain.
1639  *
1640  * This function i set one new and overwrite any previous custom focus chain
1641  * with the list of objects. The previous list will be deleted and this list
1642  * will be managed. After setted, don't modity it.
1643  *
1644  * @note On focus cycle, only will be evaluated children of this container.
1645  *
1646  * @param obj The container widget
1647  * @param objs Chain of objects to pass focus
1648  * @ingroup Widget
1649  */
1650 EAPI void
1651 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1652                                   Eina_List *objs)
1653 {
1654    API_ENTRY return;
1655
1656    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1657
1658    elm_widget_focus_custom_chain_unset(obj);
1659
1660    Eina_List *l;
1661    Evas_Object *o;
1662
1663    EINA_LIST_FOREACH(objs, l, o)
1664      {
1665         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1666                                        _elm_object_focus_chain_del_cb, sd);
1667      }
1668
1669    sd->focus_chain = objs;
1670 }
1671
1672 /**
1673  * @internal
1674  *
1675  * Get custom focus chain
1676  *
1677  * @param obj The container widget
1678  * @ingroup Widget
1679  */
1680 EAPI const Eina_List *
1681 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1682 {
1683    API_ENTRY return NULL;
1684    return (const Eina_List *)sd->focus_chain;
1685 }
1686
1687 /**
1688  * @internal
1689  *
1690  * Unset custom focus chain
1691  *
1692  * @param obj The container widget
1693  * @ingroup Widget
1694  */
1695 EAPI void
1696 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1697 {
1698    API_ENTRY return;
1699    Eina_List *l, *l_next;
1700    Evas_Object *o;
1701
1702    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1703      {
1704         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1705                                             _elm_object_focus_chain_del_cb, sd);
1706         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1707      }
1708 }
1709
1710 /**
1711  * @internal
1712  *
1713  * Append object to custom focus chain.
1714  *
1715  * @note If relative_child equal to NULL or not in custom chain, the object
1716  * will be added in end.
1717  *
1718  * @note On focus cycle, only will be evaluated children of this container.
1719  *
1720  * @param obj The container widget
1721  * @param child The child to be added in custom chain
1722  * @param relative_child The relative object to position the child
1723  * @ingroup Widget
1724  */
1725 EAPI void
1726 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1727                                      Evas_Object *child,
1728                                      Evas_Object *relative_child)
1729 {
1730    API_ENTRY return;
1731    EINA_SAFETY_ON_NULL_RETURN(child);
1732
1733    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1734
1735    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1736                                        _elm_object_focus_chain_del_cb, sd);
1737
1738    if (!relative_child)
1739      sd->focus_chain = eina_list_append(sd->focus_chain, child);
1740    else
1741      sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1742                                                  child, relative_child);
1743 }
1744
1745 /**
1746  * @internal
1747  *
1748  * Prepend object to custom focus chain.
1749  *
1750  * @note If relative_child equal to NULL or not in custom chain, the object
1751  * will be added in begin.
1752  *
1753  * @note On focus cycle, only will be evaluated children of this container.
1754  *
1755  * @param obj The container widget
1756  * @param child The child to be added in custom chain
1757  * @param relative_child The relative object to position the child
1758  * @ingroup Widget
1759  */
1760 EAPI void
1761 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1762                                       Evas_Object *child,
1763                                       Evas_Object *relative_child)
1764 {
1765    API_ENTRY return;
1766    EINA_SAFETY_ON_NULL_RETURN(child);
1767
1768    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1769
1770    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1771                                        _elm_object_focus_chain_del_cb, sd);
1772
1773    if (!relative_child)
1774      sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1775    else
1776      sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1777                                                   child, relative_child);
1778 }
1779
1780 /**
1781  * @internal
1782  *
1783  * Give focus to next object in object tree.
1784  *
1785  * Give focus to next object in focus chain of one object sub-tree.
1786  * If the last object of chain already have focus, the focus will go to the
1787  * first object of chain.
1788  *
1789  * @param obj The widget root of sub-tree
1790  * @param dir Direction to cycle the focus
1791  *
1792  * @ingroup Widget
1793  */
1794 EAPI void
1795 elm_widget_focus_cycle(Evas_Object *obj,
1796                        Elm_Focus_Direction dir)
1797 {
1798    Evas_Object *target = NULL;
1799    if (!_elm_widget_is(obj))
1800      return;
1801    elm_widget_focus_next_get(obj, dir, &target);
1802    if (target)
1803      {
1804         /* access */
1805         if (_elm_config->access_mode && _elm_access_read_mode_get())
1806           {
1807              _elm_access_highlight_set(target);
1808              _elm_widget_focus_region_show(target);
1809           }
1810         else elm_widget_focus_steal(target);
1811      }
1812 }
1813
1814 /**
1815  * @internal
1816  *
1817  * Give focus to near object(in object tree) in one direction.
1818  *
1819  * Give focus to near object(in object tree) in direction of current
1820  * focused object.  If none focusable object in given direction or
1821  * none focused object in object tree, the focus will not change.
1822  *
1823  * @param obj The reference widget
1824  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
1825  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
1826  * @return EINA_TRUE if focus is moved.
1827  *
1828  * @ingroup Widget
1829  */
1830 EAPI Eina_Bool
1831 elm_widget_focus_direction_go(Evas_Object *obj,
1832                               double degree)
1833 {
1834    Evas_Object *target = NULL;
1835    Evas_Object *current_focused = NULL;
1836    double weight = 0.0;
1837
1838    if (!_elm_widget_is(obj)) return EINA_FALSE;
1839    if (!elm_widget_focus_get(obj)) return EINA_FALSE;
1840
1841    current_focused = elm_widget_focused_object_get(obj);
1842
1843    if (elm_widget_focus_direction_get
1844          (obj, current_focused, degree, &target, &weight))
1845      {
1846         elm_widget_focus_steal(target);
1847         return EINA_TRUE;
1848      }
1849    return EINA_FALSE;
1850 }
1851
1852 static double
1853 _direction_weight_get(const Evas_Object *obj1,
1854                       const Evas_Object *obj2,
1855                       double degree)
1856 {
1857    Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
1858    double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
1859    double ax, ay, cx, cy;
1860    double weight = -1.0, g = 0.0;
1861
1862    if (obj1 == obj2) return 0.0;
1863
1864    degree -= 90.0;
1865    while (degree >= 360.0)
1866      degree -= 360.0;
1867    while (degree < 0.0)
1868      degree += 360.0;
1869
1870    evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
1871    cx = obj_x1 + (w1 / 2.0);
1872    cy = obj_y1 + (h1 / 2.0);
1873    evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
1874
1875    /* For overlapping cases. */
1876    if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2))
1877      return 0.0;
1878
1879    /* Change all points to relative one. */
1880    x1 = obj_x1 - cx;
1881    xx1 = x1 + w1;
1882    yy1 = obj_y1 - cy;
1883    yyy1 = yy1 + h1;
1884    x2 = obj_x2 - cx;
1885    xx2 = x2 + w2;
1886    yy2 = obj_y2 - cy;
1887    yyy2 = yy2 + h2;
1888
1889    /* Get crossing points (ax, ay) between obj1 and a line extending
1890     * to the direction of current degree. */
1891    if (degree == 0.0)
1892      {
1893         ax = xx1;
1894         ay = 0.0;
1895      }
1896    else if (degree == 90.0)
1897      {
1898         ax = 0.0;
1899         ay = yyy1;
1900      }
1901    else if (degree == 180.0)
1902      {
1903         ax = x1;
1904         ay = 0.0;
1905      }
1906    else if (degree == 270.0)
1907      {
1908         ax = 0.0;
1909         ay = yy1;
1910      }
1911    else
1912      {
1913         g = tan(degree * (M_PI / 180.0));
1914         if ((degree > 0.0) && (degree < 90.0))
1915           {
1916              ay = g * xx1;
1917              if (ay <= yyy1) ax = xx1;
1918              else
1919                {
1920                   ax = yyy1 / g;
1921                   ay = yyy1;
1922                }
1923           }
1924         else if ((degree > 90.0) && (degree < 180.0))
1925           {
1926              ay = g * x1;
1927              if (ay <= yyy1) ax = x1;
1928              else
1929                {
1930                   ax = yyy1 / g;
1931                   ay = yyy1;
1932                }
1933           }
1934         else if ((degree > 180.0) && (degree < 270.0))
1935           {
1936              ay = g * x1;
1937              if (ay >= yy1) ax = x1;
1938              else
1939                {
1940                   ax = yy1 / g;
1941                   ay = yy1;
1942                }
1943           }
1944         else
1945           {
1946              ay = g * xx1;
1947              if (ay >= yy1) ax = xx1;
1948              else
1949                {
1950                   ax = yy1 / g;
1951                   ay = yy1;
1952                }
1953           }
1954      }
1955
1956    /* Filter obj2, if it is not in the specific derection. */
1957    int i = 0;
1958    double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
1959    double t1, t2, u1, v1, u2, v2;
1960
1961    if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) ||
1962        (degree == 315.0))
1963      {
1964         u1 = 1.0;
1965         v1 = 0.0;
1966         u2 = 0.0;
1967         v2 = 1.0;
1968      }
1969    else
1970      {
1971         double g2 = tan((degree + 45.0) * (M_PI / 180.0));
1972         u1 = (-1.0 * g2);
1973         u2 = (1.0 / g2);
1974         v1 = v2 = 1.0;
1975      }
1976    t1 = (u1 * ax) + (v1 * ay);
1977    t2 = (u2 * ax) + (v2 * ay);
1978
1979 #define _R(x) (int)((x + 0.05) * 10.0)
1980
1981    if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) +
1982                                                             (v2 * yy2))) > 0))
1983      {
1984         rx[i] = x2;
1985         ry[i++] = yy2;
1986      }
1987    if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) +
1988                                                              (v2 * yyy2))) > 0))
1989      {
1990         rx[i] = x2;
1991         ry[i++] = yyy2;
1992      }
1993    if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) +
1994                                                              (v2 * yy2))) > 0))
1995      {
1996         rx[i] = xx2;
1997         ry[i++] = yy2;
1998      }
1999    if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) &&
2000        (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
2001      {
2002         rx[i] = xx2;
2003         ry[i++] = yyy2;
2004      }
2005    if (i == 0)
2006      {
2007         if (degree == 0.0)
2008           {
2009              if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2010           }
2011         else if (degree == 90.0)
2012           {
2013              if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2014           }
2015         else if (degree == 180.0)
2016           {
2017              if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2018           }
2019         else if (degree == 270.0)
2020           {
2021              if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2022           }
2023         else
2024           {
2025              if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
2026                {
2027                   if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0)))
2028                     return 0.0;
2029                }
2030              else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
2031                {
2032                   if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0)))
2033                     return 0.0;
2034                }
2035              else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2)
2036                                                            <= _R(xx2)))
2037                {
2038                   if (!((_R(ax * ((1.0 / g) * yy2)) > 0)
2039                         && (_R(ay * yy2) > 0)))
2040                     return 0.0;
2041                }
2042              else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) &&
2043                       (_R((1.0 / g) * yyy2) <= _R(xx2)))
2044                {
2045                   if (!((_R(ax * ((1.0 / g) * yyy2)) > 0)
2046                         && (_R(ay * yyy2) > 0))) return 0.0;
2047                }
2048              else return 0.0;
2049           }
2050      }
2051
2052    /* Calculate the weight for obj2. */
2053    if (degree == 0.0)
2054      {
2055         if (_R(xx1) > _R(x2)) weight = -1.0;
2056         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2057           weight = (x2 - xx1) * (x2 - xx1);
2058         else if (_R(yy2) > 0)
2059           weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
2060         else if (_R(yyy2) < 0)
2061           weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
2062         else weight = (x2 - xx1) * (x2 - xx1);
2063      }
2064    else if (degree == 90.0)
2065      {
2066         if (_R(yyy1) > _R(yy2)) weight = -1.0;
2067         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2068           weight = (yy2 - yyy1) * (yy2 - yyy1);
2069         else if (_R(x2) > 0)
2070           weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
2071         else if (_R(xx2) < 0)
2072           weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
2073         else weight = (yy2 - yyy1) * (yy2 - yyy1);
2074      }
2075    else if (degree == 180.0)
2076      {
2077         if (_R(x1) < _R(xx2)) weight = -1.0;
2078         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2079           weight = (x1 - xx2) * (x1 - xx2);
2080         else if (_R(yy2) > 0)
2081           weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
2082         else if (_R(yyy2) < 0)
2083           weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
2084         else weight = (x1 - xx2) * (x1 - xx2);
2085      }
2086    else if (degree == 270.0)
2087      {
2088         if (_R(yy1) < _R(yyy2)) weight = -1.0;
2089         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2090           weight = (yy1 - yyy2) * (yy1 - yyy2);
2091         else if (_R(x2) > 0)
2092           weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
2093         else if (_R(xx2) < 0)
2094           weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
2095         else weight = (yy1 - yyy2) * (yy1 - yyy2);
2096      }
2097    else
2098      {
2099         int j = 0, k = 0;
2100         double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
2101         double t_weight[4] = {-1.0, -1.0, -1.0, -1.0};
2102         if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
2103           {
2104              sx[j] = x2;
2105              sy[j] = g * x2;
2106              t_weight[j++] = ((ax - x2) * (ax - x2)) +
2107                ((ay - (g * x2)) * (ay - (g * x2)));
2108           }
2109         if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
2110           {
2111              sx[j] = xx2;
2112              sy[j] = g * xx2;
2113              t_weight[j++] = ((ax - xx2) * (ax - xx2)) +
2114                ((ay - (g * xx2)) * (ay - (g * xx2)));
2115           }
2116         if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
2117           {
2118              sx[j] = (1.0 / g) * yy2;
2119              sy[j] = yy2;
2120              t_weight[j++] =
2121                ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) +
2122                ((ay - yy2) * (ay - yy2));
2123           }
2124         if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2)
2125                                                  <= _R(xx2)))
2126           {
2127              sx[j] = (1.0 / g) * yyy2;
2128              sy[j] = yyy2;
2129              t_weight[j++] =
2130                ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) +
2131                ((ay - yyy2) * (ay - yyy2));
2132           }
2133
2134         if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) ||
2135                                      (_R(sy[0]) != _R(sy[1])))))
2136           {
2137              for (; k < j; k++)
2138                {
2139                   if (_R(t_weight[k]) == 0) return -1.0;
2140                   if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
2141                }
2142           }
2143         else
2144           {
2145              for (; k < i; k++)
2146                {
2147                   double ccx, ccy, t1_weight, x_diff, y_diff;
2148                   ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
2149                   ccy = g * ccx;
2150                   x_diff = rx[k] - ccx;
2151                   if (x_diff < 0) x_diff *= -1.0;
2152                   y_diff = ry[k] - ccy;
2153                   if (y_diff < 0) y_diff *= -1.0;
2154                   t1_weight =
2155                     (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
2156                     ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
2157                   if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
2158                     weight = t1_weight;
2159                }
2160           }
2161      }
2162    /* Return the current object's weight. */
2163    if (weight == -1.0) return 0.0;
2164    if (_R(weight) == 0) return -1.0;
2165
2166 #undef _R
2167
2168    return 1.0 / weight;
2169 }
2170
2171 /**
2172  * @internal
2173  *
2174  * Get near object in one direction of base object.
2175  *
2176  * Get near object(in the object sub-tree) in one direction of
2177  * base object. Return the near object by reference.
2178  * By initializing weight, you can filter objects locating far
2179  * from base object. If object is in the specific direction,
2180  * weight is (1/(distance^2)). If object is not exactly in one
2181  * direction, some penalty will be added.
2182  *
2183  * @param obj The widget root of sub-tree
2184  * @param base The base object of the direction
2185  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2186  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2187  * @param direction The near object in one direction
2188  * @param weight The weight is bigger when the object is located near
2189  * @return EINA_TRUE if near object is updated.
2190  *
2191  * @ingroup Widget
2192  */
2193 EAPI Eina_Bool
2194 elm_widget_focus_direction_get(const Evas_Object *obj,
2195                                const Evas_Object *base,
2196                                double degree,
2197                                Evas_Object **direction,
2198                                double *weight)
2199 {
2200    double c_weight;
2201
2202    API_ENTRY return EINA_FALSE;
2203
2204    /* -1 means the best was already decided. Don't need any more searching. */
2205    if (!direction || !weight || !base || (obj == base))
2206      return EINA_FALSE;
2207
2208    /* Ignore if disabled */
2209    if ((!evas_object_visible_get(obj))
2210        || (elm_widget_disabled_get(obj))
2211        || (elm_widget_tree_unfocusable_get(obj)))
2212      return EINA_FALSE;
2213
2214    if (!sd->api) return EINA_FALSE;
2215
2216    /* Try use hook */
2217    if (_elm_widget_focus_direction_manager_is(obj))
2218      return sd->api->focus_direction(obj, base, degree, direction, weight);
2219
2220    if (!elm_widget_can_focus_get(obj) || elm_widget_focus_get(obj))
2221      return EINA_FALSE;
2222
2223    c_weight = _direction_weight_get(base, obj, degree);
2224    if ((c_weight == -1.0) ||
2225        ((c_weight != 0.0) && (*weight != -1.0) &&
2226         ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
2227      {
2228         if ((int)(*weight * 1000000) == (int)(c_weight * 1000000))
2229           {
2230              Elm_Widget_Smart_Data *sd1 =
2231                evas_object_smart_data_get(*direction);
2232              if (sd1)
2233                {
2234                   if (sd->focus_order <= sd1->focus_order)
2235                     return EINA_FALSE;
2236                }
2237           }
2238         *direction = (Evas_Object *)obj;
2239         *weight = c_weight;
2240         return EINA_TRUE;
2241      }
2242    return EINA_FALSE;
2243 }
2244
2245 /**
2246  * @internal
2247  *
2248  * Get near object in one direction of base object in list.
2249  *
2250  * Get near object in one direction of base object in the specific
2251  * object list. Return the near object by reference.
2252  * By initializing weight, you can filter objects locating far
2253  * from base object. If object is in the specific direction,
2254  * weight is (1/(distance^2)). If object is not exactly in one
2255  * direction, some penalty will be added.
2256  *
2257  * @param obj The widget root of sub-tree
2258  * @param base The base object of the direction
2259  * @param items list with ordered objects
2260  * @param list_data_get function to get the object from one item of list
2261  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2262  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2263  * @param direction The near object in one direction
2264  * @param weight The weight is bigger when the object is located near
2265  * @return EINA_TRUE if near object is updated.
2266  *
2267  * @ingroup Widget
2268  */
2269 EAPI Eina_Bool
2270 elm_widget_focus_list_direction_get(const Evas_Object *obj,
2271                                     const Evas_Object *base,
2272                                     const Eina_List *items,
2273                                     void *(*list_data_get)(const Eina_List *l),
2274                                     double degree,
2275                                     Evas_Object **direction,
2276                                     double *weight)
2277 {
2278    API_ENTRY return EINA_FALSE;
2279    if (!direction || !weight || !base || !items)
2280      return EINA_FALSE;
2281
2282    const Eina_List *l = items;
2283    Evas_Object *current_best = *direction;
2284
2285    for (; l; l = eina_list_next(l))
2286      {
2287         Evas_Object *cur = list_data_get(l);
2288         elm_widget_focus_direction_get(cur, base, degree, direction, weight);
2289      }
2290    if (current_best != *direction)
2291      return EINA_TRUE;
2292    else
2293      return EINA_FALSE;
2294 }
2295
2296 /**
2297  * @internal
2298  *
2299  * Get next object in focus chain of object tree.
2300  *
2301  * Get next object in focus chain of one object sub-tree.
2302  * Return the next object by reference. If don't have any candidate to receive
2303  * focus before chain end, the first candidate will be returned.
2304  *
2305  * @param obj The widget root of sub-tree
2306  * @param dir Direction os focus chain
2307  * @param next The next object in focus chain
2308  * @return EINA_TRUE if don't need focus chain restart/loop back
2309  *         to use 'next' obj.
2310  *
2311  * @ingroup Widget
2312  */
2313 EAPI Eina_Bool
2314 elm_widget_focus_next_get(const Evas_Object *obj,
2315                           Elm_Focus_Direction dir,
2316                           Evas_Object **next)
2317 {
2318    if (!next)
2319      return EINA_FALSE;
2320    *next = NULL;
2321
2322    API_ENTRY return EINA_FALSE;
2323
2324    /* Ignore if disabled */
2325    if ((!evas_object_visible_get(obj))
2326        || (elm_widget_disabled_get(obj))
2327        || (elm_widget_tree_unfocusable_get(obj)))
2328      return EINA_FALSE;
2329
2330    if (!sd->api) return EINA_FALSE;
2331
2332    /* Try use hook */
2333    if (_elm_widget_focus_chain_manager_is(obj))
2334      {
2335         Eina_Bool ret;
2336         ret = sd->api->focus_next(obj, dir, next);
2337         if (!ret && elm_widget_focus_get(obj))
2338           {
2339              Evas_Object *o = NULL;
2340              if (dir == ELM_FOCUS_PREVIOUS)
2341                o = sd->focus_previous;
2342              else if (dir == ELM_FOCUS_NEXT)
2343                o = sd->focus_next;
2344              else if (dir == ELM_FOCUS_UP)
2345                o = sd->focus_up;
2346              else if (dir == ELM_FOCUS_DOWN)
2347                o = sd->focus_down;
2348              else if (dir == ELM_FOCUS_RIGHT)
2349                o = sd->focus_right;
2350              else if (dir == ELM_FOCUS_LEFT)
2351                o = sd->focus_left;
2352
2353              if (o)
2354                {
2355                   *next = o;
2356                   return EINA_TRUE;
2357                }
2358           }
2359         else
2360           return ret;
2361      }
2362
2363    if (!elm_widget_can_focus_get(obj))
2364      return EINA_FALSE;
2365
2366    /* focusable object but does not have access info */
2367    if (_elm_config->access_mode)
2368      {
2369         if (!_elm_access_object_get(obj)) return EINA_FALSE;
2370      }
2371
2372    if (elm_widget_focus_get(obj))
2373      {
2374         if (dir == ELM_FOCUS_PREVIOUS)
2375           *next = sd->focus_previous;
2376         else if (dir == ELM_FOCUS_NEXT)
2377           *next = sd->focus_next;
2378         else if (dir == ELM_FOCUS_UP)
2379           *next = sd->focus_up;
2380         else if (dir == ELM_FOCUS_DOWN)
2381           *next = sd->focus_down;
2382         else if (dir == ELM_FOCUS_RIGHT)
2383           *next = sd->focus_right;
2384         else if (dir == ELM_FOCUS_LEFT)
2385           *next = sd->focus_left;
2386
2387         if (*next)
2388           return EINA_TRUE;
2389      }
2390    /* Return */
2391    *next = (Evas_Object *)obj;
2392    return !ELM_WIDGET_FOCUS_GET(obj);
2393 }
2394
2395 /**
2396  * @internal
2397  *
2398  * Get next object in focus chain of object tree in list.
2399  *
2400  * Get next object in focus chain of one object sub-tree ordered by one list.
2401  * Return the next object by reference. If don't have any candidate to receive
2402  * focus before list end, the first candidate will be returned.
2403  *
2404  * @param obj The widget root of sub-tree
2405  * @param dir Direction os focus chain
2406  * @param items list with ordered objects
2407  * @param list_data_get function to get the object from one item of list
2408  * @param next The next object in focus chain
2409  * @return EINA_TRUE if don't need focus chain restart/loop back
2410  *         to use 'next' obj.
2411  *
2412  * @ingroup Widget
2413  */
2414 EAPI Eina_Bool
2415 elm_widget_focus_list_next_get(const Evas_Object *obj,
2416                                const Eina_List *items,
2417                                void *(*list_data_get)(const Eina_List *list),
2418                                Elm_Focus_Direction dir,
2419                                Evas_Object **next)
2420 {
2421    Eina_List *(*list_next)(const Eina_List *list) = NULL;
2422    Evas_Object *focused_object = NULL;
2423
2424    if (!next)
2425      return EINA_FALSE;
2426    *next = NULL;
2427
2428    if (!_elm_widget_is(obj))
2429      return EINA_FALSE;
2430
2431    if (!items)
2432      return EINA_FALSE;
2433
2434    /* When Up, Down, Right, or Left, try direction_get first. */
2435    focused_object = elm_widget_focused_object_get(obj);
2436    if (focused_object)
2437      {
2438         if((dir == ELM_FOCUS_UP)
2439            || (dir == ELM_FOCUS_DOWN)
2440            || (dir == ELM_FOCUS_RIGHT)
2441            || (dir == ELM_FOCUS_LEFT))
2442           {
2443              *next = elm_widget_focus_next_object_get(focused_object, dir);
2444              if (*next)
2445                return EINA_TRUE;
2446              else
2447                {
2448                   Evas_Object *n;
2449                   double degree;
2450                   double weight;
2451
2452                   if (dir == ELM_FOCUS_UP) degree = 0.0;
2453                   else if (dir == ELM_FOCUS_DOWN) degree = 180.0;
2454                   else if (dir == ELM_FOCUS_RIGHT) degree = 90.0;
2455                   else if (dir == ELM_FOCUS_LEFT) degree = 270.0;
2456
2457                   if (elm_widget_focus_list_direction_get(obj, focused_object,
2458                                                           items, list_data_get,
2459                                                           degree, &n, &weight))
2460                     {
2461                        *next = n;
2462                        return EINA_TRUE;
2463                     }
2464                }
2465           }
2466      }
2467
2468    /* Direction */
2469    if (dir == ELM_FOCUS_PREVIOUS)
2470      {
2471         items = eina_list_last(items);
2472         list_next = eina_list_prev;
2473      }
2474    else if ((dir == ELM_FOCUS_NEXT)
2475             || (dir == ELM_FOCUS_UP)
2476             || (dir == ELM_FOCUS_DOWN)
2477             || (dir == ELM_FOCUS_RIGHT)
2478             || (dir == ELM_FOCUS_LEFT))
2479      list_next = eina_list_next;
2480    else
2481      return EINA_FALSE;
2482
2483    const Eina_List *l = items;
2484
2485    /* Recovery last focused sub item */
2486    if (ELM_WIDGET_FOCUS_GET(obj))
2487      {
2488         for (; l; l = list_next(l))
2489           {
2490              Evas_Object *cur = list_data_get(l);
2491              if (ELM_WIDGET_FOCUS_GET(cur)) break;
2492           }
2493
2494          /* Focused object, but no focused sub item */
2495          if (!l) l = items;
2496      }
2497
2498    const Eina_List *start = l;
2499    Evas_Object *to_focus = NULL;
2500
2501    /* Interate sub items */
2502    /* Go to end of list */
2503    for (; l; l = list_next(l))
2504      {
2505         Evas_Object *tmp = NULL;
2506         Evas_Object *cur = list_data_get(l);
2507
2508         if (elm_widget_parent_get(cur) != obj)
2509           continue;
2510
2511         /* Try Focus cycle in subitem */
2512         if (elm_widget_focus_next_get(cur, dir, &tmp))
2513           {
2514              *next = tmp;
2515              return EINA_TRUE;
2516           }
2517         else if ((dir == ELM_FOCUS_UP)
2518                  || (dir == ELM_FOCUS_DOWN)
2519                  || (dir == ELM_FOCUS_RIGHT)
2520                  || (dir == ELM_FOCUS_LEFT))
2521           {
2522              if (tmp && elm_widget_focus_get(cur))
2523                {
2524                   *next = tmp;
2525                   return EINA_FALSE;
2526                }
2527           }
2528         else if ((tmp) && (!to_focus))
2529           to_focus = tmp;
2530      }
2531
2532    l = items;
2533
2534    /* Get First possible */
2535    for (; l != start; l = list_next(l))
2536      {
2537         Evas_Object *tmp = NULL;
2538         Evas_Object *cur = list_data_get(l);
2539
2540         if (elm_widget_parent_get(cur) != obj)
2541           continue;
2542
2543         /* Try Focus cycle in subitem */
2544         elm_widget_focus_next_get(cur, dir, &tmp);
2545         if (tmp)
2546           {
2547              *next = tmp;
2548              return EINA_FALSE;
2549           }
2550      }
2551
2552    *next = to_focus;
2553    return EINA_FALSE;
2554 }
2555
2556
2557 /**
2558  * @internal
2559  *
2560  * Get next object which was set with specific focus direction.
2561  *
2562  * Get next object which was set by elm_widget_focus_next_object_set
2563  * with specific focus directioin.
2564  *
2565  * @param obj The widget
2566  * @param dir Direction of focus
2567  * @return Widget which was registered with sepecific focus direction.
2568  *
2569  * @ingroup Widget
2570  */
2571 EAPI Evas_Object *
2572 elm_widget_focus_next_object_get(const Evas_Object *obj, Elm_Focus_Direction dir)
2573 {
2574    API_ENTRY return NULL;
2575
2576    if (dir == ELM_FOCUS_PREVIOUS)
2577      return sd->focus_previous;
2578    else if (dir == ELM_FOCUS_NEXT)
2579      return sd->focus_next;
2580    else if (dir == ELM_FOCUS_UP)
2581      return sd->focus_up;
2582    else if (dir == ELM_FOCUS_DOWN)
2583      return sd->focus_down;
2584    else if (dir == ELM_FOCUS_RIGHT)
2585      return sd->focus_right;
2586    else if (dir == ELM_FOCUS_LEFT)
2587      return sd->focus_left;
2588
2589    return NULL;
2590 }
2591
2592 /**
2593  * @internal
2594  *
2595  * Set next object with specific focus direction.
2596  *
2597  * When a widget is set with specific focus direction, this widget will be
2598  * the first candidate when finding the next focus object.
2599  * Focus next object can be registered with six directions that are previous,
2600  * next, up, down, right, and left.
2601  *
2602  * @param obj The widget
2603  * @param next Next focus object
2604  * @param dir Direction of focus
2605  *
2606  * @ingroup Widget
2607  */
2608 EAPI void
2609 elm_widget_focus_next_object_set(Evas_Object *obj, Evas_Object *next, Elm_Focus_Direction dir)
2610 {
2611    API_ENTRY return;
2612
2613    if (dir == ELM_FOCUS_PREVIOUS)
2614      sd->focus_previous = next;
2615    else if (dir == ELM_FOCUS_NEXT)
2616      sd->focus_next = next;
2617    else if (dir == ELM_FOCUS_UP)
2618      sd->focus_up = next;
2619    else if (dir == ELM_FOCUS_DOWN)
2620      sd->focus_down = next;
2621    else if (dir == ELM_FOCUS_RIGHT)
2622      sd->focus_right = next;
2623    else if (dir == ELM_FOCUS_LEFT)
2624      sd->focus_left = next;
2625 }
2626
2627
2628 EAPI Eina_Bool
2629 elm_widget_highlight_get(const Evas_Object *obj)
2630 {
2631    API_ENTRY return EINA_FALSE;
2632    return sd->highlighted;
2633 }
2634
2635 EAPI void
2636 elm_widget_parent_highlight_set(Evas_Object *obj,
2637                                 Eina_Bool highlighted)
2638 {
2639    API_ENTRY return;
2640
2641    highlighted = !!highlighted;
2642
2643    Evas_Object *o = elm_widget_parent_get(obj);
2644
2645    if (o) elm_widget_parent_highlight_set(o, highlighted);
2646
2647    sd->highlighted = highlighted;
2648 }
2649
2650 EAPI void
2651 elm_widget_signal_emit(Evas_Object *obj,
2652                        const char *emission,
2653                        const char *source)
2654 {
2655    API_ENTRY return;
2656
2657    if (evas_object_smart_type_check(obj, "elm_layout"))
2658      elm_layout_signal_emit(obj, emission, source);
2659    else if (evas_object_smart_type_check(obj, "elm_icon"))
2660      {
2661         WRN("Deprecated function. This functionality on icon objects"
2662             " will be dropped on a next release.");
2663         _elm_icon_signal_emit(obj, emission, source);
2664      }
2665 }
2666
2667 EAPI void
2668 elm_widget_signal_callback_add(Evas_Object *obj,
2669                                const char *emission,
2670                                const char *source,
2671                                Edje_Signal_Cb func,
2672                                void *data)
2673 {
2674    API_ENTRY return;
2675
2676    EINA_SAFETY_ON_NULL_RETURN(func);
2677
2678    if (evas_object_smart_type_check(obj, "elm_layout"))
2679      elm_layout_signal_callback_add(obj, emission, source, func, data);
2680    else if (evas_object_smart_type_check(obj, "elm_icon"))
2681      {
2682         WRN("Deprecated function. This functionality on icon objects"
2683             " will be dropped on a next release.");
2684
2685         _elm_icon_signal_callback_add(obj, emission, source, func, data);
2686      }
2687 }
2688
2689 EAPI void *
2690 elm_widget_signal_callback_del(Evas_Object *obj,
2691                                const char *emission,
2692                                const char *source,
2693                                Edje_Signal_Cb func)
2694 {
2695    void *data = NULL;
2696
2697    API_ENTRY return NULL;
2698
2699    if (evas_object_smart_type_check(obj, "elm_layout"))
2700      data = elm_layout_signal_callback_del(obj, emission, source, func);
2701    else if (evas_object_smart_type_check(obj, "elm_icon"))
2702      {
2703         WRN("Deprecated function. This functionality on icon objects"
2704             " will be dropped on a next release.");
2705
2706         data = _elm_icon_signal_callback_del(obj, emission, source, func);
2707      }
2708
2709    return data;
2710 }
2711
2712 EAPI void
2713 elm_widget_focus_set(Evas_Object *obj,
2714                      int first)
2715 {
2716    API_ENTRY return;
2717
2718    if (!sd->api) return;
2719
2720    if (!sd->focused)
2721      {
2722         focus_order++;
2723         sd->focus_order = focus_order;
2724         sd->focused = EINA_TRUE;
2725         sd->api->on_focus(obj);
2726      }
2727
2728    if (first)
2729      {
2730         if ((_is_focusable(sd->resize_obj)) &&
2731             (!elm_widget_disabled_get(sd->resize_obj)))
2732           {
2733              elm_widget_focus_set(sd->resize_obj, first);
2734           }
2735         else
2736           {
2737              const Eina_List *l;
2738              Evas_Object *child;
2739
2740              EINA_LIST_FOREACH(sd->subobjs, l, child)
2741                {
2742                   if ((_is_focusable(child)) &&
2743                       (!elm_widget_disabled_get(child)))
2744                     {
2745                        elm_widget_focus_set(child, first);
2746                        break;
2747                     }
2748                }
2749           }
2750      }
2751    else
2752      {
2753         const Eina_List *l;
2754         Evas_Object *child;
2755
2756         EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
2757           {
2758              if ((_is_focusable(child)) &&
2759                  (!elm_widget_disabled_get(child)))
2760                {
2761                   elm_widget_focus_set(child, first);
2762                   break;
2763                }
2764           }
2765         if (!l)
2766           {
2767              if ((_is_focusable(sd->resize_obj)) &&
2768                  (!elm_widget_disabled_get(sd->resize_obj)))
2769                {
2770                   elm_widget_focus_set(sd->resize_obj, first);
2771                }
2772           }
2773      }
2774 }
2775
2776 EAPI Evas_Object *
2777 elm_widget_parent_get(const Evas_Object *obj)
2778 {
2779    API_ENTRY return NULL;
2780    return sd->parent_obj;
2781 }
2782
2783 EAPI void
2784 elm_widget_focused_object_clear(Evas_Object *obj)
2785 {
2786    API_ENTRY return;
2787
2788    if (!sd->api) return;
2789
2790    if (!sd->focused) return;
2791
2792    // FIXME: evas_object_ref/unref is temporary code to fix logical issue.
2793    // After Eo is applied to elementary, remove these.
2794    evas_object_ref(obj);
2795    if (sd->resize_obj && elm_widget_focus_get(sd->resize_obj))
2796      elm_widget_focused_object_clear(sd->resize_obj);
2797    else
2798      {
2799         const Eina_List *l;
2800         Evas_Object *child;
2801         EINA_LIST_FOREACH(sd->subobjs, l, child)
2802           {
2803              if (elm_widget_focus_get(child))
2804                {
2805                   elm_widget_focused_object_clear(child);
2806                   break;
2807                }
2808           }
2809      }
2810    sd->focused = EINA_FALSE;
2811    sd->api->on_focus(obj);
2812    evas_object_unref(obj);
2813 }
2814
2815 EAPI void
2816 elm_widget_focus_steal(Evas_Object *obj)
2817 {
2818    Evas_Object *parent, *parent2, *o;
2819    API_ENTRY return;
2820
2821    if (sd->focused) return;
2822    if (sd->disabled) return;
2823    if (!sd->can_focus) return;
2824    if (sd->tree_unfocusable) return;
2825    parent = obj;
2826    for (;; )
2827      {
2828         o = elm_widget_parent_get(parent);
2829         if (!o) break;
2830         sd = evas_object_smart_data_get(o);
2831         if (sd->disabled || sd->tree_unfocusable) return;
2832         if (sd->focused) break;
2833         parent = o;
2834      }
2835    if ((!elm_widget_parent_get(parent)) &&
2836        (!elm_widget_parent2_get(parent)))
2837      elm_widget_focused_object_clear(parent);
2838    else
2839      {
2840         parent2 = elm_widget_parent_get(parent);
2841         if (!parent2) parent2 = elm_widget_parent2_get(parent);
2842         parent = parent2;
2843         sd = evas_object_smart_data_get(parent);
2844         if (sd)
2845           {
2846              if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
2847                elm_widget_focused_object_clear(sd->resize_obj);
2848              else
2849                {
2850                   const Eina_List *l;
2851                   Evas_Object *child;
2852                   EINA_LIST_FOREACH(sd->subobjs, l, child)
2853                     {
2854                        if (elm_widget_focus_get(child))
2855                          {
2856                             elm_widget_focused_object_clear(child);
2857                             break;
2858                          }
2859                     }
2860                }
2861           }
2862      }
2863    _parent_focus(obj);
2864    _elm_widget_focus_region_show(obj);
2865    return;
2866 }
2867
2868 EAPI void
2869 elm_widget_focus_restore(Evas_Object *obj)
2870 {
2871    Evas_Object *newest = NULL;
2872    unsigned int newest_focus_order = 0;
2873    API_ENTRY return;
2874
2875    newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2876    if (newest)
2877      {
2878         elm_object_focus_set(newest, EINA_FALSE);
2879         elm_object_focus_set(newest, EINA_TRUE);
2880      }
2881 }
2882
2883 void
2884 _elm_widget_top_win_focused_set(Evas_Object *obj,
2885                                 Eina_Bool top_win_focused)
2886 {
2887    const Eina_List *l;
2888    Evas_Object *child;
2889    API_ENTRY return;
2890
2891    if (sd->top_win_focused == top_win_focused) return;
2892    if (sd->resize_obj)
2893      _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2894    EINA_LIST_FOREACH(sd->subobjs, l, child)
2895      {
2896         _elm_widget_top_win_focused_set(child, top_win_focused);
2897      }
2898    sd->top_win_focused = top_win_focused;
2899 }
2900
2901 Eina_Bool
2902 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2903 {
2904    API_ENTRY return EINA_FALSE;
2905    return sd->top_win_focused;
2906 }
2907
2908 EAPI void
2909 elm_widget_disabled_set(Evas_Object *obj,
2910                         Eina_Bool disabled)
2911 {
2912    API_ENTRY return;
2913
2914    if (sd->disabled == disabled) return;
2915    sd->disabled = !!disabled;
2916    elm_widget_focus_disabled_handle(obj);
2917    if (!sd->api) return;
2918    sd->api->disable(obj);
2919 }
2920
2921 EAPI Eina_Bool
2922 elm_widget_disabled_get(const Evas_Object *obj)
2923 {
2924    API_ENTRY return 0;
2925    return sd->disabled;
2926 }
2927
2928 EAPI void
2929 elm_widget_show_region_set(Evas_Object *obj,
2930                            Evas_Coord x,
2931                            Evas_Coord y,
2932                            Evas_Coord w,
2933                            Evas_Coord h,
2934                            Eina_Bool forceshow)
2935 {
2936    Evas_Object *parent_obj, *child_obj;
2937    Evas_Coord px, py, cx, cy;
2938
2939    API_ENTRY return;
2940
2941    evas_smart_objects_calculate(evas_object_evas_get(obj));
2942    ELM_WIDGET_CHECK_OR_RETURN(obj);
2943
2944    if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
2945        (w == sd->rw) && (h == sd->rh)) return;
2946
2947    sd->rx = x;
2948    sd->ry = y;
2949    sd->rw = w;
2950    sd->rh = h;
2951    if (sd->on_show_region)
2952      sd->on_show_region
2953        (sd->on_show_region_data, obj);
2954
2955    do
2956      {
2957         parent_obj = sd->parent_obj;
2958         child_obj = sd->obj;
2959         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2960         sd = evas_object_smart_data_get(parent_obj);
2961         if (!sd) break;
2962
2963         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2964         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2965
2966         x += (cx - px);
2967         y += (cy - py);
2968         sd->rx = x;
2969         sd->ry = y;
2970         sd->rw = w;
2971         sd->rh = h;
2972
2973         if (sd->on_show_region)
2974           {
2975              sd->on_show_region
2976                (sd->on_show_region_data, parent_obj);
2977           }
2978      }
2979    while (parent_obj);
2980 }
2981
2982 EAPI void
2983 elm_widget_show_region_get(const Evas_Object *obj,
2984                            Evas_Coord *x,
2985                            Evas_Coord *y,
2986                            Evas_Coord *w,
2987                            Evas_Coord *h)
2988 {
2989    API_ENTRY return;
2990    if (x) *x = sd->rx;
2991    if (y) *y = sd->ry;
2992    if (w) *w = sd->rw;
2993    if (h) *h = sd->rh;
2994 }
2995
2996 /**
2997  * @internal
2998  *
2999  * Get the focus region of the given widget.
3000  *
3001  * @return show region or not
3002  * (@c EINA_TRUE = show region/@c EINA_FALSE = do not show region). Default is @c EINA_FALSE.
3003  *
3004  * The focus region is the area of a widget that should brought into the
3005  * visible area when the widget is focused. Mostly used to show the part of
3006  * an entry where the cursor is, for example. The area returned is relative
3007  * to the object @p obj.
3008  *
3009  * @param obj The widget object
3010  * @param x Where to store the x coordinate of the area
3011  * @param y Where to store the y coordinate of the area
3012  * @param w Where to store the width of the area
3013  * @param h Where to store the height of the area
3014  *
3015  * @ingroup Widget
3016  */
3017 EAPI Eina_Bool
3018 elm_widget_focus_region_get(const Evas_Object *obj,
3019                             Evas_Coord *x,
3020                             Evas_Coord *y,
3021                             Evas_Coord *w,
3022                             Evas_Coord *h)
3023 {
3024    API_ENTRY return EINA_FALSE;
3025    if (!sd->api->on_focus_region(obj, x, y, w, h))
3026      {
3027         evas_object_geometry_get(obj, NULL, NULL, w, h);
3028         if (x) *x = 0;
3029         if (y) *y = 0;
3030      }
3031    return EINA_TRUE;
3032 }
3033
3034 EAPI Eina_List *
3035 elm_widget_scrollable_children_get(Evas_Object *obj)
3036 {
3037    Eina_List *l, *ret = NULL;
3038    Evas_Object *child;
3039
3040    API_ENTRY return NULL;
3041
3042    EINA_LIST_FOREACH(sd->subobjs, l, child)
3043      {
3044         if (_elm_scrollable_is(child))
3045           ret = eina_list_append(ret, child);
3046      }
3047
3048    return ret;
3049 }
3050
3051 EAPI void
3052 elm_widget_scroll_hold_push(Evas_Object *obj)
3053 {
3054    API_ENTRY return;
3055    sd->scroll_hold++;
3056    if (sd->scroll_hold == 1)
3057      {
3058         if (_elm_scrollable_is(obj))
3059           {
3060              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3061              s_iface->hold_set(obj, EINA_TRUE);
3062           }
3063         else
3064           {
3065              Eina_List *scr_children, *l;
3066              Evas_Object *child;
3067
3068              scr_children = elm_widget_scrollable_children_get(obj);
3069              EINA_LIST_FOREACH(scr_children, l, child)
3070                {
3071                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3072                   s_iface->hold_set(child, EINA_TRUE);
3073                }
3074              eina_list_free(scr_children);
3075           }
3076      }
3077    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
3078    // FIXME: on delete/reparent hold pop
3079 }
3080
3081 EAPI void
3082 elm_widget_scroll_hold_pop(Evas_Object *obj)
3083 {
3084    API_ENTRY return;
3085    sd->scroll_hold--;
3086    if (!sd->scroll_hold)
3087      {
3088         if (_elm_scrollable_is(obj))
3089           {
3090              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3091              s_iface->hold_set(obj, EINA_FALSE);
3092           }
3093         else
3094           {
3095              Eina_List *scr_children, *l;
3096              Evas_Object *child;
3097
3098              scr_children = elm_widget_scrollable_children_get(obj);
3099              EINA_LIST_FOREACH(scr_children, l, child)
3100                {
3101                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3102                   s_iface->hold_set(child, EINA_FALSE);
3103                }
3104              eina_list_free(scr_children);
3105           }
3106      }
3107    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
3108    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
3109 }
3110
3111 EAPI int
3112 elm_widget_scroll_hold_get(const Evas_Object *obj)
3113 {
3114    API_ENTRY return 0;
3115    return sd->scroll_hold;
3116 }
3117
3118 EAPI void
3119 elm_widget_scroll_freeze_push(Evas_Object *obj)
3120 {
3121    API_ENTRY return;
3122    sd->scroll_freeze++;
3123    if (sd->scroll_freeze == 1)
3124      {
3125         if (_elm_scrollable_is(obj))
3126           {
3127              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3128              s_iface->freeze_set(obj, EINA_TRUE);
3129           }
3130         else
3131           {
3132              Eina_List *scr_children, *l;
3133              Evas_Object *child;
3134
3135              scr_children = elm_widget_scrollable_children_get(obj);
3136              EINA_LIST_FOREACH(scr_children, l, child)
3137                {
3138                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3139                   s_iface->freeze_set(child, EINA_TRUE);
3140                }
3141              eina_list_free(scr_children);
3142           }
3143      }
3144    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
3145    // FIXME: on delete/reparent freeze pop
3146 }
3147
3148 EAPI void
3149 elm_widget_scroll_freeze_pop(Evas_Object *obj)
3150 {
3151    API_ENTRY return;
3152    sd->scroll_freeze--;
3153    if (!sd->scroll_freeze)
3154      {
3155         if (_elm_scrollable_is(obj))
3156           {
3157              ELM_SCROLLABLE_IFACE_GET(obj, s_iface);
3158              s_iface->freeze_set(obj, EINA_FALSE);
3159           }
3160         else
3161           {
3162              Eina_List *scr_children, *l;
3163              Evas_Object *child;
3164
3165              scr_children = elm_widget_scrollable_children_get(obj);
3166              EINA_LIST_FOREACH(scr_children, l, child)
3167                {
3168                   ELM_SCROLLABLE_IFACE_GET(child, s_iface);
3169                   s_iface->freeze_set(child, EINA_FALSE);
3170                }
3171              eina_list_free(scr_children);
3172           }
3173      }
3174    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
3175    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
3176 }
3177
3178 EAPI int
3179 elm_widget_scroll_freeze_get(const Evas_Object *obj)
3180 {
3181    API_ENTRY return 0;
3182    return sd->scroll_freeze;
3183 }
3184
3185 EAPI void
3186 elm_widget_scale_set(Evas_Object *obj,
3187                      double scale)
3188 {
3189    API_ENTRY return;
3190    if (scale <= 0.0) scale = 0.0;
3191    if (sd->scale != scale)
3192      {
3193         sd->scale = scale;
3194         elm_widget_theme(obj);
3195      }
3196 }
3197
3198 EAPI double
3199 elm_widget_scale_get(const Evas_Object *obj)
3200 {
3201    API_ENTRY return 1.0;
3202    // FIXME: save walking up the tree by storing/caching parent scale
3203    if (sd->scale == 0.0)
3204      {
3205         if (sd->parent_obj)
3206           return elm_widget_scale_get(sd->parent_obj);
3207         else
3208           return 1.0;
3209      }
3210    return sd->scale;
3211 }
3212
3213 EAPI void
3214 elm_widget_theme_set(Evas_Object *obj,
3215                      Elm_Theme *th)
3216 {
3217    API_ENTRY return;
3218    if (sd->theme != th)
3219      {
3220         if (sd->theme) elm_theme_free(sd->theme);
3221         sd->theme = th;
3222         if (th) th->ref++;
3223         elm_widget_theme(obj);
3224      }
3225 }
3226
3227 EAPI void
3228 elm_widget_text_part_set(Evas_Object *obj,
3229                          const char *part,
3230                          const char *label)
3231 {
3232    API_ENTRY return;
3233
3234    if (evas_object_smart_type_check(obj, "elm_layout"))
3235      elm_layout_text_set(obj, part, label);
3236 }
3237
3238 EAPI const char *
3239 elm_widget_text_part_get(const Evas_Object *obj,
3240                          const char *part)
3241 {
3242    API_ENTRY return NULL;
3243
3244    if (evas_object_smart_type_check(obj, "elm_layout"))
3245      return elm_layout_text_get(obj, part);
3246
3247    return NULL;
3248 }
3249
3250 EAPI void
3251 elm_widget_domain_translatable_text_part_set(Evas_Object *obj,
3252                                              const char *part,
3253                                              const char *domain,
3254                                              const char *label)
3255 {
3256    const char *str;
3257    Eina_List *l;
3258    Elm_Translate_String_Data *ts = NULL;
3259    API_ENTRY return;
3260
3261    str = eina_stringshare_add(part);
3262    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
3263      if (ts->id == str)
3264        break;
3265      else
3266        ts = NULL;
3267
3268    if (!ts && !label)
3269      eina_stringshare_del(str);
3270    else if (!ts)
3271      {
3272         ts = malloc(sizeof(Elm_Translate_String_Data));
3273         if (!ts) return;
3274
3275         ts->id = str;
3276         ts->domain = eina_stringshare_add(domain);
3277         ts->string = eina_stringshare_add(label);
3278         sd->translate_strings = eina_list_append(sd->translate_strings, ts);
3279      }
3280    else
3281      {
3282         if (label)
3283           {
3284              eina_stringshare_replace(&ts->domain, domain);
3285              eina_stringshare_replace(&ts->string, label);
3286           }
3287         else
3288           {
3289              sd->translate_strings = eina_list_remove_list(
3290                  sd->translate_strings, l);
3291              eina_stringshare_del(ts->id);
3292              eina_stringshare_del(ts->domain);
3293              eina_stringshare_del(ts->string);
3294              free(ts);
3295           }
3296         eina_stringshare_del(str);
3297      }
3298
3299 #ifdef HAVE_GETTEXT
3300    if (label && label[0])
3301      label = dgettext(domain, label);
3302 #endif
3303    elm_widget_text_part_set(obj, part, label);
3304 }
3305
3306 EAPI const char *
3307 elm_widget_translatable_text_part_get(const Evas_Object *obj,
3308                                       const char *part)
3309 {
3310    const char *str, *ret = NULL;
3311    Eina_List *l;
3312    Elm_Translate_String_Data *ts;
3313    API_ENTRY return NULL;
3314
3315    str = eina_stringshare_add(part);
3316    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
3317      if (ts->id == str)
3318        {
3319           ret = ts->string;
3320           break;
3321        }
3322    eina_stringshare_del(str);
3323    return ret;
3324 }
3325
3326 EAPI void
3327 elm_widget_translate(Evas_Object *obj)
3328 {
3329    const Eina_List *l;
3330    Evas_Object *child;
3331 #ifdef HAVE_GETTEXT
3332    Elm_Translate_String_Data *ts;
3333 #endif
3334
3335    API_ENTRY return;
3336
3337    EINA_LIST_FOREACH(sd->subobjs, l, child)
3338      elm_widget_translate(child);
3339    if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
3340    if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
3341    if (!sd->api) return;
3342    sd->api->translate(obj);
3343
3344 #ifdef HAVE_GETTEXT
3345    EINA_LIST_FOREACH(sd->translate_strings, l, ts)
3346      {
3347         const char *s = dgettext(ts->domain, ts->string);
3348         elm_widget_text_part_set(obj, ts->id, s);
3349      }
3350 #endif
3351 }
3352
3353 EAPI void
3354 elm_widget_content_part_set(Evas_Object *obj,
3355                             const char *part,
3356                             Evas_Object *content)
3357 {
3358    API_ENTRY return;
3359
3360    if (!sd->api) return;
3361    if (evas_object_smart_type_check(obj, "elm_container"))
3362      ELM_CONTAINER_CLASS(sd->api)->content_set(obj, part, content);
3363 }
3364
3365 EAPI Evas_Object *
3366 elm_widget_content_part_get(const Evas_Object *obj,
3367                             const char *part)
3368 {
3369    API_ENTRY return NULL;
3370
3371    if (!sd->api) return NULL;
3372
3373    if (evas_object_smart_type_check(obj, "elm_container"))
3374      return ELM_CONTAINER_CLASS(sd->api)->content_get(obj, part);
3375
3376    return NULL;
3377 }
3378
3379 EAPI Evas_Object *
3380 elm_widget_content_part_unset(Evas_Object *obj,
3381                               const char *part)
3382 {
3383    API_ENTRY return NULL;
3384
3385    if (!sd->api) return NULL;
3386    if (evas_object_smart_type_check(obj, "elm_container"))
3387      return ELM_CONTAINER_CLASS(sd->api)->content_unset(obj, part);
3388
3389    return NULL;
3390 }
3391
3392 EAPI void
3393 elm_widget_access_info_set(Evas_Object *obj,
3394                            const char *txt)
3395 {
3396    API_ENTRY return;
3397    if (sd->access_info) eina_stringshare_del(sd->access_info);
3398    if (!txt) sd->access_info = NULL;
3399    else sd->access_info = eina_stringshare_add(txt);
3400 }
3401
3402 EAPI const char *
3403 elm_widget_access_info_get(const Evas_Object *obj)
3404 {
3405    API_ENTRY return NULL;
3406    return sd->access_info;
3407 }
3408
3409 EAPI Elm_Theme *
3410 elm_widget_theme_get(const Evas_Object *obj)
3411 {
3412    API_ENTRY return NULL;
3413    if (!sd->theme)
3414      {
3415         if (sd->parent_obj)
3416           return elm_widget_theme_get(sd->parent_obj);
3417         else
3418           return NULL;
3419      }
3420    return sd->theme;
3421 }
3422
3423 EAPI Eina_Bool
3424 elm_widget_style_set(Evas_Object *obj,
3425                      const char *style)
3426 {
3427    API_ENTRY return EINA_FALSE;
3428
3429    if (eina_stringshare_replace(&sd->style, style))
3430      return elm_widget_theme(obj);
3431
3432    return EINA_TRUE;
3433 }
3434
3435 EAPI const char *
3436 elm_widget_style_get(const Evas_Object *obj)
3437 {
3438    API_ENTRY return NULL;
3439    if (sd->style) return sd->style;
3440    return "default";
3441 }
3442
3443 EAPI void
3444 elm_widget_tooltip_add(Evas_Object *obj,
3445                        Elm_Tooltip *tt)
3446 {
3447    API_ENTRY return;
3448    sd->tooltips = eina_list_append(sd->tooltips, tt);
3449 }
3450
3451 EAPI void
3452 elm_widget_tooltip_del(Evas_Object *obj,
3453                        Elm_Tooltip *tt)
3454 {
3455    API_ENTRY return;
3456    sd->tooltips = eina_list_remove(sd->tooltips, tt);
3457 }
3458
3459 EAPI void
3460 elm_widget_cursor_add(Evas_Object *obj,
3461                       Elm_Cursor *cur)
3462 {
3463    API_ENTRY return;
3464    sd->cursors = eina_list_append(sd->cursors, cur);
3465 }
3466
3467 EAPI void
3468 elm_widget_cursor_del(Evas_Object *obj,
3469                       Elm_Cursor *cur)
3470 {
3471    API_ENTRY return;
3472    sd->cursors = eina_list_remove(sd->cursors, cur);
3473 }
3474
3475 EAPI void
3476 elm_widget_drag_lock_x_set(Evas_Object *obj,
3477                            Eina_Bool lock)
3478 {
3479    API_ENTRY return;
3480    if (sd->drag_x_locked == lock) return;
3481    sd->drag_x_locked = lock;
3482    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
3483    else _propagate_x_drag_lock(obj, -1);
3484 }
3485
3486 EAPI void
3487 elm_widget_drag_lock_y_set(Evas_Object *obj,
3488                            Eina_Bool lock)
3489 {
3490    API_ENTRY return;
3491    if (sd->drag_y_locked == lock) return;
3492    sd->drag_y_locked = lock;
3493    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
3494    else _propagate_y_drag_lock(obj, -1);
3495 }
3496
3497 EAPI Eina_Bool
3498 elm_widget_drag_lock_x_get(const Evas_Object *obj)
3499 {
3500    API_ENTRY return EINA_FALSE;
3501    return sd->drag_x_locked;
3502 }
3503
3504 EAPI Eina_Bool
3505 elm_widget_drag_lock_y_get(const Evas_Object *obj)
3506 {
3507    API_ENTRY return EINA_FALSE;
3508    return sd->drag_y_locked;
3509 }
3510
3511 EAPI int
3512 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
3513 {
3514    API_ENTRY return 0;
3515    return sd->child_drag_x_locked;
3516 }
3517
3518 EAPI int
3519 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
3520 {
3521    API_ENTRY return 0;
3522    return sd->child_drag_y_locked;
3523 }
3524
3525 EAPI Eina_Bool
3526 elm_widget_theme_object_set(Evas_Object *obj,
3527                             Evas_Object *edj,
3528                             const char *wname,
3529                             const char *welement,
3530                             const char *wstyle)
3531 {
3532    API_ENTRY return EINA_FALSE;
3533    char buf[128];
3534    int ret;
3535
3536    if (!_elm_theme_object_set(obj, edj, wname, welement, wstyle))
3537      return EINA_FALSE;
3538
3539    if (sd->orient_mode != -1)
3540      {
3541
3542         snprintf(buf, sizeof(buf), "elm,state,orient,%d", ret);
3543         elm_widget_signal_emit(obj, buf, "elm");
3544
3545      }
3546    return EINA_TRUE;
3547 }
3548
3549 EAPI Eina_Bool
3550 elm_widget_is_check(const Evas_Object *obj)
3551 {
3552    static int abort_on_warn = -1;
3553    if (elm_widget_is(obj))
3554      return EINA_TRUE;
3555
3556    ERR("Passing Object: %p.", obj);
3557    if (abort_on_warn == -1)
3558      {
3559         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3560         else abort_on_warn = 0;
3561      }
3562    if (abort_on_warn == 1) abort();
3563    return EINA_FALSE;
3564 }
3565
3566 EAPI const char *
3567 elm_widget_type_get(const Evas_Object *obj)
3568 {
3569    API_ENTRY return NULL;
3570
3571    return evas_object_type_get(obj);
3572 }
3573
3574 EAPI Eina_Bool
3575 elm_widget_type_check(const Evas_Object *obj,
3576                       const char *type,
3577                       const char *func)
3578 {
3579    const char *provided, *expected = "(unknown)";
3580    static int abort_on_warn = -1;
3581
3582    provided = elm_widget_type_get(obj);
3583    /* TODO: eventually migrate to check_ptr version */
3584    if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
3585    if (type) expected = type;
3586    if ((!provided) || (!provided[0]))
3587      {
3588         provided = evas_object_type_get(obj);
3589         if ((!provided) || (!provided[0]))
3590           provided = "(unknown)";
3591      }
3592    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
3593        " type: '%s'", obj, func, provided, expected);
3594    if (abort_on_warn == -1)
3595      {
3596         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3597         else abort_on_warn = 0;
3598      }
3599    if (abort_on_warn == 1) abort();
3600    return EINA_FALSE;
3601 }
3602
3603 static Evas_Object *
3604 _widget_name_find(const Evas_Object *obj,
3605                   const char *name,
3606                   int recurse)
3607 {
3608    Eina_List *l;
3609    Evas_Object *child;
3610    const char *s;
3611    INTERNAL_ENTRY NULL;
3612
3613    if (!_elm_widget_is(obj)) return NULL;
3614    if (sd->resize_obj)
3615      {
3616         s = evas_object_name_get(sd->resize_obj);
3617         if ((s) && (!strcmp(s, name))) return sd->resize_obj;
3618         if ((recurse != 0) &&
3619             ((child = _widget_name_find(sd->resize_obj, name, recurse - 1))))
3620           return child;
3621      }
3622    EINA_LIST_FOREACH(sd->subobjs, l, child)
3623      {
3624         s = evas_object_name_get(child);
3625         if ((s) && (!strcmp(s, name))) return child;
3626         if ((recurse != 0) &&
3627             ((child = _widget_name_find(child, name, recurse - 1))))
3628           return child;
3629      }
3630    if (sd->hover_obj)
3631      {
3632         s = evas_object_name_get(sd->hover_obj);
3633         if ((s) && (!strcmp(s, name))) return sd->hover_obj;
3634         if ((recurse != 0) &&
3635             ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
3636           return child;
3637      }
3638    return NULL;
3639 }
3640
3641 EAPI Evas_Object *
3642 elm_widget_name_find(const Evas_Object *obj,
3643                      const char *name,
3644                      int recurse)
3645 {
3646    API_ENTRY return NULL;
3647    if (!name) return NULL;
3648    return _widget_name_find(obj, name, recurse);
3649 }
3650
3651 EAPI void
3652 elm_widget_orientation_mode_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3653 {
3654    int orient_mode = -1;
3655
3656    API_ENTRY return;
3657
3658    if (disabled && (sd->orient_mode == -1)) return;
3659    if (!disabled && (sd->orient_mode != -1)) return;
3660
3661    if (!disabled)
3662      {
3663         //Get current orient mode from it's parent otherwise, 0.
3664         sd->orient_mode = 0;
3665         ELM_WIDGET_DATA_GET(sd->parent_obj, sd_parent);
3666         if (!sd_parent) orient_mode = 0;
3667         else orient_mode = sd_parent->orient_mode;
3668      }
3669    elm_widget_orientation_set(obj, orient_mode);
3670 }
3671
3672 EAPI Eina_Bool
3673 elm_widget_orientation_mode_disabled_get(const Evas_Object *obj)
3674 {
3675    Eina_Bool ret;
3676
3677    API_ENTRY return EINA_FALSE;
3678
3679    if (sd->orient_mode == -1) ret = EINA_TRUE;
3680    else ret = EINA_FALSE;
3681    return ret;
3682 }
3683
3684 EAPI void
3685 elm_widget_orientation_set(Evas_Object *obj, int rotation)
3686 {
3687    Evas_Object *child;
3688    Eina_List *l;
3689
3690    API_ENTRY return;
3691
3692    if ((sd->orient_mode == rotation) || (sd->orient_mode == -1)) return;
3693
3694    sd->orient_mode = rotation;
3695
3696    EINA_LIST_FOREACH (sd->subobjs, l, child)
3697      elm_widget_orientation_set(child, rotation);
3698
3699    if (rotation != -1)
3700      {
3701         char buf[128];
3702         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
3703         elm_widget_signal_emit(obj, buf, "elm");
3704      }
3705 }
3706
3707 /**
3708  * @internal
3709  *
3710  * Split string in words
3711  *
3712  * @param str Source string
3713  * @return List of const words
3714  *
3715  * @see elm_widget_stringlist_free()
3716  * @ingroup Widget
3717  */
3718 EAPI Eina_List *
3719 elm_widget_stringlist_get(const char *str)
3720 {
3721    Eina_List *list = NULL;
3722    const char *s, *b;
3723    if (!str) return NULL;
3724    for (b = s = str; 1; s++)
3725      {
3726         if ((*s == ' ') || (!*s))
3727           {
3728              char *t = malloc(s - b + 1);
3729              if (t)
3730                {
3731                   strncpy(t, b, s - b);
3732                   t[s - b] = 0;
3733                   list = eina_list_append(list, eina_stringshare_add(t));
3734                   free(t);
3735                }
3736              b = s + 1;
3737           }
3738         if (!*s) break;
3739      }
3740    return list;
3741 }
3742
3743 EAPI void
3744 elm_widget_stringlist_free(Eina_List *list)
3745 {
3746    const char *s;
3747    EINA_LIST_FREE (list, s)
3748      eina_stringshare_del(s);
3749 }
3750
3751 EAPI void
3752 elm_widget_focus_hide_handle(Evas_Object *obj)
3753 {
3754    if (!_elm_widget_is(obj))
3755      return;
3756    _if_focused_revert(obj, EINA_TRUE);
3757 }
3758
3759 EAPI void
3760 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
3761 {
3762    Evas_Object *o = obj;
3763    do
3764      {
3765         if (_elm_widget_is(o)) break;
3766         o = evas_object_smart_parent_get(o);
3767      }
3768    while (o);
3769    if (!o) return;
3770    if (!_is_focusable(o)) return;
3771    elm_widget_focus_steal(o);
3772 }
3773
3774 EAPI void
3775 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
3776 {
3777    API_ENTRY return;
3778
3779    //FIXME: Need to check whether the object is unfocusable or not.
3780
3781    if (!elm_widget_parent_get(obj))
3782      elm_widget_focused_object_clear(obj);
3783    else
3784      _if_focused_revert(obj, EINA_TRUE);
3785 }
3786
3787 EAPI void
3788 elm_widget_focus_disabled_handle(Evas_Object *obj)
3789 {
3790    API_ENTRY return;
3791
3792    elm_widget_focus_tree_unfocusable_handle(obj);
3793 }
3794
3795 EAPI unsigned int
3796 elm_widget_focus_order_get(const Evas_Object *obj)
3797 {
3798    API_ENTRY return 0;
3799    return sd->focus_order;
3800 }
3801
3802 EAPI Evas_Object *
3803 elm_widget_newest_focus_order_get(const Evas_Object *obj,
3804                                   unsigned int *newest_focus_order,
3805                                   Eina_Bool can_focus_only)
3806 {
3807    const Eina_List *l;
3808    Evas_Object *child, *ret, *best;
3809
3810    API_ENTRY return NULL;
3811
3812    if (!evas_object_visible_get(obj)
3813        || (elm_widget_disabled_get(obj))
3814        || (elm_widget_tree_unfocusable_get(obj)))
3815      return NULL;
3816
3817    best = NULL;
3818    if (*newest_focus_order < sd->focus_order)
3819      {
3820         *newest_focus_order = sd->focus_order;
3821         best = (Evas_Object *)obj;
3822      }
3823    EINA_LIST_FOREACH(sd->subobjs, l, child)
3824      {
3825         ret = elm_widget_newest_focus_order_get
3826            (child, newest_focus_order, can_focus_only);
3827         if (!ret) continue;
3828         best = ret;
3829      }
3830    if (can_focus_only)
3831      {
3832         if ((!best) || (!elm_widget_can_focus_get(best)))
3833           return NULL;
3834      }
3835    return best;
3836 }
3837
3838 EAPI void
3839 elm_widget_activate(Evas_Object *obj, Elm_Activate act)
3840 {
3841    Evas_Object *parent;
3842    Eina_Bool ret;
3843
3844    API_ENTRY return;
3845
3846    ret = EINA_FALSE;
3847    if (sd->api->activate)
3848      ret = sd->api->activate(obj, act);
3849
3850    if (ret) return;
3851
3852    parent = elm_widget_parent_get(obj);
3853    if (parent)
3854      elm_widget_activate(parent, act);
3855
3856    return;
3857 }
3858
3859 /**
3860  * @internal
3861  *
3862  * Returns the widget's Evas_Display_Mode
3863  *
3864  * @param obj The widget.
3865  * @return Evas_Display_Mode of the object.
3866  *
3867  * @see elm_widget_display_mode_set().
3868  * @ingroup Widget
3869  **/
3870 EAPI Evas_Display_Mode
3871 elm_widget_display_mode_get(const Evas_Object *obj)
3872 {
3873    Evas_Display_Mode new_mode;
3874    Evas_Object *parent;
3875
3876    API_ENTRY return EVAS_DISPLAY_MODE_NONE;
3877
3878    new_mode = evas_object_size_hint_display_mode_get(obj);
3879    parent = elm_widget_parent_get(obj);
3880
3881    if ((new_mode == EVAS_DISPLAY_MODE_INHERIT) && parent)
3882      return elm_widget_display_mode_get(parent);
3883    return new_mode;
3884
3885 }
3886
3887 /**
3888  * @internal
3889  *
3890  * Sets the widget and child widget's Evas_Display_Mode.
3891  *
3892  * @param obj The widget.
3893  * @param dispmode Evas_Display_Mode to set widget's mode.
3894  *
3895  * Widgets are resized by several reasons.
3896  * Evas_Display_Mode can help for widgets to get one more reason of resize.
3897  * For example, elm conform widget resizes it's contents when keypad state changed.
3898  * After keypad showing, conform widget can change child's Evas_Display_Mode.
3899  * @ingroup Widget
3900  */
3901 EAPI void
3902 elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode)
3903 {
3904    Evas_Display_Mode child_mode;
3905    Evas_Object *child;
3906    Eina_List *l;
3907
3908    API_ENTRY return;
3909
3910    if (elm_widget_display_mode_get(obj) == dispmode) return;
3911    evas_object_size_hint_display_mode_set(obj, dispmode);
3912
3913    //TODO: Need to deal with EVAS_DISPLAY_MODE_INHERIT efficiently.
3914    EINA_LIST_FOREACH (sd->subobjs, l, child)
3915      {
3916         child_mode = evas_object_size_hint_display_mode_get(child);
3917         if (child_mode != EVAS_DISPLAY_MODE_DONT_CHANGE)
3918           {
3919              elm_widget_display_mode_set(child, dispmode);
3920           }
3921      }
3922
3923 }
3924
3925 // temporary code. should be removed after eo is applied.
3926 EAPI void
3927 _elm_widget_orient_signal_emit(Evas_Object *obj)
3928 {
3929    ELM_WIDGET_DATA_GET(obj, sd);
3930    char buf[128];
3931    if (sd->orient_mode > 0)
3932      {
3933         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
3934         elm_widget_signal_emit(obj, buf, "elm");
3935      }
3936 }
3937
3938 /**
3939  * @internal
3940  *
3941  * Allocate a new Elm_Widget_Item-derived structure.
3942  *
3943  * The goal of this structure is to provide common ground for actions
3944  * that a widget item have, such as the owner widget, callback to
3945  * notify deletion, data pointer and maybe more.
3946  *
3947  * @param widget the owner widget that holds this item, must be an elm_widget!
3948  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
3949  *        be used to allocate memory.
3950  *
3951  * @return allocated memory that is already zeroed out, or NULL on errors.
3952  *
3953  * @see elm_widget_item_new() convenience macro.
3954  * @see elm_widget_item_del() to release memory.
3955  * @ingroup Widget
3956  */
3957 EAPI Elm_Widget_Item *
3958 _elm_widget_item_new(Evas_Object *widget,
3959                      size_t alloc_size)
3960 {
3961    if (!_elm_widget_is(widget))
3962      return NULL;
3963
3964    Elm_Widget_Item *item;
3965
3966    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
3967    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
3968
3969    item = calloc(1, alloc_size);
3970    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
3971
3972    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
3973    item->widget = widget;
3974    return item;
3975 }
3976
3977 EAPI void
3978 _elm_widget_item_free(Elm_Widget_Item *item)
3979 {
3980    Elm_Widget_Item_Signal_Data *wisd;
3981
3982    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3983
3984    if (item->del_func)
3985      item->del_func((void *)item->data, item->widget, item);
3986
3987    if (item->view)
3988      evas_object_del(item->view);
3989
3990    if (item->access_info)
3991      eina_stringshare_del(item->access_info);
3992
3993    EINA_LIST_FREE(item->signals, wisd)
3994      {
3995         eina_stringshare_del(wisd->emission);
3996         eina_stringshare_del(wisd->source);
3997         free(wisd);
3998      }
3999
4000    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
4001    free(item);
4002 }
4003
4004 /**
4005  * @internal
4006  *
4007  * Releases widget item memory, calling back del_cb() if it exists.
4008  *
4009  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
4010  * to memory release. Note that elm_widget_item_pre_notify_del() calls
4011  * this function and then unset it, thus being useful for 2 step
4012  * cleanup whenever the del_cb may use any of the data that must be
4013  * deleted from item.
4014  *
4015  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
4016  * is presented!
4017  *
4018  * @param item a valid #Elm_Widget_Item to be deleted.
4019  * @see elm_widget_item_del() convenience macro.
4020  * @ingroup Widget
4021  */
4022 EAPI void
4023 _elm_widget_item_del(Elm_Widget_Item *item)
4024 {
4025    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4026    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4027    item->on_deletion = EINA_TRUE;
4028
4029    //Widget item delete callback
4030    if (item->del_pre_func)
4031       if (item->del_pre_func((Elm_Object_Item *)item))
4032          _elm_widget_item_free(item);
4033  }
4034
4035 /**
4036  * @internal
4037  *
4038  * Set the function to notify to widgets when item is being deleted by user.
4039  *
4040  * @param item a valid #Elm_Widget_Item to be notified
4041  * @see elm_widget_item_del_pre_hook_set() convenience macro.
4042  * @ingroup Widget
4043  */
4044 EAPI void
4045 _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item,
4046                                   Elm_Widget_Del_Pre_Cb func)
4047 {
4048    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4049    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4050    item->del_pre_func = func;
4051 }
4052
4053 /**
4054  * @internal
4055  *
4056  * Notify object will be deleted without actually deleting it.
4057  *
4058  * This function will callback Elm_Widget_Item::del_cb if it is set
4059  * and then unset it so it is not called twice (ie: from
4060  * elm_widget_item_del()).
4061  *
4062  * @param item a valid #Elm_Widget_Item to be notified
4063  * @see elm_widget_item_pre_notify_del() convenience macro.
4064  * @ingroup Widget
4065  */
4066 EAPI void
4067 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
4068 {
4069    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4070    if (!item->del_func) return;
4071    item->del_func((void *)item->data, item->widget, item);
4072    item->del_func = NULL;
4073 }
4074
4075 /**
4076  * @internal
4077  *
4078  * Set the function to notify when item is being deleted.
4079  *
4080  * This function will complain if there was a callback set already,
4081  * however it will set the new one.
4082  *
4083  * The callback will be called from elm_widget_item_pre_notify_del()
4084  * or elm_widget_item_del() will be called with:
4085  *   - data: the Elm_Widget_Item::data value.
4086  *   - obj: the Elm_Widget_Item::widget evas object.
4087  *   - event_info: the item being deleted.
4088  *
4089  * @param item a valid #Elm_Widget_Item to be notified
4090  * @see elm_widget_item_del_cb_set() convenience macro.
4091  * @ingroup Widget
4092  */
4093 EAPI void
4094 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
4095                             Evas_Smart_Cb func)
4096 {
4097    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4098    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4099
4100    if ((item->del_func) && (item->del_func != func))
4101      WRN("You're replacing a previously set del_cb %p of item %p with %p",
4102          item->del_func, item, func);
4103
4104    item->del_func = func;
4105 }
4106
4107 /**
4108  * @internal
4109  *
4110  * Retrieves owner widget of this item.
4111  *
4112  * @param item a valid #Elm_Widget_Item to get data from.
4113  * @return owner widget of this item.
4114  * @ingroup Widget
4115  */
4116 EAPI Evas_Object *
4117 _elm_widget_item_widget_get(const Elm_Widget_Item *item)
4118 {
4119    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4120    return item->widget;
4121 }
4122
4123 /**
4124  * @internal
4125  *
4126  * Set user-data in this item.
4127  *
4128  * User data may be used to identify this item or just store any
4129  * application data. It is automatically given as the first parameter
4130  * of the deletion notify callback.
4131  *
4132  * @param item a valid #Elm_Widget_Item to store data in.
4133  * @param data user data to store.
4134  * @see elm_widget_item_del_cb_set() convenience macro.
4135  * @ingroup Widget
4136  */
4137 EAPI void
4138 _elm_widget_item_data_set(Elm_Widget_Item *item,
4139                           const void *data)
4140 {
4141    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4142    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4143
4144    if ((item->data) && (item->data != data))
4145      DBG("Replacing item %p data %p with %p", item, item->data, data);
4146    item->data = data;
4147 }
4148
4149 /**
4150  * @internal
4151  *
4152  * Retrieves user-data of this item.
4153  *
4154  * @param item a valid #Elm_Widget_Item to get data from.
4155  * @see elm_widget_item_data_set()
4156  * @ingroup Widget
4157  */
4158 EAPI void *
4159 _elm_widget_item_data_get(const Elm_Widget_Item *item)
4160 {
4161    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4162    return (void *)item->data;
4163 }
4164
4165 EAPI void
4166 _elm_widget_item_disabled_set(Elm_Widget_Item *item,
4167                               Eina_Bool disabled)
4168 {
4169    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4170    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4171
4172    if (item->disabled == disabled) return;
4173    item->disabled = !!disabled;
4174    if (item->disable_func) item->disable_func(item);
4175 }
4176
4177 EAPI Eina_Bool
4178 _elm_widget_item_disabled_get(const Elm_Widget_Item *item)
4179 {
4180    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4181    return item->disabled;
4182 }
4183
4184 EAPI void
4185 _elm_widget_item_disable_hook_set(Elm_Widget_Item *item,
4186                                   Elm_Widget_Disable_Cb func)
4187 {
4188    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4189    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4190
4191    item->disable_func = func;
4192 }
4193
4194 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
4195
4196 struct _Elm_Widget_Item_Tooltip
4197 {
4198    Elm_Widget_Item            *item;
4199    Elm_Tooltip_Item_Content_Cb func;
4200    Evas_Smart_Cb               del_cb;
4201    const void                 *data;
4202 };
4203
4204 static Evas_Object *
4205 _elm_widget_item_tooltip_label_create(void *data,
4206                                       Evas_Object *obj __UNUSED__,
4207                                       Evas_Object *tooltip,
4208                                       void *item __UNUSED__)
4209 {
4210    Evas_Object *label = elm_label_add(tooltip);
4211    if (!label)
4212      return NULL;
4213    elm_object_style_set(label, "tooltip");
4214    elm_object_text_set(label, data);
4215    return label;
4216 }
4217
4218 static Evas_Object *
4219 _elm_widget_item_tooltip_trans_label_create(void *data,
4220                                             Evas_Object *obj __UNUSED__,
4221                                             Evas_Object *tooltip,
4222                                             void *item __UNUSED__)
4223 {
4224    Evas_Object *label = elm_label_add(tooltip);
4225    if (!label)
4226      return NULL;
4227    elm_object_style_set(label, "tooltip");
4228    elm_object_translatable_text_set(label, data);
4229    return label;
4230 }
4231
4232 static void
4233 _elm_widget_item_tooltip_label_del_cb(void *data,
4234                                       Evas_Object *obj __UNUSED__,
4235                                       void *event_info __UNUSED__)
4236 {
4237    eina_stringshare_del(data);
4238 }
4239
4240 /**
4241  * @internal
4242  *
4243  * Set the text to be shown in the widget item.
4244  *
4245  * @param item Target item
4246  * @param text The text to set in the content
4247  *
4248  * Setup the text as tooltip to object. The item can have only one tooltip,
4249  * so any previous tooltip data is removed.
4250  *
4251  * @ingroup Widget
4252  */
4253 EAPI void
4254 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
4255                                   const char *text)
4256 {
4257    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4258    EINA_SAFETY_ON_NULL_RETURN(text);
4259    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4260
4261    text = eina_stringshare_add(text);
4262    _elm_widget_item_tooltip_content_cb_set
4263      (item, _elm_widget_item_tooltip_label_create, text,
4264      _elm_widget_item_tooltip_label_del_cb);
4265 }
4266
4267 EAPI void
4268 _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
4269                                                const char *text)
4270 {
4271    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4272    EINA_SAFETY_ON_NULL_RETURN(text);
4273    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4274
4275    text = eina_stringshare_add(text);
4276    _elm_widget_item_tooltip_content_cb_set
4277      (item, _elm_widget_item_tooltip_trans_label_create, text,
4278      _elm_widget_item_tooltip_label_del_cb);
4279 }
4280
4281 static Evas_Object *
4282 _elm_widget_item_tooltip_create(void *data,
4283                                 Evas_Object *obj,
4284                                 Evas_Object *tooltip)
4285 {
4286    Elm_Widget_Item_Tooltip *wit = data;
4287    return wit->func((void *)wit->data, obj, tooltip, wit->item);
4288 }
4289
4290 static void
4291 _elm_widget_item_tooltip_del_cb(void *data,
4292                                 Evas_Object *obj,
4293                                 void *event_info __UNUSED__)
4294 {
4295    Elm_Widget_Item_Tooltip *wit = data;
4296    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
4297    free(wit);
4298 }
4299
4300 /**
4301  * @internal
4302  *
4303  * Set the content to be shown in the tooltip item
4304  *
4305  * Setup the tooltip to item. The item can have only one tooltip,
4306  * so any previous tooltip data is removed. @p func(with @p data) will
4307  * be called every time that need show the tooltip and it should
4308  * return a valid Evas_Object. This object is then managed fully by
4309  * tooltip system and is deleted when the tooltip is gone.
4310  *
4311  * @param item the widget item being attached a tooltip.
4312  * @param func the function used to create the tooltip contents.
4313  * @param data what to provide to @a func as callback data/context.
4314  * @param del_cb called when data is not needed anymore, either when
4315  *        another callback replaces @func, the tooltip is unset with
4316  *        elm_widget_item_tooltip_unset() or the owner @a item
4317  *        dies. This callback receives as the first parameter the
4318  *        given @a data, and @c event_info is the item.
4319  *
4320  * @ingroup Widget
4321  */
4322 EAPI void
4323 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item,
4324                                         Elm_Tooltip_Item_Content_Cb func,
4325                                         const void *data,
4326                                         Evas_Smart_Cb del_cb)
4327 {
4328    Elm_Widget_Item_Tooltip *wit;
4329
4330    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
4331    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4332    if (!func)
4333      {
4334         _elm_widget_item_tooltip_unset(item);
4335         return;
4336      }
4337
4338    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
4339    if (!wit) goto error;
4340    wit->item = item;
4341    wit->func = func;
4342    wit->data = data;
4343    wit->del_cb = del_cb;
4344
4345    elm_object_sub_tooltip_content_cb_set
4346      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
4347      _elm_widget_item_tooltip_del_cb);
4348
4349    return;
4350
4351 error_noitem:
4352    if (del_cb) del_cb((void *)data, NULL, item);
4353    return;
4354 error:
4355    if (del_cb) del_cb((void *)data, item->widget, item);
4356 }
4357
4358 /**
4359  * @internal
4360  *
4361  * Unset tooltip from item
4362  *
4363  * @param item widget item to remove previously set tooltip.
4364  *
4365  * Remove tooltip from item. The callback provided as del_cb to
4366  * elm_widget_item_tooltip_content_cb_set() will be called to notify
4367  * it is not used anymore.
4368  *
4369  * @see elm_widget_item_tooltip_content_cb_set()
4370  *
4371  * @ingroup Widget
4372  */
4373 EAPI void
4374 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
4375 {
4376    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4377    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4378
4379    elm_object_tooltip_unset(item->view);
4380 }
4381
4382 /**
4383  * @internal
4384  *
4385  * Sets a different style for this item tooltip.
4386  *
4387  * @note before you set a style you should define a tooltip with
4388  *       elm_widget_item_tooltip_content_cb_set() or
4389  *       elm_widget_item_tooltip_text_set()
4390  *
4391  * @param item widget item with tooltip already set.
4392  * @param style the theme style to use (default, transparent, ...)
4393  *
4394  * @ingroup Widget
4395  */
4396 EAPI void
4397 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
4398                                    const char *style)
4399 {
4400    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4401    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4402
4403    elm_object_tooltip_style_set(item->view, style);
4404 }
4405
4406 EAPI Eina_Bool
4407 _elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item,
4408                                          Eina_Bool disable)
4409 {
4410    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4411    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
4412
4413    return elm_object_tooltip_window_mode_set(item->view, disable);
4414 }
4415
4416 EAPI Eina_Bool
4417 _elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item)
4418 {
4419    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4420    return elm_object_tooltip_window_mode_get(item->view);
4421 }
4422
4423 /**
4424  * @internal
4425  *
4426  * Get the style for this item tooltip.
4427  *
4428  * @param item widget item with tooltip already set.
4429  * @return style the theme style in use, defaults to "default". If the
4430  *         object does not have a tooltip set, then NULL is returned.
4431  *
4432  * @ingroup Widget
4433  */
4434 EAPI const char *
4435 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
4436 {
4437    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4438    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4439
4440    return elm_object_tooltip_style_get(item->view);
4441 }
4442
4443 EAPI void
4444 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
4445                             const char *cursor)
4446 {
4447    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4448    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4449
4450    elm_object_sub_cursor_set(item->view, item->widget, cursor);
4451 }
4452
4453 EAPI const char *
4454 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
4455 {
4456    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4457    return elm_object_cursor_get(item->view);
4458 }
4459
4460 EAPI void
4461 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
4462 {
4463    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4464    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4465
4466    elm_object_cursor_unset(item->view);
4467 }
4468
4469 /**
4470  * @internal
4471  *
4472  * Sets a different style for this item cursor.
4473  *
4474  * @note before you set a style you should define a cursor with
4475  *       elm_widget_item_cursor_set()
4476  *
4477  * @param item widget item with cursor already set.
4478  * @param style the theme style to use (default, transparent, ...)
4479  *
4480  * @ingroup Widget
4481  */
4482 EAPI void
4483 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
4484                                   const char *style)
4485 {
4486    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4487    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4488
4489    elm_object_cursor_style_set(item->view, style);
4490 }
4491
4492 /**
4493  * @internal
4494  *
4495  * Get the style for this item cursor.
4496  *
4497  * @param item widget item with cursor already set.
4498  * @return style the theme style in use, defaults to "default". If the
4499  *         object does not have a cursor set, then NULL is returned.
4500  *
4501  * @ingroup Widget
4502  */
4503 EAPI const char *
4504 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
4505 {
4506    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4507    return elm_object_cursor_style_get(item->view);
4508 }
4509
4510 /**
4511  * @internal
4512  *
4513  * Set if the cursor set should be searched on the theme or should use
4514  * the provided by the engine, only.
4515  *
4516  * @note before you set if should look on theme you should define a cursor
4517  * with elm_object_cursor_set(). By default it will only look for cursors
4518  * provided by the engine.
4519  *
4520  * @param item widget item with cursor already set.
4521  * @param engine_only boolean to define it cursors should be looked only
4522  * between the provided by the engine or searched on widget's theme as well.
4523  *
4524  * @ingroup Widget
4525  */
4526 EAPI void
4527 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
4528                                         Eina_Bool engine_only)
4529 {
4530    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4531    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4532
4533    elm_object_cursor_theme_search_enabled_set(item->view, engine_only);
4534 }
4535
4536 /**
4537  * @internal
4538  *
4539  * Get the cursor engine only usage for this item cursor.
4540  *
4541  * @param item widget item with cursor already set.
4542  * @return engine_only boolean to define it cursors should be looked only
4543  * between the provided by the engine or searched on widget's theme as well. If
4544  *         the object does not have a cursor set, then EINA_FALSE is returned.
4545  *
4546  * @ingroup Widget
4547  */
4548 EAPI Eina_Bool
4549 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
4550 {
4551    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4552    return elm_object_cursor_theme_search_enabled_get(item->view);
4553 }
4554
4555 EAPI void
4556 _elm_widget_item_part_content_set(Elm_Widget_Item *item,
4557                                   const char *part,
4558                                   Evas_Object *content)
4559 {
4560    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4561    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4562    if (!item->content_set_func)
4563      {
4564         ERR("%s does not support elm_object_item_part_content_set() API.",
4565             elm_widget_type_get(item->widget));
4566         return;
4567      }
4568    item->content_set_func((Elm_Object_Item *)item, part, content);
4569 }
4570
4571 EAPI Evas_Object *
4572 _elm_widget_item_part_content_get(const Elm_Widget_Item *item,
4573                                   const char *part)
4574 {
4575    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4576    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4577
4578    return item->content_get_func((Elm_Object_Item *)item, part);
4579 }
4580
4581 EAPI Evas_Object *
4582 _elm_widget_item_part_content_unset(Elm_Widget_Item *item,
4583                                     const char *part)
4584 {
4585    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4586    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4587    if (!item->content_unset_func)
4588      {
4589         ERR("%s does not support elm_object_item_part_content_unset() API.",
4590             elm_widget_type_get(item->widget));
4591         return NULL;
4592      }
4593
4594    return item->content_unset_func((Elm_Object_Item *)item, part);
4595 }
4596
4597 EAPI void
4598 _elm_widget_item_part_text_set(Elm_Widget_Item *item,
4599                                const char *part,
4600                                const char *label)
4601 {
4602    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4603    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4604    if (!item->text_set_func)
4605      {
4606         ERR("%s does not support elm_object_item_part_text_set() API.",
4607             elm_widget_type_get(item->widget));
4608         return;
4609      }
4610
4611    item->text_set_func((Elm_Object_Item *)item, part, label);
4612 }
4613
4614 EAPI const char *
4615 _elm_widget_item_part_text_get(const Elm_Widget_Item *item,
4616                                const char *part)
4617 {
4618    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4619    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4620    if (!item->text_get_func)
4621      {
4622         ERR("%s does not support elm_object_item_part_text_get() API.",
4623             elm_widget_type_get(item->widget));
4624         return NULL;
4625      }
4626
4627    return item->text_get_func((Elm_Object_Item *)item, part);
4628 }
4629
4630 EAPI void
4631 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
4632                                       Elm_Widget_Content_Set_Cb func)
4633 {
4634    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4635    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4636
4637    item->content_set_func = func;
4638 }
4639
4640 EAPI void
4641 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
4642                                       Elm_Widget_Content_Get_Cb func)
4643 {
4644    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4645    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4646
4647    item->content_get_func = func;
4648 }
4649
4650 EAPI void
4651 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
4652                                         Elm_Widget_Content_Unset_Cb func)
4653 {
4654    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4655    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4656
4657    item->content_unset_func = func;
4658 }
4659
4660 EAPI void
4661 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
4662                                    Elm_Widget_Text_Set_Cb func)
4663 {
4664    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4665    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4666
4667    item->text_set_func = func;
4668 }
4669
4670 EAPI void
4671 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
4672                                    Elm_Widget_Text_Get_Cb func)
4673 {
4674    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4675    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4676
4677    item->text_get_func = func;
4678 }
4679
4680 EAPI void
4681 _elm_widget_item_signal_emit(Elm_Widget_Item *item,
4682                              const char *emission,
4683                              const char *source)
4684 {
4685    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4686    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4687
4688    if (item->signal_emit_func)
4689      item->signal_emit_func((Elm_Object_Item *)item, emission, source);
4690 }
4691
4692 EAPI void
4693 _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
4694                                       Elm_Widget_Signal_Emit_Cb func)
4695 {
4696    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4697    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4698
4699    item->signal_emit_func = func;
4700 }
4701
4702
4703 static void
4704 _elm_widget_item_signal_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission,
4705                            const char *source)
4706 {
4707    Elm_Widget_Item_Signal_Data *wisd = data;
4708    wisd->func(wisd->data, wisd->item, emission, source);
4709 }
4710
4711 EAPI void
4712 _elm_widget_item_signal_callback_add(Elm_Widget_Item *item,
4713                                      const char *emission,
4714                                      const char *source,
4715                                      Elm_Widget_Item_Signal_Cb func,
4716                                      void *data)
4717 {
4718    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4719    EINA_SAFETY_ON_NULL_RETURN(func);
4720
4721    Elm_Widget_Item_Signal_Data *wisd;
4722
4723    wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
4724    if (!wisd) return;
4725
4726    wisd->item = item;
4727    wisd->func = func;
4728    wisd->data = data;
4729    wisd->emission = eina_stringshare_add(emission);
4730    wisd->source = eina_stringshare_add(source);
4731
4732    if (_elm_widget_is(item->view))
4733      elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
4734    else if (!strcmp(evas_object_type_get(item->view), "edje"))
4735      edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
4736    else
4737      {
4738         WRN("The %s widget item doesn't support signal callback add!",
4739             evas_object_type_get(item->widget));
4740         free(wisd);
4741         return;
4742      }
4743
4744    item->signals = eina_list_append(item->signals, wisd);
4745 }
4746
4747 EAPI void *
4748 _elm_widget_item_signal_callback_del(Elm_Widget_Item *item,
4749                                     const char *emission,
4750                                     const char *source,
4751                                     Elm_Widget_Item_Signal_Cb func)
4752 {
4753    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4754    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
4755
4756    Elm_Widget_Item_Signal_Data *wisd;
4757    Eina_List *l;
4758    void *data = NULL;
4759
4760    EINA_LIST_FOREACH(item->signals, l, wisd)
4761      {
4762         if ((wisd->func == func) && !strcmp(wisd->emission, emission) &&
4763             !strcmp(wisd->source, source))
4764           {
4765              item->signals = eina_list_remove_list(item->signals, l);
4766              eina_stringshare_del(wisd->emission);
4767              eina_stringshare_del(wisd->source);
4768              data = wisd->data;
4769
4770              if (_elm_widget_is(item->view))
4771                elm_object_signal_callback_del(item->view, emission, source,
4772                                               _elm_widget_item_signal_cb);
4773              else if (!strcmp(evas_object_type_get(item->view), "edje"))
4774                edje_object_signal_callback_del_full(item->view, emission,
4775                                                     source,
4776                                                     _elm_widget_item_signal_cb,
4777                                                     data);
4778           }
4779      }
4780
4781    return data;
4782 }
4783
4784 EAPI void
4785 _elm_widget_item_access_info_set(Elm_Widget_Item *item,
4786                                  const char *txt)
4787 {
4788    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4789    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4790
4791    if (item->access_info) eina_stringshare_del(item->access_info);
4792    if (!txt) item->access_info = NULL;
4793    else item->access_info = eina_stringshare_add(txt);
4794 }
4795
4796 /* happy debug functions */
4797 #ifdef ELM_DEBUG
4798 static void
4799 _sub_obj_tree_dump(const Evas_Object *obj,
4800                    int lvl)
4801 {
4802    int i;
4803
4804    for (i = 0; i < lvl * 3; i++)
4805      putchar(' ');
4806
4807    if (_elm_widget_is(obj))
4808      {
4809         Eina_List *l;
4810         INTERNAL_ENTRY;
4811         printf("+ %s(%p)\n",
4812                elm_widget_type_get(obj),
4813                obj);
4814         if (sd->resize_obj)
4815           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
4816         EINA_LIST_FOREACH(sd->subobjs, l, obj)
4817           {
4818              if (obj != sd->resize_obj)
4819                _sub_obj_tree_dump(obj, lvl + 1);
4820           }
4821      }
4822    else
4823      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
4824 }
4825
4826 static void
4827 _sub_obj_tree_dot_dump(const Evas_Object *obj,
4828                        FILE *output)
4829 {
4830    if (!_elm_widget_is(obj))
4831      return;
4832    INTERNAL_ENTRY;
4833
4834    Eina_Bool visible = evas_object_visible_get(obj);
4835    Eina_Bool disabled = elm_widget_disabled_get(obj);
4836    Eina_Bool focused = elm_widget_focus_get(obj);
4837    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
4838
4839    if (sd->parent_obj)
4840      {
4841         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
4842
4843         if (focused)
4844           fprintf(output, ", style=bold");
4845
4846         if (!visible)
4847           fprintf(output, ", color=gray28");
4848
4849         fprintf(output, " ];\n");
4850      }
4851
4852    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
4853                    "disabled: %d|focused: %d/%d|focus order:%d}\"",
4854            obj, obj, elm_widget_type_get(obj),
4855            evas_object_name_get(obj), visible, disabled, focused, can_focus,
4856            sd->focus_order);
4857
4858    if (focused)
4859      fprintf(output, ", style=bold");
4860
4861    if (!visible)
4862      fprintf(output, ", fontcolor=gray28");
4863
4864    if ((disabled) || (!visible))
4865      fprintf(output, ", color=gray");
4866
4867    fprintf(output, " ];\n");
4868
4869    Eina_List *l;
4870    Evas_Object *o;
4871    EINA_LIST_FOREACH(sd->subobjs, l, o)
4872      _sub_obj_tree_dot_dump(o, output);
4873 }
4874
4875 #endif
4876
4877 EAPI void
4878 elm_widget_tree_dump(const Evas_Object *top)
4879 {
4880 #ifdef ELM_DEBUG
4881    if (!_elm_widget_is(top))
4882      return;
4883    _sub_obj_tree_dump(top, 0);
4884 #else
4885    (void)top;
4886    return;
4887 #endif
4888 }
4889
4890 EAPI void
4891 elm_widget_tree_dot_dump(const Evas_Object *top,
4892                          FILE *output)
4893 {
4894 #ifdef ELM_DEBUG
4895    if (!_elm_widget_is(top))
4896      return;
4897    fprintf(output, "graph " " { node [shape=record];\n");
4898    _sub_obj_tree_dot_dump(top, output);
4899    fprintf(output, "}\n");
4900 #else
4901    (void)top;
4902    (void)output;
4903    return;
4904 #endif
4905 }