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