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