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