[atspi] change accessible name to const char* - it is same with accessible description
[platform/upstream/elementary.git] / src / lib / elm_widget.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8 #define ELM_WIDGET_ITEM_PROTECTED
9 #include <Elementary.h>
10
11 #include "elm_priv.h"
12 #include "elm_widget_container.h"
13 #include "elm_interface_scrollable.h"
14
15 #define MY_CLASS ELM_WIDGET_CLASS
16
17 #define MY_CLASS_NAME "Elm_Widget"
18 #define MY_CLASS_NAME_LEGACY "elm_widget"
19
20 #define ELM_WIDGET_DATA_GET(o, wd)                             \
21   Elm_Widget_Smart_Data *wd = eo_data_scope_get(o, MY_CLASS)
22
23 #define API_ENTRY                                    \
24   ELM_WIDGET_DATA_GET(obj, sd);                      \
25   if ((!sd) || (!_elm_widget_is(obj)))
26 #define INTERNAL_ENTRY                               \
27   ELM_WIDGET_DATA_GET(obj, sd);                      \
28   if (!sd) return
29
30 #define ELM_WIDGET_FOCUS_GET(obj)                                          \
31   (eo_isa(obj, ELM_WIDGET_CLASS) &&                                    \
32    ((_elm_access_auto_highlight_get()) ? (elm_widget_highlight_get(obj)) : \
33                                          (elm_widget_focus_get(obj))))
34
35 const char SIG_WIDGET_FOCUSED[] = "focused";
36 const char SIG_WIDGET_UNFOCUSED[] = "unfocused";
37 const char SIG_WIDGET_LANG_CHANGED[] = "language,changed";
38 const char SIG_WIDGET_ACCESS_CHANGED[] = "access,changed";
39
40 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
41 const char SIG_WIDGET_ATSPI_HIGHLIGHTED[] = "atspi,highlighted";
42 const char SIG_WIDGET_ATSPI_UNHIGHLIGHTED[] = "atspi,unhighlighted";
43 //
44
45 typedef struct _Elm_Event_Cb_Data         Elm_Event_Cb_Data;
46 typedef struct _Elm_Label_Data            Elm_Label_Data;
47 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
48
49 struct _Elm_Event_Cb_Data
50 {
51    Elm_Event_Cb func;
52    const void  *data;
53 };
54
55 struct _Elm_Label_Data
56 {
57    const char *part;
58    const char *text;
59 };
60
61 struct _Elm_Translate_String_Data
62 {
63    EINA_INLIST;
64    Eina_Stringshare *id;
65    Eina_Stringshare *domain;
66    Eina_Stringshare *string;
67    Eina_Bool   preset : 1;
68 };
69
70 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
71 static void
72 _elm_widget_evas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir);
73 /* END */
74
75 /* local subsystem globals */
76 static unsigned int focus_order = 0;
77
78 static inline Eina_Bool
79 _elm_widget_is(const Evas_Object *obj)
80 {
81    return eo_isa(obj, MY_CLASS);
82 }
83
84 static inline Eina_Bool
85 _is_focusable(Evas_Object *obj)
86 {
87    API_ENTRY return EINA_FALSE;
88    return sd->can_focus || (sd->child_can_focus);
89 }
90
91 static inline Eina_Bool
92 _is_focused(Evas_Object *obj)
93 {
94    API_ENTRY return EINA_FALSE;
95    return sd->focused;
96 }
97
98 static inline Eina_Bool
99 _elm_scrollable_is(const Evas_Object *obj)
100 {
101    INTERNAL_ENTRY EINA_FALSE;
102    return
103       eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
104 }
105
106 static void
107 elm_widget_disabled_internal(Eo *obj, Eina_Bool disabled);
108 static Eina_Bool
109 _on_sub_obj_del(void *data,
110                 Eo *obj,
111                 const Eo_Event_Description *desc,
112                 void *event_info);
113 static Eina_Bool
114 _on_sub_obj_hide(void *data,
115                  Eo *obj,
116                  const Eo_Event_Description *desc,
117                  void *event_info);
118 static Eina_Bool
119 _propagate_event(void *data,
120                  Eo *obj,
121                  const Eo_Event_Description *desc,
122                  void *event_info);
123
124 EO_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks,
125                           { EVAS_OBJECT_EVENT_DEL, _on_sub_obj_del },
126                           { EVAS_OBJECT_EVENT_HIDE, _on_sub_obj_hide });
127 EO_CALLBACKS_ARRAY_DEFINE(efl_subitems_callbacks,
128                           { EVAS_OBJECT_EVENT_DEL, _on_sub_obj_del });
129 EO_CALLBACKS_ARRAY_DEFINE(focus_callbacks,
130                           { EVAS_OBJECT_EVENT_KEY_DOWN, _propagate_event },
131                           { EVAS_OBJECT_EVENT_KEY_UP, _propagate_event },
132                           { EVAS_OBJECT_EVENT_MOUSE_WHEEL, _propagate_event });
133
134 static inline void
135 _callbacks_add(Eo *widget, void *data)
136 {
137    if (_elm_widget_is(widget))
138      {
139         eo_do(widget,
140               eo_event_callback_array_add(elm_widget_subitems_callbacks(), data));
141      }
142    else
143      {
144         eo_do(widget,
145               eo_event_callback_array_add(efl_subitems_callbacks(), data));
146      }
147 }
148
149 static inline void
150 _callbacks_del(Eo *widget, void *data)
151 {
152    if (_elm_widget_is(widget))
153      {
154         eo_do(widget,
155               eo_event_callback_array_del(elm_widget_subitems_callbacks(), data));
156      }
157    else
158      {
159         eo_do(widget,
160               eo_event_callback_array_del(efl_subitems_callbacks(), data));
161      }
162 }
163
164 void
165 _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *eo_it)
166 {
167    const char *str;
168
169    if (!eo_it) return;
170    if (eo_isa(eo_it, ELM_WIDGET_ITEM_CLASS))
171      {
172         Elm_Widget_Item_Data *it = eo_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
173
174         if (eo_isa(it->view, ELM_LAYOUT_CLASS))
175           str = edje_object_data_get(elm_layout_edje_get(it->view), "focus_highlight");
176         else
177           str = edje_object_data_get(it->view, "focus_highlight");
178      }
179    else
180       str = edje_object_data_get(((Elm_Widget_Item_Data *)eo_it)->view, "focus_highlight");
181    if ((str) && (!strcmp(str, "on")))
182      elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
183    else
184      elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
185 }
186
187 void
188 _elm_widget_focus_highlight_start(const Evas_Object *obj)
189 {
190    Evas_Object *top = elm_widget_top_get(obj);
191
192    if (top && eo_isa(top, ELM_WIN_CLASS))
193      _elm_win_focus_highlight_start(top);
194 }
195
196 Evas_Object *
197 _elm_widget_focus_highlight_object_get(const Evas_Object *obj)
198 {
199    Evas_Object *top = elm_widget_top_get(obj);
200
201    if (top && eo_isa(top, ELM_WIN_CLASS))
202      return _elm_win_focus_highlight_object_get(top);
203    return NULL;
204 }
205
206 EAPI Eina_Bool
207 elm_widget_focus_highlight_enabled_get(const Evas_Object *obj)
208 {
209    const Evas_Object *win = elm_widget_top_get(obj);
210
211    if (win && eo_isa(win, ELM_WIN_CLASS))
212      return elm_win_focus_highlight_enabled_get(win);
213    return EINA_FALSE;
214 }
215
216 /**
217  * @internal
218  *
219  * Resets the mirrored mode from the system mirror mode for widgets that are in
220  * automatic mirroring mode. This function does not call elm_widget_theme.
221  *
222  * @param obj The widget.
223  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
224  */
225 static void
226 _elm_widget_mirrored_reload(Evas_Object *obj)
227 {
228    API_ENTRY return;
229    Eina_Bool mirrored = elm_config_mirrored_get();
230
231    if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
232      {
233         sd->is_mirrored = mirrored;
234      }
235 }
236
237 EOLIAN static Eina_Bool
238 _elm_widget_on_focus_region(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Coord *x EINA_UNUSED, Evas_Coord *y EINA_UNUSED, Evas_Coord *w EINA_UNUSED, Evas_Coord *h EINA_UNUSED)
239 {
240    WRN("The %s widget does not implement the \"on_focus_region\" function.",
241        eo_class_name_get(eo_class_get(obj)));
242
243    return EINA_FALSE;
244 }
245
246 static void
247 _parents_focus(Evas_Object *obj)
248 {
249    for (; obj; obj = elm_widget_parent_get(obj))
250      {
251         INTERNAL_ENTRY;
252         if (sd->focused) return;
253         sd->focused = 1;
254      }
255 }
256
257 static void
258 _parents_unfocus(Evas_Object *obj)
259 {
260    for (; obj; obj = elm_widget_parent_get(obj))
261      {
262         INTERNAL_ENTRY;
263         if (!sd->focused) return;
264         sd->focused = 0;
265      }
266 }
267
268 static Eina_Bool
269 _on_sub_obj_hide(void *data EINA_UNUSED,
270                  Eo *obj,
271                  const Eo_Event_Description *desc EINA_UNUSED,
272                  void *event_info EINA_UNUSED)
273 {
274    elm_widget_focus_hide_handle(obj);
275    return EO_CALLBACK_CONTINUE;
276 }
277
278 static Eina_Bool
279 _on_sub_obj_del(void *data,
280                 Eo *obj,
281                 const Eo_Event_Description *desc EINA_UNUSED,
282                 void *event_info EINA_UNUSED)
283 {
284    ELM_WIDGET_DATA_GET(data, sd);
285
286    if (_elm_widget_is(obj))
287      {
288         if (_is_focused((Eo *)obj)) _parents_unfocus(sd->obj);
289      }
290    if (obj == sd->resize_obj)
291      {
292         /* already dels sub object */
293         elm_widget_resize_object_set(sd->obj, NULL, EINA_TRUE);
294      }
295    else if (obj == sd->hover_obj)
296      {
297         sd->hover_obj = NULL;
298      }
299    else
300      {
301         if (!elm_widget_sub_object_del(sd->obj, obj))
302           ERR("failed to remove sub object %p from %p\n", obj, sd->obj);
303      }
304
305    return EO_CALLBACK_CONTINUE;
306 }
307
308 static const Evas_Smart_Cb_Description _smart_callbacks[] =
309 {
310    {SIG_WIDGET_FOCUSED, ""},
311    {SIG_WIDGET_UNFOCUSED, ""},
312    {SIG_WIDGET_LANG_CHANGED, ""},
313    {SIG_WIDGET_ACCESS_CHANGED, ""},
314    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
315    {SIG_WIDGET_ATSPI_HIGHLIGHTED, ""},
316    {SIG_WIDGET_ATSPI_UNHIGHLIGHTED, ""},
317    //
318    {NULL, NULL}
319 };
320
321 static void
322 _obj_mouse_down(void *data,
323                 Evas *e EINA_UNUSED,
324                 Evas_Object *obj EINA_UNUSED,
325                 void *event_info)
326 {
327    Evas_Object *top;
328
329    ELM_WIDGET_DATA_GET(data, sd);
330    Evas_Event_Mouse_Down *ev = event_info;
331    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
332
333    top = elm_widget_top_get(data);
334    if (top && eo_isa(top, ELM_WIN_CLASS)) _elm_win_focus_auto_hide(top);
335    sd->still_in = EINA_TRUE;
336 }
337
338 static void
339 _obj_mouse_move(void *data,
340                 Evas *e EINA_UNUSED,
341                 Evas_Object *obj,
342                 void *event_info)
343 {
344    ELM_WIDGET_DATA_GET(data, sd);
345    Evas_Event_Mouse_Move *ev = event_info;
346    if (!sd->still_in) return;
347
348    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
349      sd->still_in = EINA_FALSE;
350    else
351      {
352         Evas_Coord x, y, w, h;
353         evas_object_geometry_get(obj, &x, &y, &w, &h);
354         if (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y))
355           sd->still_in = EINA_FALSE;
356      }
357 }
358
359 static void
360 _obj_mouse_up(void *data,
361               Evas *e EINA_UNUSED,
362               Evas_Object *obj,
363               void *event_info EINA_UNUSED)
364 {
365    ELM_WIDGET_DATA_GET(data, sd);
366    if (sd->still_in &&
367        (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_CLICK))
368      elm_widget_focus_mouse_up_handle(obj);
369
370    sd->still_in = EINA_FALSE;
371 }
372
373 static void
374 _obj_mouse_in(void *data,
375               Evas *e EINA_UNUSED,
376               Evas_Object *obj,
377               void *event_info EINA_UNUSED)
378 {
379    ELM_WIDGET_DATA_GET(data, sd);
380    if (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN)
381      elm_widget_focus_mouse_up_handle(obj);
382 }
383
384 EOLIAN static void
385 _elm_widget_evas_object_smart_add(Eo *obj, Elm_Widget_Smart_Data *priv)
386 {
387
388    priv->obj = obj;
389    priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale
390                                           * settings */
391    priv->focus_move_policy_auto_mode = EINA_TRUE;
392    priv->focus_region_show_mode = ELM_FOCUS_REGION_SHOW_WIDGET;
393    elm_widget_can_focus_set(obj, EINA_TRUE);
394    priv->is_mirrored = elm_config_mirrored_get();
395    priv->focus_move_policy = _elm_config->focus_move_policy;
396
397    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
398                                   _obj_mouse_down, obj);
399    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
400                                   _obj_mouse_move, obj);
401    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
402                                   _obj_mouse_up, obj);
403    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_IN,
404                                   _obj_mouse_in, obj);
405    /* just a helper for inheriting classes */
406    if (priv->resize_obj)
407      {
408         Evas_Object *r_obj = priv->resize_obj;
409         priv->resize_obj = NULL;
410
411         elm_widget_resize_object_set(obj, r_obj, EINA_TRUE);
412      }
413 }
414
415 static void
416 _if_focused_revert(Evas_Object *obj,
417                    Eina_Bool can_focus_only)
418 {
419    Evas_Object *top;
420    Evas_Object *newest = NULL;
421    unsigned int newest_focus_order = 0;
422
423    INTERNAL_ENTRY;
424
425    if (!sd->focused) return;
426    if (!sd->parent_obj) return;
427
428    top = elm_widget_top_get(sd->parent_obj);
429    if (top)
430      {
431         newest = elm_widget_newest_focus_order_get
432            (top, &newest_focus_order, can_focus_only);
433         if (newest)
434           {
435              if (newest == top)
436                {
437                   ELM_WIDGET_DATA_GET(newest, sd2);
438                   if (!sd2) return;
439
440                   if (!_is_focused(newest))
441                     elm_widget_focus_steal(newest, NULL);
442                   else
443                     {
444                        if (sd2->resize_obj && _is_focused(sd2->resize_obj))
445                          elm_widget_focused_object_clear(sd2->resize_obj);
446                        else
447                          {
448                             const Eina_List *l;
449                             Evas_Object *child;
450                             EINA_LIST_FOREACH(sd2->subobjs, l, child)
451                               {
452                                  if (_is_focused(child))
453                                    {
454                                       elm_widget_focused_object_clear(child);
455                                       break;
456                                    }
457                               }
458                          }
459                     }
460                   evas_object_focus_set(newest, EINA_TRUE);
461                }
462              else
463                {
464                   elm_object_focus_set(newest, EINA_FALSE);
465                   elm_object_focus_set(newest, EINA_TRUE);
466                }
467           }
468      }
469 }
470
471 EOLIAN static void
472 _elm_widget_evas_object_smart_del(Eo *obj, Elm_Widget_Smart_Data *sd)
473 {
474    Evas_Object *sobj;
475    Elm_Translate_String_Data *ts;
476    Elm_Event_Cb_Data *ecb;
477
478    if (sd->hover_obj)
479      {
480         /* detach it from us */
481         _callbacks_del(sd->hover_obj, obj);
482         sd->hover_obj = NULL;
483      }
484
485    while (sd->subobjs)
486      {
487         sobj = eina_list_data_get(sd->subobjs);
488
489         /* let the objects clean-up themselves and get rid of this list */
490         if (!elm_widget_sub_object_del(obj, sobj))
491           {
492              ERR("failed to remove sub object %p from %p\n", sobj, obj);
493              sd->subobjs = eina_list_remove_list
494                  (sd->subobjs, sd->subobjs);
495           }
496         evas_object_del(sobj);
497      }
498    sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
499    sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
500    while (sd->translate_strings)
501      {
502         ts = EINA_INLIST_CONTAINER_GET(sd->translate_strings,
503                                        Elm_Translate_String_Data);
504         eina_stringshare_del(ts->id);
505         eina_stringshare_del(ts->domain);
506         eina_stringshare_del(ts->string);
507         sd->translate_strings = eina_inlist_remove(sd->translate_strings,
508                                                    sd->translate_strings);
509         free(ts);
510      }
511
512    EINA_LIST_FREE(sd->event_cb, ecb)
513       free(ecb);
514
515    eina_stringshare_del(sd->style);
516    if (sd->theme) elm_theme_free(sd->theme);
517    _if_focused_revert(obj, EINA_TRUE);
518    elm_widget_focus_custom_chain_unset(obj);
519    eina_stringshare_del(sd->access_info);
520    eina_stringshare_del(sd->accessible_name);
521    evas_object_smart_data_set(obj, NULL);
522 }
523
524 static void
525 _smart_reconfigure(Elm_Widget_Smart_Data *sd)
526 {
527    if (sd->resize_obj)
528      {
529         evas_object_move(sd->resize_obj, sd->x, sd->y);
530         evas_object_resize(sd->resize_obj, sd->w, sd->h);
531      }
532    if (sd->hover_obj)
533      {
534         evas_object_move(sd->hover_obj, sd->x, sd->y);
535         evas_object_resize(sd->hover_obj, sd->w, sd->h);
536      }
537 }
538
539 EOLIAN static void
540 _elm_widget_evas_object_smart_move(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord x, Evas_Coord y)
541 {
542    sd->x = x;
543    sd->y = y;
544
545    _smart_reconfigure(sd);
546 }
547
548 EOLIAN static void
549 _elm_widget_evas_object_smart_resize(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord w, Evas_Coord h)
550 {
551    sd->w = w;
552    sd->h = h;
553
554    _smart_reconfigure(sd);
555 }
556
557 EOLIAN static void
558 _elm_widget_evas_object_smart_show(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
559 {
560    Eina_Iterator *it;
561    Evas_Object *o;
562
563    if (_elm_atspi_enabled())
564      {
565         Eo *parent;
566         eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
567         if (parent) elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, obj);
568      }
569
570    it = evas_object_smart_iterator_new(obj);
571    EINA_ITERATOR_FOREACH(it, o)
572      {
573        if (evas_object_data_get(o, "_elm_leaveme")) continue;
574        evas_object_show(o);
575      }
576    eina_iterator_free(it);
577
578    if (_elm_atspi_enabled())
579      {
580         elm_interface_atspi_accessible_added(obj);
581         if (_elm_widget_onscreen_is(obj))
582            elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, EINA_TRUE);
583      }
584 }
585
586 EOLIAN static void
587 _elm_widget_evas_object_smart_hide(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
588 {
589    Eina_Iterator *it;
590    Evas_Object *o;
591
592    it = evas_object_smart_iterator_new(obj);
593    EINA_ITERATOR_FOREACH(it, o)
594      {
595         if (evas_object_data_get(o, "_elm_leaveme")) continue;
596         evas_object_hide(o);
597      }
598    eina_iterator_free(it);
599
600    if (_elm_atspi_enabled())
601      elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, EINA_FALSE);
602 }
603
604 EOLIAN static void
605 _elm_widget_evas_object_smart_color_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, int r, int g, int b, int a)
606 {
607    Eina_Iterator *it;
608    Evas_Object *o;
609
610    it = evas_object_smart_iterator_new(obj);
611    EINA_ITERATOR_FOREACH(it, o)
612      {
613        if (evas_object_data_get(o, "_elm_leaveme")) continue;
614        evas_object_color_set(o, r, g, b, a);
615      }
616    eina_iterator_free(it);
617 }
618
619 EOLIAN static void
620 _elm_widget_evas_object_smart_clip_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *clip)
621 {
622    Eina_Iterator *it;
623    Evas_Object *o;
624
625    it = evas_object_smart_iterator_new(obj);
626    EINA_ITERATOR_FOREACH(it, o)
627      {
628        if (evas_object_data_get(o, "_elm_leaveme")) continue;
629        evas_object_clip_set(o, clip);
630      }
631    eina_iterator_free(it);
632 }
633
634 EOLIAN static void
635 _elm_widget_evas_object_smart_clip_unset(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
636 {
637    Eina_Iterator *it;
638    Evas_Object *o;
639
640    it = evas_object_smart_iterator_new(obj);
641    EINA_ITERATOR_FOREACH(it, o)
642      {
643        if (evas_object_data_get(o, "_elm_leaveme")) continue;
644        evas_object_clip_unset(o);
645      }
646    eina_iterator_free(it);
647 }
648
649 EOLIAN static void
650 _elm_widget_evas_object_smart_calculate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
651 {
652    /* a NO-OP, on the base */
653 }
654
655 EOLIAN static void
656 _elm_widget_evas_object_smart_member_add(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
657 {
658    int r, g, b, a;
659    eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(child));
660
661    if (evas_object_data_get(child, "_elm_leaveme")) return;
662
663    evas_object_color_get(obj, &r, &g, &b, &a);
664    evas_object_color_set(child, r, g, b, a);
665
666    evas_object_clip_set(child, evas_object_clip_get(obj));
667
668    if (evas_object_visible_get(obj))
669      evas_object_show(child);
670    else
671      evas_object_hide(child);
672 }
673
674 EOLIAN static void
675 _elm_widget_evas_object_smart_member_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
676 {
677    if (!evas_object_data_get(child, "_elm_leaveme"))
678       evas_object_clip_unset(child);
679    eo_do_super(obj, MY_CLASS, evas_obj_smart_member_del(child));
680 }
681
682 // internal funcs
683 /**
684  * @internal
685  *
686  * Check if the widget has its own focus next function.
687  *
688  * @param obj The widget.
689  * @return focus next function is implemented/unimplemented.
690  * (@c EINA_TRUE = implemented/@c EINA_FALSE = unimplemented.)
691  */
692 static inline Eina_Bool
693 _elm_widget_focus_chain_manager_is(const Evas_Object *obj)
694 {
695    ELM_WIDGET_CHECK(obj) EINA_FALSE;
696
697    Eina_Bool manager_is = EINA_FALSE;
698    eo_do((Eo *)obj, manager_is = elm_obj_widget_focus_next_manager_is());
699    return manager_is;
700 }
701
702 static inline Eina_Bool
703 _internal_elm_widget_focus_direction_manager_is(const Evas_Object *obj)
704 {
705    ELM_WIDGET_CHECK(obj) EINA_FALSE;
706
707    Eina_Bool manager_is = EINA_FALSE;
708    eo_do((Eo *)obj, manager_is = elm_obj_widget_focus_direction_manager_is());
709    return manager_is;
710 }
711
712 static void
713 _propagate_x_drag_lock(Evas_Object *obj,
714                        int dir)
715 {
716    INTERNAL_ENTRY;
717    if (sd->parent_obj)
718      {
719         ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
720         if (sd2)
721           {
722              sd2->child_drag_x_locked += dir;
723              _propagate_x_drag_lock(sd->parent_obj, dir);
724           }
725      }
726 }
727
728 static void
729 _propagate_y_drag_lock(Evas_Object *obj,
730                        int dir)
731 {
732    INTERNAL_ENTRY;
733    if (sd->parent_obj)
734      {
735         ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
736         if (sd2)
737           {
738              sd2->child_drag_y_locked += dir;
739              _propagate_y_drag_lock(sd->parent_obj, dir);
740           }
741      }
742 }
743
744 static Eina_Bool
745 _propagate_event(void *data EINA_UNUSED,
746                  Eo *obj,
747                  const Eo_Event_Description *desc,
748                  void *event_info)
749 {
750    INTERNAL_ENTRY EO_CALLBACK_CONTINUE;
751    Evas_Callback_Type type;
752    Evas_Event_Flags *event_flags = NULL;
753
754    if (desc == EVAS_OBJECT_EVENT_KEY_DOWN)
755      {
756         Evas_Event_Key_Down *ev = event_info;
757         event_flags = &(ev->event_flags);
758         type = EVAS_CALLBACK_KEY_DOWN;
759      }
760    else if (desc == EVAS_OBJECT_EVENT_KEY_UP)
761      {
762         Evas_Event_Key_Up *ev = event_info;
763         event_flags = &(ev->event_flags);
764         type = EVAS_CALLBACK_KEY_UP;
765      }
766    else if (desc == EVAS_OBJECT_EVENT_MOUSE_WHEEL)
767      {
768         Evas_Event_Mouse_Wheel *ev = event_info;
769         event_flags = &(ev->event_flags);
770         type = EVAS_CALLBACK_MOUSE_WHEEL;
771      }
772    else
773      return EO_CALLBACK_CONTINUE;
774
775    elm_widget_event_propagate(obj, type, event_info, event_flags);
776
777    return EO_CALLBACK_CONTINUE;
778 }
779
780 /**
781  * @internal
782  *
783  * If elm_widget_focus_region_get() returns EINA_FALSE, this function will
784  * ignore region show action.
785  */
786 EOLIAN static void
787 _elm_widget_focus_region_show(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
788 {
789    Evas_Coord x, y, w, h, ox, oy;
790    Evas_Object *o;
791
792    o = elm_widget_parent_get(obj);
793    if (!o) return;
794
795    if (!elm_widget_focus_region_get(obj, &x, &y, &w, &h))
796      return;
797
798    evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
799
800    while (o)
801      {
802         Evas_Coord px, py;
803         evas_object_geometry_get(o, &px, &py, NULL, NULL);
804
805         if (_elm_scrollable_is(o) && !elm_widget_disabled_get(o))
806           {
807              Evas_Coord sx, sy;
808              eo_do(o, elm_interface_scrollable_content_region_get(&sx, &sy, NULL, NULL));
809
810              // Get the object's on_focus_region position relative to the scroller.
811              Evas_Coord rx, ry;
812              rx = ox + x - px + sx;
813              ry = oy + y - py + sy;
814
815              switch (_elm_config->focus_autoscroll_mode)
816                {
817                 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
818                    eo_do(o, elm_interface_scrollable_content_region_show(rx, ry, w, h));
819                    break;
820                 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
821                    eo_do(o, elm_interface_scrollable_region_bring_in(rx, ry, w, h));
822                    break;
823                 default:
824                    break;
825                }
826
827              if (!elm_widget_focus_region_get(o, &x, &y, &w, &h))
828                {
829                   o = elm_widget_parent_get(o);
830                   continue;
831                }
832           }
833         else
834           {
835              x += ox - px;
836              y += oy - py;
837              ox = px;
838              oy = py;
839           }
840         o = elm_widget_parent_get(o);
841      }
842 }
843
844 EOLIAN static Eina_Bool
845 _elm_widget_focus_highlight_style_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *style)
846 {
847    if (eina_stringshare_replace(&sd->focus_highlight_style, style)) return EINA_TRUE;
848    return EINA_FALSE;
849 }
850
851 EOLIAN static const char*
852 _elm_widget_focus_highlight_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
853 {
854    return sd->focus_highlight_style;
855 }
856
857 static void
858 _parent_focus(Evas_Object *obj, Elm_Object_Item *item)
859 {
860    API_ENTRY return;
861
862    if (sd->focused) return;
863
864    Evas_Object *o = elm_widget_parent_get(obj);
865    sd->focus_order_on_calc = EINA_TRUE;
866
867    if (o) _parent_focus(o, item);
868
869    if (!sd->focus_order_on_calc)
870      return;  /* we don't want to override it if by means of any of the
871                  callbacks below one gets to calculate our order
872                  first. */
873
874    focus_order++;
875    sd->focus_order = focus_order;
876    sd->focused = EINA_TRUE;
877
878    if (sd->top_win_focused)
879      eo_do(obj, elm_obj_widget_on_focus(item));
880    sd->focus_order_on_calc = EINA_FALSE;
881
882    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
883      _elm_access_highlight_set(obj);
884 }
885
886 static void
887 _elm_object_focus_chain_del_cb(void *data,
888                                Evas *e EINA_UNUSED,
889                                Evas_Object *obj,
890                                void *event_info EINA_UNUSED)
891 {
892    ELM_WIDGET_DATA_GET(data, sd);
893
894    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
895 }
896
897 EOLIAN static void
898 _elm_widget_parent_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *parent EINA_UNUSED)
899 {
900 }
901
902 EAPI Eina_Bool
903 elm_widget_api_check(int ver)
904 {
905    if (ver != ELM_INTERNAL_API_VERSION)
906      {
907         CRI("Elementary widget api versions do not match");
908         return EINA_FALSE;
909      }
910    return EINA_TRUE;
911 }
912
913 EAPI Eina_Bool
914 elm_widget_access(Evas_Object *obj,
915                   Eina_Bool is_access)
916 {
917    const Eina_List *l;
918    Evas_Object *child;
919    Eina_Bool ret = EINA_TRUE;
920
921    API_ENTRY return EINA_FALSE;
922    EINA_LIST_FOREACH(sd->subobjs, l, child)
923      {
924         if (elm_widget_is(child))
925           ret &= elm_widget_access(child, is_access);
926      }
927
928    eo_do(obj, elm_obj_widget_access(is_access));
929    eo_do(obj, eo_event_callback_call(ELM_WIDGET_EVENT_ACCESS_CHANGED, NULL));
930
931    return ret;
932 }
933
934 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
935 //register/unregister access objects accordingly.
936 EAPI Eina_Bool
937 elm_widget_atspi(Evas_Object *obj,
938                   Eina_Bool is_atspi)
939 {
940    const Eina_List *l;
941    Evas_Object *child;
942    Eina_Bool ret = EINA_TRUE;
943
944    API_ENTRY return EINA_FALSE;
945    EINA_LIST_FOREACH(sd->subobjs, l, child)
946      {
947         if (elm_widget_is(child))
948           ret &= elm_widget_atspi(child, is_atspi);
949      }
950    eo_do(obj, elm_obj_widget_atspi(is_atspi));
951
952    return ret;
953 }
954
955 EOLIAN static void
956 _elm_widget_atspi(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_atspi EINA_UNUSED)
957 {
958 }
959 //
960
961 EOLIAN static void
962 _elm_widget_access(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_access EINA_UNUSED)
963 {
964 }
965
966 EAPI Elm_Theme_Apply
967 elm_widget_theme(Evas_Object *obj)
968 {
969    const Eina_List *l;
970    Evas_Object *child;
971    Elm_Tooltip *tt;
972    Elm_Cursor *cur;
973    Elm_Theme_Apply ret = ELM_THEME_APPLY_SUCCESS;
974
975    API_ENTRY return ELM_THEME_APPLY_FAILED;
976
977    EINA_LIST_FOREACH(sd->subobjs, l, child)
978      if (_elm_widget_is(child))
979        ret &= elm_widget_theme(child);
980
981    if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
982
983    EINA_LIST_FOREACH(sd->tooltips, l, tt)
984      elm_tooltip_theme(tt);
985    EINA_LIST_FOREACH(sd->cursors, l, cur)
986      elm_cursor_theme(cur);
987
988    Elm_Theme_Apply ret2 = ELM_THEME_APPLY_FAILED;
989    eo_do(obj, ret2 = elm_obj_widget_theme_apply());
990    ret &= ret2;
991
992    return ret;
993 }
994
995 EAPI void
996 elm_widget_theme_specific(Evas_Object *obj,
997                           Elm_Theme *th,
998                           Eina_Bool force)
999 {
1000    const Eina_List *l;
1001    Evas_Object *child;
1002    Elm_Tooltip *tt;
1003    Elm_Cursor *cur;
1004    Elm_Theme *th2, *thdef;
1005
1006    API_ENTRY return;
1007
1008    thdef = elm_theme_default_get();
1009    if (!th) th = thdef;
1010    if (!force)
1011      {
1012         th2 = sd->theme;
1013         if (!th2) th2 = thdef;
1014         while (th2)
1015           {
1016              if (th2 == th)
1017                {
1018                   force = EINA_TRUE;
1019                   break;
1020                }
1021              if (th2 == thdef) break;
1022              th2 = th2->ref_theme;
1023              if (!th2) th2 = thdef;
1024           }
1025      }
1026    if (!force) return;
1027    EINA_LIST_FOREACH(sd->subobjs, l, child)
1028      {
1029         if (elm_widget_is(child))
1030           elm_widget_theme_specific(child, th, force);
1031      }
1032    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
1033    EINA_LIST_FOREACH(sd->tooltips, l, tt)
1034      elm_tooltip_theme(tt);
1035    EINA_LIST_FOREACH(sd->cursors, l, cur)
1036      elm_cursor_theme(cur);
1037    eo_do(obj, elm_obj_widget_theme_apply());
1038 }
1039
1040 EOLIAN static Elm_Theme_Apply
1041 _elm_widget_theme_apply(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
1042 {
1043    _elm_widget_mirrored_reload(obj);
1044    if (elm_widget_disabled_get(obj))
1045      elm_widget_disabled_internal(obj, elm_widget_disabled_get(obj));
1046
1047    return ELM_THEME_APPLY_SUCCESS;
1048 }
1049
1050 /**
1051  * @internal
1052  *
1053  * Returns the widget's mirrored mode.
1054  *
1055  * @param obj The widget.
1056  * @return mirrored mode of the object.
1057  *
1058  **/
1059 EOLIAN static Eina_Bool
1060 _elm_widget_mirrored_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1061 {
1062    return sd->is_mirrored;
1063 }
1064
1065 /**
1066  * @internal
1067  *
1068  * Sets the widget's mirrored mode.
1069  *
1070  * @param obj The widget.
1071  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
1072  */
1073 EOLIAN static void
1074 _elm_widget_mirrored_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool mirrored)
1075 {
1076    mirrored = !!mirrored;
1077
1078    if (sd->is_mirrored == mirrored) return;
1079
1080    sd->is_mirrored = mirrored;
1081    elm_widget_theme(obj);
1082 }
1083
1084 /**
1085  * Returns the widget's mirrored mode setting.
1086  *
1087  * @param obj The widget.
1088  * @return mirrored mode setting of the object.
1089  *
1090  **/
1091 EOLIAN static Eina_Bool
1092 _elm_widget_mirrored_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1093 {
1094    return sd->mirrored_auto_mode;
1095 }
1096
1097 /**
1098  * @internal
1099  *
1100  * Sets the widget's mirrored mode setting.
1101  * When widget in automatic mode, it follows the system mirrored mode set by
1102  * elm_mirrored_set().
1103  * @param obj The widget.
1104  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
1105  */
1106 EOLIAN static void
1107 _elm_widget_mirrored_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
1108 {
1109    if (sd->mirrored_auto_mode != automatic)
1110      {
1111         sd->mirrored_auto_mode = automatic;
1112
1113         if (automatic)
1114           {
1115              elm_widget_mirrored_set(obj, elm_config_mirrored_get());
1116           }
1117      }
1118 }
1119
1120 EOLIAN static void
1121 _elm_widget_on_show_region_hook_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, region_hook_func_type func, void *data)
1122 {
1123    sd->on_show_region = func;
1124    sd->on_show_region_data = data;
1125 }
1126
1127 /*
1128  * @internal
1129  *
1130  * Add myself as a sub object of parent object
1131  *
1132  * @see elm_widget_sub_object_add()
1133  */
1134 EAPI Eina_Bool
1135 elm_widget_sub_object_parent_add(Evas_Object *sobj)
1136 {
1137    Eina_Bool ret = EINA_FALSE;
1138    Eo *parent = NULL;
1139
1140    eo_do(sobj, parent = eo_parent_get());
1141    if (!eo_isa(parent, ELM_WIDGET_CLASS))
1142      {
1143         ERR("You passed a wrong parent parameter (%p %s). "
1144             "Elementary widget's parent should be an elementary widget.", parent, evas_object_type_get(parent));
1145         return ret;
1146      }
1147
1148    eo_do(parent, ret = elm_obj_widget_sub_object_add(sobj));
1149
1150    return ret;
1151 }
1152
1153 /*
1154  * @internal
1155  *
1156  * Add sobj to obj's sub object.
1157  *
1158  * What does elementary sub object mean? This is unique in elementary, it
1159  * handles overall elementary policies between parent and sub objects.
1160  *   focus, access, deletion, theme, scale, mirror, scrollable child get,
1161  *   translate, name find, display mode set, orientation set, tree dump
1162  *   AUTOMATICALLY.
1163  *
1164  * @see elm_widget_sub_object_parent_add()
1165  */
1166 EOLIAN static Eina_Bool
1167 _elm_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1168 {
1169    Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
1170
1171    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1172
1173    if (sobj == sd->parent_obj)
1174      {
1175         /* in this case, sobj must be an elm widget, or something
1176          * very wrong is happening */
1177         if (!_elm_widget_is(sobj)) return EINA_FALSE;
1178
1179         if (!elm_widget_sub_object_del(sobj, obj)) return EINA_FALSE;
1180         WRN("You passed a parent object of obj = %p as the sub object = %p!",
1181             obj, sobj);
1182      }
1183
1184    if (_elm_widget_is(sobj))
1185      {
1186         ELM_WIDGET_DATA_GET(sobj, sdc);
1187
1188         if (sdc->parent_obj == obj) goto end;
1189         if (sdc->parent_obj)
1190           {
1191              if (!elm_widget_sub_object_del(sdc->parent_obj, sobj))
1192                return EINA_FALSE;
1193           }
1194         sdc->parent_obj = obj;
1195
1196         if (!sdc->on_create)
1197           eo_do(sobj, elm_obj_widget_orientation_set(sd->orient_mode));
1198         else
1199           sdc->orient_mode = sd->orient_mode;
1200
1201         if (!sdc->on_create)
1202           {
1203              if (!sdc->disabled && (elm_widget_disabled_get(obj)))
1204                {
1205                   elm_widget_focus_disabled_handle(sobj);
1206                   eo_do(sobj, elm_obj_widget_disable());
1207                }
1208           }
1209
1210         _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
1211
1212         /* update child focusable-ness on self and parents, now that a
1213          * focusable child got in */
1214         if (!sd->child_can_focus && (_is_focusable(sobj)))
1215           {
1216              Elm_Widget_Smart_Data *sdp = sd;
1217
1218              sdp->child_can_focus = EINA_TRUE;
1219              while (sdp->parent_obj)
1220                {
1221                   sdp = eo_data_scope_get(sdp->parent_obj, MY_CLASS);
1222
1223                   if (sdp->child_can_focus) break;
1224
1225                   sdp->child_can_focus = EINA_TRUE;
1226                }
1227           }
1228      }
1229    else
1230      {
1231         void *data = evas_object_data_get(sobj, "elm-parent");
1232
1233         if (data)
1234           {
1235              if (data == obj) goto end;
1236              if (!elm_widget_sub_object_del(data, sobj)) return EINA_FALSE;
1237           }
1238      }
1239    sd->subobjs = eina_list_append(sd->subobjs, sobj);
1240    evas_object_data_set(sobj, "elm-parent", obj);
1241
1242    _callbacks_add(sobj, obj);
1243    if (_elm_widget_is(sobj))
1244      {
1245         ELM_WIDGET_DATA_GET(sobj, sdc);
1246
1247         /* NOTE: In the following two lines, 'sobj' is correct. Do not change it.
1248          * Due to elementary's scale policy, scale and pscale can be different in
1249          * some cases. This happens when sobj's previous parent and new parent have
1250          * different scale value.
1251          * For example, if sobj's previous parent's scale is 5 and new parent's scale
1252          * is 2 while sobj's scale is 0. Then 'pscale' is 5 and 'scale' is 2. So we
1253          * need to reset sobj's scale to 5.
1254          * Note that each widget's scale is 0 by default.
1255          */
1256         double scale, pscale = elm_widget_scale_get(sobj);
1257         Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
1258
1259         scale = elm_widget_scale_get(sobj);
1260         th = elm_widget_theme_get(sobj);
1261         mirrored = elm_widget_mirrored_get(sobj);
1262
1263         if (!sdc->on_create)
1264           {
1265              if ((scale != pscale) || (th != pth) || (pmirrored != mirrored))
1266                elm_widget_theme(sobj);
1267           }
1268
1269         if (_is_focused(sobj)) _parents_focus(obj);
1270
1271         elm_widget_display_mode_set(sobj,
1272               evas_object_size_hint_display_mode_get(obj));
1273         if (_elm_atspi_enabled() && !sdc->on_create)
1274           {
1275              Elm_Interface_Atspi_Accessible *aparent;
1276              eo_do(sobj, aparent = elm_interface_atspi_accessible_parent_get());
1277              if (obj == aparent)
1278                 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, sobj);
1279           }
1280
1281         /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
1282         if (sdc->inherit_paragraph_direction &&
1283             (sdc->paragraph_direction != evas_object_paragraph_direction_get(obj)))
1284           {
1285              sdc->paragraph_direction = evas_object_paragraph_direction_get(obj);
1286              _elm_widget_evas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1287           }
1288         /* END */
1289      }
1290
1291 end:
1292    return EINA_TRUE;
1293 }
1294
1295 EOLIAN static Eina_Bool
1296 _elm_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1297 {
1298    Evas_Object *sobj_parent;
1299
1300    if (!sobj) return EINA_FALSE;
1301
1302    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1303
1304    sobj_parent = evas_object_data_del(sobj, "elm-parent");
1305    if (sobj_parent && sobj_parent != obj)
1306      {
1307         static int abort_on_warn = -1;
1308
1309         ERR("removing sub object %p (%s) from parent %p (%s), "
1310             "but elm-parent is different %p (%s)!",
1311             sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
1312             sobj_parent, elm_widget_type_get(sobj_parent));
1313
1314         if (EINA_UNLIKELY(abort_on_warn == -1))
1315           {
1316              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1317              else abort_on_warn = 0;
1318           }
1319         if (abort_on_warn == 1) abort();
1320
1321         return EINA_FALSE;
1322      }
1323
1324    if (_elm_widget_is(sobj))
1325      {
1326         if (_is_focused(sobj))
1327           {
1328              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1329              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1330           }
1331         if ((sd->child_can_focus) && (_is_focusable(sobj)))
1332           {
1333              Evas_Object *parent = obj;
1334
1335              /* update child focusable-ness on self and parents, now that a
1336               * focusable child is gone */
1337              while (parent)
1338                {
1339                   const Eina_List *l;
1340                   Evas_Object *subobj;
1341
1342                   ELM_WIDGET_DATA_GET(parent, sdp);
1343
1344                   sdp->child_can_focus = EINA_FALSE;
1345                   EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
1346                     {
1347                        if ((subobj != sobj) && (_is_focusable(subobj)))
1348                          {
1349                             sdp->child_can_focus = EINA_TRUE;
1350                             break;
1351                          }
1352                     }
1353
1354                   /* break again, child_can_focus went back to
1355                    * original value */
1356                   if (sdp->child_can_focus) break;
1357                   parent = sdp->parent_obj;
1358                }
1359           }
1360         if (_elm_atspi_enabled() && !sd->on_destroy)
1361           {
1362              Elm_Interface_Atspi_Accessible *aparent;
1363              eo_do(sobj, aparent = elm_interface_atspi_accessible_parent_get());
1364              if (obj == aparent)
1365                 elm_interface_atspi_accessible_children_changed_del_signal_emit(obj, sobj);
1366           }
1367
1368         ELM_WIDGET_DATA_GET(sobj, sdc);
1369         sdc->parent_obj = NULL;
1370
1371         /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
1372         if (sdc->inherit_paragraph_direction &&
1373             (sdc->paragraph_direction != EVAS_BIDI_DIRECTION_NEUTRAL))
1374           {
1375              sdc->paragraph_direction = EVAS_BIDI_DIRECTION_NEUTRAL;
1376              _elm_widget_evas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1377           }
1378         /* END */
1379      }
1380
1381    if (sd->resize_obj == sobj) sd->resize_obj = NULL;
1382
1383    sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1384
1385    _callbacks_del(sobj, obj);
1386
1387    return EINA_TRUE;
1388 }
1389
1390 /*
1391  * @internal
1392  *
1393  * a resize object is added to and deleted from the smart member and the sub object
1394  * of the parent if the third argument, Eina_Bool sub_obj, is set as EINA_TRUE.
1395  */
1396 EOLIAN static void
1397 _elm_widget_resize_object_set(Eo *obj, Elm_Widget_Smart_Data *sd,
1398                              Evas_Object *sobj,
1399                              Eina_Bool sub_obj)
1400 {
1401    Evas_Object *parent;
1402
1403    if (sd->resize_obj == sobj) return;
1404
1405    // orphan previous resize obj
1406    if (sd->resize_obj && sub_obj)
1407      {
1408         evas_object_clip_unset(sd->resize_obj);
1409         evas_object_smart_member_del(sd->resize_obj);
1410
1411         if (_elm_widget_is(sd->resize_obj))
1412           {
1413              if (_is_focused(sd->resize_obj)) _parents_unfocus(obj);
1414           }
1415         elm_widget_sub_object_del(obj, sd->resize_obj);
1416      }
1417
1418    sd->resize_obj = sobj;
1419    if (!sobj) return;
1420
1421    // orphan new resize obj
1422    parent = evas_object_data_get(sobj, "elm-parent");
1423    if (parent && parent != obj)
1424      {
1425         ELM_WIDGET_DATA_GET(parent, sdp);
1426
1427         /* should be there, just being paranoid */
1428         if (sdp)
1429           {
1430              if (sdp->resize_obj == sobj)
1431                elm_widget_resize_object_set(parent, NULL, sub_obj);
1432              else if (sub_obj)
1433                elm_widget_sub_object_del(parent, sobj);
1434           }
1435      }
1436    if (sub_obj)
1437      {
1438         elm_widget_sub_object_add(obj, sobj);
1439         evas_object_smart_member_add(sobj, obj);
1440      }
1441
1442    _smart_reconfigure(sd);
1443 }
1444
1445 /*
1446  * @internal
1447  *
1448  * WARNING: the programmer is responsible, in the scenario of
1449  * exchanging a hover object, of cleaning the old hover "target"
1450  * before
1451  */
1452 EOLIAN static void
1453 _elm_widget_hover_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1454 {
1455    if (sd->hover_obj)
1456      {
1457         _callbacks_del(sd->hover_obj, obj);
1458      }
1459    sd->hover_obj = sobj;
1460    if (sd->hover_obj)
1461      {
1462         _callbacks_add(sobj, obj);
1463         _smart_reconfigure(sd);
1464      }
1465 }
1466
1467 EOLIAN static void
1468 _elm_widget_can_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool can_focus)
1469 {
1470    can_focus = !!can_focus;
1471
1472    if (sd->can_focus == can_focus) return;
1473    sd->can_focus = can_focus;
1474    if (sd->can_focus)
1475      {
1476         /* update child_can_focus of parents */
1477         Evas_Object *o = obj;
1478
1479         for (;;)
1480           {
1481              o = elm_widget_parent_get(o);
1482              if (!o) break;
1483              sd = eo_data_scope_get(o, MY_CLASS);
1484              if (!sd || sd->child_can_focus) break;
1485              sd->child_can_focus = EINA_TRUE;
1486           }
1487
1488         eo_do(obj, eo_event_callback_array_add(focus_callbacks(), NULL));
1489      }
1490    else
1491      {
1492         // update child_can_focus of parents */
1493         Evas_Object *parent = elm_widget_parent_get(obj);
1494         while (parent)
1495           {
1496              const Eina_List *l;
1497              Evas_Object *subobj;
1498
1499              ELM_WIDGET_DATA_GET(parent, sdp);
1500
1501              sdp->child_can_focus = EINA_FALSE;
1502              EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
1503                {
1504                   if (_is_focusable(subobj))
1505                     {
1506                        sdp->child_can_focus = EINA_TRUE;
1507                        break;
1508                     }
1509                }
1510              /* break again, child_can_focus went back to
1511               * original value */
1512              if (sdp->child_can_focus) break;
1513              parent = sdp->parent_obj;
1514           }
1515         eo_do(obj, eo_event_callback_array_del(focus_callbacks(), NULL));
1516      }
1517 }
1518
1519 EOLIAN static Eina_Bool
1520 _elm_widget_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1521 {
1522    return sd->can_focus;
1523 }
1524
1525 EOLIAN static Eina_Bool
1526 _elm_widget_child_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1527 {
1528    return sd->child_can_focus;
1529 }
1530
1531 /**
1532  * @internal
1533  *
1534  * This API makes the widget object and its children to be unfocusable.
1535  *
1536  * This API can be helpful for an object to be deleted.
1537  * When an object will be deleted soon, it and its children may not
1538  * want to get focus (by focus reverting or by other focus controls).
1539  * Then, just use this API before deleting.
1540  *
1541  * @param obj The widget root of sub-tree
1542  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1543  *
1544  * @ingroup Widget
1545  */
1546 EOLIAN static void
1547 _elm_widget_tree_unfocusable_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool tree_unfocusable)
1548 {
1549    tree_unfocusable = !!tree_unfocusable;
1550    if (sd->tree_unfocusable == tree_unfocusable) return;
1551    sd->tree_unfocusable = tree_unfocusable;
1552    elm_widget_focus_tree_unfocusable_handle(obj);
1553 }
1554
1555 /**
1556  * @internal
1557  *
1558  * This returns true, if the object sub-tree is unfocusable.
1559  *
1560  * @param obj The widget root of sub-tree
1561  * @return EINA_TRUE if the object sub-tree is unfocusable
1562  *
1563  * @ingroup Widget
1564  */
1565 EOLIAN static Eina_Bool
1566 _elm_widget_tree_unfocusable_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1567 {
1568    return sd->tree_unfocusable;
1569 }
1570
1571 /**
1572  * @internal
1573  *
1574  * Get the list of focusable child objects.
1575  *
1576  * This function retruns list of child objects which can get focus.
1577  *
1578  * @param obj The parent widget
1579  * @retrun list of focusable child objects.
1580  *
1581  * @ingroup Widget
1582  */
1583 EOLIAN static Eina_List*
1584 _elm_widget_can_focus_child_list_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1585 {
1586    const Eina_List *l;
1587    Eina_List *child_list = NULL;
1588    Evas_Object *child;
1589
1590    EINA_LIST_FOREACH(sd->subobjs, l, child)
1591      {
1592         if (!_elm_widget_is(child)) continue;
1593         if ((elm_widget_can_focus_get(child)) &&
1594             (evas_object_visible_get(child)) &&
1595             (!elm_widget_disabled_get(child)))
1596           child_list = eina_list_append(child_list, child);
1597         else
1598           {
1599              Eina_List *can_focus_list;
1600              can_focus_list = elm_widget_can_focus_child_list_get(child);
1601              if (can_focus_list)
1602                child_list = eina_list_merge(child_list, can_focus_list);
1603           }
1604      }
1605
1606    return child_list;
1607 }
1608
1609 EOLIAN static void
1610 _elm_widget_highlight_ignore_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool ignore)
1611 {
1612    sd->highlight_ignore = !!ignore;
1613 }
1614
1615 EOLIAN static Eina_Bool
1616 _elm_widget_highlight_ignore_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1617 {
1618    return sd->highlight_ignore;
1619 }
1620
1621 EOLIAN static void
1622 _elm_widget_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight)
1623 {
1624    sd->highlight_in_theme = !!highlight;
1625    /* FIXME: if focused, it should switch from one mode to the other */
1626 }
1627
1628 void
1629 _elm_widget_highlight_in_theme_update(Eo *obj)
1630 {
1631    Evas_Object *top = elm_widget_top_get(obj);
1632
1633    if (top && eo_isa(top, ELM_WIN_CLASS))
1634      {
1635         _elm_win_focus_highlight_in_theme_update(
1636            top, elm_widget_highlight_in_theme_get(obj));
1637      }
1638 }
1639
1640 EOLIAN static Eina_Bool
1641 _elm_widget_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1642 {
1643    return sd->highlight_in_theme;
1644 }
1645
1646 EOLIAN static void
1647 _elm_widget_access_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight)
1648 {
1649    sd->access_highlight_in_theme = !!highlight;
1650 }
1651
1652 EOLIAN static Eina_Bool
1653 _elm_widget_access_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1654 {
1655    return sd->access_highlight_in_theme;
1656 }
1657
1658 EOLIAN static Eina_Bool
1659 _elm_widget_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1660 {
1661    return (sd->focused && sd->top_win_focused);
1662 }
1663
1664 EOLIAN static Eina_Bool
1665 _elm_widget_highlight_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1666 {
1667    return sd->highlighted;
1668 }
1669
1670 EOLIAN static Evas_Object*
1671 _elm_widget_focused_object_get(Eo *obj, Elm_Widget_Smart_Data *sd)
1672 {
1673    const Evas_Object *subobj;
1674    const Eina_List *l;
1675
1676    if (!sd->focused || !sd->top_win_focused) return NULL;
1677    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1678      {
1679         Evas_Object *fobj;
1680         if (!_elm_widget_is(subobj)) continue;
1681         fobj = elm_widget_focused_object_get(subobj);
1682         if (fobj) return fobj;
1683      }
1684    return (Evas_Object *)obj;
1685 }
1686
1687 EOLIAN static Evas_Object*
1688 _elm_widget_top_get(Eo *obj, Elm_Widget_Smart_Data *sd)
1689 {
1690    if (sd->parent_obj)
1691      {
1692         Evas_Object *ret = NULL;
1693         if (!eo_isa(sd->parent_obj, ELM_WIDGET_CLASS)) return NULL;
1694         eo_do((Eo *) sd->parent_obj, ret = elm_obj_widget_top_get());
1695         return ret;
1696      }
1697    return (Evas_Object *)obj;
1698 }
1699
1700 EAPI Eina_Bool
1701 elm_widget_is(const Evas_Object *obj)
1702 {
1703    return _elm_widget_is(obj);
1704 }
1705
1706 EAPI Evas_Object *
1707 elm_widget_parent_widget_get(const Evas_Object *obj)
1708 {
1709    Evas_Object *parent;
1710
1711    if (_elm_widget_is(obj))
1712      {
1713         ELM_WIDGET_DATA_GET(obj, sd);
1714         if (!sd) return NULL;
1715         parent = sd->parent_obj;
1716      }
1717    else
1718      {
1719         parent = evas_object_data_get(obj, "elm-parent");
1720         if (!parent) parent = evas_object_smart_parent_get(obj);
1721      }
1722
1723    while (parent)
1724      {
1725         Evas_Object *elm_parent;
1726         if (_elm_widget_is(parent)) break;
1727         elm_parent = evas_object_data_get(parent, "elm-parent");
1728         if (elm_parent) parent = elm_parent;
1729         else parent = evas_object_smart_parent_get(parent);
1730      }
1731    return parent;
1732 }
1733
1734 EOLIAN static Evas_Object *
1735 _elm_widget_parent2_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1736 {
1737    return sd->parent2;
1738 }
1739
1740 EOLIAN static void
1741 _elm_widget_parent2_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *parent)
1742 {
1743    sd->parent2 = parent;
1744 }
1745
1746 EOLIAN static void
1747 _elm_widget_event_callback_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Event_Cb func, const void *data)
1748 {
1749    EINA_SAFETY_ON_NULL_RETURN(func);
1750
1751    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1752    if (!ecb)
1753      {
1754         ERR("Failed to allocate memory");
1755         return;
1756      }
1757    ecb->func = func;
1758    ecb->data = data;
1759    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1760 }
1761
1762 EOLIAN static void*
1763 _elm_widget_event_callback_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Event_Cb func, const void *data)
1764 {
1765    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1766    Eina_List *l;
1767    Elm_Event_Cb_Data *ecd;
1768    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1769      if ((ecd->func == func) && (ecd->data == data))
1770        {
1771           free(ecd);
1772           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1773           return (void *)data;
1774        }
1775
1776    return NULL;
1777 }
1778
1779 EOLIAN static Eina_Bool
1780 _elm_widget_event_propagate(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags)
1781 {
1782    Evas_Object *parent = obj;
1783    Elm_Event_Cb_Data *ecd;
1784    Eina_List *l, *l_prev;
1785
1786    while (parent &&
1787           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1788      {
1789         ELM_WIDGET_CHECK(parent) EINA_FALSE;
1790         Elm_Widget_Smart_Data *sd = eo_data_scope_get(parent, MY_CLASS);
1791
1792         Eina_Bool int_ret = EINA_FALSE;
1793
1794         if (elm_widget_disabled_get(obj))
1795           {
1796              parent = sd->parent_obj;
1797              continue;
1798           }
1799
1800         eo_do(parent, int_ret = elm_obj_widget_event(obj, type, event_info));
1801         if (int_ret) return EINA_TRUE;
1802
1803         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1804           {
1805              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1806                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1807                 return EINA_TRUE;
1808           }
1809         parent = sd->parent_obj;
1810      }
1811
1812    return EINA_FALSE;
1813 }
1814
1815 /**
1816  * @internal
1817  *
1818  * Set custom focus chain.
1819  *
1820  * This function i set one new and overwrite any previous custom focus chain
1821  * with the list of objects. The previous list will be deleted and this list
1822  * will be managed. After setted, don't modity it.
1823  *
1824  * @note On focus cycle, only will be evaluated children of this container.
1825  *
1826  * @param obj The container widget
1827  * @param objs Chain of objects to pass focus
1828  * @ingroup Widget
1829  */
1830 EOLIAN static void
1831 _elm_widget_focus_custom_chain_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_List *objs)
1832 {
1833    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1834
1835    elm_widget_focus_custom_chain_unset(obj);
1836
1837    Eina_List *l;
1838    Evas_Object *o;
1839
1840    EINA_LIST_FOREACH(objs, l, o)
1841      {
1842         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1843                                        _elm_object_focus_chain_del_cb, obj);
1844      }
1845
1846    sd->focus_chain = objs;
1847 }
1848
1849 /**
1850  * @internal
1851  *
1852  * Get custom focus chain
1853  *
1854  * @param obj The container widget
1855  * @ingroup Widget
1856  */
1857 EOLIAN static const Eina_List*
1858 _elm_widget_focus_custom_chain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1859 {
1860    return (const Eina_List *)sd->focus_chain;
1861 }
1862
1863 /**
1864  * @internal
1865  *
1866  * Unset custom focus chain
1867  *
1868  * @param obj The container widget
1869  * @ingroup Widget
1870  */
1871 EOLIAN static void
1872 _elm_widget_focus_custom_chain_unset(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1873 {
1874    Eina_List *l, *l_next;
1875    Evas_Object *o;
1876
1877    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1878      {
1879         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1880                                             _elm_object_focus_chain_del_cb, obj);
1881         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1882      }
1883 }
1884
1885 /**
1886  * @internal
1887  *
1888  * Append object to custom focus chain.
1889  *
1890  * @note If relative_child equal to NULL or not in custom chain, the object
1891  * will be added in end.
1892  *
1893  * @note On focus cycle, only will be evaluated children of this container.
1894  *
1895  * @param obj The container widget
1896  * @param child The child to be added in custom chain
1897  * @param relative_child The relative object to position the child
1898  * @ingroup Widget
1899  */
1900 EOLIAN static void
1901 _elm_widget_focus_custom_chain_append(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
1902 {
1903    EINA_SAFETY_ON_NULL_RETURN(child);
1904
1905    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1906
1907    evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
1908                                   _elm_object_focus_chain_del_cb, obj);
1909
1910    if (!relative_child)
1911      sd->focus_chain = eina_list_append(sd->focus_chain, child);
1912    else
1913      sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1914                                                  child, relative_child);
1915 }
1916
1917 /**
1918  * @internal
1919  *
1920  * Prepend object to custom focus chain.
1921  *
1922  * @note If relative_child equal to NULL or not in custom chain, the object
1923  * will be added in begin.
1924  *
1925  * @note On focus cycle, only will be evaluated children of this container.
1926  *
1927  * @param obj The container widget
1928  * @param child The child to be added in custom chain
1929  * @param relative_child The relative object to position the child
1930  * @ingroup Widget
1931  */
1932 EOLIAN static void
1933 _elm_widget_focus_custom_chain_prepend(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
1934 {
1935    EINA_SAFETY_ON_NULL_RETURN(child);
1936
1937    if (!_elm_widget_focus_chain_manager_is(obj)) return;
1938
1939    evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
1940                                   _elm_object_focus_chain_del_cb, obj);
1941
1942    if (!relative_child)
1943      sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1944    else
1945      sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1946                                                   child, relative_child);
1947 }
1948
1949 /**
1950  * @internal
1951  *
1952  * Give focus to next object in object tree.
1953  *
1954  * Give focus to next object in focus chain of one object sub-tree.
1955  * If the last object of chain already have focus, the focus will go to the
1956  * first object of chain.
1957  *
1958  * @param obj The widget root of sub-tree
1959  * @param dir Direction to cycle the focus
1960  *
1961  * @ingroup Widget
1962  */
1963 EOLIAN static void
1964 _elm_widget_focus_cycle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Focus_Direction dir)
1965 {
1966    Evas_Object *target = NULL;
1967    Elm_Object_Item *target_item = NULL;
1968    if (!_elm_widget_is(obj))
1969      return;
1970    elm_widget_focus_next_get(obj, dir, &target, &target_item);
1971    if (target)
1972      {
1973         /* access */
1974         if (_elm_config->access_mode)
1975           {
1976              /* highlight cycle does not steal a focus, only after window gets
1977                 the ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE message,
1978                 target will steal focus, or focus its own job. */
1979              if (!_elm_access_auto_highlight_get())
1980                elm_widget_focus_steal(target, target_item);
1981
1982              _elm_access_highlight_set(target);
1983              elm_widget_focus_region_show(target);
1984           }
1985         else elm_widget_focus_steal(target, target_item);
1986      }
1987 }
1988
1989 /**
1990  * @internal
1991  *
1992  * Give focus to near object(in object tree) in one direction.
1993  *
1994  * Give focus to near object(in object tree) in direction of current
1995  * focused object.  If none focusable object in given direction or
1996  * none focused object in object tree, the focus will not change.
1997  *
1998  * @param obj The reference widget
1999  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2000  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2001  * @return EINA_TRUE if focus is moved.
2002  *
2003  * @ingroup Widget
2004  */
2005 EOLIAN static Eina_Bool
2006 _elm_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, double degree)
2007 {
2008    Evas_Object *target = NULL;
2009    Elm_Object_Item *target_item = NULL;
2010    Evas_Object *current_focused = NULL;
2011    double weight = 0.0;
2012
2013    if (!_elm_widget_is(obj)) return EINA_FALSE;
2014    if (!_is_focused(obj)) return EINA_FALSE;
2015
2016    current_focused = elm_widget_focused_object_get(obj);
2017
2018    if (elm_widget_focus_direction_get
2019          (obj, current_focused, degree, &target, &target_item, &weight))
2020      {
2021         elm_widget_focus_steal(target, NULL);
2022         return EINA_TRUE;
2023      }
2024
2025    return EINA_FALSE;
2026 }
2027
2028 double
2029 _elm_widget_focus_direction_weight_get(const Evas_Object *obj1,
2030                       const Evas_Object *obj2,
2031                       double degree)
2032 {
2033    Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
2034    double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
2035    double ax, ay, cx, cy;
2036    double weight = -1.0, g = 0.0;
2037
2038    if (obj1 == obj2) return 0.0;
2039
2040    degree -= 90.0;
2041    while (degree >= 360.0)
2042      degree -= 360.0;
2043    while (degree < 0.0)
2044      degree += 360.0;
2045
2046    evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
2047    cx = obj_x1 + (w1 / 2.0);
2048    cy = obj_y1 + (h1 / 2.0);
2049    evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
2050
2051    /* For overlapping cases. */
2052    if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2))
2053      return 0.0;
2054
2055    /* Change all points to relative one. */
2056    x1 = obj_x1 - cx;
2057    xx1 = x1 + w1;
2058    yy1 = obj_y1 - cy;
2059    yyy1 = yy1 + h1;
2060    x2 = obj_x2 - cx;
2061    xx2 = x2 + w2;
2062    yy2 = obj_y2 - cy;
2063    yyy2 = yy2 + h2;
2064
2065    /* Get crossing points (ax, ay) between obj1 and a line extending
2066     * to the direction of current degree. */
2067    if (degree == 0.0)
2068      {
2069         ax = xx1;
2070         ay = 0.0;
2071      }
2072    else if (degree == 90.0)
2073      {
2074         ax = 0.0;
2075         ay = yyy1;
2076      }
2077    else if (degree == 180.0)
2078      {
2079         ax = x1;
2080         ay = 0.0;
2081      }
2082    else if (degree == 270.0)
2083      {
2084         ax = 0.0;
2085         ay = yy1;
2086      }
2087    else
2088      {
2089         g = tan(degree * (M_PI / 180.0));
2090         if ((degree > 0.0) && (degree < 90.0))
2091           {
2092              ay = g * xx1;
2093              if (ay <= yyy1) ax = xx1;
2094              else
2095                {
2096                   ax = yyy1 / g;
2097                   ay = yyy1;
2098                }
2099           }
2100         else if ((degree > 90.0) && (degree < 180.0))
2101           {
2102              ay = g * x1;
2103              if (ay <= yyy1) ax = x1;
2104              else
2105                {
2106                   ax = yyy1 / g;
2107                   ay = yyy1;
2108                }
2109           }
2110         else if ((degree > 180.0) && (degree < 270.0))
2111           {
2112              ay = g * x1;
2113              if (ay >= yy1) ax = x1;
2114              else
2115                {
2116                   ax = yy1 / g;
2117                   ay = yy1;
2118                }
2119           }
2120         else
2121           {
2122              ay = g * xx1;
2123              if (ay >= yy1) ax = xx1;
2124              else
2125                {
2126                   ax = yy1 / g;
2127                   ay = yy1;
2128                }
2129           }
2130      }
2131
2132    /* Filter obj2, if it is not in the specific derection. */
2133    int i = 0;
2134    double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
2135    double t1, t2, u1, v1, u2, v2;
2136
2137    if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) ||
2138        (degree == 315.0))
2139      {
2140         u1 = 1.0;
2141         v1 = 0.0;
2142         u2 = 0.0;
2143         v2 = 1.0;
2144      }
2145    else
2146      {
2147         double g2 = tan((degree + 45.0) * (M_PI / 180.0));
2148         u1 = (-1.0 * g2);
2149         u2 = (1.0 / g2);
2150         v1 = v2 = 1.0;
2151      }
2152    t1 = (u1 * ax) + (v1 * ay);
2153    t2 = (u2 * ax) + (v2 * ay);
2154
2155 #define _R(x) (int)((x + 0.05) * 10.0)
2156
2157    if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) +
2158                                                             (v2 * yy2))) > 0))
2159      {
2160         rx[i] = x2;
2161         ry[i++] = yy2;
2162      }
2163    if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) +
2164                                                              (v2 * yyy2))) > 0))
2165      {
2166         rx[i] = x2;
2167         ry[i++] = yyy2;
2168      }
2169    if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) +
2170                                                              (v2 * yy2))) > 0))
2171      {
2172         rx[i] = xx2;
2173         ry[i++] = yy2;
2174      }
2175    if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) &&
2176        (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
2177      {
2178         rx[i] = xx2;
2179         ry[i++] = yyy2;
2180      }
2181    if (i == 0)
2182      {
2183         if (degree == 0.0)
2184           {
2185              if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2186           }
2187         else if (degree == 90.0)
2188           {
2189              if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2190           }
2191         else if (degree == 180.0)
2192           {
2193              if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2194           }
2195         else if (degree == 270.0)
2196           {
2197              if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2198           }
2199         else
2200           {
2201              if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
2202                {
2203                   if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0)))
2204                     return 0.0;
2205                }
2206              else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
2207                {
2208                   if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0)))
2209                     return 0.0;
2210                }
2211              else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2)
2212                                                            <= _R(xx2)))
2213                {
2214                   if (!((_R(ax * ((1.0 / g) * yy2)) > 0)
2215                         && (_R(ay * yy2) > 0)))
2216                     return 0.0;
2217                }
2218              else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) &&
2219                       (_R((1.0 / g) * yyy2) <= _R(xx2)))
2220                {
2221                   if (!((_R(ax * ((1.0 / g) * yyy2)) > 0)
2222                         && (_R(ay * yyy2) > 0))) return 0.0;
2223                }
2224              else return 0.0;
2225           }
2226      }
2227
2228    /* Calculate the weight for obj2. */
2229    if (degree == 0.0)
2230      {
2231         if (_R(xx1) > _R(x2)) weight = -1.0;
2232         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2233           weight = (x2 - xx1) * (x2 - xx1);
2234         else if (_R(yy2) > 0)
2235           weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
2236         else if (_R(yyy2) < 0)
2237           weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
2238         else weight = (x2 - xx1) * (x2 - xx1);
2239      }
2240    else if (degree == 90.0)
2241      {
2242         if (_R(yyy1) > _R(yy2)) weight = -1.0;
2243         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2244           weight = (yy2 - yyy1) * (yy2 - yyy1);
2245         else if (_R(x2) > 0)
2246           weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
2247         else if (_R(xx2) < 0)
2248           weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
2249         else weight = (yy2 - yyy1) * (yy2 - yyy1);
2250      }
2251    else if (degree == 180.0)
2252      {
2253         if (_R(x1) < _R(xx2)) weight = -1.0;
2254         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2255           weight = (x1 - xx2) * (x1 - xx2);
2256         else if (_R(yy2) > 0)
2257           weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
2258         else if (_R(yyy2) < 0)
2259           weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
2260         else weight = (x1 - xx2) * (x1 - xx2);
2261      }
2262    else if (degree == 270.0)
2263      {
2264         if (_R(yy1) < _R(yyy2)) weight = -1.0;
2265         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2266           weight = (yy1 - yyy2) * (yy1 - yyy2);
2267         else if (_R(x2) > 0)
2268           weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
2269         else if (_R(xx2) < 0)
2270           weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
2271         else weight = (yy1 - yyy2) * (yy1 - yyy2);
2272      }
2273    else
2274      {
2275         int j = 0, k = 0;
2276         double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
2277         double t_weight[4] = {-1.0, -1.0, -1.0, -1.0};
2278         if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
2279           {
2280              sx[j] = x2;
2281              sy[j] = g * x2;
2282              t_weight[j++] = ((ax - x2) * (ax - x2)) +
2283                ((ay - (g * x2)) * (ay - (g * x2)));
2284           }
2285         if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
2286           {
2287              sx[j] = xx2;
2288              sy[j] = g * xx2;
2289              t_weight[j++] = ((ax - xx2) * (ax - xx2)) +
2290                ((ay - (g * xx2)) * (ay - (g * xx2)));
2291           }
2292         if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
2293           {
2294              sx[j] = (1.0 / g) * yy2;
2295              sy[j] = yy2;
2296              t_weight[j++] =
2297                ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) +
2298                ((ay - yy2) * (ay - yy2));
2299           }
2300         if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2)
2301                                                  <= _R(xx2)))
2302           {
2303              sx[j] = (1.0 / g) * yyy2;
2304              sy[j] = yyy2;
2305              t_weight[j++] =
2306                ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) +
2307                ((ay - yyy2) * (ay - yyy2));
2308           }
2309
2310         if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) ||
2311                                      (_R(sy[0]) != _R(sy[1])))))
2312           {
2313              for (; k < j; k++)
2314                {
2315                   if (_R(t_weight[k]) == 0) return -1.0;
2316                   if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
2317                }
2318           }
2319         else
2320           {
2321              for (; k < i; k++)
2322                {
2323                   double ccx, ccy, t1_weight, x_diff, y_diff;
2324                   ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
2325                   ccy = g * ccx;
2326                   x_diff = rx[k] - ccx;
2327                   if (x_diff < 0) x_diff *= -1.0;
2328                   y_diff = ry[k] - ccy;
2329                   if (y_diff < 0) y_diff *= -1.0;
2330                   t1_weight =
2331                     (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
2332                     ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
2333                   if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
2334                     weight = t1_weight;
2335                }
2336           }
2337      }
2338    /* Return the current object's weight. */
2339    if (weight == -1.0) return 0.0;
2340    if (_R(weight) == 0) return -1.0;
2341
2342 #undef _R
2343
2344    return 1.0 / weight;
2345 }
2346
2347 /**
2348  * @internal
2349  *
2350  * Get near object in one direction of base object.
2351  *
2352  * Get near object(in the object sub-tree) in one direction of
2353  * base object. Return the near object by reference.
2354  * By initializing weight, you can filter objects locating far
2355  * from base object. If object is in the specific direction,
2356  * weight is (1/(distance^2)). If object is not exactly in one
2357  * direction, some penalty will be added.
2358  *
2359  * @param obj The widget root of sub-tree
2360  * @param base The base object of the direction
2361  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2362  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2363  * @param direction The near object in one direction
2364  * @param weight The weight is bigger when the object is located near
2365  * @return EINA_TRUE if near object is updated.
2366  *
2367  * @ingroup Widget
2368  */
2369
2370 EOLIAN static Eina_Bool
2371 _elm_widget_focus_direction_get(const Eo *obj, Elm_Widget_Smart_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight)
2372 {
2373    double c_weight;
2374
2375    /* -1 means the best was already decided. Don't need any more searching. */
2376    if (!direction || !weight || !base || (obj == base))
2377      return EINA_FALSE;
2378
2379    /* Ignore if disabled */
2380    if ((!evas_object_visible_get(obj))
2381        || (elm_widget_disabled_get(obj))
2382        || (elm_widget_tree_unfocusable_get(obj)))
2383      return EINA_FALSE;
2384
2385    /* Try use hook */
2386    if (_internal_elm_widget_focus_direction_manager_is(obj))
2387      {
2388         Eina_Bool int_ret = EINA_FALSE;
2389         eo_do((Eo *)obj, int_ret = elm_obj_widget_focus_direction(base, degree, direction, direction_item, weight));
2390         return int_ret;
2391      }
2392
2393    if (!elm_widget_can_focus_get(obj) || _is_focused((Eo *)obj))
2394      return EINA_FALSE;
2395
2396    c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree);
2397    if ((c_weight == -1.0) ||
2398        ((c_weight != 0.0) && (*weight != -1.0) &&
2399         ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
2400      {
2401         if (*direction &&
2402             ((int)(*weight * 1000000) == (int)(c_weight * 1000000)))
2403           {
2404              ELM_WIDGET_DATA_GET(*direction, sd1);
2405              if (sd1)
2406                {
2407                   if (sd->focus_order <= sd1->focus_order)
2408                     return EINA_FALSE;
2409                }
2410           }
2411         *direction = (Evas_Object *)obj;
2412         *weight = c_weight;
2413         return EINA_TRUE;
2414      }
2415
2416    return EINA_FALSE;
2417 }
2418
2419 /**
2420  * @internal
2421  *
2422  * Get near object in one direction of base object in list.
2423  *
2424  * Get near object in one direction of base object in the specific
2425  * object list. Return the near object by reference.
2426  * By initializing weight, you can filter objects locating far
2427  * from base object. If object is in the specific direction,
2428  * weight is (1/(distance^2)). If object is not exactly in one
2429  * direction, some penalty will be added.
2430  *
2431  * @param obj The widget root of sub-tree
2432  * @param base The base object of the direction
2433  * @param items list with ordered objects
2434  * @param list_data_get function to get the object from one item of list
2435  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2436  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
2437  * @param direction The near object in one direction
2438  * @param weight The weight is bigger when the object is located near
2439  * @return EINA_TRUE if near object is updated.
2440  *
2441  * @ingroup Widget
2442  */
2443 EOLIAN static Eina_Bool
2444 _elm_widget_focus_list_direction_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Evas_Object *base, const Eina_List *items, list_data_get_func_type list_data_get, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight)
2445 {
2446    if (!direction || !weight || !base || !items)
2447      return EINA_FALSE;
2448
2449    const Eina_List *l = items;
2450    Evas_Object *current_best = *direction;
2451
2452    for (; l; l = eina_list_next(l))
2453      {
2454         Evas_Object *cur = list_data_get(l);
2455         if (cur && _elm_widget_is(cur))
2456           elm_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight);
2457      }
2458    if (current_best != *direction) return EINA_TRUE;
2459
2460    return EINA_FALSE;
2461 }
2462
2463 /**
2464  * @internal
2465  *
2466  * Get next object in focus chain of object tree.
2467  *
2468  * Get next object in focus chain of one object sub-tree.
2469  * Return the next object by reference. If don't have any candidate to receive
2470  * focus before chain end, the first candidate will be returned.
2471  *
2472  * @param obj The widget root of sub-tree
2473  * @param dir Direction of focus chain
2474  * @param next The next object in focus chain
2475  * @return EINA_TRUE if don't need focus chain restart/loop back
2476  *         to use 'next' obj.
2477  *
2478  * @ingroup Widget
2479  */
2480 EOLIAN static Eina_Bool
2481 _elm_widget_focus_next_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
2482 {
2483    Elm_Access_Info *ac;
2484
2485    if (!next)
2486      return EINA_FALSE;
2487    *next = NULL;
2488
2489    /* Ignore if disabled */
2490    if (_elm_config->access_mode && _elm_access_auto_highlight_get())
2491      {
2492         if (!evas_object_visible_get(obj)
2493             || (elm_widget_tree_unfocusable_get(obj)))
2494           return EINA_FALSE;
2495      }
2496    else
2497      {
2498         if ((!evas_object_visible_get(obj))
2499             || (elm_widget_disabled_get(obj))
2500             || (elm_widget_tree_unfocusable_get(obj)))
2501           return EINA_FALSE;
2502      }
2503
2504    /* Try use hook */
2505    if (_elm_widget_focus_chain_manager_is(obj))
2506      {
2507         Eina_Bool int_ret = EINA_FALSE;
2508         eo_do((Eo *)obj, int_ret = elm_obj_widget_focus_next(dir, next, next_item));
2509         if (!int_ret && _is_focused((Eo *)obj))
2510           {
2511              Evas_Object *o = NULL;
2512              if (dir == ELM_FOCUS_PREVIOUS)
2513                *next_item = sd->item_focus_previous;
2514              else if (dir == ELM_FOCUS_NEXT)
2515                *next_item = sd->item_focus_next;
2516              else if (dir == ELM_FOCUS_UP)
2517                *next_item = sd->item_focus_up;
2518              else if (dir == ELM_FOCUS_DOWN)
2519                *next_item = sd->item_focus_down;
2520              else if (dir == ELM_FOCUS_RIGHT)
2521                *next_item = sd->item_focus_right;
2522              else if (dir == ELM_FOCUS_LEFT)
2523                *next_item = sd->item_focus_left;
2524              o = elm_object_item_widget_get(*next_item);
2525
2526              if (!o)
2527                {
2528                   if (dir == ELM_FOCUS_PREVIOUS)
2529                     o = sd->focus_previous;
2530                   else if (dir == ELM_FOCUS_NEXT)
2531                     o = sd->focus_next;
2532                   else if (dir == ELM_FOCUS_UP)
2533                     o = sd->focus_up;
2534                   else if (dir == ELM_FOCUS_DOWN)
2535                     o = sd->focus_down;
2536                   else if (dir == ELM_FOCUS_RIGHT)
2537                     o = sd->focus_right;
2538                   else if (dir == ELM_FOCUS_LEFT)
2539                     o = sd->focus_left;
2540                }
2541
2542              if (o)
2543                {
2544                   *next = o;
2545                   return EINA_TRUE;
2546                }
2547           }
2548         return int_ret;
2549      }
2550
2551    /* access object does not check sd->can_focus, because an object could
2552       have highlight even though the object is not focusable. */
2553    if (_elm_config->access_mode && _elm_access_auto_highlight_get())
2554      {
2555         ac = _elm_access_info_get(obj);
2556         if (!ac) return EINA_FALSE;
2557
2558         /* check whether the hover object is visible or not */
2559         if (!evas_object_visible_get(ac->hoverobj))
2560           return EINA_FALSE;
2561      }
2562    else if (!elm_widget_can_focus_get(obj))
2563      return EINA_FALSE;
2564
2565    if (_is_focused((Eo *)obj))
2566      {
2567         if (dir == ELM_FOCUS_PREVIOUS)
2568           *next_item = sd->item_focus_previous;
2569         else if (dir == ELM_FOCUS_NEXT)
2570           *next_item = sd->item_focus_next;
2571         else if (dir == ELM_FOCUS_UP)
2572           *next_item = sd->item_focus_up;
2573         else if (dir == ELM_FOCUS_DOWN)
2574           *next_item = sd->item_focus_down;
2575         else if (dir == ELM_FOCUS_RIGHT)
2576           *next_item = sd->item_focus_right;
2577         else if (dir == ELM_FOCUS_LEFT)
2578           *next_item = sd->item_focus_left;
2579         *next = elm_object_item_widget_get(*next_item);
2580
2581         if (!(*next))
2582           {
2583              if (dir == ELM_FOCUS_PREVIOUS)
2584                *next = sd->focus_previous;
2585              else if (dir == ELM_FOCUS_NEXT)
2586                *next = sd->focus_next;
2587              else if (dir == ELM_FOCUS_UP)
2588                *next = sd->focus_up;
2589              else if (dir == ELM_FOCUS_DOWN)
2590                *next = sd->focus_down;
2591              else if (dir == ELM_FOCUS_RIGHT)
2592                *next = sd->focus_right;
2593              else if (dir == ELM_FOCUS_LEFT)
2594                *next = sd->focus_left;
2595           }
2596
2597         if (*next) return EINA_TRUE;
2598      }
2599
2600    /* Return */
2601    *next = (Evas_Object *)obj;
2602    return !ELM_WIDGET_FOCUS_GET(obj);
2603 }
2604
2605 /**
2606  * @internal
2607  *
2608  * Get next object in focus chain of object tree in list.
2609  *
2610  * Get next object in focus chain of one object sub-tree ordered by one list.
2611  * Return the next object by reference. If don't have any candidate to receive
2612  * focus before list end, the first candidate will be returned.
2613  *
2614  * @param obj The widget root of sub-tree
2615  * @param items list with ordered objects
2616  * @param list_data_get function to get the object from one item of list
2617  * @param dir Direction of focus chain
2618  * @param next The next object in focus chain
2619  * @return EINA_TRUE if don't need focus chain restart/loop back
2620  *         to use 'next' obj.
2621  *
2622  * @ingroup Widget
2623  */
2624 EOLIAN static Eina_Bool
2625 _elm_widget_focus_list_next_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Eina_List *items, list_data_get_func_type list_data_get, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
2626 {
2627    Eina_List *(*list_next)(const Eina_List *list) = NULL;
2628    Evas_Object *focused_object = NULL;
2629
2630    if (!next)
2631      return EINA_FALSE;
2632    *next = NULL;
2633
2634    if (!_elm_widget_is(obj))
2635      return EINA_FALSE;
2636
2637    if (!items)
2638      return EINA_FALSE;
2639
2640    /* When Up, Down, Right, or Left, try direction_get first. */
2641    focused_object = elm_widget_focused_object_get(obj);
2642    if (focused_object)
2643      {
2644         if ((dir == ELM_FOCUS_UP)
2645            || (dir == ELM_FOCUS_DOWN)
2646            || (dir == ELM_FOCUS_RIGHT)
2647            || (dir == ELM_FOCUS_LEFT))
2648           {
2649              *next_item = elm_widget_focus_next_item_get(focused_object, dir);
2650              if (*next_item)
2651                *next = elm_object_item_widget_get(*next_item);
2652              else
2653                *next = elm_widget_focus_next_object_get(focused_object, dir);
2654              if (*next) return EINA_TRUE;
2655              else
2656                {
2657                   Evas_Object *n = NULL;
2658                   Elm_Object_Item *n_item = NULL;
2659                   double degree = 0;
2660                   double weight = 0.0;
2661
2662                   if (dir == ELM_FOCUS_UP) degree = 0.0;
2663                   else if (dir == ELM_FOCUS_DOWN) degree = 180.0;
2664                   else if (dir == ELM_FOCUS_RIGHT) degree = 90.0;
2665                   else if (dir == ELM_FOCUS_LEFT) degree = 270.0;
2666
2667                   if (elm_widget_focus_list_direction_get(obj, focused_object,
2668                                                           items, list_data_get,
2669                                                           degree, &n, &n_item,
2670                                                           &weight))
2671                     {
2672                        *next_item = n_item;
2673                        *next = n;
2674                        return EINA_TRUE;
2675                     }
2676                }
2677           }
2678      }
2679
2680    /* Direction */
2681    if (dir == ELM_FOCUS_PREVIOUS)
2682      {
2683         items = eina_list_last(items);
2684         list_next = eina_list_prev;
2685      }
2686    else if ((dir == ELM_FOCUS_NEXT)
2687             || (dir == ELM_FOCUS_UP)
2688             || (dir == ELM_FOCUS_DOWN)
2689             || (dir == ELM_FOCUS_RIGHT)
2690             || (dir == ELM_FOCUS_LEFT))
2691      list_next = eina_list_next;
2692    else
2693      return EINA_FALSE;
2694
2695    const Eina_List *l = items;
2696
2697    /* Recovery last focused sub item */
2698    if (ELM_WIDGET_FOCUS_GET(obj))
2699      {
2700         for (; l; l = list_next(l))
2701           {
2702              Evas_Object *cur = list_data_get(l);
2703              if (ELM_WIDGET_FOCUS_GET(cur)) break;
2704           }
2705
2706          /* Focused object, but no focused sub item */
2707          if (!l) l = items;
2708      }
2709
2710    const Eina_List *start = l;
2711    Evas_Object *to_focus = NULL;
2712    Elm_Object_Item *to_focus_item = NULL;
2713
2714    /* Iterate sub items */
2715    /* Go to the end of list */
2716    for (; l; l = list_next(l))
2717      {
2718         Evas_Object *tmp = NULL;
2719         Elm_Object_Item *tmp_item = NULL;
2720         Evas_Object *cur = list_data_get(l);
2721
2722         if (!cur) continue;
2723         if (!_elm_widget_is(cur)) continue;
2724         if (elm_widget_parent_get(cur) != obj)
2725           continue;
2726
2727         /* Try Focus cycle in subitem */
2728         if (elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item))
2729           {
2730              *next = tmp;
2731              *next_item = tmp_item;
2732              return EINA_TRUE;
2733           }
2734         else if ((dir == ELM_FOCUS_UP)
2735                  || (dir == ELM_FOCUS_DOWN)
2736                  || (dir == ELM_FOCUS_RIGHT)
2737                  || (dir == ELM_FOCUS_LEFT))
2738           {
2739              if (tmp && _is_focused(cur))
2740                {
2741                   *next = tmp;
2742                   *next_item = tmp_item;
2743                   return EINA_FALSE;
2744                }
2745           }
2746         else if ((tmp) && (!to_focus))
2747           {
2748              to_focus = tmp;
2749              to_focus_item = tmp_item;
2750           }
2751      }
2752
2753    l = items;
2754
2755    /* Get First possible */
2756    for (; l != start; l = list_next(l))
2757      {
2758         Evas_Object *tmp = NULL;
2759         Elm_Object_Item *tmp_item = NULL;
2760         Evas_Object *cur = list_data_get(l);
2761
2762         if (elm_widget_parent_get(cur) != obj)
2763           continue;
2764
2765         /* Try Focus cycle in subitem */
2766         elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item);
2767         if (tmp)
2768           {
2769              *next = tmp;
2770              *next_item = tmp_item;
2771              return EINA_FALSE;
2772           }
2773      }
2774
2775    *next = to_focus;
2776    *next_item = to_focus_item;
2777    return EINA_FALSE;
2778 }
2779
2780 /**
2781  * @internal
2782  *
2783  * Get next object which was set with specific focus direction.
2784  *
2785  * Get next object which was set by elm_widget_focus_next_object_set
2786  * with specific focus directioin.
2787  *
2788  * @param obj The widget
2789  * @param dir Direction of focus
2790  * @return Widget which was registered with sepecific focus direction.
2791  *
2792  * @ingroup Widget
2793  */
2794 EOLIAN static Evas_Object*
2795 _elm_widget_focus_next_object_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir)
2796 {
2797    Evas_Object *ret = NULL;
2798
2799    if (dir == ELM_FOCUS_PREVIOUS)
2800      ret = sd->focus_previous;
2801    else if (dir == ELM_FOCUS_NEXT)
2802      ret = sd->focus_next;
2803    else if (dir == ELM_FOCUS_UP)
2804      ret = sd->focus_up;
2805    else if (dir == ELM_FOCUS_DOWN)
2806      ret = sd->focus_down;
2807    else if (dir == ELM_FOCUS_RIGHT)
2808      ret = sd->focus_right;
2809    else if (dir == ELM_FOCUS_LEFT)
2810      ret = sd->focus_left;
2811
2812    return ret;
2813 }
2814
2815 /**
2816  * @internal
2817  *
2818  * Set next object with specific focus direction.
2819  *
2820  * When a widget is set with specific focus direction, this widget will be
2821  * the first candidate when finding the next focus object.
2822  * Focus next object can be registered with six directions that are previous,
2823  * next, up, down, right, and left.
2824  *
2825  * @param obj The widget
2826  * @param next Next focus object
2827  * @param dir Direction of focus
2828  *
2829  * @ingroup Widget
2830  */
2831 EOLIAN static void
2832 _elm_widget_focus_next_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *next, Elm_Focus_Direction dir)
2833 {
2834
2835    if (dir == ELM_FOCUS_PREVIOUS)
2836      sd->focus_previous = next;
2837    else if (dir == ELM_FOCUS_NEXT)
2838      sd->focus_next = next;
2839    else if (dir == ELM_FOCUS_UP)
2840      sd->focus_up = next;
2841    else if (dir == ELM_FOCUS_DOWN)
2842      sd->focus_down = next;
2843    else if (dir == ELM_FOCUS_RIGHT)
2844      sd->focus_right = next;
2845    else if (dir == ELM_FOCUS_LEFT)
2846      sd->focus_left = next;
2847 }
2848
2849 EOLIAN static Elm_Object_Item*
2850 _elm_widget_focus_next_item_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir)
2851 {
2852    Elm_Object_Item *ret = NULL;
2853
2854    if (dir == ELM_FOCUS_PREVIOUS)
2855      ret = sd->item_focus_previous;
2856    else if (dir == ELM_FOCUS_NEXT)
2857      ret = sd->item_focus_next;
2858    else if (dir == ELM_FOCUS_UP)
2859      ret = sd->item_focus_up;
2860    else if (dir == ELM_FOCUS_DOWN)
2861      ret = sd->item_focus_down;
2862    else if (dir == ELM_FOCUS_RIGHT)
2863      ret = sd->item_focus_right;
2864    else if (dir == ELM_FOCUS_LEFT)
2865      ret = sd->item_focus_left;
2866
2867    return ret;
2868 }
2869
2870 EOLIAN static void
2871 _elm_widget_focus_next_item_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Object_Item *next_item, Elm_Focus_Direction dir)
2872 {
2873    if (dir == ELM_FOCUS_PREVIOUS)
2874      sd->item_focus_previous = next_item;
2875    else if (dir == ELM_FOCUS_NEXT)
2876      sd->item_focus_next = next_item;
2877    else if (dir == ELM_FOCUS_UP)
2878      sd->item_focus_up = next_item;
2879    else if (dir == ELM_FOCUS_DOWN)
2880      sd->item_focus_down = next_item;
2881    else if (dir == ELM_FOCUS_RIGHT)
2882      sd->item_focus_right = next_item;
2883    else if (dir == ELM_FOCUS_LEFT)
2884      sd->item_focus_left = next_item;
2885 }
2886
2887 EOLIAN static void
2888 _elm_widget_parent_highlight_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool highlighted)
2889 {
2890    highlighted = !!highlighted;
2891
2892    Evas_Object *o = elm_widget_parent_get(obj);
2893
2894    if (o) elm_widget_parent_highlight_set(o, highlighted);
2895
2896    sd->highlighted = highlighted;
2897 }
2898
2899 EOLIAN static void
2900 _elm_widget_signal_emit(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source)
2901 {
2902    if (evas_object_smart_type_check(obj, "elm_layout"))
2903      elm_layout_signal_emit(obj, emission, source);
2904    else if (evas_object_smart_type_check(obj, "elm_icon"))
2905      {
2906         WRN("Deprecated function. This functionality on icon objects"
2907             " will be dropped on a next release.");
2908         _elm_icon_signal_emit(obj, emission, source);
2909      }
2910 }
2911
2912 EOLIAN static void
2913 _elm_widget_signal_callback_add(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
2914 {
2915    EINA_SAFETY_ON_NULL_RETURN(func);
2916
2917    if (evas_object_smart_type_check(obj, "elm_layout"))
2918      elm_layout_signal_callback_add(obj, emission, source, func, data);
2919    else if (evas_object_smart_type_check(obj, "elm_icon"))
2920      {
2921         WRN("Deprecated function. This functionality on icon objects"
2922             " will be dropped on a next release.");
2923
2924         _elm_icon_signal_callback_add(obj, emission, source, func, data);
2925      }
2926 }
2927
2928 EOLIAN static void*
2929 _elm_widget_signal_callback_del(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source, Edje_Signal_Cb func)
2930 {
2931    void *data = NULL;
2932
2933    if (evas_object_smart_type_check(obj, "elm_layout"))
2934      data = elm_layout_signal_callback_del(obj, emission, source, func);
2935    else if (evas_object_smart_type_check(obj, "elm_icon"))
2936      {
2937         WRN("Deprecated function. This functionality on icon objects"
2938             " will be dropped on a next release.");
2939
2940         data = _elm_icon_signal_callback_del(obj, emission, source, func);
2941      }
2942
2943    return data;
2944 }
2945
2946 EOLIAN static void
2947 _elm_widget_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool focus)
2948 {
2949    if (!sd->focused)
2950      {
2951         focus_order++;
2952         sd->focus_order = focus_order;
2953         sd->focused = EINA_TRUE;
2954         eo_do(obj, elm_obj_widget_on_focus(NULL));
2955      }
2956
2957    if (focus)
2958      {
2959         if ((_is_focusable(sd->resize_obj)) &&
2960             (!elm_widget_disabled_get(sd->resize_obj)))
2961           {
2962              elm_widget_focus_set(sd->resize_obj, focus);
2963           }
2964         else
2965           {
2966              const Eina_List *l;
2967              Evas_Object *child;
2968
2969              EINA_LIST_FOREACH(sd->subobjs, l, child)
2970                {
2971                   if (!_elm_widget_is(child)) continue;
2972                   if ((_is_focusable(child)) &&
2973                       (!elm_widget_disabled_get(child)))
2974                     {
2975                        elm_widget_focus_set(child, focus);
2976                        break;
2977                     }
2978                }
2979           }
2980      }
2981    else
2982      {
2983         const Eina_List *l;
2984         Evas_Object *child;
2985
2986         EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
2987           {
2988              if (!_elm_widget_is(child)) continue;
2989              if ((_is_focusable(child)) &&
2990                  (!elm_widget_disabled_get(child)))
2991                {
2992                   elm_widget_focus_set(child, focus);
2993                   break;
2994                }
2995           }
2996      }
2997 }
2998
2999 EOLIAN static Evas_Object*
3000 _elm_widget_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3001 {
3002    return sd->parent_obj;
3003 }
3004
3005 EOLIAN static void
3006 _elm_widget_focused_object_clear(Eo *obj, Elm_Widget_Smart_Data *sd)
3007 {
3008    if (!sd->focused) return;
3009    if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
3010        _is_focused(sd->resize_obj))
3011      {
3012         eo_do(sd->resize_obj, elm_obj_widget_focused_object_clear());
3013      }
3014    else
3015      {
3016         const Eina_List *l;
3017         Evas_Object *child;
3018         EINA_LIST_FOREACH(sd->subobjs, l, child)
3019           {
3020              if (_elm_widget_is(child) && _is_focused(child))
3021                {
3022                   eo_do(child, elm_obj_widget_focused_object_clear());
3023                   break;
3024                }
3025           }
3026      }
3027    sd->focused = EINA_FALSE;
3028    if (sd->top_win_focused)
3029      eo_do(obj, elm_obj_widget_on_focus(NULL));
3030 }
3031
3032 EOLIAN static void
3033 _elm_widget_focus_steal(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item)
3034 {
3035    Evas_Object *parent, *parent2, *o;
3036
3037    if (sd->focused) return;
3038    if (sd->disabled) return;
3039    if (!sd->can_focus) return;
3040    if (sd->tree_unfocusable) return;
3041    parent = obj;
3042    for (;; )
3043      {
3044         o = elm_widget_parent_get(parent);
3045         if (!o) break;
3046         sd = eo_data_scope_get(o, MY_CLASS);
3047         if (sd->disabled || sd->tree_unfocusable) return;
3048         if (sd->focused) break;
3049         parent = o;
3050      }
3051    if ((!elm_widget_parent_get(parent)) &&
3052        (!elm_widget_parent2_get(parent)))
3053      eo_do(parent, elm_obj_widget_focused_object_clear());
3054    else
3055      {
3056         parent2 = elm_widget_parent_get(parent);
3057         if (!parent2) parent2 = elm_widget_parent2_get(parent);
3058         parent = parent2;
3059         sd = eo_data_scope_get(parent, MY_CLASS);
3060         if (sd)
3061           {
3062              if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
3063                    _is_focused(sd->resize_obj))
3064                {
3065                   eo_do(sd->resize_obj, elm_obj_widget_focused_object_clear());
3066                }
3067              else
3068                {
3069                   const Eina_List *l;
3070                   Evas_Object *child;
3071                   EINA_LIST_FOREACH(sd->subobjs, l, child)
3072                     {
3073                        if (_elm_widget_is(child) && _is_focused(child))
3074                          {
3075                             eo_do(child, elm_obj_widget_focused_object_clear());
3076                             break;
3077                          }
3078                     }
3079                }
3080           }
3081      }
3082    _parent_focus(obj, item);
3083    elm_widget_focus_region_show(obj);
3084    return;
3085 }
3086
3087 static void
3088 _parents_on_focus(Evas_Object *obj)
3089 {
3090    API_ENTRY return;
3091    if (!sd->focused || !sd->top_win_focused) return;
3092
3093    Evas_Object *o = elm_widget_parent_get(obj);
3094    if (o) _parents_on_focus(o);
3095    eo_do(obj, elm_obj_widget_on_focus(NULL));
3096 }
3097
3098 EOLIAN static void
3099 _elm_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3100 {
3101    Evas_Object *newest = NULL;
3102    unsigned int newest_focus_order = 0;
3103
3104    newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
3105    if (newest)
3106      _parents_on_focus(newest);
3107 }
3108
3109 void
3110 _elm_widget_focus_auto_show(Evas_Object *obj)
3111 {
3112    Evas_Object *top = elm_widget_top_get(obj);
3113    if (top && eo_isa(top, ELM_WIN_CLASS)) _elm_win_focus_auto_show(top);
3114 }
3115
3116 void
3117 _elm_widget_top_win_focused_set(Evas_Object *obj,
3118                                 Eina_Bool top_win_focused)
3119 {
3120    const Eina_List *l;
3121    Evas_Object *child;
3122    API_ENTRY return;
3123
3124    if (sd->top_win_focused == top_win_focused) return;
3125    EINA_LIST_FOREACH(sd->subobjs, l, child)
3126      {
3127         if (elm_widget_is(child))
3128           _elm_widget_top_win_focused_set(child, top_win_focused);
3129      }
3130    sd->top_win_focused = top_win_focused;
3131
3132    if (sd->focused && !sd->top_win_focused)
3133      eo_do(obj, elm_obj_widget_on_focus(NULL));
3134 }
3135
3136 Eina_Bool
3137 _elm_widget_top_win_focused_get(const Evas_Object *obj)
3138 {
3139    API_ENTRY return EINA_FALSE;
3140    return sd->top_win_focused;
3141 }
3142
3143 static void
3144 _elm_widget_disabled_eval(const Evas_Object *obj, Eina_Bool disabled)
3145 {
3146    const Eina_List *l;
3147    Evas_Object *child;
3148    ELM_WIDGET_DATA_GET(obj, sd);
3149
3150    if (disabled)
3151      {
3152         EINA_LIST_FOREACH(sd->subobjs, l, child)
3153           {
3154               if (elm_widget_is(child))
3155                 {
3156                    elm_widget_focus_disabled_handle(child);
3157                    eo_do(child, elm_obj_widget_disable());
3158                    _elm_widget_disabled_eval(child, EINA_TRUE);
3159                 }
3160           }
3161      }
3162    else
3163      {
3164         EINA_LIST_FOREACH(sd->subobjs, l, child)
3165           {
3166              ELM_WIDGET_DATA_GET(child, sdc);
3167              if (elm_widget_is(child) && !sdc->disabled)
3168                {
3169                   elm_widget_focus_disabled_handle(child);
3170                   eo_do(child, elm_obj_widget_disable());
3171                   _elm_widget_disabled_eval(child, EINA_FALSE);
3172                }
3173           }
3174      }
3175 }
3176
3177 static void
3178 elm_widget_disabled_internal(Eo *obj, Eina_Bool disabled)
3179 {
3180    Eina_Bool parent_state = EINA_FALSE;
3181
3182    if (disabled)
3183      {
3184         elm_widget_focus_disabled_handle(obj);
3185         eo_do(obj, elm_obj_widget_disable());
3186         _elm_widget_disabled_eval(obj, EINA_TRUE);
3187      }
3188    else
3189      {
3190         parent_state = elm_widget_disabled_get(elm_widget_parent_get(obj));
3191         if (parent_state) return;
3192         elm_widget_focus_disabled_handle(obj);
3193         eo_do(obj, elm_obj_widget_disable());
3194         _elm_widget_disabled_eval(obj, EINA_FALSE);
3195      }
3196 }
3197
3198 EOLIAN static void
3199 _elm_widget_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled)
3200 {
3201    if (sd->disabled == disabled) return;
3202    sd->disabled = !!disabled;
3203
3204    elm_widget_disabled_internal(obj, disabled);
3205 }
3206
3207 EOLIAN static Eina_Bool
3208 _elm_widget_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3209 {
3210    Eina_Bool disabled = EINA_FALSE;
3211
3212    if (sd->disabled) disabled = EINA_TRUE;
3213    else disabled = elm_widget_disabled_get(elm_widget_parent_get(obj));
3214    return disabled;
3215 }
3216
3217 EOLIAN static void
3218 _elm_widget_show_region_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool forceshow)
3219 {
3220
3221    Evas_Object *parent_obj, *child_obj;
3222    Evas_Coord px, py, cx, cy, nx = 0, ny = 0;
3223
3224
3225    evas_smart_objects_calculate(evas_object_evas_get(obj));
3226
3227    if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
3228        (w == sd->rw) && (h == sd->rh)) return;
3229
3230    sd->rx = x;
3231    sd->ry = y;
3232    sd->rw = w;
3233    sd->rh = h;
3234    if (sd->on_show_region)
3235      {
3236         sd->on_show_region
3237            (sd->on_show_region_data, obj);
3238
3239         if (_elm_scrollable_is(obj))
3240           {
3241              eo_do(obj, elm_interface_scrollable_content_pos_get(&nx, &ny));
3242              x -= nx;
3243              y -= ny;
3244           }
3245      }
3246
3247    do
3248      {
3249         parent_obj = sd->parent_obj;
3250         child_obj = sd->obj;
3251         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
3252         sd = eo_data_scope_get(parent_obj, MY_CLASS);
3253         if (!sd) break;
3254
3255         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
3256         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
3257
3258         x += (cx - px);
3259         y += (cy - py);
3260         sd->rx = x;
3261         sd->ry = y;
3262         sd->rw = w;
3263         sd->rh = h;
3264
3265         if (sd->on_show_region)
3266           {
3267              sd->on_show_region
3268                (sd->on_show_region_data, parent_obj);
3269           }
3270      }
3271    while (parent_obj);
3272 }
3273
3274 EOLIAN static void
3275 _elm_widget_show_region_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3276 {
3277    if (x) *x = sd->rx;
3278    if (y) *y = sd->ry;
3279    if (w) *w = sd->rw;
3280    if (h) *h = sd->rh;
3281 }
3282
3283 /**
3284  * @internal
3285  *
3286  * Get the focus region of the given widget.
3287  *
3288  * @return show region or not
3289  * (@c EINA_TRUE = show region/@c EINA_FALSE = do not show region). Default is @c EINA_FALSE.
3290  *
3291  * The focus region is the area of a widget that should brought into the
3292  * visible area when the widget is focused. Mostly used to show the part of
3293  * an entry where the cursor is, for example. The area returned is relative
3294  * to the object @p obj.
3295  *
3296  * @param obj The widget object
3297  * @param x Where to store the x coordinate of the area
3298  * @param y Where to store the y coordinate of the area
3299  * @param w Where to store the width of the area
3300  * @param h Where to store the height of the area
3301  *
3302  * @ingroup Widget
3303  */
3304 EOLIAN static Eina_Bool
3305 _elm_widget_focus_region_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3306 {
3307    Eina_Bool int_ret = EINA_FALSE;
3308    eo_do((Eo *)obj, int_ret = elm_obj_widget_on_focus_region(x, y, w, h));
3309    if (!int_ret)
3310      {
3311         evas_object_geometry_get(obj, NULL, NULL, w, h);
3312         if (x) *x = 0;
3313         if (y) *y = 0;
3314      }
3315    if ((*w <= 0) || (*h <= 0)) return EINA_FALSE;
3316    return EINA_TRUE;
3317 }
3318
3319 EOLIAN static void
3320 _elm_widget_parents_bounce_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool *horiz, Eina_Bool *vert)
3321 {
3322    Evas_Object *parent_obj = obj;
3323    Eina_Bool h = EINA_FALSE, v = EINA_FALSE;
3324
3325    *horiz = EINA_FALSE;
3326    *vert = EINA_FALSE;
3327
3328    do
3329      {
3330         parent_obj = elm_widget_parent_get(parent_obj);
3331         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
3332
3333         if (_elm_scrollable_is(parent_obj))
3334           {
3335              eo_do(parent_obj, elm_interface_scrollable_bounce_allow_get(&h, &v));
3336              if (h) *horiz = EINA_TRUE;
3337              if (v) *vert = EINA_TRUE;
3338           }
3339      }
3340    while (parent_obj);
3341 }
3342
3343 EOLIAN static Eina_List*
3344 _elm_widget_scrollable_children_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3345 {
3346    Eina_List *ret;
3347    ret = NULL;
3348
3349    Eina_List *l;
3350    Evas_Object *child;
3351
3352
3353    EINA_LIST_FOREACH(sd->subobjs, l, child)
3354      {
3355         if (elm_widget_is(child) && _elm_scrollable_is(child))
3356           ret = eina_list_append(ret, child);
3357      }
3358
3359    return ret;
3360 }
3361
3362 EOLIAN static void
3363 _elm_widget_scroll_hold_push(Eo *obj, Elm_Widget_Smart_Data *sd)
3364 {
3365    sd->scroll_hold++;
3366    if (sd->scroll_hold == 1)
3367      {
3368         if (_elm_scrollable_is(obj))
3369            eo_do(obj, elm_interface_scrollable_hold_set(EINA_TRUE));
3370         else
3371           {
3372              Eina_List *scr_children, *l;
3373              Evas_Object *child;
3374
3375              scr_children = elm_widget_scrollable_children_get(obj);
3376              EINA_LIST_FOREACH(scr_children, l, child)
3377                {
3378                   eo_do(child, elm_interface_scrollable_hold_set(EINA_TRUE));
3379                }
3380              eina_list_free(scr_children);
3381           }
3382      }
3383    if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_hold_push());
3384    // FIXME: on delete/reparent hold pop
3385 }
3386
3387 EOLIAN static void
3388 _elm_widget_scroll_hold_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
3389 {
3390    sd->scroll_hold--;
3391    if (!sd->scroll_hold)
3392      {
3393         if (_elm_scrollable_is(obj))
3394            eo_do(obj, elm_interface_scrollable_hold_set(EINA_FALSE));
3395         else
3396           {
3397              Eina_List *scr_children, *l;
3398              Evas_Object *child;
3399
3400              scr_children = elm_widget_scrollable_children_get(obj);
3401              EINA_LIST_FOREACH(scr_children, l, child)
3402                {
3403                   eo_do(child, elm_interface_scrollable_hold_set(EINA_FALSE));
3404                }
3405              eina_list_free(scr_children);
3406           }
3407      }
3408    if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_hold_pop());
3409    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
3410 }
3411
3412 EOLIAN static int
3413 _elm_widget_scroll_hold_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3414 {
3415    return sd->scroll_hold;
3416 }
3417
3418 EOLIAN static void
3419 _elm_widget_scroll_freeze_push(Eo *obj, Elm_Widget_Smart_Data *sd)
3420 {
3421    sd->scroll_freeze++;
3422    if (sd->scroll_freeze == 1)
3423      {
3424         if (_elm_scrollable_is(obj))
3425            eo_do(obj, elm_interface_scrollable_freeze_set(EINA_TRUE));
3426         else
3427           {
3428              Eina_List *scr_children, *l;
3429              Evas_Object *child;
3430
3431              scr_children = elm_widget_scrollable_children_get(obj);
3432              EINA_LIST_FOREACH(scr_children, l, child)
3433                {
3434                   eo_do(child, elm_interface_scrollable_freeze_set(EINA_TRUE));
3435                }
3436              eina_list_free(scr_children);
3437           }
3438      }
3439    if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_freeze_push());
3440    // FIXME: on delete/reparent freeze pop
3441 }
3442
3443 EOLIAN static void
3444 _elm_widget_scroll_freeze_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
3445 {
3446    sd->scroll_freeze--;
3447    if (!sd->scroll_freeze)
3448      {
3449         if (_elm_scrollable_is(obj))
3450            eo_do(obj, elm_interface_scrollable_freeze_set(EINA_FALSE));
3451         else
3452           {
3453              Eina_List *scr_children, *l;
3454              Evas_Object *child;
3455
3456              scr_children = elm_widget_scrollable_children_get(obj);
3457              EINA_LIST_FOREACH(scr_children, l, child)
3458                {
3459                   eo_do(child, elm_interface_scrollable_freeze_set(EINA_FALSE));
3460                }
3461              eina_list_free(scr_children);
3462           }
3463      }
3464    if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_freeze_pop());
3465    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
3466 }
3467
3468 EOLIAN static int
3469 _elm_widget_scroll_freeze_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3470 {
3471    return sd->scroll_freeze;
3472 }
3473
3474 // TIZEN_ONLY(20150705): Genlist item align feature
3475 EAPI void
3476 elm_widget_scroll_item_align_enabled_set(Evas_Object *obj,
3477                                         Eina_Bool scroll_item_align_enable)
3478 {
3479    API_ENTRY return;
3480    if (sd->scroll_item_align_enable == scroll_item_align_enable) return;
3481    sd->scroll_item_align_enable = scroll_item_align_enable;
3482 }
3483
3484 EAPI Eina_Bool
3485 elm_widget_scroll_item_align_enabled_get(const Evas_Object *obj)
3486 {
3487    API_ENTRY return EINA_FALSE;
3488    return sd->scroll_item_align_enable;
3489 }
3490
3491 EAPI void
3492 elm_widget_scroll_item_valign_set(Evas_Object *obj,
3493                                   const char *scroll_item_valign)
3494 {
3495    API_ENTRY return;
3496    if (sd->scroll_item_valign) eina_stringshare_del(sd->scroll_item_valign);
3497    if (!scroll_item_valign) sd->scroll_item_valign = NULL;
3498    else sd->scroll_item_valign = eina_stringshare_add(scroll_item_valign);
3499 }
3500
3501 EAPI const char*
3502 elm_widget_scroll_item_valign_get(const Evas_Object *obj)
3503 {
3504    API_ENTRY return NULL;
3505    return sd->scroll_item_valign;
3506 }
3507 //
3508
3509 EOLIAN static void
3510 _elm_widget_scale_set(Eo *obj, Elm_Widget_Smart_Data *sd, double scale)
3511 {
3512    if (scale < 0.0) scale = 0.0;
3513    if (sd->scale != scale)
3514      {
3515         sd->scale = scale;
3516         elm_widget_theme(obj);
3517      }
3518 }
3519
3520 EOLIAN static double
3521 _elm_widget_scale_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3522 {
3523    // FIXME: save walking up the tree by storing/caching parent scale
3524    if (sd->scale == 0.0)
3525      {
3526         if (sd->parent_obj && elm_widget_is(sd->parent_obj))
3527           {
3528              return elm_widget_scale_get(sd->parent_obj);
3529           }
3530         else
3531           {
3532              return 1.0;
3533           }
3534      }
3535    return sd->scale;
3536 }
3537
3538 EOLIAN static void
3539 _elm_widget_theme_set(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Theme *th)
3540 {
3541    Eina_Bool apply = EINA_FALSE;
3542    if (sd->theme != th)
3543      {
3544         if (elm_widget_theme_get(obj) != th) apply = EINA_TRUE;
3545         if (sd->theme) elm_theme_free(sd->theme);
3546         sd->theme = th;
3547         if (th) th->ref++;
3548         if (apply) elm_widget_theme(obj);
3549      }
3550 }
3551
3552 EOLIAN static void
3553 _elm_widget_part_text_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part, const char *label)
3554 {
3555    if (evas_object_smart_type_check(obj, "elm_layout"))
3556      elm_layout_text_set(obj, part, label);
3557 }
3558
3559 EOLIAN static const char*
3560 _elm_widget_part_text_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part)
3561 {
3562    if (evas_object_smart_type_check(obj, "elm_layout"))
3563      return elm_layout_text_get(obj, part);
3564
3565    return NULL;
3566 }
3567
3568 static Elm_Translate_String_Data *
3569 _translate_string_data_get(Eina_Inlist *translate_strings, const char *part)
3570 {
3571    Elm_Translate_String_Data *ts;
3572    Eina_Stringshare *str;
3573
3574    if (!translate_strings) return NULL;
3575
3576    str = eina_stringshare_add(part);
3577    EINA_INLIST_FOREACH(translate_strings, ts)
3578      {
3579         if (ts->id == str) break;
3580      }
3581
3582    eina_stringshare_del(str);
3583
3584    return ts;
3585 }
3586
3587 static Elm_Translate_String_Data *
3588 _part_text_translatable_set(Eina_Inlist **translate_strings, const char *part, Eina_Bool translatable, Eina_Bool preset)
3589 {
3590    Eina_Inlist *t;
3591    Elm_Translate_String_Data *ts;
3592    t = *translate_strings;
3593    ts = _translate_string_data_get(t, part);
3594
3595    if (translatable)
3596      {
3597         if (!ts)
3598           {
3599              ts = ELM_NEW(Elm_Translate_String_Data);
3600              if (!ts) return NULL;
3601
3602              ts->id = eina_stringshare_add(part);
3603              t = eina_inlist_append(t, (Eina_Inlist*) ts);
3604           }
3605         if (preset) ts->preset = EINA_TRUE;
3606      }
3607    //Delete this exist one if this part has been not preset.
3608    //see elm_widget_part_text_translatable_set()
3609    else if (ts && ((preset) || (!ts->preset)))
3610      {
3611         t = eina_inlist_remove(t, EINA_INLIST_GET(ts));
3612         eina_stringshare_del(ts->id);
3613         eina_stringshare_del(ts->domain);
3614         eina_stringshare_del(ts->string);
3615         ELM_SAFE_FREE(ts, free);
3616      }
3617
3618    *translate_strings = t;
3619
3620    return ts;
3621 }
3622
3623 EOLIAN static void
3624 _elm_widget_domain_translatable_part_text_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, const char *label)
3625 {
3626
3627    Elm_Translate_String_Data *ts;
3628
3629    if (!label)
3630      {
3631         _part_text_translatable_set(&sd->translate_strings, part, EINA_FALSE,
3632                                     EINA_FALSE);
3633      }
3634    else
3635      {
3636         ts = _part_text_translatable_set(&sd->translate_strings, part,
3637                                          EINA_TRUE, EINA_FALSE);
3638         if (!ts) return;
3639         if (!ts->string) ts->string = eina_stringshare_add(label);
3640         else eina_stringshare_replace(&ts->string, label);
3641         if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3642         else eina_stringshare_replace(&ts->domain, domain);
3643 #ifdef HAVE_GETTEXT
3644         if (label[0]) label = dgettext(domain, label);
3645 #endif
3646      }
3647
3648    sd->on_translate = EINA_TRUE;
3649    eo_do(obj, elm_obj_widget_part_text_set(part, label));
3650    sd->on_translate = EINA_FALSE;
3651 }
3652
3653 EOLIAN static const char*
3654 _elm_widget_translatable_part_text_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part)
3655 {
3656    Elm_Translate_String_Data *ts;
3657
3658    ts = _translate_string_data_get(sd->translate_strings, part);
3659    if (ts) return ts->string;
3660    else return NULL;
3661 }
3662
3663 EOLIAN static void
3664 _elm_widget_domain_part_text_translatable_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, Eina_Bool translatable)
3665 {
3666    Elm_Translate_String_Data *ts;
3667    const char *text = NULL;
3668
3669    ts = _part_text_translatable_set(&sd->translate_strings, part,
3670                                     translatable, EINA_TRUE);
3671    if (!ts) return;
3672    if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3673    else eina_stringshare_replace(&ts->domain, domain);
3674
3675    eo_do(obj, text = elm_obj_widget_part_text_get(part));
3676    if (!text || !text[0]) return;
3677
3678    if (!ts->string) ts->string = eina_stringshare_add(text);
3679
3680 //Try to translate text since we don't know the text is already translated.
3681 #ifdef HAVE_GETTEXT
3682    text = dgettext(domain, text);
3683 #endif
3684    sd->on_translate = EINA_TRUE;
3685    eo_do(obj, elm_obj_widget_part_text_set(part, text));
3686    sd->on_translate = EINA_FALSE;
3687 }
3688
3689 EAPI void
3690 elm_widget_translate(Evas_Object *obj)
3691 {
3692    ELM_WIDGET_CHECK(obj);
3693    eo_do(obj, elm_obj_widget_translate());
3694 }
3695
3696 static const char*
3697 _part_text_translate(Eina_Inlist *translate_strings,
3698                      const char *part,
3699                      const char *text)
3700 {
3701    Elm_Translate_String_Data *ts;
3702    ts = _translate_string_data_get(translate_strings, part);
3703    if (!ts) return text;
3704
3705    if (!ts->string) ts->string = eina_stringshare_add(text);
3706    else eina_stringshare_replace(&ts->string, text);
3707 #ifdef HAVE_GETTEXT
3708    if (text && text[0])
3709      text = dgettext(ts->domain, text);
3710 #endif
3711    return text;
3712 }
3713
3714 EOLIAN static const char*
3715 _elm_widget_part_text_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part, const char *text)
3716 {
3717
3718
3719    if (!sd->translate_strings || sd->on_translate) return text;
3720    return _part_text_translate(sd->translate_strings, part, text);
3721 }
3722
3723 EOLIAN static Eina_Bool
3724 _elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3725 {
3726    const Eina_List *l;
3727    Evas_Object *child;
3728    API_ENTRY return EINA_FALSE;
3729
3730    EINA_LIST_FOREACH(sd->subobjs, l, child)
3731      {
3732         if (elm_widget_is(child))
3733           elm_widget_translate(child);
3734      }
3735
3736    if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
3737
3738 #ifdef HAVE_GETTEXT
3739    Elm_Translate_String_Data *ts;
3740    EINA_INLIST_FOREACH(sd->translate_strings, ts)
3741      {
3742         if (!ts->string) continue;
3743         const char *s = dgettext(ts->domain, ts->string);
3744         sd->on_translate = EINA_TRUE;
3745         eo_do(obj, elm_obj_widget_part_text_set(ts->id, s));
3746         sd->on_translate = EINA_FALSE;
3747      }
3748 #endif
3749    eo_do(obj, eo_event_callback_call(ELM_WIDGET_EVENT_LANGUAGE_CHANGED, NULL));
3750    return EINA_TRUE;
3751 }
3752
3753 /**
3754  * @internal
3755  *
3756  * Resets the focus_move_policy mode from the system one
3757  * for widgets that are in automatic mode.
3758  *
3759  * @param obj The widget.
3760  *
3761  */
3762 static void
3763 _elm_widget_focus_move_policy_reload(Evas_Object *obj)
3764 {
3765    API_ENTRY return;
3766    Elm_Focus_Move_Policy focus_move_policy = elm_config_focus_move_policy_get();
3767
3768    if (elm_widget_focus_move_policy_automatic_get(obj) &&
3769        (sd->focus_move_policy != focus_move_policy))
3770      {
3771         sd->focus_move_policy = focus_move_policy;
3772      }
3773 }
3774
3775 EOLIAN static void
3776 _elm_widget_focus_reconfigure(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3777 {
3778    const Eina_List *l;
3779    Evas_Object *child;
3780    API_ENTRY return;
3781
3782    EINA_LIST_FOREACH(sd->subobjs, l, child)
3783      {
3784         if (elm_widget_is(child))
3785           elm_widget_focus_reconfigure(child);
3786      }
3787
3788    if (sd->hover_obj) elm_widget_focus_reconfigure(sd->hover_obj);
3789
3790    _elm_widget_focus_move_policy_reload(obj);
3791 }
3792
3793 //TIZEN_ONLY(20160726): add API elm_object_part_access_object_get
3794 EOLIAN static Evas_Object*
3795 _elm_widget_part_access_object_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part EINA_UNUSED)
3796 {
3797    WRN("The %s widget does not implement the \"part_access_object_get\" functions.",
3798        eo_class_name_get(eo_class_get(obj)));
3799    return NULL;
3800 }
3801 //
3802
3803 EAPI void
3804 elm_widget_content_part_set(Evas_Object *obj,
3805                             const char *part,
3806                             Evas_Object *content)
3807 {
3808    ELM_WIDGET_CHECK(obj);
3809    eo_do(obj, elm_obj_container_content_set(part, content));
3810 }
3811
3812 /**
3813  * Returns the widget's focus_move_policy mode setting.
3814  *
3815  * @param obj The widget.
3816  * @return focus_move_policy mode setting of the object.
3817  *
3818  **/
3819 EOLIAN static Eina_Bool
3820 _elm_widget_focus_move_policy_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3821 {
3822    return sd->focus_move_policy_auto_mode;
3823 }
3824
3825 /**
3826  * @internal
3827  *
3828  * Sets the widget's focus_move_policy mode setting.
3829  * When widget in automatic mode, it follows the system focus_move_policy mode set by
3830  * elm_config_focus_move_policy_set().
3831  * @param obj The widget.
3832  * @param automatic EINA_TRUE for auto focus_move_policy mode. EINA_FALSE for manual.
3833  */
3834 EOLIAN static void
3835 _elm_widget_focus_move_policy_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
3836 {
3837    if (sd->focus_move_policy_auto_mode != automatic)
3838      {
3839         sd->focus_move_policy_auto_mode = automatic;
3840
3841         if (automatic)
3842           {
3843              elm_widget_focus_move_policy_set(obj, elm_config_focus_move_policy_get());
3844           }
3845      }
3846 }
3847
3848 EAPI Evas_Object *
3849 elm_widget_content_part_get(const Evas_Object *obj,
3850                             const char *part)
3851 {
3852    ELM_WIDGET_CHECK(obj) NULL;
3853    Evas_Object *ret = NULL;
3854    eo_do((Eo *) obj, ret = elm_obj_container_content_get(part));
3855    return ret;
3856 }
3857
3858 EAPI Evas_Object *
3859 elm_widget_content_part_unset(Evas_Object *obj,
3860                               const char *part)
3861 {
3862    ELM_WIDGET_CHECK(obj) NULL;
3863    Evas_Object *ret = NULL;
3864    eo_do(obj, ret = elm_obj_container_content_unset(part));
3865    return ret;
3866 }
3867
3868 EOLIAN static void
3869 _elm_widget_access_info_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *txt)
3870 {
3871    eina_stringshare_del(sd->access_info);
3872    if (!txt) sd->access_info = NULL;
3873    else sd->access_info = eina_stringshare_add(txt);
3874 }
3875
3876 EOLIAN static const char*
3877 _elm_widget_access_info_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3878 {
3879    return sd->access_info;
3880 }
3881
3882 EOLIAN static Elm_Theme*
3883 _elm_widget_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3884 {
3885    if (!sd->theme)
3886      {
3887         if (sd->parent_obj && elm_widget_is(sd->parent_obj))
3888            return elm_widget_theme_get(sd->parent_obj);
3889         else return NULL;
3890      }
3891    return sd->theme;
3892 }
3893
3894 EOLIAN static Elm_Theme_Apply
3895 _elm_widget_style_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *style)
3896 {
3897    if (eina_stringshare_replace(&sd->style, style))
3898       return elm_widget_theme(obj);
3899
3900    return ELM_THEME_APPLY_SUCCESS;
3901 }
3902
3903 EOLIAN static const char*
3904 _elm_widget_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3905 {
3906    const char *ret;
3907    ret = "default";
3908    if (sd->style) ret = sd->style;
3909
3910    return ret;
3911 }
3912
3913 EOLIAN static void
3914 _elm_widget_tooltip_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt)
3915 {
3916    sd->tooltips = eina_list_append(sd->tooltips, tt);
3917 }
3918
3919 EOLIAN static void
3920 _elm_widget_tooltip_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt)
3921 {
3922    sd->tooltips = eina_list_remove(sd->tooltips, tt);
3923 }
3924
3925 EOLIAN static void
3926 _elm_widget_cursor_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Cursor *cur)
3927 {
3928    sd->cursors = eina_list_append(sd->cursors, cur);
3929 }
3930
3931 EOLIAN static void
3932 _elm_widget_cursor_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Cursor *cur)
3933 {
3934    sd->cursors = eina_list_remove(sd->cursors, cur);
3935 }
3936
3937 EOLIAN static void
3938 _elm_widget_drag_lock_x_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock)
3939 {
3940    if (sd->drag_x_locked == lock) return;
3941    sd->drag_x_locked = lock;
3942    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
3943    else _propagate_x_drag_lock(obj, -1);
3944 }
3945
3946 EOLIAN static void
3947 _elm_widget_drag_lock_y_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock)
3948 {
3949    if (sd->drag_y_locked == lock) return;
3950    sd->drag_y_locked = lock;
3951    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
3952    else _propagate_y_drag_lock(obj, -1);
3953 }
3954
3955 EOLIAN static Eina_Bool
3956 _elm_widget_drag_lock_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3957 {
3958    return sd->drag_x_locked;
3959 }
3960
3961 EOLIAN static Eina_Bool
3962 _elm_widget_drag_lock_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3963 {
3964    return sd->drag_y_locked;
3965 }
3966
3967 EOLIAN static int
3968 _elm_widget_drag_child_locked_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3969 {
3970    return sd->child_drag_x_locked;
3971 }
3972
3973 EOLIAN static int
3974 _elm_widget_drag_child_locked_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3975 {
3976    return sd->child_drag_y_locked;
3977 }
3978
3979 EOLIAN static void
3980 _elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Bool enable EINA_UNUSED)
3981 {
3982         return;
3983 }
3984
3985 EOLIAN static Eina_Bool
3986 _elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED)
3987 {
3988         return EINA_FALSE;
3989 }
3990
3991 EOLIAN static Elm_Theme_Apply
3992 _elm_widget_theme_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle)
3993 {
3994    Elm_Theme_Apply ret = _elm_theme_object_set(obj, edj, wname, welement, wstyle);
3995    if (!ret)
3996      {
3997         return ELM_THEME_APPLY_FAILED;
3998      }
3999
4000    if (sd->orient_mode != -1)
4001      {
4002         char buf[128];
4003         snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
4004         eo_do(obj, elm_obj_widget_signal_emit(buf, "elm"));
4005      }
4006
4007    return ret;
4008 }
4009
4010 EOLIAN static void
4011 _elm_widget_eo_base_dbg_info_get(Eo *eo_obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eo_Dbg_Info *root)
4012 {
4013    eo_do_super(eo_obj, MY_CLASS, eo_dbg_info_get(root));
4014    Eo_Dbg_Info *group = EO_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
4015
4016    EO_DBG_INFO_APPEND(group, "Wid-Type", EINA_VALUE_TYPE_STRING, elm_widget_type_get(eo_obj));
4017    EO_DBG_INFO_APPEND(group, "Style", EINA_VALUE_TYPE_STRING, elm_widget_style_get(eo_obj));
4018    EO_DBG_INFO_APPEND(group, "Layer", EINA_VALUE_TYPE_INT,
4019          (int) evas_object_layer_get(eo_obj));
4020    EO_DBG_INFO_APPEND(group, "Scale", EINA_VALUE_TYPE_DOUBLE,
4021          evas_object_scale_get(eo_obj));
4022    EO_DBG_INFO_APPEND(group, "Has focus", EINA_VALUE_TYPE_CHAR,
4023          elm_object_focus_get(eo_obj));
4024    EO_DBG_INFO_APPEND(group, "Disabled", EINA_VALUE_TYPE_CHAR,
4025          elm_widget_disabled_get(eo_obj));
4026    EO_DBG_INFO_APPEND(group, "Mirrored", EINA_VALUE_TYPE_CHAR,
4027          elm_widget_mirrored_get(eo_obj));
4028    EO_DBG_INFO_APPEND(group, "Automatic mirroring", EINA_VALUE_TYPE_CHAR,
4029          elm_widget_mirrored_automatic_get(eo_obj));
4030 }
4031
4032 EAPI Eina_Bool
4033 elm_widget_is_check(const Evas_Object *obj)
4034 {
4035    static int abort_on_warn = -1;
4036    if (elm_widget_is(obj))
4037      return EINA_TRUE;
4038
4039    ERR("Passing Object: %p.", obj);
4040    if (abort_on_warn == -1)
4041      {
4042         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
4043         else abort_on_warn = 0;
4044      }
4045    if (abort_on_warn == 1) abort();
4046    return EINA_FALSE;
4047 }
4048
4049 EAPI const char *
4050 elm_widget_type_get(const Evas_Object *obj)
4051 {
4052    API_ENTRY return NULL;
4053
4054    return eo_class_name_get(eo_class_get(obj));
4055 }
4056
4057 EAPI Eina_Bool
4058 elm_widget_type_check(const Evas_Object *obj,
4059                       const char *type,
4060                       const char *func)
4061 {
4062    const char *provided, *expected = "(unknown)";
4063    static int abort_on_warn = -1;
4064
4065    provided = elm_widget_type_get(obj);
4066    /* TODO: eventually migrate to check_ptr version */
4067    if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
4068    if (type) expected = type;
4069    if ((!provided) || (!provided[0]))
4070      {
4071         provided = evas_object_type_get(obj);
4072         if ((!provided) || (!provided[0]))
4073           provided = "(unknown)";
4074      }
4075    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
4076        " type: '%s'", obj, func, provided, expected);
4077    if (abort_on_warn == -1)
4078      {
4079         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
4080         else abort_on_warn = 0;
4081      }
4082    if (abort_on_warn == 1) abort();
4083    return EINA_FALSE;
4084 }
4085
4086 static Evas_Object *
4087 _widget_name_find(const Evas_Object *obj,
4088                   const char *name,
4089                   int recurse)
4090 {
4091    Eina_List *l;
4092    Evas_Object *child;
4093    const char *s;
4094    INTERNAL_ENTRY NULL;
4095
4096    if (!_elm_widget_is(obj)) return NULL;
4097    EINA_LIST_FOREACH(sd->subobjs, l, child)
4098      {
4099         s = evas_object_name_get(child);
4100         if ((s) && (!strcmp(s, name))) return child;
4101         if ((recurse != 0) &&
4102             ((child = _widget_name_find(child, name, recurse - 1))))
4103           return child;
4104      }
4105    if (sd->hover_obj)
4106      {
4107         s = evas_object_name_get(sd->hover_obj);
4108         if ((s) && (!strcmp(s, name))) return sd->hover_obj;
4109         if ((recurse != 0) &&
4110             ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
4111           return child;
4112      }
4113    return NULL;
4114 }
4115
4116 EOLIAN static Evas_Object*
4117 _elm_widget_name_find(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *name, int recurse)
4118 {
4119    if (!name) return NULL;
4120    return _widget_name_find(obj, name, recurse);
4121 }
4122
4123 /**
4124  * @internal
4125  *
4126  * Split string in words
4127  *
4128  * @param str Source string
4129  * @return List of const words
4130  *
4131  * @see elm_widget_stringlist_free()
4132  * @ingroup Widget
4133  */
4134 EAPI Eina_List *
4135 elm_widget_stringlist_get(const char *str)
4136 {
4137    Eina_List *list = NULL;
4138    const char *s, *b;
4139    if (!str) return NULL;
4140    for (b = s = str; 1; s++)
4141      {
4142         if ((*s == ' ') || (!*s))
4143           {
4144              char *t = malloc(s - b + 1);
4145              if (t)
4146                {
4147                   strncpy(t, b, s - b);
4148                   t[s - b] = 0;
4149                   list = eina_list_append(list, eina_stringshare_add(t));
4150                   free(t);
4151                }
4152              b = s + 1;
4153           }
4154         if (!*s) break;
4155      }
4156    return list;
4157 }
4158
4159 EAPI void
4160 elm_widget_stringlist_free(Eina_List *list)
4161 {
4162    const char *s;
4163    EINA_LIST_FREE(list, s)
4164      eina_stringshare_del(s);
4165 }
4166
4167 EOLIAN static void
4168 _elm_widget_focus_hide_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4169 {
4170    if (!_elm_widget_is(obj))
4171      return;
4172    _if_focused_revert(obj, EINA_TRUE);
4173 }
4174
4175 EAPI void
4176 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
4177 {
4178    Evas_Object *o = obj;
4179    do
4180      {
4181         if (_elm_widget_is(o)) break;
4182         o = evas_object_smart_parent_get(o);
4183      }
4184    while (o);
4185
4186    eo_do(o, elm_obj_widget_focus_mouse_up_handle());
4187 }
4188
4189 EOLIAN static void
4190 _elm_widget_focus_mouse_up_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4191 {
4192    if (!obj) return;
4193    if (!_is_focusable(obj)) return;
4194
4195    elm_widget_focus_steal(obj, NULL);
4196 }
4197
4198 EOLIAN static void
4199 _elm_widget_focus_tree_unfocusable_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4200 {
4201    if (!elm_widget_parent_get(obj))
4202      elm_widget_focused_object_clear(obj);
4203    else
4204      _if_focused_revert(obj, EINA_TRUE);
4205 }
4206
4207 EOLIAN static void
4208 _elm_widget_focus_disabled_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4209 {
4210    elm_widget_focus_tree_unfocusable_handle(obj);
4211 }
4212
4213 EOLIAN static unsigned int
4214 _elm_widget_focus_order_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4215 {
4216    return sd->focus_order;
4217 }
4218
4219 EOLIAN static Evas_Object*
4220 _elm_widget_newest_focus_order_get(const Eo *obj, Elm_Widget_Smart_Data *sd, unsigned int *newest_focus_order, Eina_Bool can_focus_only)
4221 {
4222    const Eina_List *l;
4223    Evas_Object *child, *cur, *best;
4224
4225    if (!evas_object_visible_get(obj)
4226        || (elm_widget_disabled_get(obj))
4227        || (elm_widget_tree_unfocusable_get(obj)))
4228      return NULL;
4229
4230    best = NULL;
4231    if (*newest_focus_order < sd->focus_order)
4232      {
4233         if (!can_focus_only || elm_widget_can_focus_get(obj))
4234           {
4235              *newest_focus_order = sd->focus_order;
4236              best = (Evas_Object *)obj;
4237           }
4238      }
4239    EINA_LIST_FOREACH(sd->subobjs, l, child)
4240      {
4241         if (!_elm_widget_is(child)) continue;
4242
4243         cur = elm_widget_newest_focus_order_get
4244            (child, newest_focus_order, can_focus_only);
4245         if (!cur) continue;
4246         best = cur;
4247      }
4248    return best;
4249 }
4250
4251 /*
4252  * @internal
4253  *
4254  * Get the focus highlight geometry of an widget.
4255  *
4256  * @param obj Widget object for the focus highlight
4257  * @param x Focus highlight x coordinate
4258  * @param y Focus highlight y coordinate
4259  * @param w Focus highlight object width
4260  * @param h Focus highlight object height
4261  * @param is_next @c EINA_TRUE if this request is for the new focused object,
4262  * @c EINA_FALSE if this request is for the previously focused object. This
4263  * information becomes important when the focus highlight is changed inside one
4264  * widget.
4265  *
4266  * @ingroup Widget
4267  */
4268 /*
4269  * @internal
4270  *
4271  * Get the 'focus_part' geometry if there is any
4272  *
4273  * This queries if there is a 'focus_part' request from the edc style. If edc
4274  * style offers 'focus_part' edje data item, this function requests for the
4275  * geometry of a specific part which is described in 'focus_part' edje data.
4276  *
4277  * @param obj Widget object for the focus highlight
4278  * @param x Focus highlight x coordinate
4279  * @param y Focus highlight y coordinate
4280  * @param w Focus highlight object width
4281  * @param h Focus highlight object height
4282  *
4283  * x, y, w, h already contain the object's geometry. If there is a 'focus_part'
4284  * support, these values will be updated accordingly or the values will be
4285  * remained as they were.
4286  *
4287  * @ingroup Widget
4288  */
4289 EAPI void
4290 elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj,
4291                                                    Evas_Coord *x,
4292                                                    Evas_Coord *y,
4293                                                    Evas_Coord *w,
4294                                                    Evas_Coord *h)
4295 {
4296    Evas_Coord tx = 0, ty = 0, tw = 0, th = 0;
4297    const char *target_hl_part = NULL;
4298    const Evas_Object *edje_obj = NULL;
4299
4300    if (obj && eo_isa(obj, EDJE_OBJECT_CLASS))
4301      {
4302         edje_obj = obj;
4303         if (!(target_hl_part = edje_object_data_get(edje_obj, "focus_part")))
4304           return;
4305      }
4306    else if (obj && eo_isa(obj, ELM_LAYOUT_CLASS))
4307      {
4308         edje_obj = elm_layout_edje_get(obj);
4309         if (!(target_hl_part = elm_layout_data_get(obj, "focus_part")))
4310           return;
4311      }
4312    else
4313      return;
4314
4315   edje_object_part_geometry_get(edje_obj, target_hl_part,
4316                                 &tx, &ty, &tw, &th);
4317   *x += tx;
4318   *y += ty;
4319   if (tw != *w) *w = tw;
4320   if (th != *h) *h = th;
4321 }
4322
4323 EOLIAN static void
4324 _elm_widget_focus_highlight_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
4325 {
4326    Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
4327    Evas_Object *scroller = (Evas_Object *)obj;
4328
4329    evas_object_geometry_get(obj, x, y, w, h);
4330    elm_widget_focus_highlight_focus_part_geometry_get(sd->resize_obj, x, y, w, h);
4331
4332    if (_elm_config->focus_autoscroll_mode != ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN)
4333      return;
4334
4335    while (scroller)
4336      {
4337         if (_elm_scrollable_is(scroller))
4338           {
4339              eo_do(scroller,
4340                    elm_interface_scrollable_content_viewport_geometry_get(&ox, &oy, &ow, &oh));
4341
4342              if (*y < oy)
4343                *y = oy;
4344              else if ((oy + oh) < (*y + *h))
4345                *y = (oy + oh - *h);
4346              else if (*x < ox)
4347                *x = ox;
4348              else if ((ox + ow) < (*x + *w))
4349                *x = (ox + ow - *w);
4350
4351              break;
4352           }
4353         scroller = elm_widget_parent_get(scroller);
4354      }
4355 }
4356
4357 EOLIAN static Elm_Object_Item*
4358 _elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4359 {
4360    return NULL;
4361 }
4362
4363 EOLIAN static void
4364 _elm_widget_focus_region_show_mode_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Elm_Focus_Region_Show_Mode mode)
4365 {
4366    _pd->focus_region_show_mode = mode;
4367 }
4368
4369 EOLIAN static Elm_Focus_Region_Show_Mode
4370 _elm_widget_focus_region_show_mode_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
4371 {
4372    return _pd->focus_region_show_mode;
4373 }
4374
4375 EAPI void
4376 elm_widget_activate(Evas_Object *obj, Elm_Activate act)
4377 {
4378    Evas_Object *parent;
4379    Eina_Bool ret;
4380
4381    ELM_WIDGET_CHECK(obj);
4382
4383    ret = EINA_FALSE;
4384
4385    eo_do(obj, ret = elm_obj_widget_activate(act));
4386
4387    if (ret) return;
4388
4389    parent = elm_widget_parent_get(obj);
4390    if (parent)
4391      elm_widget_activate(parent, act);
4392
4393    return;
4394 }
4395
4396 /**
4397  * @internal
4398  *
4399  * Sets the widget and child widget's Evas_Display_Mode.
4400  *
4401  * @param obj The widget.
4402  * @param dispmode Evas_Display_Mode to set widget's mode.
4403  *
4404  * Widgets are resized by several reasons.
4405  * Evas_Display_Mode can help for widgets to get one more reason of resize.
4406  * For example, elm conform widget resizes it's contents when keypad state changed.
4407  * After keypad showing, conform widget can change child's Evas_Display_Mode.
4408  * @ingroup Widget
4409  */
4410 EOLIAN static void
4411 _elm_widget_display_mode_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Display_Mode dispmode)
4412 {
4413    Evas_Display_Mode prev_dispmode;
4414    Evas_Object *child;
4415    Eina_List *l;
4416
4417    prev_dispmode = evas_object_size_hint_display_mode_get(obj);
4418
4419    if ((prev_dispmode == dispmode) ||
4420        (prev_dispmode == EVAS_DISPLAY_MODE_DONT_CHANGE)) return;
4421
4422    evas_object_size_hint_display_mode_set(obj, dispmode);
4423
4424    EINA_LIST_FOREACH (sd->subobjs, l, child)
4425      {
4426         if (elm_widget_is(child))
4427           elm_widget_display_mode_set(child, dispmode);
4428      }
4429 }
4430
4431 EOLIAN static void
4432 _elm_widget_orientation_mode_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled)
4433 {
4434    int orient_mode = -1;
4435
4436    if (!disabled)
4437      {
4438         //Get current orient mode from it's parent otherwise, 0.
4439         sd->orient_mode = 0;
4440         ELM_WIDGET_DATA_GET(sd->parent_obj, sd_parent);
4441         if (!sd_parent) orient_mode = 0;
4442         else orient_mode = sd_parent->orient_mode;
4443      }
4444    eo_do(obj, elm_obj_widget_orientation_set(orient_mode));
4445 }
4446
4447 EOLIAN static Eina_Bool
4448 _elm_widget_orientation_mode_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4449 {
4450    if (sd->orient_mode == -1) return EINA_TRUE;
4451    else return EINA_FALSE;
4452 }
4453
4454 EOLIAN static void
4455 _elm_widget_orientation_set(Eo *obj, Elm_Widget_Smart_Data *sd, int orient_mode)
4456 {
4457    Evas_Object *child;
4458    Eina_List *l;
4459
4460    sd->orient_mode = orient_mode;
4461
4462    EINA_LIST_FOREACH (sd->subobjs, l, child)
4463      {
4464         if (elm_widget_is(child))
4465           eo_do(child, elm_obj_widget_orientation_set(orient_mode));
4466      }
4467
4468    if (orient_mode != -1)
4469      {
4470         char buf[128];
4471         snprintf(buf, sizeof(buf), "elm,state,orient,%d", orient_mode);
4472         eo_do(obj, elm_obj_widget_signal_emit(buf, "elm"));
4473      }
4474 }
4475
4476 /**
4477  * @internal
4478  *
4479  * Returns the widget's focus move policy.
4480  *
4481  * @param obj The widget.
4482  * @return focus move policy of the object.
4483  *
4484  **/
4485 EOLIAN static Elm_Focus_Move_Policy
4486 _elm_widget_focus_move_policy_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4487 {
4488    return sd->focus_move_policy;
4489 }
4490
4491 /**
4492  * @internal
4493  *
4494  * Sets the widget's focus move policy.
4495  *
4496  * @param obj The widget.
4497  * @param policy Elm_Focus_Move_Policy to set object's focus move policy.
4498  */
4499
4500 EOLIAN static void
4501 _elm_widget_focus_move_policy_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Move_Policy policy)
4502 {
4503    if (sd->focus_move_policy == policy) return;
4504    sd->focus_move_policy = policy;
4505 }
4506 static void
4507 _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
4508
4509 static void
4510 _track_obj_update(Evas_Object *track, Evas_Object *obj)
4511 {
4512    //Geometry
4513    Evas_Coord x, y, w, h;
4514    evas_object_geometry_get(obj, &x, &y, &w, &h);
4515    evas_object_move(track, x, y);
4516    evas_object_resize(track, w, h);
4517
4518    //Visibility
4519    if (evas_object_visible_get(obj)) evas_object_show(track);
4520    else evas_object_hide(track);
4521 }
4522
4523 static Eina_Bool
4524 _track_obj_view_update(void *data, Eo *obj,
4525                        const Eo_Event_Description *desc EINA_UNUSED,
4526                        void *event_info EINA_UNUSED)
4527 {
4528    Elm_Widget_Item_Data *item = data;
4529    _track_obj_update(item->track_obj, obj);
4530    return EO_CALLBACK_CONTINUE;
4531 }
4532
4533 static Eina_Bool
4534 _track_obj_view_del(void *data, Eo *obj EINA_UNUSED,
4535                     const Eo_Event_Description *desc EINA_UNUSED,
4536                     void *event_info EINA_UNUSED);
4537
4538 EO_CALLBACKS_ARRAY_DEFINE(tracker_callbacks,
4539                           { EVAS_OBJECT_EVENT_RESIZE, _track_obj_view_update },
4540                           { EVAS_OBJECT_EVENT_MOVE, _track_obj_view_update },
4541                           { EVAS_OBJECT_EVENT_SHOW, _track_obj_view_update },
4542                           { EVAS_OBJECT_EVENT_HIDE, _track_obj_view_update },
4543                           { EVAS_OBJECT_EVENT_DEL, _track_obj_view_del });
4544
4545 static Eina_Bool
4546 _track_obj_view_del(void *data, Eo *obj EINA_UNUSED,
4547                     const Eo_Event_Description *desc EINA_UNUSED,
4548                     void *event_info EINA_UNUSED)
4549 {
4550    Elm_Widget_Item_Data *item = data;
4551
4552    while (evas_object_ref_get(item->track_obj) > 0)
4553      evas_object_unref(item->track_obj);
4554
4555    evas_object_event_callback_del(item->track_obj, EVAS_CALLBACK_DEL,
4556                                   _track_obj_del);
4557    evas_object_del(item->track_obj);
4558    item->track_obj = NULL;
4559
4560    return EO_CALLBACK_CONTINUE;
4561 }
4562
4563 static void
4564 _track_obj_del(void *data, Evas *e EINA_UNUSED,
4565                     Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
4566 {
4567    Elm_Widget_Item_Data *item = data;
4568    item->track_obj = NULL;
4569
4570    if (!item->view) return;
4571
4572    eo_do(item->view, eo_event_callback_array_del(tracker_callbacks(), item));
4573 }
4574
4575 static void
4576 _elm_widget_item_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission,
4577                            const char *source)
4578 {
4579    Elm_Widget_Item_Signal_Data *wisd = data;
4580    wisd->func(wisd->data, wisd->item, emission, source);
4581 }
4582
4583 static void *
4584 _elm_widget_item_signal_callback_list_get(Elm_Widget_Item_Data *item, Eina_List *position)
4585 {
4586    Elm_Widget_Item_Signal_Data *wisd = eina_list_data_get(position);
4587    void *data;
4588
4589    item->signals = eina_list_remove_list(item->signals, position);
4590    data = wisd->data;
4591
4592    if (_elm_widget_is(item->view))
4593      elm_object_signal_callback_del(item->view,
4594                                     wisd->emission, wisd->source,
4595                                     _elm_widget_item_signal_cb);
4596    else if (eo_isa(item->view, EDJE_OBJECT_CLASS))
4597      edje_object_signal_callback_del_full(item->view,
4598                                           wisd->emission, wisd->source,
4599                                           _elm_widget_item_signal_cb, wisd);
4600
4601    eina_stringshare_del(wisd->emission);
4602    eina_stringshare_del(wisd->source);
4603    free(wisd);
4604
4605    return data;
4606 }
4607
4608 #define ERR_NOT_SUPPORTED(item, method)  ERR("%s does not support %s API.", elm_widget_type_get(item->widget), method);
4609
4610 static Eina_Bool
4611 _eo_del_cb(void *data EINA_UNUSED, Eo *eo_item, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
4612 {
4613    Elm_Widget_Item_Data *item = eo_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS);
4614    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_TRUE);
4615    if (item->del_func)
4616       item->del_func((void *) WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4617    return EINA_TRUE;
4618 }
4619
4620 /**
4621  * @internal
4622  *
4623  * Allocate a new Elm_Widget_Item-derived structure.
4624  *
4625  * The goal of this structure is to provide common ground for actions
4626  * that a widget item have, such as the owner widget, callback to
4627  * notify deletion, data pointer and maybe more.
4628  *
4629  * @param widget the owner widget that holds this item, must be an elm_widget!
4630  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
4631  *        be used to allocate memory.
4632  *
4633  * @return allocated memory that is already zeroed out, or NULL on errors.
4634  *
4635  * @see elm_widget_item_new() convenience macro.
4636  * @see elm_widget_item_del() to release memory.
4637  * @ingroup Widget
4638  */
4639 EOLIAN static Eo *
4640 _elm_widget_item_eo_base_constructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4641 {
4642    Evas_Object *widget;
4643    eo_do (eo_item, widget = eo_parent_get());
4644
4645    if (!_elm_widget_is(widget))
4646      {
4647         ERR("Failed");
4648         return NULL;
4649      }
4650
4651    eo_item = eo_do_super_ret(eo_item, ELM_WIDGET_ITEM_CLASS, eo_item, eo_constructor());
4652
4653    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
4654
4655    item->widget = widget;
4656    item->eo_obj = eo_item;
4657    //TIZEN_ONLY(20170717) : expose highlight information on atspi
4658    item->can_highlight = EINA_TRUE;
4659    //
4660
4661    eo_do(eo_item, eo_event_callback_add(EO_BASE_EVENT_DEL, _eo_del_cb, NULL));
4662
4663    return eo_item;
4664 }
4665
4666 EOLIAN static void
4667 _elm_widget_item_eo_base_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4668 {
4669    Elm_Translate_String_Data *ts;
4670
4671    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4672
4673    evas_object_del(item->view);
4674
4675    eina_stringshare_del(item->access_info);
4676    eina_stringshare_del(item->accessible_name);
4677
4678    while (item->signals)
4679      _elm_widget_item_signal_callback_list_get(item, item->signals);
4680
4681    while (item->translate_strings)
4682      {
4683         ts = EINA_INLIST_CONTAINER_GET(item->translate_strings,
4684                                        Elm_Translate_String_Data);
4685         eina_stringshare_del(ts->id);
4686         eina_stringshare_del(ts->domain);
4687         eina_stringshare_del(ts->string);
4688         item->translate_strings = eina_inlist_remove(item->translate_strings,
4689                                                      item->translate_strings);
4690         free(ts);
4691      }
4692    eina_hash_free(item->labels);
4693
4694    eo_do(eo_item,
4695          elm_interface_atspi_accessible_description_set(NULL),
4696          elm_interface_atspi_accessible_name_set(NULL),
4697          //TIZEN_ONLY(20190922): add name callback, description callback.
4698          elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
4699          elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
4700          //
4701          elm_interface_atspi_accessible_translation_domain_set(NULL),
4702          elm_interface_atspi_accessible_relationships_clear(),
4703                  // TIZEN_ONLY(20160930) : endless recursion fix
4704          elm_interface_atspi_accessible_attributes_clear()
4705                  //
4706          );
4707
4708    if (item->name)
4709      eina_stringshare_del(item->name);
4710
4711    if (item->atspi_custom_relations)
4712      elm_atspi_relation_set_free(&item->atspi_custom_relations);
4713
4714    //TIZEN_ONLY(20150731) : add i18n support for name and description
4715    if (item->atspi_translation_domain)
4716      eina_stringshare_del(item->atspi_translation_domain);
4717    //
4718    //Tizen Only(20160728) free attribute list
4719    if (item->attr_list)
4720    {
4721       Elm_Atspi_Attribute *attr;
4722       EINA_LIST_FREE(item->attr_list, attr)
4723        {
4724           eina_stringshare_del(attr->key);
4725           eina_stringshare_del(attr->value);
4726           free(attr);
4727        }
4728    }
4729    //
4730
4731 //TIZEN_ONLY(20161013): clean up elm color class feature
4732    if (item->color_classes)
4733      ELM_SAFE_FREE(item->color_classes, eina_hash_free);
4734 //
4735
4736    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
4737
4738    eo_do_super(eo_item, ELM_WIDGET_ITEM_CLASS, eo_destructor());
4739 }
4740
4741 /**
4742  * @internal
4743  *
4744  * Releases widget item memory, calling back item_del_pre_hook() and
4745  * item_del_cb() if they exist.
4746  *
4747  * @param item a valid #Elm_Widget_Item to be deleted.
4748  *
4749  * If there is an Elm_Widget_Item::del_cb, then it will be called prior
4750  * to memory release. Note that elm_widget_item_pre_notify_del() calls
4751  * this function and then unset it, thus being useful for 2 step
4752  * cleanup whenever the del_cb may use any of the data that must be
4753  * deleted from item.
4754  *
4755  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
4756  * is presented!
4757  *
4758  * Note that if item_del_pre_hook() returns @c EINA_TRUE, item free will be
4759  * deferred, or item will be freed here if it returns @c EINA_FALSE.
4760  *
4761  * @see elm_widget_item_del() convenience macro.
4762  * @ingroup Widget
4763  */
4764 EOLIAN static void
4765 _elm_widget_item_del(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4766 {
4767    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4768    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4769    item->on_deletion = EINA_TRUE;
4770
4771    //Widget item delete callback
4772    Eina_Bool del_ok;
4773    eo_do(item->eo_obj, del_ok = elm_wdg_item_del_pre());
4774    if (del_ok)
4775       eo_del(item->eo_obj);
4776    return;
4777 }
4778
4779 EOLIAN static Eina_Bool
4780 _elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4781 {
4782    return EINA_TRUE;
4783 }
4784
4785 /**
4786  * @internal
4787  *
4788  * Notify object will be deleted without actually deleting it.
4789  *
4790  * This function will callback Elm_Widget_Item::del_cb if it is set
4791  * and then unset it so it is not called twice (ie: from
4792  * elm_widget_item_del()).
4793  *
4794  * @param item a valid #Elm_Widget_Item to be notified
4795  * @see elm_widget_item_pre_notify_del() convenience macro.
4796  * @ingroup Widget
4797  */
4798 EOLIAN static void
4799 _elm_widget_item_pre_notify_del(Eo *eo_item, Elm_Widget_Item_Data *item)
4800 {
4801    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4802    if (!item->del_func) return;
4803    item->del_func((void *)WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4804    item->del_func = NULL;
4805 }
4806
4807 /**
4808  * @internal
4809  *
4810  * Set the function to notify when item is being deleted.
4811  *
4812  * This function will complain if there was a callback set already,
4813  * however it will set the new one.
4814  *
4815  * The callback will be called from elm_widget_item_pre_notify_del()
4816  * or elm_widget_item_del() will be called with:
4817  *   - data: the Elm_Widget_Item::data value.
4818  *   - obj: the Elm_Widget_Item::widget evas object.
4819  *   - event_info: the item being deleted.
4820  *
4821  * @param item a valid #Elm_Widget_Item to be notified
4822  * @see elm_widget_item_del_cb_set() convenience macro.
4823  * @ingroup Widget
4824  */
4825 EOLIAN static void
4826 _elm_widget_item_del_cb_set(Eo *eo_item EINA_UNUSED,
4827                             Elm_Widget_Item_Data *item,
4828                             Evas_Smart_Cb func)
4829 {
4830    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4831    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4832
4833    if ((item->del_func) && (item->del_func != func))
4834      WRN("You're replacing a previously set del_cb %p of item %p with %p",
4835          item->del_func, item->eo_obj, func);
4836
4837    item->del_func = func;
4838 }
4839
4840 /**
4841  * @internal
4842  *
4843  * Get owner widget of this item.
4844  *
4845  * @param item a valid #Elm_Widget_Item to get data from.
4846  * @return owner widget of this item.
4847  * @ingroup Widget
4848  */
4849 EOLIAN static Evas_Object *
4850 _elm_widget_item_widget_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4851 {
4852    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4853    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4854
4855    return item->widget;
4856 }
4857
4858 EAPI Eina_Bool
4859 _elm_widget_onscreen_is(Evas_Object *widget)
4860 {
4861    Evas_Object *parent = widget;
4862    Evas_Coord x, y, w, h, wx, wy, ww, wh;
4863
4864    Evas *evas = evas_object_evas_get(widget);
4865    if (!evas) return EINA_FALSE;
4866
4867    // check if on canvas
4868    evas_output_viewport_get(evas, &x, &y, &w, &h);
4869    evas_object_geometry_get(widget, &wx, &wy, &ww, &wh);
4870    if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4871        ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4872      return EINA_FALSE;
4873
4874    // check if inside scrollable parent viewport
4875    do {
4876       parent = elm_widget_parent_get(parent);
4877       if (parent && !evas_object_visible_get(parent))
4878         return EINA_FALSE;
4879       if (parent && eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4880         {
4881            evas_object_geometry_get(parent, &x, &y, &w, &h);
4882            if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4883                ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4884              return EINA_FALSE;
4885         }
4886    } while (parent && (parent != elm_widget_top_get(widget)));
4887
4888    return EINA_TRUE;
4889 }
4890
4891 EAPI Eina_Bool
4892 _elm_widget_item_onscreen_is(Elm_Object_Item *item)
4893 {
4894    Evas_Coord x, y, w, h, wx, wy, ww, wh;
4895    Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4896    if (!id || !id->view) return EINA_FALSE;
4897
4898    if (!evas_object_visible_get(id->view))
4899      return EINA_FALSE;
4900
4901    if (!_elm_widget_onscreen_is(id->widget))
4902      return EINA_FALSE;
4903
4904    evas_object_geometry_get(id->view, &x, &y, &w, &h);
4905    evas_object_geometry_get(id->widget, &wx, &wy, &ww, &wh);
4906    if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4907        ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4908      return EINA_FALSE;
4909
4910    return EINA_TRUE;
4911 }
4912
4913 EOLIAN static Elm_Atspi_State_Set
4914 _elm_widget_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_item,
4915                                                               Elm_Widget_Item_Data *item)
4916 {
4917    Elm_Atspi_State_Set states = 0;
4918
4919    STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
4920
4921    if (elm_object_item_focus_get(eo_item))
4922      STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
4923    if (!elm_object_item_disabled_get(eo_item))
4924      {
4925         STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
4926         STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
4927         STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
4928      }
4929    if (_elm_widget_item_onscreen_is(eo_item))
4930      STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
4931
4932    //TIZEN_ONLY(20170717) : expose highlight information on atspi
4933    if (item->can_highlight)
4934      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
4935    else
4936      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
4937
4938    if (_elm_object_accessibility_currently_highlighted_get() == (void*)item->eo_obj)
4939      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
4940    //
4941    return states;
4942 }
4943
4944 EOLIAN static Eo*
4945 _elm_widget_item_elm_interface_atspi_accessible_parent_get(Eo *eo_item, Elm_Widget_Item_Data *item EINA_UNUSED)
4946 {
4947    Eo *parent;
4948    eo_do(eo_item, parent = eo_parent_get());
4949    return parent;
4950 }
4951
4952 EAPI void
4953 elm_object_item_data_set(Elm_Object_Item *it, void *data)
4954 {
4955    WIDGET_ITEM_DATA_SET(it, data);
4956 }
4957
4958 EAPI void *
4959 elm_object_item_data_get(const Elm_Object_Item *it)
4960 {
4961    return (void *) WIDGET_ITEM_DATA_GET(it);
4962 }
4963
4964 EOLIAN static void
4965 _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED,
4966                               Elm_Widget_Item_Data *item,
4967                               Eina_Bool disabled)
4968 {
4969    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4970    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4971
4972    if (item->disabled == disabled) return;
4973    item->disabled = !!disabled;
4974    eo_do(item->eo_obj, elm_wdg_item_disable());
4975 }
4976
4977 EOLIAN static Eina_Bool
4978 _elm_widget_item_disabled_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4979 {
4980    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4981    return item->disabled;
4982 }
4983
4984 EOLIAN static void
4985 _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style EINA_UNUSED)
4986 {
4987    ERR_NOT_SUPPORTED(item, "elm_object_style_set()");
4988 }
4989
4990 EOLIAN static const char *
4991 _elm_widget_item_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4992 {
4993    ERR_NOT_SUPPORTED(item, "elm_object_style_get()");
4994    return NULL;
4995 }
4996
4997 EOLIAN static void
4998 _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4999 {
5000 }
5001
5002 EOLIAN static void
5003 _elm_widget_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED)
5004 {
5005    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set");
5006 }
5007
5008 EOLIAN static Eina_Bool
5009 _elm_widget_item_focus_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5010 {
5011    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get");
5012    return EINA_FALSE;
5013 }
5014
5015 EOLIAN static void
5016 _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED,
5017                                                    Elm_Widget_Item_Data *item,
5018                                                    const char *part,
5019                                                    const char *domain,
5020                                                    const char *label)
5021 {
5022    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5023    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5024    Elm_Translate_String_Data *ts;
5025
5026    if (!label)
5027      {
5028         _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE,
5029                                     EINA_FALSE);
5030      }
5031    else
5032      {
5033         ts = _part_text_translatable_set(&item->translate_strings, part,
5034                                          EINA_TRUE, EINA_FALSE);
5035         if (!ts) return;
5036         if (!ts->string) ts->string = eina_stringshare_add(label);
5037         else eina_stringshare_replace(&ts->string, label);
5038         if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5039         else eina_stringshare_replace(&ts->domain, domain);
5040 #ifdef HAVE_GETTEXT
5041         if (label[0]) label = dgettext(domain, label);
5042 #endif
5043      }
5044    item->on_translate = EINA_TRUE;
5045    eo_do(item->eo_obj, elm_wdg_item_part_text_set(part, label));
5046    item->on_translate = EINA_FALSE;
5047 }
5048
5049 EOLIAN static const char *
5050 _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED,
5051                                             Elm_Widget_Item_Data *item,
5052                                             const char *part)
5053 {
5054    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5055    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5056
5057    Elm_Translate_String_Data *ts;
5058    ts = _translate_string_data_get(item->translate_strings, part);
5059    if (ts) return ts->string;
5060    return NULL;
5061 }
5062
5063 EOLIAN static void
5064 _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED,
5065                                                    Elm_Widget_Item_Data *item,
5066                                                    const char *part,
5067                                                    const char *domain,
5068                                                    Eina_Bool translatable)
5069 {
5070    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5071    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5072    Elm_Translate_String_Data *ts;
5073    const char *text;
5074
5075    ts = _part_text_translatable_set(&item->translate_strings, part,
5076                                     translatable, EINA_TRUE);
5077    if (!ts) return;
5078    if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5079    else eina_stringshare_replace(&ts->domain, domain);
5080
5081    eo_do(item->eo_obj, text = elm_wdg_item_part_text_get(part));
5082
5083    if (!text || !text[0]) return;
5084
5085    if (!ts->string) ts->string = eina_stringshare_add(text);
5086
5087 //Try to translate text since we don't know the text is already translated.
5088 #ifdef HAVE_GETTEXT
5089    text = dgettext(domain, text);
5090 #endif
5091    item->on_translate = EINA_TRUE;
5092    eo_do (item->eo_obj, elm_wdg_item_part_text_set(part, text));
5093    item->on_translate = EINA_FALSE;
5094 }
5095
5096 EOLIAN static void
5097 _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5098 {
5099    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5100    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5101
5102    if (!item->track_obj) return;
5103
5104    while (evas_object_ref_get(item->track_obj) > 0)
5105      evas_object_unref(item->track_obj);
5106
5107    evas_object_del(item->track_obj);
5108 }
5109
5110 EOLIAN static Evas_Object *
5111 _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5112 {
5113    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5114    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5115
5116    if (item->track_obj)
5117      {
5118         evas_object_ref(item->track_obj);
5119         return item->track_obj;
5120      }
5121
5122    if (!item->view)
5123      {
5124         WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item);
5125         return NULL;
5126      }
5127
5128    Evas_Object *track =
5129       evas_object_rectangle_add(evas_object_evas_get(item->widget));
5130    evas_object_color_set(track, 0, 0, 0, 0);
5131    evas_object_pass_events_set(track, EINA_TRUE);
5132    _track_obj_update(track, item->view);
5133    evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del,
5134                                   item);
5135
5136    eo_do(item->view,
5137          eo_event_callback_array_add(tracker_callbacks(), item));
5138
5139    evas_object_ref(track);
5140
5141    item->track_obj = track;
5142
5143    return track;
5144 }
5145
5146 EOLIAN static void
5147 _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5148 {
5149    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5150    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5151
5152    if (!item->track_obj) return;
5153    evas_object_unref(item->track_obj);
5154
5155    if (evas_object_ref_get(item->track_obj) == 0)
5156      evas_object_del(item->track_obj);
5157 }
5158
5159 EOLIAN static int
5160 _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5161 {
5162    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0);
5163    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0);
5164
5165    if (!item->track_obj) return 0;
5166    return evas_object_ref_get(item->track_obj);
5167 }
5168
5169 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
5170
5171 struct _Elm_Widget_Item_Tooltip
5172 {
5173    Elm_Widget_Item_Data       *item;
5174    Elm_Tooltip_Item_Content_Cb func;
5175    Evas_Smart_Cb               del_cb;
5176    const void                 *data;
5177 };
5178
5179 static Evas_Object *
5180 _elm_widget_item_tooltip_label_create(void *data,
5181                                       Evas_Object *obj EINA_UNUSED,
5182                                       Evas_Object *tooltip,
5183                                       void *item EINA_UNUSED)
5184 {
5185    Evas_Object *label = elm_label_add(tooltip);
5186    if (!label)
5187      return NULL;
5188    elm_object_style_set(label, "tooltip");
5189    elm_object_text_set(label, data);
5190    return label;
5191 }
5192
5193 static Evas_Object *
5194 _elm_widget_item_tooltip_trans_label_create(void *data,
5195                                             Evas_Object *obj EINA_UNUSED,
5196                                             Evas_Object *tooltip,
5197                                             void *item EINA_UNUSED)
5198 {
5199    Evas_Object *label = elm_label_add(tooltip);
5200    if (!label)
5201      return NULL;
5202    elm_object_style_set(label, "tooltip");
5203    elm_object_translatable_text_set(label, data);
5204    return label;
5205 }
5206
5207 static void
5208 _elm_widget_item_tooltip_label_del_cb(void *data,
5209                                       Evas_Object *obj EINA_UNUSED,
5210                                       void *event_info EINA_UNUSED)
5211 {
5212    eina_stringshare_del(data);
5213 }
5214
5215 /**
5216  * @internal
5217  *
5218  * Set the text to be shown in the widget item.
5219  *
5220  * @param item Target item
5221  * @param text The text to set in the content
5222  *
5223  * Setup the text as tooltip to object. The item can have only one tooltip,
5224  * so any previous tooltip data is removed.
5225  *
5226  * @ingroup Widget
5227  */
5228 EOLIAN static void
5229 _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED,
5230                                   Elm_Widget_Item_Data *item EINA_UNUSED,
5231                                   const char *text)
5232 {
5233    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5234    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5235    EINA_SAFETY_ON_NULL_RETURN(text);
5236
5237    text = eina_stringshare_add(text);
5238    eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5239             _elm_widget_item_tooltip_label_create,
5240             text,
5241             _elm_widget_item_tooltip_label_del_cb));
5242 }
5243
5244 EOLIAN static void
5245 _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED,
5246                                                Elm_Widget_Item_Data *item EINA_UNUSED,
5247                                                const char *text)
5248 {
5249    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5250    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5251    EINA_SAFETY_ON_NULL_RETURN(text);
5252
5253    text = eina_stringshare_add(text);
5254    eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5255             _elm_widget_item_tooltip_trans_label_create,
5256             text,
5257             _elm_widget_item_tooltip_label_del_cb));
5258 }
5259
5260 static Evas_Object *
5261 _elm_widget_item_tooltip_create(void *data,
5262                                 Evas_Object *obj,
5263                                 Evas_Object *tooltip)
5264 {
5265    Elm_Widget_Item_Tooltip *wit = data;
5266    return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj);
5267 }
5268
5269 static void
5270 _elm_widget_item_tooltip_del_cb(void *data,
5271                                 Evas_Object *obj,
5272                                 void *event_info EINA_UNUSED)
5273 {
5274    Elm_Widget_Item_Tooltip *wit = data;
5275    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj);
5276    free(wit);
5277 }
5278
5279 /**
5280  * @internal
5281  *
5282  * Set the content to be shown in the tooltip item
5283  *
5284  * Setup the tooltip to item. The item can have only one tooltip,
5285  * so any previous tooltip data is removed. @p func(with @p data) will
5286  * be called every time that need show the tooltip and it should
5287  * return a valid Evas_Object. This object is then managed fully by
5288  * tooltip system and is deleted when the tooltip is gone.
5289  *
5290  * @param item the widget item being attached a tooltip.
5291  * @param func the function used to create the tooltip contents.
5292  * @param data what to provide to @a func as callback data/context.
5293  * @param del_cb called when data is not needed anymore, either when
5294  *        another callback replaces @func, the tooltip is unset with
5295  *        elm_widget_item_tooltip_unset() or the owner @a item
5296  *        dies. This callback receives as the first parameter the
5297  *        given @a data, and @c event_info is the item.
5298  *
5299  * @ingroup Widget
5300  */
5301 EOLIAN static void
5302 _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED,
5303                                         Elm_Widget_Item_Data *item,
5304                                         Elm_Tooltip_Item_Content_Cb func,
5305                                         const void *data,
5306                                         Evas_Smart_Cb del_cb)
5307 {
5308    Elm_Widget_Item_Tooltip *wit;
5309
5310    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
5311    //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem);
5312
5313    if (!func)
5314      {
5315         eo_do(item->eo_obj, elm_wdg_item_tooltip_unset());
5316         return;
5317      }
5318
5319    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
5320    if (!wit) goto error;
5321    wit->item = item;
5322    wit->func = func;
5323    wit->data = data;
5324    wit->del_cb = del_cb;
5325
5326    elm_object_sub_tooltip_content_cb_set
5327      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
5328      _elm_widget_item_tooltip_del_cb);
5329
5330    return;
5331
5332 error_noitem:
5333    if (del_cb) del_cb((void *)data, NULL, item);
5334    return;
5335 error:
5336    if (del_cb) del_cb((void *)data, item->widget, item);
5337 }
5338
5339 /**
5340  * @internal
5341  *
5342  * Unset tooltip from item
5343  *
5344  * @param item widget item to remove previously set tooltip.
5345  *
5346  * Remove tooltip from item. The callback provided as del_cb to
5347  * elm_widget_item_tooltip_content_cb_set() will be called to notify
5348  * it is not used anymore.
5349  *
5350  * @see elm_widget_item_tooltip_content_cb_set()
5351  *
5352  * @ingroup Widget
5353  */
5354 EOLIAN static void
5355 _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5356 {
5357    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5358    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5359
5360    elm_object_tooltip_unset(item->view);
5361 }
5362
5363 /**
5364  * @internal
5365  *
5366  * Sets a different style for this item tooltip.
5367  *
5368  * @note before you set a style you should define a tooltip with
5369  *       elm_widget_item_tooltip_content_cb_set() or
5370  *       elm_widget_item_tooltip_text_set()
5371  *
5372  * @param item widget item with tooltip already set.
5373  * @param style the theme style to use (default, transparent, ...)
5374  *
5375  * @ingroup Widget
5376  */
5377 EOLIAN static void
5378 _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED,
5379                                    Elm_Widget_Item_Data *item,
5380                                    const char *style)
5381 {
5382    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5383    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5384
5385    elm_object_tooltip_style_set(item->view, style);
5386 }
5387
5388 EOLIAN static Eina_Bool
5389 _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED,
5390                                          Elm_Widget_Item_Data *item,
5391                                          Eina_Bool disable)
5392 {
5393    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5394    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5395
5396    return elm_object_tooltip_window_mode_set(item->view, disable);
5397 }
5398
5399 EOLIAN static Eina_Bool
5400 _elm_widget_item_tooltip_window_mode_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5401 {
5402    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5403    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5404
5405    return elm_object_tooltip_window_mode_get(item->view);
5406 }
5407
5408 /**
5409  * @internal
5410  *
5411  * Get the style for this item tooltip.
5412  *
5413  * @param item widget item with tooltip already set.
5414  * @return style the theme style in use, defaults to "default". If the
5415  *         object does not have a tooltip set, then NULL is returned.
5416  *
5417  * @ingroup Widget
5418  */
5419 EOLIAN static const char *
5420 _elm_widget_item_tooltip_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5421 {
5422    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5423
5424    return elm_object_tooltip_style_get(item->view);
5425 }
5426
5427 EOLIAN static void
5428 _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED,
5429                             Elm_Widget_Item_Data *item,
5430                             const char *cursor)
5431 {
5432    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5433    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5434
5435    elm_object_sub_cursor_set(item->view, item->widget, cursor);
5436 }
5437
5438 EOLIAN static const char *
5439 _elm_widget_item_cursor_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5440 {
5441    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5442    return elm_object_cursor_get(item->view);
5443 }
5444
5445 EOLIAN static void
5446 _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5447 {
5448    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5449    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5450
5451    elm_object_cursor_unset(item->view);
5452 }
5453
5454 /**
5455  * @internal
5456  *
5457  * Sets a different style for this item cursor.
5458  *
5459  * @note before you set a style you should define a cursor with
5460  *       elm_widget_item_cursor_set()
5461  *
5462  * @param item widget item with cursor already set.
5463  * @param style the theme style to use (default, transparent, ...)
5464  *
5465  * @ingroup Widget
5466  */
5467 EOLIAN static void
5468 _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED,
5469                                   Elm_Widget_Item_Data *item,
5470                                   const char *style)
5471 {
5472    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5473    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5474
5475    elm_object_cursor_style_set(item->view, style);
5476 }
5477
5478 /**
5479  * @internal
5480  *
5481  * Get the style for this item cursor.
5482  *
5483  * @param item widget item with cursor already set.
5484  * @return style the theme style in use, defaults to "default". If the
5485  *         object does not have a cursor set, then NULL is returned.
5486  *
5487  * @ingroup Widget
5488  */
5489 EOLIAN static const char *
5490 _elm_widget_item_cursor_style_get(Eo *eo_item EINA_UNUSED,
5491                                   Elm_Widget_Item_Data *item)
5492 {
5493    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5494    return elm_object_cursor_style_get(item->view);
5495 }
5496
5497 /**
5498  * @internal
5499  *
5500  * Set if the cursor set should be searched on the theme or should use
5501  * the provided by the engine, only.
5502  *
5503  * @note before you set if should look on theme you should define a cursor
5504  * with elm_object_cursor_set(). By default it will only look for cursors
5505  * provided by the engine.
5506  *
5507  * @param item widget item with cursor already set.
5508  * @param engine_only boolean to define it cursors should be looked only
5509  * between the provided by the engine or searched on widget's theme as well.
5510  *
5511  * @ingroup Widget
5512  */
5513 EOLIAN static void
5514 _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED,
5515                                         Elm_Widget_Item_Data *item,
5516                                         Eina_Bool engine_only)
5517 {
5518    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5519    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5520
5521    elm_object_cursor_theme_search_enabled_set(item->view, !engine_only);
5522 }
5523
5524 /**
5525  * @internal
5526  *
5527  * Get the cursor engine only usage for this item cursor.
5528  *
5529  * @param item widget item with cursor already set.
5530  * @return engine_only boolean to define it cursors should be looked only
5531  * between the provided by the engine or searched on widget's theme as well. If
5532  *         the object does not have a cursor set, then EINA_FALSE is returned.
5533  *
5534  * @ingroup Widget
5535  */
5536 EOLIAN static Eina_Bool
5537 _elm_widget_item_cursor_engine_only_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5538 {
5539    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5540    return !elm_object_cursor_theme_search_enabled_get(item->view);
5541 }
5542
5543 EOLIAN static void
5544 _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED,
5545                                   Elm_Widget_Item_Data *item,
5546                                   const char *part EINA_UNUSED,
5547                                   Evas_Object *content EINA_UNUSED)
5548 {
5549    ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()");
5550 }
5551
5552 EOLIAN static Evas_Object *
5553 _elm_widget_item_part_content_get(Eo *eo_item EINA_UNUSED,
5554                                   Elm_Widget_Item_Data *item,
5555                                   const char *part EINA_UNUSED)
5556 {
5557    ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()");
5558    return NULL;
5559 }
5560
5561 EOLIAN static Evas_Object *
5562 _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED,
5563                                     Elm_Widget_Item_Data *item,
5564                                     const char *part EINA_UNUSED)
5565 {
5566    ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()");
5567    return NULL;
5568 }
5569
5570 EOLIAN static void
5571 _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
5572                                Elm_Widget_Item_Data *item,
5573                                const char *part EINA_UNUSED,
5574                                const char *label EINA_UNUSED)
5575 {
5576    ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()");
5577 }
5578
5579 EOLIAN static const char *
5580 _elm_widget_item_part_text_get(Eo *eo_item EINA_UNUSED,
5581                                Elm_Widget_Item_Data *item,
5582                                const char *part EINA_UNUSED)
5583 {
5584    ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()");
5585    return NULL;
5586 }
5587
5588 static void
5589 _elm_widget_item_part_text_custom_free(void *data)
5590 {
5591    Elm_Label_Data *label;
5592    label = data;
5593    eina_stringshare_del(label->part);
5594    eina_stringshare_del(label->text);
5595    free(label);
5596 }
5597
5598 EOLIAN static void
5599 _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED,
5600                                       Elm_Widget_Item_Data *item,
5601                                       const char *part,
5602                                       const char *text)
5603 {
5604    Elm_Label_Data *label;
5605    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5606    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5607
5608    if (!item->labels)
5609      item->labels =
5610         eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free);
5611    label = eina_hash_find(item->labels, part);
5612    if (!label)
5613      {
5614         label = malloc(sizeof(Elm_Label_Data));
5615         if (!label)
5616           {
5617              ERR("Failed to allocate memory");
5618              return;
5619           }
5620         label->part = eina_stringshare_add(part);
5621         label->text = eina_stringshare_add(text);
5622         eina_hash_add(item->labels, part, label);
5623      }
5624    else
5625      eina_stringshare_replace(&label->text, text);
5626 }
5627
5628 EOLIAN static const char *
5629 _elm_widget_item_part_text_custom_get(Eo *eo_item EINA_UNUSED,
5630                                       Elm_Widget_Item_Data *item,
5631                                       const char *part)
5632 {
5633    Elm_Label_Data *label;
5634    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5635    label = eina_hash_find(item->labels, part);
5636    return label ? label->text : NULL;
5637 }
5638
5639 static Eina_Bool
5640 _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED,
5641                                           const void *key EINA_UNUSED,
5642                                           void *data,
5643                                           void *func_data)
5644 {
5645    Elm_Label_Data *label;
5646    Elm_Widget_Item_Data *item;
5647    label = data;
5648    item = func_data;
5649
5650    eo_do(item->eo_obj, elm_wdg_item_part_text_set(label->part, label->text));
5651
5652    return EINA_TRUE;
5653 }
5654
5655 EOLIAN static void
5656 _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5657 {
5658    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5659    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5660    if (item->labels)
5661      eina_hash_foreach(item->labels,
5662                        _elm_widget_item_part_text_custom_foreach, item);
5663 }
5664
5665 EOLIAN static void
5666 _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
5667                              Elm_Widget_Item_Data *item EINA_UNUSED,
5668                              const char *emission EINA_UNUSED,
5669                              const char *source EINA_UNUSED)
5670 {
5671
5672 }
5673
5674 EOLIAN static void
5675 _elm_widget_item_signal_callback_add(Eo *eo_item,
5676                                      Elm_Widget_Item_Data *item,
5677                                      const char *emission,
5678                                      const char *source,
5679                                      Elm_Object_Item_Signal_Cb func,
5680                                      void *data)
5681 {
5682    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5683    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5684    EINA_SAFETY_ON_NULL_RETURN(func);
5685
5686    Elm_Widget_Item_Signal_Data *wisd;
5687
5688    wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
5689    if (!wisd) return;
5690
5691    wisd->item = eo_item;
5692    wisd->func = (Elm_Widget_Item_Signal_Cb)func;
5693    wisd->data = data;
5694    wisd->emission = eina_stringshare_add(emission);
5695    wisd->source = eina_stringshare_add(source);
5696
5697    if (_elm_widget_is(item->view))
5698      elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5699    else if (eo_isa(item->view, EDJE_OBJECT_CLASS))
5700      edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5701    else
5702      {
5703         WRN("The %s widget item doesn't support signal callback add!",
5704             eo_class_name_get(eo_class_get(item->widget)));
5705         free(wisd);
5706         return;
5707      }
5708
5709    item->signals = eina_list_append(item->signals, wisd);
5710 }
5711
5712 EOLIAN static void *
5713 _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED,
5714                                      Elm_Widget_Item_Data *item,
5715                                      const char *emission,
5716                                      const char *source,
5717                                      Elm_Object_Item_Signal_Cb func)
5718 {
5719    Elm_Widget_Item_Signal_Data *wisd;
5720    Eina_List *l;
5721
5722    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5723    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5724    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
5725
5726    EINA_LIST_FOREACH(item->signals, l, wisd)
5727      {
5728         if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) &&
5729             !strcmp(wisd->emission, emission) &&
5730             !strcmp(wisd->source, source))
5731           return _elm_widget_item_signal_callback_list_get(item, l);
5732      }
5733
5734    return NULL;
5735 }
5736
5737 EOLIAN static void
5738 _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED,
5739                                  Elm_Widget_Item_Data *item,
5740                                  const char *txt)
5741 {
5742    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5743    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5744
5745    eina_stringshare_del(item->access_info);
5746    if (!txt) item->access_info = NULL;
5747    else item->access_info = eina_stringshare_add(txt);
5748 }
5749
5750 EOLIAN static void
5751 _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5752 {
5753    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5754    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5755
5756 #ifdef HAVE_GETTEXT
5757    Elm_Translate_String_Data *ts;
5758    EINA_INLIST_FOREACH(item->translate_strings, ts)
5759      {
5760         if (!ts->string) continue;
5761         const char *s = dgettext(ts->domain, ts->string);
5762         item->on_translate = EINA_TRUE;
5763         eo_do(item->eo_obj, elm_wdg_item_part_text_set(ts->id, s));
5764         item->on_translate = EINA_FALSE;
5765      }
5766 #endif
5767 }
5768
5769 EOLIAN static void
5770 _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED,
5771                                   Elm_Widget_Item_Data *item,
5772                                   Eina_List *objs)
5773 {
5774    _elm_access_widget_item_access_order_set(item, objs);
5775 }
5776
5777 EOLIAN static const Eina_List *
5778 _elm_widget_item_access_order_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5779 {
5780    return _elm_access_widget_item_access_order_get(item);
5781 }
5782
5783 EOLIAN static void
5784 _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5785 {
5786    _elm_access_widget_item_access_order_unset(item);
5787 }
5788
5789 EOLIAN static Evas_Object*
5790 _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5791 {
5792    _elm_access_widget_item_register(item);
5793    return item->access_obj;
5794 }
5795
5796 EOLIAN static void
5797 _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5798 {
5799    _elm_access_widget_item_unregister(item);
5800 }
5801
5802 EOLIAN static Evas_Object*
5803 _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5804 {
5805    return item->access_obj;
5806 }
5807
5808 EOLIAN static Evas_Object *
5809 _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5810 {
5811    Evas_Object *ret = NULL;
5812
5813    if (dir == ELM_FOCUS_PREVIOUS)
5814      ret = item->focus_previous;
5815    else if (dir == ELM_FOCUS_NEXT)
5816      ret = item->focus_next;
5817    else if (dir == ELM_FOCUS_UP)
5818      ret = item->focus_up;
5819    else if (dir == ELM_FOCUS_DOWN)
5820      ret = item->focus_down;
5821    else if (dir == ELM_FOCUS_RIGHT)
5822      ret = item->focus_right;
5823    else if (dir == ELM_FOCUS_LEFT)
5824      ret = item->focus_left;
5825
5826    return ret;
5827 }
5828
5829 EOLIAN static void
5830 _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir)
5831 {
5832    if (dir == ELM_FOCUS_PREVIOUS)
5833      item->focus_previous = next;
5834    else if (dir == ELM_FOCUS_NEXT)
5835      item->focus_next = next;
5836    else if (dir == ELM_FOCUS_UP)
5837      item->focus_up = next;
5838    else if (dir == ELM_FOCUS_DOWN)
5839      item->focus_down = next;
5840    else if (dir == ELM_FOCUS_RIGHT)
5841      item->focus_right = next;
5842    else if (dir == ELM_FOCUS_LEFT)
5843      item->focus_left = next;
5844 }
5845
5846 EOLIAN static Elm_Object_Item*
5847 _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5848 {
5849    Elm_Object_Item *ret = NULL;
5850
5851    if (dir == ELM_FOCUS_PREVIOUS)
5852      ret = item->item_focus_previous;
5853    else if (dir == ELM_FOCUS_NEXT)
5854      ret = item->item_focus_next;
5855    else if (dir == ELM_FOCUS_UP)
5856      ret = item->item_focus_up;
5857    else if (dir == ELM_FOCUS_DOWN)
5858      ret = item->item_focus_down;
5859    else if (dir == ELM_FOCUS_RIGHT)
5860      ret = item->item_focus_right;
5861    else if (dir == ELM_FOCUS_LEFT)
5862      ret = item->item_focus_left;
5863
5864    return ret;
5865 }
5866
5867 EOLIAN static void
5868 _elm_widget_item_focus_next_item_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Object_Item *next_item, Elm_Focus_Direction dir)
5869 {
5870    if (dir == ELM_FOCUS_PREVIOUS)
5871      item->item_focus_previous = next_item;
5872    else if (dir == ELM_FOCUS_NEXT)
5873      item->item_focus_next = next_item;
5874    else if (dir == ELM_FOCUS_UP)
5875      item->item_focus_up = next_item;
5876    else if (dir == ELM_FOCUS_DOWN)
5877      item->item_focus_down = next_item;
5878    else if (dir == ELM_FOCUS_RIGHT)
5879      item->item_focus_right = next_item;
5880    else if (dir == ELM_FOCUS_LEFT)
5881      item->item_focus_left = next_item;
5882 }
5883
5884 /* happy debug functions */
5885 #ifdef ELM_DEBUG
5886 static void
5887 _sub_obj_tree_dump(const Evas_Object *obj,
5888                    int lvl)
5889 {
5890    int i;
5891
5892    for (i = 0; i < lvl * 3; i++)
5893      putchar(' ');
5894
5895    if (_elm_widget_is(obj))
5896      {
5897         Eina_List *l;
5898         INTERNAL_ENTRY;
5899         DBG("+ %s(%p)\n",
5900             elm_widget_type_get(obj),
5901             obj);
5902         EINA_LIST_FOREACH(sd->subobjs, l, obj)
5903           _sub_obj_tree_dump(obj, lvl + 1);
5904      }
5905    else
5906      DBG("+ %s(%p)\n", evas_object_type_get(obj), obj);
5907 }
5908
5909 static void
5910 _sub_obj_tree_dot_dump(const Evas_Object *obj,
5911                        FILE *output)
5912 {
5913    if (!_elm_widget_is(obj))
5914      return;
5915    INTERNAL_ENTRY;
5916
5917    Eina_Bool visible = evas_object_visible_get(obj);
5918    Eina_Bool disabled = elm_widget_disabled_get(obj);
5919    Eina_Bool focused = elm_widget_focus_get(obj);
5920    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
5921
5922    if (sd->parent_obj)
5923      {
5924         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
5925
5926         if (focused)
5927           fprintf(output, ", style=bold");
5928
5929         if (!visible)
5930           fprintf(output, ", color=gray28");
5931
5932         fprintf(output, " ];\n");
5933      }
5934
5935    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
5936                    "disabled: %d|focused: %d/%d|focus order:%d}\"",
5937            obj, obj, elm_widget_type_get(obj),
5938            evas_object_name_get(obj), visible, disabled, focused, can_focus,
5939            sd->focus_order);
5940
5941    if (focused)
5942      fprintf(output, ", style=bold");
5943
5944    if (!visible)
5945      fprintf(output, ", fontcolor=gray28");
5946
5947    if ((disabled) || (!visible))
5948      fprintf(output, ", color=gray");
5949
5950    fprintf(output, " ];\n");
5951
5952    Eina_List *l;
5953    Evas_Object *o;
5954    EINA_LIST_FOREACH(sd->subobjs, l, o)
5955      _sub_obj_tree_dot_dump(o, output);
5956 }
5957
5958 #endif
5959
5960 EAPI void
5961 elm_widget_tree_dump(const Evas_Object *top)
5962 {
5963 #ifdef ELM_DEBUG
5964    if (!_elm_widget_is(top))
5965      return;
5966    _sub_obj_tree_dump(top, 0);
5967 #else
5968    (void)top;
5969    return;
5970 #endif
5971 }
5972
5973 EAPI void
5974 elm_widget_tree_dot_dump(const Evas_Object *top,
5975                          FILE *output)
5976 {
5977 #ifdef ELM_DEBUG
5978    if (!_elm_widget_is(top))
5979      return;
5980    fprintf(output, "graph " " { node [shape=record];\n");
5981    _sub_obj_tree_dot_dump(top, output);
5982    fprintf(output, "}\n");
5983 #else
5984    (void)top;
5985    (void)output;
5986    return;
5987 #endif
5988 }
5989
5990 EOLIAN static Eo *
5991 _elm_widget_eo_base_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
5992 {
5993    Eo *parent = NULL;
5994
5995    sd->on_create = EINA_TRUE;
5996    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
5997    eo_do(obj,
5998          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
5999          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
6000          parent = eo_parent_get());
6001    eo_do(obj, elm_obj_widget_parent_set(parent));
6002    sd->on_create = EINA_FALSE;
6003    //TIZEN_ONLY(20170717) : expose highlight information on atspi
6004    sd->can_highlight = EINA_TRUE;
6005    //
6006    /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
6007    sd->inherit_paragraph_direction = EINA_TRUE;
6008    /* END */
6009
6010    eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_UNKNOWN));
6011    return obj;
6012 }
6013
6014 EOLIAN static void
6015 _elm_widget_eo_base_destructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
6016 {
6017    sd->on_destroy = EINA_TRUE;
6018    eo_do(obj,
6019          elm_interface_atspi_accessible_description_set(NULL),
6020          elm_interface_atspi_accessible_name_set(NULL),
6021          //TIZEN_ONLY(20190922): add name callback, description callback.
6022          elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
6023          elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
6024          //
6025          elm_interface_atspi_accessible_translation_domain_set(NULL),
6026          elm_interface_atspi_accessible_relationships_clear(),
6027          // TIZEN_ONLY(20160930) : endless recursion fix
6028          elm_interface_atspi_accessible_attributes_clear()
6029          //
6030          );
6031    // TIZEN_ONLY(20150709) : atspi relations api
6032    if (sd->atspi_custom_relations)
6033      elm_atspi_relation_set_free(&sd->atspi_custom_relations);
6034    //
6035    //TIZEN_ONLY(20150717) add widget name setter
6036    if (sd->name)
6037      eina_stringshare_del(sd->name);
6038    //
6039
6040    //TIZEN_ONLY(20150731) : add i18n support for name and description
6041    if (sd->atspi_translation_domain)
6042      eina_stringshare_del(sd->atspi_translation_domain);
6043    //
6044    //Tizen Only(20160728) free attribute list
6045    if (sd->attr_list)
6046    {
6047       Elm_Atspi_Attribute *attr;
6048       EINA_LIST_FREE(sd->attr_list, attr)
6049        {
6050           eina_stringshare_del(attr->key);
6051           eina_stringshare_del(attr->value);
6052           free(attr);
6053        }
6054    }
6055    //
6056
6057    eo_do_super(obj, ELM_WIDGET_CLASS, eo_destructor());
6058    sd->on_destroy = EINA_FALSE;
6059
6060    elm_interface_atspi_accessible_removed(obj);
6061 }
6062
6063 EOLIAN static Eina_Bool
6064 _elm_widget_on_focus(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item EINA_UNUSED)
6065 {
6066    if (elm_widget_can_focus_get(obj))
6067      {
6068         if (elm_widget_focus_get(obj))
6069           {
6070              if (!sd->resize_obj)
6071                evas_object_focus_set(obj, EINA_TRUE);
6072               eo_do(obj, eo_event_callback_call
6073                (ELM_WIDGET_EVENT_FOCUSED, NULL));
6074              if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6075                elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_TRUE);
6076           }
6077         else
6078           {
6079              if (!sd->resize_obj)
6080                evas_object_focus_set(obj, EINA_FALSE);
6081              eo_do(obj, eo_event_callback_call
6082                (ELM_WIDGET_EVENT_UNFOCUSED, NULL));
6083              if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6084                elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_FALSE);
6085     }
6086      }
6087    else
6088      return EINA_FALSE;
6089
6090    return EINA_TRUE;
6091 }
6092
6093 EOLIAN static Eina_Bool
6094 _elm_widget_disable(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6095 {
6096    return EINA_FALSE;
6097 }
6098
6099 EOLIAN static Eina_Bool
6100 _elm_widget_event(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *source EINA_UNUSED, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
6101 {
6102    return EINA_FALSE;
6103 }
6104
6105 EOLIAN static Eina_Bool
6106 _elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6107 {
6108    WRN("The %s widget does not implement the \"focus_next/focus_next_manager_is\" functions.",
6109        eo_class_name_get(eo_class_get(obj)));
6110    return EINA_FALSE;
6111 }
6112
6113 static Eina_Bool
6114 _elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6115 {
6116    WRN("The %s widget does not implement the \"focus_direction/focus_direction_manager_is\" functions.",
6117        eo_class_name_get(eo_class_get(obj)));
6118    return EINA_FALSE;
6119 }
6120
6121 EOLIAN static Eina_Bool
6122 _elm_widget_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Activate act EINA_UNUSED)
6123 {
6124    WRN("The %s widget does not implement the \"activate\" functions.",
6125        eo_class_name_get(eo_class_get(obj)));
6126    return EINA_TRUE;
6127 }
6128
6129 EOLIAN static void
6130 _elm_widget_class_constructor(Eo_Class *klass)
6131 {
6132    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
6133 }
6134
6135 EOLIAN static Eina_Bool
6136 _elm_widget_elm_interface_atspi_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6137 {
6138    if (elm_object_focus_allow_get(obj))
6139      {
6140        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
6141        if (!ee) return EINA_FALSE;
6142        ecore_evas_activate(ee);
6143        elm_object_focus_set(obj, EINA_TRUE);
6144        return EINA_TRUE;
6145      }
6146    return EINA_FALSE;
6147 }
6148
6149 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
6150 EOLIAN static Eina_Bool
6151 _elm_widget_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6152 {
6153    if(!_elm_atspi_enabled())
6154       return EINA_FALSE;
6155
6156    Evas_Coord sx, sy, sw, sh;
6157    Evas_Coord x, y, w, h;
6158    Evas_Object *parent, *scroll_parent;
6159    evas_object_geometry_get(obj, &x, &y, &w, &h);
6160    sx = sy = sw = sh = 0;
6161    parent = evas_object_smart_parent_get(obj);
6162    scroll_parent = evas_object_smart_parent_get(obj);
6163    while (scroll_parent)
6164      {
6165         if (eo_isa(scroll_parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
6166           {
6167              evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
6168              x -= sx;
6169              y -= sy;
6170              switch (_elm_config->focus_autoscroll_mode)
6171                {
6172                 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
6173                    eo_do(scroll_parent, elm_interface_scrollable_content_region_show(x, y, w, h));
6174                    break;
6175                 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
6176                    eo_do(scroll_parent, elm_interface_scrollable_region_bring_in(x, y, w, h));
6177                    break;
6178                 default:
6179                    break;
6180                }
6181              break;
6182           }
6183         scroll_parent = evas_object_smart_parent_get(scroll_parent);
6184      }
6185    elm_object_accessibility_highlight_set(obj, EINA_TRUE);
6186    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
6187
6188    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6189    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_HIGHLIGHTED, NULL);
6190    //
6191    return EINA_TRUE;
6192 }
6193
6194 EOLIAN static Eina_Bool
6195 _elm_widget_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6196 {
6197    if(!_elm_atspi_enabled())
6198       return EINA_FALSE;
6199    elm_object_accessibility_highlight_set(obj, EINA_FALSE);
6200    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
6201
6202    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6203    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, NULL);
6204    //
6205    return EINA_TRUE;
6206 }
6207 //
6208
6209 EOLIAN static const char*
6210 _elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
6211 {
6212    char *accessible_name;
6213    //TIZEN_ONLY(20190922): add name callback, description callback.
6214    const char *ret = NULL;
6215    eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_name_get());
6216    if (ret) return ret;
6217    //
6218
6219    //TIZEN_ONLY(20150717) add widget name setter
6220    if (_pd->name)
6221      {
6222 #ifdef HAVE_GETTEXT
6223         if (_pd->atspi_translation_domain)
6224           return dgettext(_pd->atspi_translation_domain, _pd->name);
6225 #endif
6226         return _pd->name;
6227      }
6228    //
6229
6230    ret = elm_object_text_get(obj);
6231    if (!ret) return NULL;
6232
6233    accessible_name = _elm_util_mkup_to_text(ret);
6234    eina_stringshare_del(_pd->accessible_name);
6235    _pd->accessible_name =  eina_stringshare_add(accessible_name);
6236    free(accessible_name);
6237    return _pd->accessible_name;
6238 }
6239
6240 //TIZEN_ONLY(20150713) : add atspi name setter to widget_item
6241 EOLIAN void
6242 _elm_widget_item_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *name)
6243 {
6244    if (_pd->name)
6245      eina_stringshare_del(_pd->name);
6246
6247    _pd->name = eina_stringshare_add(name);
6248 }
6249
6250 EOLIAN const char*
6251 _elm_widget_item_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6252 {
6253    //TIZEN_ONLY(20190922): add name callback, description callback.
6254    const char *ret = NULL;
6255    eo_do_super(obj, ELM_WIDGET_ITEM_CLASS, ret = elm_interface_atspi_accessible_name_get());
6256    if (ret) return ret;
6257    //
6258
6259    if (_pd->name)
6260      {
6261 #ifdef HAVE_GETTEXT
6262         if (_pd->atspi_translation_domain)
6263           return dgettext(_pd->atspi_translation_domain, _pd->name);
6264 #endif
6265         return _pd->name;
6266      }
6267
6268    return NULL;
6269 }
6270 //
6271
6272 //TIZEN_ONLY(20150709) : spatially sort atspi children
6273 static int _sort_vertically(const void *data1, const void *data2)
6274 {
6275    Evas_Coord y1, y2;
6276    evas_object_geometry_get(data1, NULL, &y1, NULL, NULL);
6277    evas_object_geometry_get(data2, NULL, &y2, NULL, NULL);
6278
6279    return y1 < y2 ? -1 : 1;
6280 }
6281
6282 static int _sort_horizontally(const void *data1, const void *data2)
6283 {
6284    Evas_Coord x1, x2;
6285    evas_object_geometry_get(data1, &x1, NULL, NULL, NULL);
6286    evas_object_geometry_get(data2, &x2, NULL, NULL, NULL);
6287
6288    return x1 < x2 ? -1 : 1;
6289 }
6290
6291 static Eina_List *_lines_split(Eina_List *children)
6292 {
6293    Eo *c;
6294    Eina_List *lines, *line, *l;
6295    Evas_Coord yl, y, hl, h;
6296    lines = line = NULL;
6297
6298    if (!children) return NULL;
6299
6300    EINA_LIST_FOREACH(children, l, c)
6301      {
6302         evas_object_geometry_get(c, NULL, &yl, NULL, &hl);
6303
6304         /* remove child if its height == 0 */
6305         if (hl != 0) break;
6306      }
6307
6308    EINA_LIST_FREE(children, c)
6309      {
6310         evas_object_geometry_get(c, NULL, &y, NULL, &h);
6311
6312         /* remove child if its height == 0 */
6313         if (h == 0) continue;
6314
6315         if ((yl + (int)(0.25 * hl)) >= y)
6316           {
6317              //same line
6318              line = eina_list_append(line,c);
6319           }
6320         else
6321           {
6322              // finish current line & start new
6323              lines = eina_list_append(lines, line);
6324              yl = y, hl = h;
6325              line = eina_list_append(NULL, c);
6326           }
6327      }
6328
6329    return eina_list_append(lines, line);
6330 }
6331 //
6332
6333 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6334 static void
6335 _proxy_widget_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6336 {
6337    Evas_Coord x, y;
6338    Eo *proxy = data;
6339
6340    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
6341    elm_atspi_bridge_utils_proxy_offset_set(proxy, x, y);
6342 }
6343 //
6344
6345 static Eina_Bool
6346 _on_widget_del(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6347 {
6348    Eo *plug = data;
6349    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6350    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
6351                                        _proxy_widget_move_cb, plug);
6352    //
6353    eo_del(plug);
6354    return EINA_TRUE;
6355 }
6356
6357 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6358 static Eina_Bool
6359 _on_proxy_connected_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6360 {
6361    Evas_Coord x, y;
6362    Evas_Object *widget = data;
6363
6364    evas_object_geometry_get(widget, &x, &y, NULL, NULL);
6365    elm_atspi_bridge_utils_proxy_offset_set(obj, x, y);
6366
6367    evas_object_event_callback_add(widget, EVAS_CALLBACK_MOVE, _proxy_widget_move_cb, obj);
6368    return EINA_TRUE;
6369 }
6370 //
6371 // TIZEN ONLY - END
6372
6373 EOLIAN static Eina_List*
6374 _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6375 {
6376    Eina_List *l, *accs = NULL;
6377    Elm_Widget_Smart_Data *wd;
6378    Evas_Object *widget;
6379    // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6380    Eo *parent;
6381    //
6382
6383    wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6384    if (!wd) return NULL;
6385
6386    EINA_LIST_FOREACH(wd->subobjs, l, widget)
6387      {
6388         const char *type = evas_object_type_get(widget);
6389         // TIZEN ONLY
6390         // Ugly Tizen hack to integrate AT-SPI2 accessibility provided by WebKit/Chromium with elementary one.
6391         // This wrapper class should be implemented in Webkit/Chromium EFL ports
6392         if (type && (!strcmp(type, "EWebView") || !strcmp(type, "WebView"))) {
6393            elm_atspi_ewk_wrapper_a11y_init(obj, widget);
6394         }
6395      }
6396
6397    EINA_LIST_FOREACH(wd->subobjs, l, widget)
6398      {
6399         // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6400         if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) {
6401            eo_do(widget, parent = elm_interface_atspi_accessible_parent_get());
6402            if (parent && (parent != obj)) continue;
6403         }
6404
6405         // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6406         const char *plug_id_2;
6407         if ((plug_id_2 = evas_object_data_get(widget, "___PLUGID")) != NULL)
6408           {
6409             // TIZEN_ONLY(20160930) : endless recursion fix
6410             eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id_2));
6411
6412              Eo *proxy;
6413              char *svcname, *svcnum;
6414
6415              proxy = evas_object_data_get(widget, "__widget_proxy");
6416              if (proxy)
6417                {
6418                   accs = eina_list_append(accs, proxy);
6419                   continue;
6420                }
6421
6422              if (_elm_atspi_bridge_plug_id_split(plug_id_2, &svcname, &svcnum))
6423                {
6424                   proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
6425                   evas_object_data_set(widget, "__widget_proxy", proxy);
6426                   eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
6427                   eo_do(proxy, eo_event_callback_add(ELM_ATSPI_PROXY_EVENT_CONNECTED,  _on_proxy_connected_cb, widget));
6428                   elm_atspi_bridge_utils_proxy_connect(proxy);
6429                   accs = eina_list_append(accs, proxy);
6430                   free(svcname);
6431                   free(svcnum);
6432                }
6433              continue;
6434           }
6435         //
6436         // TIZEN ONLY - END
6437         if (!elm_object_widget_check(widget)) continue;
6438         if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6439           accs = eina_list_append(accs, widget);
6440      }
6441    //TIZEN_ONLY(20150709) : spatially sort atspi children
6442    // sort children using its top-left coordinate
6443    accs = eina_list_sort(accs, -1, _sort_vertically);
6444    Eina_List *line, *lines = _lines_split(accs);
6445    accs = NULL;
6446    EINA_LIST_FREE(lines, line)
6447      accs = eina_list_merge(accs, eina_list_sort(line, -1, _sort_horizontally));
6448    //
6449    return accs;
6450 }
6451
6452 EOLIAN static Eo*
6453 _elm_widget_elm_interface_atspi_accessible_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
6454 {
6455    Eo *ret;
6456    eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_parent_get());
6457
6458    return ret ? ret : pd->parent_obj;
6459 }
6460
6461 EOLIAN static Elm_Atspi_State_Set
6462 _elm_widget_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Widget_Smart_Data *pd)
6463 {
6464    Elm_Atspi_State_Set states = 0;
6465
6466    eo_do_super(obj, ELM_WIDGET_CLASS, states = elm_interface_atspi_accessible_state_set_get());
6467
6468    if (evas_object_visible_get(obj))
6469      {
6470         STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
6471         if (_elm_widget_onscreen_is(obj))
6472           STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
6473      }
6474    if (!elm_widget_child_can_focus_get(obj))
6475      {
6476         if (elm_object_focus_allow_get(obj))
6477           STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
6478         if (elm_object_focus_get(obj))
6479           STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
6480      }
6481    if (!elm_object_disabled_get(obj))
6482      {
6483         STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
6484         STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
6485      }
6486
6487    //TIZEN_ONLY(20170717) : expose highlight information on atspi
6488    if (pd->can_highlight)
6489      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6490    else
6491      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6492
6493    if (_elm_object_accessibility_currently_highlighted_get() == (void*)pd->obj)
6494      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
6495    //
6496
6497    return states;
6498 }
6499
6500 //TIZEN_ONLY(20160729): attributes_get, append APIs added/updated.
6501 EOLIAN static Eina_List*
6502 _elm_widget_elm_interface_atspi_accessible_attributes_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6503 {
6504    Eina_List *attr_list = NULL;
6505    // TIZEN_ONLY(20160930) : endless recursion fix
6506    eo_do_super(obj, MY_CLASS, attr_list = elm_interface_atspi_accessible_attributes_get());
6507    //
6508    //Add type and style information in addition.
6509    Elm_Atspi_Attribute *attr = NULL;
6510    attr = calloc(1, sizeof(Elm_Atspi_Attribute));
6511    if (attr)
6512      {
6513         attr->key = eina_stringshare_add("type");
6514         attr->value = eina_stringshare_add(elm_widget_type_get(obj));
6515         attr_list = eina_list_append(attr_list, attr);
6516      }
6517
6518    attr = calloc(1, sizeof(Elm_Atspi_Attribute));
6519    if (attr)
6520      {
6521         attr->key = eina_stringshare_add("style");
6522         attr->value = eina_stringshare_add(elm_widget_style_get(obj));
6523         attr_list = eina_list_append(attr_list, attr);
6524      }
6525
6526    return attr_list;
6527 }
6528
6529 //TIZEN_ONLY(20150709) : atspi relations api
6530 EOLIAN static Elm_Atspi_Relation_Set
6531 _elm_widget_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
6532 {
6533    return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
6534 }
6535
6536 EOLIAN static Elm_Atspi_Relation_Set
6537 _elm_widget_item_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
6538 {
6539    return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
6540 }
6541 //
6542
6543 EOLIAN static void
6544 _elm_widget_item_elm_interface_atspi_component_extents_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords, int *x, int *y, int *w, int *h)
6545 {
6546    int ee_x, ee_y;
6547
6548    if (!sd->view)
6549      {
6550         if (x) *x = -1;
6551         if (y) *y = -1;
6552         if (w) *w = -1;
6553         if (h) *h = -1;
6554         return;
6555      }
6556
6557    evas_object_geometry_get(sd->view, x, y, w, h);
6558    if (screen_coords)
6559      {
6560         Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->view));
6561         if (!ee) return;
6562         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
6563         if (x) *x += ee_x;
6564         if (y) *y += ee_y;
6565      }
6566 }
6567
6568 EOLIAN static Eina_Bool
6569 _elm_widget_item_elm_interface_atspi_component_extents_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
6570 {
6571    return EINA_FALSE;
6572 }
6573
6574 EOLIAN static int
6575 _elm_widget_item_elm_interface_atspi_component_layer_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
6576 {
6577    if (!sd->view)
6578      return -1;
6579    return evas_object_layer_get(sd->view);
6580 }
6581
6582 EOLIAN static Eina_Bool
6583 _elm_widget_item_elm_interface_atspi_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6584 {
6585    elm_object_item_focus_set(obj, EINA_TRUE);
6586    return elm_object_item_focus_get(obj);
6587 }
6588
6589 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods
6590 EOLIAN static Eina_Bool
6591 _elm_widget_item_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
6592 {
6593
6594    if (!obj) return EINA_FALSE;
6595
6596    Evas_Object *o = elm_object_parent_widget_get(sd->view);
6597    if (_elm_scrollable_is(o))
6598      {
6599         Evas_Coord bx, by, bw, bh;
6600         Evas_Coord x, y, w, h;
6601         Evas_Object *w1 = elm_object_parent_widget_get(o);
6602         evas_object_geometry_get(sd->view, &x, &y, &w, &h);
6603         evas_object_geometry_get(o, &bx, &by, &bw, &bh);
6604         x -= bx;
6605         y -= by;
6606         switch (_elm_config->focus_autoscroll_mode)
6607           {
6608            case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
6609               eo_do(w1, elm_interface_scrollable_content_region_show(x, y, w, h));
6610               break;
6611            case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
6612               eo_do(w1, elm_interface_scrollable_region_bring_in(x, y, w, h));
6613               break;
6614            default:
6615               break;
6616           }
6617      }
6618
6619    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_TRUE);
6620    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
6621
6622    return EINA_TRUE;
6623
6624 }
6625
6626 EOLIAN static Eina_Bool
6627 _elm_widget_item_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
6628 {
6629    if (!obj) return EINA_FALSE;
6630    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_FALSE);
6631    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
6632    return EINA_TRUE;
6633 }
6634 //
6635
6636 EOLIAN static double
6637 _elm_widget_item_elm_interface_atspi_component_alpha_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
6638 {
6639    int alpha;
6640
6641    if (!sd->view) return -1.0;
6642    evas_object_color_get(sd->view, NULL, NULL, NULL, &alpha);
6643    return (double)alpha / 255.0;
6644 }
6645
6646 //TIZEN_ONLY(20150717) add widget name setter
6647 EOLIAN void
6648 _elm_widget_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *name)
6649 {
6650    if (_pd->name)
6651      eina_stringshare_del(_pd->name);
6652
6653    _pd->name = eina_stringshare_add(name);
6654 }
6655 //
6656
6657 //TIZEN_ONLY(20160329): widget: improve accessibile_at_point getter (a8aff0423202b9a55dbb3843205875226678fbd6)
6658 EOLIAN static Eo *
6659 _elm_widget_elm_interface_atspi_component_accessible_at_point_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
6660 {
6661    Eina_List *l, *l2, *children;
6662    Eo *child;
6663    Evas_Object *stack_item;
6664    Eo *compare_obj;
6665    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6666    Eo *proxy;
6667    Evas_Coord px, py, pw, ph;
6668    //
6669    int ee_x, ee_y;
6670
6671    if (screen_coords)
6672      {
6673         Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
6674         if (!ee) return NULL;
6675         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
6676         x -= ee_x;
6677         y -= ee_y;
6678      }
6679
6680    eo_do(obj, children = elm_interface_atspi_accessible_children_get());
6681
6682    /* Get evas_object stacked at given x,y coordinates starting from top */
6683    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
6684    /* Foreach stacked object starting from top */
6685    EINA_LIST_FOREACH(stack, l, stack_item)
6686      {
6687         /* Foreach at-spi children traverse stack_item evas_objects hierarchy */
6688         EINA_LIST_FOREACH(children, l2, child)
6689           {
6690              Elm_Atspi_Role role;
6691              eo_do(child, role = elm_interface_atspi_accessible_role_get());
6692              if (role == ELM_ATSPI_ROLE_REDUNDANT_OBJECT)
6693                {
6694                   /* The redundant object ignores */
6695                   continue;
6696                }
6697              /* Compare object used to compare with stacked evas objects */
6698              compare_obj = child;
6699              /* In case of widget_items compare should be different then elm_widget_ item  object */
6700              if (eo_isa(child, ELM_WIDGET_ITEM_CLASS))
6701                {
6702                   Elm_Widget_Item_Data *id = eo_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
6703                   compare_obj = id->view;
6704                }
6705              /* In case of access object compare should be 'wrapped' evas_object */
6706              if (eo_isa(child, ELM_ACCESS_CLASS))
6707                {
6708                   Elm_Access_Info *info = _elm_access_info_get(child);
6709                   compare_obj = info->part_object;
6710                }
6711
6712              /* In case of ewk wrapper object compare with internal ewk_view evas_object */
6713              if (eo_isa(child, ELM_ATSPI_EWK_WRAPPER_CLASS))
6714                {
6715                   compare_obj = elm_atspi_ewk_wrapper_ewk_view_get(child);
6716                }
6717
6718              /* If spacial eo children do not have backing evas_object continue with search */
6719              if (!compare_obj)
6720                continue;
6721
6722              Evas_Object *smart_parent = stack_item;
6723              while (smart_parent)
6724                {
6725                    if (smart_parent == compare_obj)
6726                      {
6727                         eina_list_free(children);
6728                         eina_list_free(stack);
6729                         return child;
6730                      }
6731
6732                    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6733                    proxy = evas_object_data_get(smart_parent, "__widget_proxy");
6734                    if (proxy)
6735                      {
6736                         evas_object_geometry_get(smart_parent, &px, &py, &pw, &ph);
6737                         if (x >= px && x <= px + pw && y >= py && y <= py +ph)
6738                           {
6739                              eina_list_free(children);
6740                              eina_list_free(stack);
6741                              return proxy;
6742                           }
6743                      }
6744                    //
6745                    smart_parent = evas_object_smart_parent_get(smart_parent);
6746                }
6747           }
6748      }
6749
6750    eina_list_free(children);
6751    eina_list_free(stack);
6752    return NULL;
6753 }
6754 //
6755
6756 //TIZEN_ONLY(20150709) add relations atpi
6757 EOLIAN static Eina_Bool
6758 _elm_widget_elm_interface_atspi_accessible_relationship_append(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
6759 {
6760    return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
6761 }
6762
6763 EOLIAN static void
6764 _elm_widget_elm_interface_atspi_accessible_relationship_remove(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
6765 {
6766    elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
6767 }
6768
6769 EOLIAN static Eina_Bool
6770 _elm_widget_item_elm_interface_atspi_accessible_relationship_append(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
6771 {
6772    return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
6773 }
6774
6775 EOLIAN static void
6776 _elm_widget_item_elm_interface_atspi_accessible_relationship_remove(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
6777 {
6778    elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
6779 }
6780 //
6781
6782 //TIZEN_ONLY(20150731) : add i18n support for name and description
6783 EOLIAN static void
6784 _elm_widget_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, const char *domain)
6785 {
6786    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
6787 }
6788
6789 EOLIAN static const char*
6790 _elm_widget_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
6791 {
6792    return _pd->atspi_translation_domain;
6793 }
6794
6795 EOLIAN static void
6796 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, const char *domain)
6797 {
6798    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
6799 }
6800
6801 EOLIAN static const char*
6802 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd)
6803 {
6804    return _pd->atspi_translation_domain;
6805 }
6806
6807 //TIZEN_ONLY(20160726): add API elm_atspi_accessible_can_highlight_set/get
6808 EOLIAN static void
6809 _elm_widget_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Eina_Bool can_highlight)
6810 {
6811    _pd->can_highlight = !!can_highlight;
6812 }
6813
6814 EOLIAN static Eina_Bool
6815 _elm_widget_elm_interface_atspi_accessible_can_highlight_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
6816 {
6817    return _pd->can_highlight;
6818 }
6819
6820 EOLIAN static void
6821 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, Eina_Bool can_highlight)
6822 {
6823    _pd->can_highlight = !!can_highlight;
6824 }
6825
6826 EOLIAN static Eina_Bool
6827 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd)
6828 {
6829    return _pd->can_highlight;
6830 }
6831 //
6832
6833 //TIZEN_ONLY(20160622): Override Paragraph Direction APIs
6834 static void
6835 _elm_widget_evas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
6836 {
6837    Evas_Object *child;
6838    Eina_List *l;
6839
6840    if (sd->on_destroy) return;
6841
6842    EINA_LIST_FOREACH(sd->subobjs, l, child)
6843      {
6844         if (_elm_widget_is(child))
6845           {
6846              Elm_Widget_Smart_Data *sdc = eo_data_scope_get(child, MY_CLASS);
6847
6848              if (sdc->inherit_paragraph_direction &&
6849                  (sdc->paragraph_direction != dir))
6850                {
6851                   sdc->paragraph_direction = dir;
6852                   _elm_widget_evas_object_paragraph_direction_set_internal(child, sdc, dir);
6853                   eo_do_super(child, MY_CLASS, evas_obj_paragraph_direction_set(dir));
6854                }
6855           }
6856
6857         /* FIXME: There is no way to handle non-widget child object.
6858          * If a non-widget child object has smart parent, it will get the direction
6859          * from the smart parent. */
6860      }
6861 }
6862
6863 EOLIAN static void
6864 _elm_widget_evas_object_paragraph_direction_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
6865 {
6866    if ((!(sd->inherit_paragraph_direction) && (sd->paragraph_direction == dir)) ||
6867        (sd->inherit_paragraph_direction && (dir == EVAS_BIDI_DIRECTION_INHERIT)))
6868      return;
6869
6870    if (dir == EVAS_BIDI_DIRECTION_INHERIT)
6871      {
6872         sd->inherit_paragraph_direction = EINA_TRUE;
6873         Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
6874
6875         if (sd->parent_obj)
6876           parent_dir = evas_object_paragraph_direction_get(sd->parent_obj);
6877
6878         if (parent_dir != sd->paragraph_direction)
6879           {
6880              sd->paragraph_direction = parent_dir;
6881              _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, parent_dir);
6882           }
6883      }
6884    else
6885      {
6886         sd->inherit_paragraph_direction = EINA_FALSE;
6887         sd->paragraph_direction = dir;
6888         _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, dir);
6889      }
6890
6891    eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(dir));
6892 }
6893 //
6894
6895
6896 //TIZEN_ONLY(20161013): clean up elm color class feature
6897 void
6898 _edje_color_class_free(void *data)
6899 {
6900    Edje_Color_Class *cc = data;
6901
6902    if (cc->name) eina_stringshare_del(cc->name);
6903    free(cc);
6904 }
6905
6906 Eina_Stringshare *
6907 _elm_widget_edje_class_get(const Eo_Class *klass, const char *style, const char *part)
6908 {
6909    Eina_Strbuf *buf;
6910    Eina_Stringshare *str;
6911
6912    buf = eina_strbuf_new();
6913
6914    eina_strbuf_append(buf, strchr(eo_class_name_get(klass), '_') + 1);
6915    eina_strbuf_tolower(buf);
6916
6917    if (style)
6918      {
6919         eina_strbuf_append_printf(buf, "/%s/%s", style, part);
6920      }
6921    else
6922      {
6923         eina_strbuf_append_printf(buf, "/%s", part);
6924      }
6925
6926    str = eina_stringshare_add(eina_strbuf_string_get(buf));
6927
6928    eina_strbuf_free(buf);
6929    return str;
6930 }
6931
6932 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
6933 Eina_Bool
6934 _elm_widget_color_class_set_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
6935                                      int r, int g, int b, int a,
6936                                      int r2, int g2, int b2, int a2,
6937                                      int r3, int g3, int b3, int a3)
6938 {
6939    Eina_Bool int_ret = EINA_TRUE;
6940    Eina_Stringshare *buf;
6941    int temp_color[3][4] = { { r,  g,  b,  a },
6942                             { r2, g2, b2, a2 },
6943                             { r3, g3, b3, a3 } };
6944
6945    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
6946
6947 #define TEMP_COLOR(x, y) \
6948    ((temp_color[x][y] == -1) ? &temp_color[x][y] : NULL)
6949
6950    edje_object_color_class_get(edje, buf,
6951                                TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
6952                                TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
6953                                TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
6954
6955 #undef TEMP_COLOR
6956
6957 #define TEMP_COLOR(x, y) \
6958    ((temp_color[x][y] == -1) ? 0 : temp_color[x][y])
6959
6960    int_ret &= edje_object_color_class_set(edje, buf,
6961                                           TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
6962                                           TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
6963                                           TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
6964
6965 #undef TEMP_COLOR
6966
6967    eina_stringshare_del(buf);
6968
6969    return int_ret;
6970 }
6971
6972 Eina_Bool
6973 _elm_widget_color_class_get_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
6974                                      int *r, int *g, int *b, int *a,
6975                                      int *r2, int *g2, int *b2, int *a2,
6976                                      int *r3, int *g3, int *b3, int *a3)
6977 {
6978    Eina_Bool int_ret = EINA_TRUE;
6979    Eina_Stringshare *buf;
6980
6981    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
6982
6983    int_ret &= edje_object_color_class_get(edje, buf,
6984                                           r,  g,  b,  a,
6985                                           r2, g2, b2, a2,
6986                                           r3, g3, b3, a3);
6987
6988    eina_stringshare_del(buf);
6989
6990    return int_ret;
6991 }
6992 /* END */
6993
6994 EOLIAN Eina_Bool
6995 _elm_widget_class_color_set(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int r, int g, int b, int a)
6996 {
6997    Evas_Object *edje;
6998    Eina_Bool int_ret = EINA_TRUE;
6999
7000    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7001
7002    edje = elm_layout_edje_get(obj);
7003    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7004                                                    r, g, b, a,
7005                                                    -1, -1, -1, -1,
7006                                                    -1, -1, -1, -1);
7007
7008    return int_ret;
7009 }
7010
7011 EOLIAN Eina_Bool
7012 _elm_widget_class_color_get(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int *r, int *g, int *b, int *a)
7013 {
7014    Evas_Object *edje;
7015    Eina_Bool int_ret = EINA_TRUE;
7016
7017    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7018
7019    edje = elm_layout_edje_get(obj);
7020    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7021                                                    r, g, b, a,
7022                                                    NULL, NULL, NULL, NULL,
7023                                                    NULL, NULL, NULL, NULL);
7024
7025    return int_ret;
7026 }
7027
7028 EOLIAN Eina_Bool
7029 _elm_widget_class_color2_set(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int r, int g, int b, int a)
7030 {
7031    Evas_Object *edje;
7032    Eina_Bool int_ret = EINA_TRUE;
7033
7034    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7035
7036    edje = elm_layout_edje_get(obj);
7037    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7038                                                    -1, -1, -1, -1,
7039                                                    r, g, b, a,
7040                                                    -1, -1, -1, -1);
7041
7042    return int_ret;
7043 }
7044
7045 EOLIAN Eina_Bool
7046 _elm_widget_class_color2_get(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int *r, int *g, int *b, int *a)
7047 {
7048    Evas_Object *edje;
7049    Eina_Bool int_ret = EINA_TRUE;
7050
7051    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7052
7053    edje = elm_layout_edje_get(obj);
7054    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7055                                                    NULL, NULL, NULL, NULL,
7056                                                    r, g, b, a,
7057                                                    NULL, NULL, NULL, NULL);
7058
7059    return int_ret;
7060 }
7061
7062 EOLIAN Eina_Bool
7063 _elm_widget_class_color3_set(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int r, int g, int b, int a)
7064 {
7065    Evas_Object *edje;
7066    Eina_Bool int_ret = EINA_TRUE;
7067
7068    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7069
7070    edje = elm_layout_edje_get(obj);
7071    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7072                                                    -1, -1, -1, -1,
7073                                                    -1, -1, -1, -1,
7074                                                    r, g, b, a);
7075
7076    return int_ret;
7077 }
7078
7079 EOLIAN Eina_Bool
7080 _elm_widget_class_color3_get(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int *r, int *g, int *b, int *a)
7081 {
7082    Evas_Object *edje;
7083    Eina_Bool int_ret = EINA_TRUE;
7084
7085    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7086
7087    edje = elm_layout_edje_get(obj);
7088    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7089                                                    NULL, NULL, NULL, NULL,
7090                                                    NULL, NULL, NULL, NULL,
7091                                                    r, g, b, a);
7092
7093    return int_ret;
7094 }
7095
7096 #define ELM_COLOR_CLASS_UPDATE(obj, hash, cond)                                  \
7097    Evas_Object *edje = NULL;                                                     \
7098    Eina_Iterator *itr;                                                           \
7099    Edje_Color_Class *cc;                                                         \
7100    Eina_Bool int_ret = EINA_TRUE;                                                \
7101    if (cond) return EINA_FALSE;                                                  \
7102    if (eo_isa(obj, ELM_LAYOUT_CLASS))                                            \
7103      edje =  elm_layout_edje_get(obj);                                           \
7104    else if (eo_isa(obj, EDJE_OBJECT_CLASS))                                      \
7105      edje = obj;                                                                 \
7106    if (!edje) return EINA_FALSE;                                                 \
7107    itr = eina_hash_iterator_data_new(hash);                                      \
7108    EINA_ITERATOR_FOREACH(itr, cc)                                                \
7109      {                                                                           \
7110         int_ret &= edje_object_color_class_set(edje, cc->name,                   \
7111                                                cc->r, cc->g, cc->b, cc->a,       \
7112                                                cc->r2, cc->g2, cc->b2, cc->a2,   \
7113                                                cc->r3, cc->g3, cc->b3, cc->a3);  \
7114      }                                                                           \
7115    eina_iterator_free(itr);                                                      \
7116    return int_ret
7117
7118
7119 #define CHECK_BOUND(x)                                                           \
7120    if (x > 0xff) x = 0xff;                                                       \
7121    else if (x < 0) x = 0
7122
7123 #define ELM_COLOR_CLASS_SET_START(obj, cr, cg, cb, ca)                           \
7124    Eina_Bool int_ret = EINA_FALSE;                                               \
7125    Edje_Color_Class *cc = NULL;                                                  \
7126    Eina_Stringshare *buf;                                                        \
7127    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);       \
7128    CHECK_BOUND(r);                                                               \
7129    CHECK_BOUND(g);                                                               \
7130    CHECK_BOUND(b);                                                               \
7131    CHECK_BOUND(a);                                                               \
7132    _elm_color_unpremul(a, &r, &g, &b);                                           \
7133    if (!sd->color_classes)                                                       \
7134      sd->color_classes = eina_hash_string_small_new(_edje_color_class_free);     \
7135    else                                                                          \
7136      cc = eina_hash_find(sd->color_classes, buf);                                \
7137    if (!cc)                                                                      \
7138      {                                                                           \
7139         cc = calloc(1, sizeof(Edje_Color_Class));                                \
7140         cc->name = eina_stringshare_add(buf);                                    \
7141         if (!cc->name)                                                           \
7142           {                                                                      \
7143              free(cc);                                                           \
7144              eina_stringshare_del(buf);                                          \
7145              return EINA_FALSE;                                                  \
7146           }                                                                      \
7147         eina_hash_direct_add(sd->color_classes, cc->name, cc);                   \
7148      }                                                                           \
7149    else if ((cc->cr == r) && (cc->cg == g) &&                                    \
7150             (cc->cb == b) && (cc->ca == a))                                      \
7151      {                                                                           \
7152         eina_stringshare_del(buf);                                               \
7153         return EINA_TRUE;                                                        \
7154      }                                                                           \
7155    cc->cr = r;                                                                   \
7156    cc->cg = g;                                                                   \
7157    cc->cb = b;                                                                   \
7158    cc->ca = a;                                                                   \
7159    int_ret = EINA_TRUE
7160
7161 #define ELM_COLOR_CLASS_SET_END()                                                \
7162    eina_stringshare_del(buf);                                                    \
7163    return int_ret
7164
7165 #define ELM_COLOR_CLASS_GET(obj, cr, cg, cb, ca)                                 \
7166    Eina_Bool int_ret = EINA_FALSE;                                               \
7167    Edje_Color_Class *cc;                                                         \
7168    Eina_Stringshare *buf;                                                        \
7169    int alpha = 0;                                                                \
7170    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);       \
7171    if ((!sd->color_classes) || !(cc = eina_hash_find(sd->color_classes, buf)))   \
7172      {                                                                           \
7173         if (r) *r = 0;                                                           \
7174         if (g) *g = 0;                                                           \
7175         if (b) *b = 0;                                                           \
7176         if (a) *a = 0;                                                           \
7177         int_ret = EINA_FALSE;                                                    \
7178      }                                                                           \
7179    else                                                                          \
7180      {                                                                           \
7181         if (r) *r = cc->cr;                                                      \
7182         if (g) *g = cc->cg;                                                      \
7183         if (b) *b = cc->cb;                                                      \
7184         if (a) *a = cc->ca;                                                      \
7185         alpha = cc->ca;                                                          \
7186         int_ret = EINA_TRUE;                                                     \
7187      }                                                                           \
7188    _elm_color_premul(alpha, r, g, b);                                            \
7189    eina_stringshare_del(buf);                                                    \
7190    return int_ret
7191
7192 Eina_Bool
7193 _elm_widget_item_color_class_update(Elm_Widget_Item_Data *sd)
7194 {
7195    ELM_COLOR_CLASS_UPDATE(sd->view, sd->color_classes, (!sd) || (!sd->color_classes) || (!sd->view));
7196 }
7197
7198 EOLIAN Eina_Bool
7199 _elm_widget_item_class_color_set(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int r, int g, int b, int a)
7200 {
7201    ELM_COLOR_CLASS_SET_START(obj, r, g, b, a);
7202
7203    int_ret &= _elm_widget_item_color_class_update(sd);
7204
7205    ELM_COLOR_CLASS_SET_END();
7206 }
7207
7208 EOLIAN Eina_Bool
7209 _elm_widget_item_class_color_get(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
7210 {
7211    ELM_COLOR_CLASS_GET(obj, r, g, b, a);
7212 }
7213
7214 EOLIAN Eina_Bool
7215 _elm_widget_item_class_color2_set(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int r, int g, int b, int a)
7216 {
7217    ELM_COLOR_CLASS_SET_START(obj, r2, g2, b2, a2);
7218
7219    int_ret &= _elm_widget_item_color_class_update(sd);
7220
7221    ELM_COLOR_CLASS_SET_END();
7222 }
7223
7224 EOLIAN Eina_Bool
7225 _elm_widget_item_class_color2_get(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
7226 {
7227    ELM_COLOR_CLASS_GET(obj, r2, g2, b2, a2);
7228 }
7229
7230 EOLIAN Eina_Bool
7231 _elm_widget_item_class_color3_set(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int r, int g, int b, int a)
7232 {
7233    ELM_COLOR_CLASS_SET_START(obj, r3, g3, b3, a3);
7234
7235    int_ret &= _elm_widget_item_color_class_update(sd);
7236
7237    ELM_COLOR_CLASS_SET_END();
7238 }
7239
7240 EOLIAN Eina_Bool
7241 _elm_widget_item_class_color3_get(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
7242 {
7243    ELM_COLOR_CLASS_GET(obj, r3, g3, b3, a3);
7244 }
7245 //
7246
7247 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
7248 void
7249 _elm_widget_color_class_parent_set(Evas_Object *obj, Evas_Object *parent)
7250 {
7251    Evas_Object *edje = NULL, *parent_edje = NULL;
7252
7253    if (!obj || !parent) return;
7254
7255    if (eo_isa(obj, ELM_LAYOUT_CLASS))
7256      edje =  elm_layout_edje_get(obj);
7257    else if (eo_isa(obj, EDJE_OBJECT_CLASS))
7258      edje = obj;
7259
7260    if (eo_isa(parent, ELM_LAYOUT_CLASS))
7261      parent_edje =  elm_layout_edje_get(parent);
7262    else if (eo_isa(parent, EDJE_OBJECT_CLASS))
7263      parent_edje = parent;
7264
7265    if (!edje || !parent_edje) return;
7266
7267    edje_object_color_class_parent_set(edje, parent_edje);
7268 }
7269
7270 void
7271 _elm_widget_color_class_parent_unset(Evas_Object *obj)
7272 {
7273    Evas_Object *edje = NULL;
7274
7275    if (!obj) return;
7276
7277    if (eo_isa(obj, ELM_LAYOUT_CLASS))
7278      edje =  elm_layout_edje_get(obj);
7279    else if (eo_isa(obj, EDJE_OBJECT_CLASS))
7280      edje = obj;
7281
7282    if (!edje) return;
7283
7284    edje_object_color_class_parent_unset(edje);
7285 }
7286 /* END */
7287
7288 //TIZEN_ONLY(20160527): widget: add AtspiAction interface to all widgets and widget_items, add handlers for reading stopped/cancelled
7289 EOLIAN const Elm_Atspi_Action *
7290 _elm_widget_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
7291 {
7292    return NULL;
7293 }
7294
7295 EOLIAN const Elm_Atspi_Action *
7296 _elm_widget_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *pd EINA_UNUSED)
7297 {
7298    return NULL;
7299 }
7300 //
7301
7302 #include "elm_widget_item.eo.c"
7303 #include "elm_widget.eo.c"