atspi: remove unacceptable leaf node
[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(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
5056 EAPI Eina_Bool
5057 _elm_widget_item_highlightable(Elm_Object_Item *item)
5058 {
5059    Eo *parent;
5060    Eina_Bool can_highlight;
5061
5062    Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
5063    if (!id) return EINA_FALSE;
5064    if (!id->can_highlight) return EINA_FALSE;
5065
5066    eo_do(item, parent = elm_interface_atspi_accessible_parent_get());
5067    while (parent && !eo_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
5068      {
5069         eo_do(parent, can_highlight = elm_interface_atspi_accessible_can_highlight_get());
5070         if (!can_highlight) return EINA_FALSE;
5071         eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
5072      }
5073    return EINA_TRUE;
5074 }
5075 //
5076
5077 //TIZEN_ONLY(20170206): Add check the object is in the scroller content size
5078 Eina_Bool
5079 _accessible_object_on_scroll_is(Eo* obj)
5080 {
5081    /* in case of genlist item, the item->view is NULL if item is unrealized.
5082       this function is used to check if obj could have HIGHLIGHTABLE or not.
5083       the unrealized genlist item should have HIGHLIGHTABLE state.
5084       so if obj is NULL return EINA_TRUE */
5085    if(!obj) return EINA_TRUE;
5086
5087    Evas_Object *target = obj;
5088    Evas_Object *parent = NULL;
5089    Evas_Coord x, y, w, h, wx, wy, ww = 0, wh = 0, nx = 0, ny = 0;
5090
5091    evas_object_geometry_get(target, &x, &y ,&w, &h);
5092
5093    if (elm_widget_is(target))
5094      parent = elm_widget_parent_get(target);
5095    else
5096      parent = elm_widget_parent_widget_get(target);
5097
5098    while (parent)
5099      {
5100         if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
5101           {
5102              evas_object_geometry_get(parent, &wx, &wy, NULL, NULL);
5103              eo_do(parent, elm_interface_scrollable_content_size_get(&ww, &wh));
5104              eo_do(parent, elm_interface_scrollable_content_pos_get(&nx, &ny));
5105
5106              /* widget implements scrollable interface but does not use scoller
5107                 in this case, use widget geometry */
5108              if (ww == 0 || wh == 0)
5109                {
5110                   INF("%s is zero sized scrollable content", eo_class_name_get(eo_class_get(parent)));
5111                   evas_object_geometry_get(parent, NULL, NULL, &ww, &wh);
5112                }
5113
5114              wx -= nx;
5115              wy -= ny;
5116
5117              if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
5118                  ((wy < y) && (wy + wh < y)) || ((wy > y + h) && (wy + wh > y + h)))
5119                return EINA_FALSE;
5120
5121              break;
5122           }
5123         parent = elm_widget_parent_get(parent);
5124      }
5125
5126    return EINA_TRUE;
5127 }
5128 //
5129
5130 EOLIAN static Elm_Atspi_State_Set
5131 _elm_widget_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_item,
5132                                                               Elm_Widget_Item_Data *item)
5133 {
5134    Elm_Atspi_State_Set states = 0;
5135
5136    STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
5137
5138    if (elm_object_item_focus_get(eo_item))
5139      STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
5140    if (!elm_object_item_disabled_get(eo_item))
5141      {
5142         STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
5143         STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
5144      }
5145    if (_elm_widget_item_onscreen_is(eo_item))
5146      STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
5147
5148    //TIZEN_ONLY(20170207) : [ATSPI] enhance expose highlight information on atspi
5149    /* unrealized genlist item does not have item->view,
5150       and item cannot change its visibility, only widget can change the visibility */
5151    if (evas_object_visible_get(item->widget))
5152      STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
5153    //
5154
5155    //TIZEN_ONLY(20170717) : expose highlight information on atspi
5156    if (_elm_widget_item_highlightable(eo_item) && _accessible_object_on_scroll_is(item->view))
5157      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
5158    else
5159      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
5160
5161    if (_elm_object_accessibility_currently_highlighted_get() == (void*)item->eo_obj)
5162      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
5163    //
5164    return states;
5165 }
5166
5167 EOLIAN static Eo*
5168 _elm_widget_item_elm_interface_atspi_accessible_parent_get(Eo *eo_item, Elm_Widget_Item_Data *item EINA_UNUSED)
5169 {
5170    Eo *parent;
5171    eo_do(eo_item, parent = eo_parent_get());
5172    return parent;
5173 }
5174
5175 EAPI void
5176 elm_object_item_data_set(Elm_Object_Item *it, void *data)
5177 {
5178    WIDGET_ITEM_DATA_SET(it, data);
5179 }
5180
5181 EAPI void *
5182 elm_object_item_data_get(const Elm_Object_Item *it)
5183 {
5184    return (void *) WIDGET_ITEM_DATA_GET(it);
5185 }
5186
5187 EOLIAN static void
5188 _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED,
5189                               Elm_Widget_Item_Data *item,
5190                               Eina_Bool disabled)
5191 {
5192    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5193    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5194
5195    if (item->disabled == disabled) return;
5196    item->disabled = !!disabled;
5197    eo_do(item->eo_obj, elm_wdg_item_disable());
5198 }
5199
5200 EOLIAN static Eina_Bool
5201 _elm_widget_item_disabled_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5202 {
5203    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5204    return item->disabled;
5205 }
5206
5207 EOLIAN static void
5208 _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style EINA_UNUSED)
5209 {
5210    ERR_NOT_SUPPORTED(item, "elm_object_style_set()");
5211 }
5212
5213 EOLIAN static const char *
5214 _elm_widget_item_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5215 {
5216    ERR_NOT_SUPPORTED(item, "elm_object_style_get()");
5217    return NULL;
5218 }
5219
5220 EOLIAN static void
5221 _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
5222 {
5223 }
5224
5225 EOLIAN static void
5226 _elm_widget_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED)
5227 {
5228    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set");
5229 }
5230
5231 EOLIAN static Eina_Bool
5232 _elm_widget_item_focus_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5233 {
5234    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get");
5235    return EINA_FALSE;
5236 }
5237
5238 EOLIAN static void
5239 _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED,
5240                                                    Elm_Widget_Item_Data *item,
5241                                                    const char *part,
5242                                                    const char *domain,
5243                                                    const char *label)
5244 {
5245    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5246    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5247    Elm_Translate_String_Data *ts;
5248
5249    if (!label)
5250      {
5251         _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE,
5252                                     EINA_FALSE);
5253      }
5254    else
5255      {
5256         ts = _part_text_translatable_set(&item->translate_strings, part,
5257                                          EINA_TRUE, EINA_FALSE);
5258         if (!ts) return;
5259         if (!ts->string) ts->string = eina_stringshare_add(label);
5260         else eina_stringshare_replace(&ts->string, label);
5261         if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5262         else eina_stringshare_replace(&ts->domain, domain);
5263 #ifdef HAVE_GETTEXT
5264         if (label[0]) label = dgettext(domain, label);
5265 #endif
5266      }
5267    item->on_translate = EINA_TRUE;
5268    eo_do(item->eo_obj, elm_wdg_item_part_text_set(part, label));
5269    item->on_translate = EINA_FALSE;
5270 }
5271
5272 EOLIAN static const char *
5273 _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED,
5274                                             Elm_Widget_Item_Data *item,
5275                                             const char *part)
5276 {
5277    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5278    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5279
5280    Elm_Translate_String_Data *ts;
5281    ts = _translate_string_data_get(item->translate_strings, part);
5282    if (ts) return ts->string;
5283    return NULL;
5284 }
5285
5286 EOLIAN static void
5287 _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED,
5288                                                    Elm_Widget_Item_Data *item,
5289                                                    const char *part,
5290                                                    const char *domain,
5291                                                    Eina_Bool translatable)
5292 {
5293    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5294    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5295    Elm_Translate_String_Data *ts;
5296    const char *text;
5297
5298    ts = _part_text_translatable_set(&item->translate_strings, part,
5299                                     translatable, EINA_TRUE);
5300    if (!ts) return;
5301    if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5302    else eina_stringshare_replace(&ts->domain, domain);
5303
5304    eo_do(item->eo_obj, text = elm_wdg_item_part_text_get(part));
5305
5306    if (!text || !text[0]) return;
5307
5308    if (!ts->string) ts->string = eina_stringshare_add(text);
5309
5310 //Try to translate text since we don't know the text is already translated.
5311 #ifdef HAVE_GETTEXT
5312    text = dgettext(domain, text);
5313 #endif
5314    item->on_translate = EINA_TRUE;
5315    eo_do (item->eo_obj, elm_wdg_item_part_text_set(part, text));
5316    item->on_translate = EINA_FALSE;
5317 }
5318
5319 EOLIAN static void
5320 _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5321 {
5322    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5323    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5324
5325    if (!item->track_obj) return;
5326
5327    while (evas_object_ref_get(item->track_obj) > 0)
5328      evas_object_unref(item->track_obj);
5329
5330    evas_object_del(item->track_obj);
5331 }
5332
5333 EOLIAN static Evas_Object *
5334 _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5335 {
5336    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5337    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5338
5339    if (item->track_obj)
5340      {
5341         evas_object_ref(item->track_obj);
5342         return item->track_obj;
5343      }
5344
5345    if (!item->view)
5346      {
5347         WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item);
5348         return NULL;
5349      }
5350
5351    Evas_Object *track =
5352       evas_object_rectangle_add(evas_object_evas_get(item->widget));
5353    evas_object_color_set(track, 0, 0, 0, 0);
5354    evas_object_pass_events_set(track, EINA_TRUE);
5355    _track_obj_update(track, item->view);
5356    evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del,
5357                                   item);
5358
5359    eo_do(item->view,
5360          eo_event_callback_array_add(tracker_callbacks(), item));
5361
5362    evas_object_ref(track);
5363
5364    item->track_obj = track;
5365
5366    return track;
5367 }
5368
5369 EOLIAN static void
5370 _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5371 {
5372    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5373    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5374
5375    if (!item->track_obj) return;
5376    evas_object_unref(item->track_obj);
5377
5378    if (evas_object_ref_get(item->track_obj) == 0)
5379      evas_object_del(item->track_obj);
5380 }
5381
5382 EOLIAN static int
5383 _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5384 {
5385    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0);
5386    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0);
5387
5388    if (!item->track_obj) return 0;
5389    return evas_object_ref_get(item->track_obj);
5390 }
5391
5392 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
5393
5394 struct _Elm_Widget_Item_Tooltip
5395 {
5396    Elm_Widget_Item_Data       *item;
5397    Elm_Tooltip_Item_Content_Cb func;
5398    Evas_Smart_Cb               del_cb;
5399    const void                 *data;
5400 };
5401
5402 static Evas_Object *
5403 _elm_widget_item_tooltip_label_create(void *data,
5404                                       Evas_Object *obj EINA_UNUSED,
5405                                       Evas_Object *tooltip,
5406                                       void *item EINA_UNUSED)
5407 {
5408    Evas_Object *label = elm_label_add(tooltip);
5409    if (!label)
5410      return NULL;
5411    elm_object_style_set(label, "tooltip");
5412    elm_object_text_set(label, data);
5413    return label;
5414 }
5415
5416 static Evas_Object *
5417 _elm_widget_item_tooltip_trans_label_create(void *data,
5418                                             Evas_Object *obj EINA_UNUSED,
5419                                             Evas_Object *tooltip,
5420                                             void *item EINA_UNUSED)
5421 {
5422    Evas_Object *label = elm_label_add(tooltip);
5423    if (!label)
5424      return NULL;
5425    elm_object_style_set(label, "tooltip");
5426    elm_object_translatable_text_set(label, data);
5427    return label;
5428 }
5429
5430 static void
5431 _elm_widget_item_tooltip_label_del_cb(void *data,
5432                                       Evas_Object *obj EINA_UNUSED,
5433                                       void *event_info EINA_UNUSED)
5434 {
5435    eina_stringshare_del(data);
5436 }
5437
5438 /**
5439  * @internal
5440  *
5441  * Set the text to be shown in the widget item.
5442  *
5443  * @param item Target item
5444  * @param text The text to set in the content
5445  *
5446  * Setup the text as tooltip to object. The item can have only one tooltip,
5447  * so any previous tooltip data is removed.
5448  *
5449  * @ingroup Widget
5450  */
5451 EOLIAN static void
5452 _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED,
5453                                   Elm_Widget_Item_Data *item EINA_UNUSED,
5454                                   const char *text)
5455 {
5456    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5457    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5458    EINA_SAFETY_ON_NULL_RETURN(text);
5459
5460    text = eina_stringshare_add(text);
5461    eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5462             _elm_widget_item_tooltip_label_create,
5463             text,
5464             _elm_widget_item_tooltip_label_del_cb));
5465 }
5466
5467 EOLIAN static void
5468 _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED,
5469                                                Elm_Widget_Item_Data *item EINA_UNUSED,
5470                                                const char *text)
5471 {
5472    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5473    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5474    EINA_SAFETY_ON_NULL_RETURN(text);
5475
5476    text = eina_stringshare_add(text);
5477    eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5478             _elm_widget_item_tooltip_trans_label_create,
5479             text,
5480             _elm_widget_item_tooltip_label_del_cb));
5481 }
5482
5483 static Evas_Object *
5484 _elm_widget_item_tooltip_create(void *data,
5485                                 Evas_Object *obj,
5486                                 Evas_Object *tooltip)
5487 {
5488    Elm_Widget_Item_Tooltip *wit = data;
5489    return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj);
5490 }
5491
5492 static void
5493 _elm_widget_item_tooltip_del_cb(void *data,
5494                                 Evas_Object *obj,
5495                                 void *event_info EINA_UNUSED)
5496 {
5497    Elm_Widget_Item_Tooltip *wit = data;
5498    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj);
5499    free(wit);
5500 }
5501
5502 /**
5503  * @internal
5504  *
5505  * Set the content to be shown in the tooltip item
5506  *
5507  * Setup the tooltip to item. The item can have only one tooltip,
5508  * so any previous tooltip data is removed. @p func(with @p data) will
5509  * be called every time that need show the tooltip and it should
5510  * return a valid Evas_Object. This object is then managed fully by
5511  * tooltip system and is deleted when the tooltip is gone.
5512  *
5513  * @param item the widget item being attached a tooltip.
5514  * @param func the function used to create the tooltip contents.
5515  * @param data what to provide to @a func as callback data/context.
5516  * @param del_cb called when data is not needed anymore, either when
5517  *        another callback replaces @func, the tooltip is unset with
5518  *        elm_widget_item_tooltip_unset() or the owner @a item
5519  *        dies. This callback receives as the first parameter the
5520  *        given @a data, and @c event_info is the item.
5521  *
5522  * @ingroup Widget
5523  */
5524 EOLIAN static void
5525 _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED,
5526                                         Elm_Widget_Item_Data *item,
5527                                         Elm_Tooltip_Item_Content_Cb func,
5528                                         const void *data,
5529                                         Evas_Smart_Cb del_cb)
5530 {
5531    Elm_Widget_Item_Tooltip *wit;
5532
5533    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
5534    //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem);
5535
5536    if (!func)
5537      {
5538         eo_do(item->eo_obj, elm_wdg_item_tooltip_unset());
5539         return;
5540      }
5541
5542    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
5543    if (!wit) goto error;
5544    wit->item = item;
5545    wit->func = func;
5546    wit->data = data;
5547    wit->del_cb = del_cb;
5548
5549    elm_object_sub_tooltip_content_cb_set
5550      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
5551      _elm_widget_item_tooltip_del_cb);
5552
5553    return;
5554
5555 error_noitem:
5556    if (del_cb) del_cb((void *)data, NULL, item);
5557    return;
5558 error:
5559    if (del_cb) del_cb((void *)data, item->widget, item);
5560 }
5561
5562 /**
5563  * @internal
5564  *
5565  * Unset tooltip from item
5566  *
5567  * @param item widget item to remove previously set tooltip.
5568  *
5569  * Remove tooltip from item. The callback provided as del_cb to
5570  * elm_widget_item_tooltip_content_cb_set() will be called to notify
5571  * it is not used anymore.
5572  *
5573  * @see elm_widget_item_tooltip_content_cb_set()
5574  *
5575  * @ingroup Widget
5576  */
5577 EOLIAN static void
5578 _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5579 {
5580    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5581    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5582
5583    elm_object_tooltip_unset(item->view);
5584 }
5585
5586 /**
5587  * @internal
5588  *
5589  * Sets a different style for this item tooltip.
5590  *
5591  * @note before you set a style you should define a tooltip with
5592  *       elm_widget_item_tooltip_content_cb_set() or
5593  *       elm_widget_item_tooltip_text_set()
5594  *
5595  * @param item widget item with tooltip already set.
5596  * @param style the theme style to use (default, transparent, ...)
5597  *
5598  * @ingroup Widget
5599  */
5600 EOLIAN static void
5601 _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED,
5602                                    Elm_Widget_Item_Data *item,
5603                                    const char *style)
5604 {
5605    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5606    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5607
5608    elm_object_tooltip_style_set(item->view, style);
5609 }
5610
5611 EOLIAN static Eina_Bool
5612 _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED,
5613                                          Elm_Widget_Item_Data *item,
5614                                          Eina_Bool disable)
5615 {
5616    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5617    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5618
5619    return elm_object_tooltip_window_mode_set(item->view, disable);
5620 }
5621
5622 EOLIAN static Eina_Bool
5623 _elm_widget_item_tooltip_window_mode_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5624 {
5625    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5626    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5627
5628    return elm_object_tooltip_window_mode_get(item->view);
5629 }
5630
5631 /**
5632  * @internal
5633  *
5634  * Get the style for this item tooltip.
5635  *
5636  * @param item widget item with tooltip already set.
5637  * @return style the theme style in use, defaults to "default". If the
5638  *         object does not have a tooltip set, then NULL is returned.
5639  *
5640  * @ingroup Widget
5641  */
5642 EOLIAN static const char *
5643 _elm_widget_item_tooltip_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5644 {
5645    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5646
5647    return elm_object_tooltip_style_get(item->view);
5648 }
5649
5650 EOLIAN static void
5651 _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED,
5652                             Elm_Widget_Item_Data *item,
5653                             const char *cursor)
5654 {
5655    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5656    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5657
5658    elm_object_sub_cursor_set(item->view, item->widget, cursor);
5659 }
5660
5661 EOLIAN static const char *
5662 _elm_widget_item_cursor_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5663 {
5664    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5665    return elm_object_cursor_get(item->view);
5666 }
5667
5668 EOLIAN static void
5669 _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5670 {
5671    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5672    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5673
5674    elm_object_cursor_unset(item->view);
5675 }
5676
5677 /**
5678  * @internal
5679  *
5680  * Sets a different style for this item cursor.
5681  *
5682  * @note before you set a style you should define a cursor with
5683  *       elm_widget_item_cursor_set()
5684  *
5685  * @param item widget item with cursor already set.
5686  * @param style the theme style to use (default, transparent, ...)
5687  *
5688  * @ingroup Widget
5689  */
5690 EOLIAN static void
5691 _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED,
5692                                   Elm_Widget_Item_Data *item,
5693                                   const char *style)
5694 {
5695    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5696    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5697
5698    elm_object_cursor_style_set(item->view, style);
5699 }
5700
5701 /**
5702  * @internal
5703  *
5704  * Get the style for this item cursor.
5705  *
5706  * @param item widget item with cursor already set.
5707  * @return style the theme style in use, defaults to "default". If the
5708  *         object does not have a cursor set, then NULL is returned.
5709  *
5710  * @ingroup Widget
5711  */
5712 EOLIAN static const char *
5713 _elm_widget_item_cursor_style_get(Eo *eo_item EINA_UNUSED,
5714                                   Elm_Widget_Item_Data *item)
5715 {
5716    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5717    return elm_object_cursor_style_get(item->view);
5718 }
5719
5720 /**
5721  * @internal
5722  *
5723  * Set if the cursor set should be searched on the theme or should use
5724  * the provided by the engine, only.
5725  *
5726  * @note before you set if should look on theme you should define a cursor
5727  * with elm_object_cursor_set(). By default it will only look for cursors
5728  * provided by the engine.
5729  *
5730  * @param item widget item with cursor already set.
5731  * @param engine_only boolean to define it cursors should be looked only
5732  * between the provided by the engine or searched on widget's theme as well.
5733  *
5734  * @ingroup Widget
5735  */
5736 EOLIAN static void
5737 _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED,
5738                                         Elm_Widget_Item_Data *item,
5739                                         Eina_Bool engine_only)
5740 {
5741    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5742    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5743
5744    elm_object_cursor_theme_search_enabled_set(item->view, !engine_only);
5745 }
5746
5747 /**
5748  * @internal
5749  *
5750  * Get the cursor engine only usage for this item cursor.
5751  *
5752  * @param item widget item with cursor already set.
5753  * @return engine_only boolean to define it cursors should be looked only
5754  * between the provided by the engine or searched on widget's theme as well. If
5755  *         the object does not have a cursor set, then EINA_FALSE is returned.
5756  *
5757  * @ingroup Widget
5758  */
5759 EOLIAN static Eina_Bool
5760 _elm_widget_item_cursor_engine_only_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5761 {
5762    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5763    return !elm_object_cursor_theme_search_enabled_get(item->view);
5764 }
5765
5766 EOLIAN static void
5767 _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED,
5768                                   Elm_Widget_Item_Data *item,
5769                                   const char *part EINA_UNUSED,
5770                                   Evas_Object *content EINA_UNUSED)
5771 {
5772    ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()");
5773 }
5774
5775 EOLIAN static Evas_Object *
5776 _elm_widget_item_part_content_get(Eo *eo_item EINA_UNUSED,
5777                                   Elm_Widget_Item_Data *item,
5778                                   const char *part EINA_UNUSED)
5779 {
5780    ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()");
5781    return NULL;
5782 }
5783
5784 EOLIAN static Evas_Object *
5785 _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED,
5786                                     Elm_Widget_Item_Data *item,
5787                                     const char *part EINA_UNUSED)
5788 {
5789    ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()");
5790    return NULL;
5791 }
5792
5793 EOLIAN static void
5794 _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
5795                                Elm_Widget_Item_Data *item,
5796                                const char *part EINA_UNUSED,
5797                                const char *label EINA_UNUSED)
5798 {
5799    ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()");
5800 }
5801
5802 EOLIAN static const char *
5803 _elm_widget_item_part_text_get(Eo *eo_item EINA_UNUSED,
5804                                Elm_Widget_Item_Data *item,
5805                                const char *part EINA_UNUSED)
5806 {
5807    ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()");
5808    return NULL;
5809 }
5810
5811 static void
5812 _elm_widget_item_part_text_custom_free(void *data)
5813 {
5814    Elm_Label_Data *label;
5815    label = data;
5816    eina_stringshare_del(label->part);
5817    eina_stringshare_del(label->text);
5818    free(label);
5819 }
5820
5821 EOLIAN static void
5822 _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED,
5823                                       Elm_Widget_Item_Data *item,
5824                                       const char *part,
5825                                       const char *text)
5826 {
5827    Elm_Label_Data *label;
5828    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5829    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5830
5831    if (!item->labels)
5832      item->labels =
5833         eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free);
5834    label = eina_hash_find(item->labels, part);
5835    if (!label)
5836      {
5837         label = malloc(sizeof(Elm_Label_Data));
5838         if (!label)
5839           {
5840              ERR("Failed to allocate memory");
5841              return;
5842           }
5843         label->part = eina_stringshare_add(part);
5844         label->text = eina_stringshare_add(text);
5845         eina_hash_add(item->labels, part, label);
5846      }
5847    else
5848      eina_stringshare_replace(&label->text, text);
5849 }
5850
5851 EOLIAN static const char *
5852 _elm_widget_item_part_text_custom_get(Eo *eo_item EINA_UNUSED,
5853                                       Elm_Widget_Item_Data *item,
5854                                       const char *part)
5855 {
5856    Elm_Label_Data *label;
5857    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5858    label = eina_hash_find(item->labels, part);
5859    return label ? label->text : NULL;
5860 }
5861
5862 static Eina_Bool
5863 _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED,
5864                                           const void *key EINA_UNUSED,
5865                                           void *data,
5866                                           void *func_data)
5867 {
5868    Elm_Label_Data *label;
5869    Elm_Widget_Item_Data *item;
5870    label = data;
5871    item = func_data;
5872
5873    eo_do(item->eo_obj, elm_wdg_item_part_text_set(label->part, label->text));
5874
5875    return EINA_TRUE;
5876 }
5877
5878 EOLIAN static void
5879 _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5880 {
5881    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5882    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5883    if (item->labels)
5884      eina_hash_foreach(item->labels,
5885                        _elm_widget_item_part_text_custom_foreach, item);
5886 }
5887
5888 EOLIAN static void
5889 _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
5890                              Elm_Widget_Item_Data *item EINA_UNUSED,
5891                              const char *emission EINA_UNUSED,
5892                              const char *source EINA_UNUSED)
5893 {
5894
5895 }
5896
5897 EOLIAN static void
5898 _elm_widget_item_signal_callback_add(Eo *eo_item,
5899                                      Elm_Widget_Item_Data *item,
5900                                      const char *emission,
5901                                      const char *source,
5902                                      Elm_Object_Item_Signal_Cb func,
5903                                      void *data)
5904 {
5905    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5906    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5907    EINA_SAFETY_ON_NULL_RETURN(func);
5908
5909    Elm_Widget_Item_Signal_Data *wisd;
5910
5911    wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
5912    if (!wisd) return;
5913
5914    wisd->item = eo_item;
5915    wisd->func = (Elm_Widget_Item_Signal_Cb)func;
5916    wisd->data = data;
5917    wisd->emission = eina_stringshare_add(emission);
5918    wisd->source = eina_stringshare_add(source);
5919
5920    if (_elm_widget_is(item->view))
5921      elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5922    else if (eo_isa(item->view, EDJE_OBJECT_CLASS))
5923      edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5924    else
5925      {
5926         WRN("The %s widget item doesn't support signal callback add!",
5927             eo_class_name_get(eo_class_get(item->widget)));
5928         free(wisd);
5929         return;
5930      }
5931
5932    item->signals = eina_list_append(item->signals, wisd);
5933 }
5934
5935 EOLIAN static void *
5936 _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED,
5937                                      Elm_Widget_Item_Data *item,
5938                                      const char *emission,
5939                                      const char *source,
5940                                      Elm_Object_Item_Signal_Cb func)
5941 {
5942    Elm_Widget_Item_Signal_Data *wisd;
5943    Eina_List *l;
5944
5945    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5946    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5947    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
5948
5949    EINA_LIST_FOREACH(item->signals, l, wisd)
5950      {
5951         if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) &&
5952             !strcmp(wisd->emission, emission) &&
5953             !strcmp(wisd->source, source))
5954           return _elm_widget_item_signal_callback_list_get(item, l);
5955      }
5956
5957    return NULL;
5958 }
5959
5960 EOLIAN static void
5961 _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED,
5962                                  Elm_Widget_Item_Data *item,
5963                                  const char *txt)
5964 {
5965    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5966    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5967
5968    eina_stringshare_del(item->access_info);
5969    if (!txt) item->access_info = NULL;
5970    else item->access_info = eina_stringshare_add(txt);
5971 }
5972
5973 EOLIAN static void
5974 _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5975 {
5976    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5977    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5978
5979 #ifdef HAVE_GETTEXT
5980    Elm_Translate_String_Data *ts;
5981    EINA_INLIST_FOREACH(item->translate_strings, ts)
5982      {
5983         if (!ts->string) continue;
5984         const char *s = dgettext(ts->domain, ts->string);
5985         item->on_translate = EINA_TRUE;
5986         eo_do(item->eo_obj, elm_wdg_item_part_text_set(ts->id, s));
5987         item->on_translate = EINA_FALSE;
5988      }
5989 #endif
5990 }
5991
5992 EOLIAN static void
5993 _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED,
5994                                   Elm_Widget_Item_Data *item,
5995                                   Eina_List *objs)
5996 {
5997    _elm_access_widget_item_access_order_set(item, objs);
5998 }
5999
6000 EOLIAN static const Eina_List *
6001 _elm_widget_item_access_order_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
6002 {
6003    return _elm_access_widget_item_access_order_get(item);
6004 }
6005
6006 EOLIAN static void
6007 _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
6008 {
6009    _elm_access_widget_item_access_order_unset(item);
6010 }
6011
6012 EOLIAN static Evas_Object*
6013 _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
6014 {
6015    _elm_access_widget_item_register(item);
6016    return item->access_obj;
6017 }
6018
6019 EOLIAN static void
6020 _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
6021 {
6022    _elm_access_widget_item_unregister(item);
6023 }
6024
6025 EOLIAN static Evas_Object*
6026 _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
6027 {
6028    return item->access_obj;
6029 }
6030
6031 EOLIAN static Evas_Object *
6032 _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
6033 {
6034    Evas_Object *ret = NULL;
6035
6036    if (dir == ELM_FOCUS_PREVIOUS)
6037      ret = item->focus_previous;
6038    else if (dir == ELM_FOCUS_NEXT)
6039      ret = item->focus_next;
6040    else if (dir == ELM_FOCUS_UP)
6041      ret = item->focus_up;
6042    else if (dir == ELM_FOCUS_DOWN)
6043      ret = item->focus_down;
6044    else if (dir == ELM_FOCUS_RIGHT)
6045      ret = item->focus_right;
6046    else if (dir == ELM_FOCUS_LEFT)
6047      ret = item->focus_left;
6048
6049    return ret;
6050 }
6051
6052 EOLIAN static void
6053 _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir)
6054 {
6055    if (dir == ELM_FOCUS_PREVIOUS)
6056      item->focus_previous = next;
6057    else if (dir == ELM_FOCUS_NEXT)
6058      item->focus_next = next;
6059    else if (dir == ELM_FOCUS_UP)
6060      item->focus_up = next;
6061    else if (dir == ELM_FOCUS_DOWN)
6062      item->focus_down = next;
6063    else if (dir == ELM_FOCUS_RIGHT)
6064      item->focus_right = next;
6065    else if (dir == ELM_FOCUS_LEFT)
6066      item->focus_left = next;
6067 }
6068
6069 EOLIAN static Elm_Object_Item*
6070 _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
6071 {
6072    Elm_Object_Item *ret = NULL;
6073
6074    if (dir == ELM_FOCUS_PREVIOUS)
6075      ret = item->item_focus_previous;
6076    else if (dir == ELM_FOCUS_NEXT)
6077      ret = item->item_focus_next;
6078    else if (dir == ELM_FOCUS_UP)
6079      ret = item->item_focus_up;
6080    else if (dir == ELM_FOCUS_DOWN)
6081      ret = item->item_focus_down;
6082    else if (dir == ELM_FOCUS_RIGHT)
6083      ret = item->item_focus_right;
6084    else if (dir == ELM_FOCUS_LEFT)
6085      ret = item->item_focus_left;
6086
6087    return ret;
6088 }
6089
6090 EOLIAN static void
6091 _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)
6092 {
6093    if (dir == ELM_FOCUS_PREVIOUS)
6094      item->item_focus_previous = next_item;
6095    else if (dir == ELM_FOCUS_NEXT)
6096      item->item_focus_next = next_item;
6097    else if (dir == ELM_FOCUS_UP)
6098      item->item_focus_up = next_item;
6099    else if (dir == ELM_FOCUS_DOWN)
6100      item->item_focus_down = next_item;
6101    else if (dir == ELM_FOCUS_RIGHT)
6102      item->item_focus_right = next_item;
6103    else if (dir == ELM_FOCUS_LEFT)
6104      item->item_focus_left = next_item;
6105 }
6106
6107 /* happy debug functions */
6108 #ifdef ELM_DEBUG
6109 static void
6110 _sub_obj_tree_dump(const Evas_Object *obj,
6111                    int lvl)
6112 {
6113    int i;
6114
6115    for (i = 0; i < lvl * 3; i++)
6116      putchar(' ');
6117
6118    if (_elm_widget_is(obj))
6119      {
6120         Eina_List *l;
6121         INTERNAL_ENTRY;
6122         DBG("+ %s(%p)\n",
6123             elm_widget_type_get(obj),
6124             obj);
6125         EINA_LIST_FOREACH(sd->subobjs, l, obj)
6126           _sub_obj_tree_dump(obj, lvl + 1);
6127      }
6128    else
6129      DBG("+ %s(%p)\n", evas_object_type_get(obj), obj);
6130 }
6131
6132 static void
6133 _sub_obj_tree_dot_dump(const Evas_Object *obj,
6134                        FILE *output)
6135 {
6136    if (!_elm_widget_is(obj))
6137      return;
6138    INTERNAL_ENTRY;
6139
6140    Eina_Bool visible = evas_object_visible_get(obj);
6141    Eina_Bool disabled = elm_widget_disabled_get(obj);
6142    Eina_Bool focused = elm_widget_focus_get(obj);
6143    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
6144
6145    if (sd->parent_obj)
6146      {
6147         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
6148
6149         if (focused)
6150           fprintf(output, ", style=bold");
6151
6152         if (!visible)
6153           fprintf(output, ", color=gray28");
6154
6155         fprintf(output, " ];\n");
6156      }
6157
6158    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
6159                    "disabled: %d|focused: %d/%d|focus order:%d}\"",
6160            obj, obj, elm_widget_type_get(obj),
6161            evas_object_name_get(obj), visible, disabled, focused, can_focus,
6162            sd->focus_order);
6163
6164    if (focused)
6165      fprintf(output, ", style=bold");
6166
6167    if (!visible)
6168      fprintf(output, ", fontcolor=gray28");
6169
6170    if ((disabled) || (!visible))
6171      fprintf(output, ", color=gray");
6172
6173    fprintf(output, " ];\n");
6174
6175    Eina_List *l;
6176    Evas_Object *o;
6177    EINA_LIST_FOREACH(sd->subobjs, l, o)
6178      _sub_obj_tree_dot_dump(o, output);
6179 }
6180
6181 #endif
6182
6183 EAPI void
6184 elm_widget_tree_dump(const Evas_Object *top)
6185 {
6186 #ifdef ELM_DEBUG
6187    if (!_elm_widget_is(top))
6188      return;
6189    _sub_obj_tree_dump(top, 0);
6190 #else
6191    (void)top;
6192    return;
6193 #endif
6194 }
6195
6196 EAPI void
6197 elm_widget_tree_dot_dump(const Evas_Object *top,
6198                          FILE *output)
6199 {
6200 #ifdef ELM_DEBUG
6201    if (!_elm_widget_is(top))
6202      return;
6203    fprintf(output, "graph " " { node [shape=record];\n");
6204    _sub_obj_tree_dot_dump(top, output);
6205    fprintf(output, "}\n");
6206 #else
6207    (void)top;
6208    (void)output;
6209    return;
6210 #endif
6211 }
6212
6213 EOLIAN static Eo *
6214 _elm_widget_eo_base_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
6215 {
6216    Eo *parent = NULL;
6217
6218    sd->on_create = EINA_TRUE;
6219    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
6220    eo_do(obj,
6221          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
6222          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
6223          parent = eo_parent_get());
6224    eo_do(obj, elm_obj_widget_parent_set(parent));
6225    sd->on_create = EINA_FALSE;
6226    //TIZEN_ONLY(20170717) : expose highlight information on atspi
6227    sd->can_highlight = EINA_TRUE;
6228    //
6229    /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
6230    sd->inherit_paragraph_direction = EINA_TRUE;
6231    /* END */
6232
6233    eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_UNKNOWN));
6234
6235    /* TIZEN_ONLY(20161117): Inherit paragraph direction from widget parent */
6236    if (sd->paragraph_direction != evas_object_paragraph_direction_get(parent))
6237      {
6238         sd->paragraph_direction = evas_object_paragraph_direction_get(parent);
6239         _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, sd->paragraph_direction);
6240         eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(sd->paragraph_direction));
6241      }
6242    /* END */
6243
6244    return obj;
6245 }
6246
6247 EOLIAN static void
6248 _elm_widget_eo_base_destructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
6249 {
6250    sd->on_destroy = EINA_TRUE;
6251    eo_do(obj,
6252          elm_interface_atspi_accessible_description_set(NULL),
6253          elm_interface_atspi_accessible_name_set(NULL),
6254          //TIZEN_ONLY(20190922): add name callback, description callback.
6255          elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
6256          elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
6257          //
6258          //TIZEN_ONLY(20170405) Add gesture method to accessible interface
6259          elm_interface_atspi_accessible_gesture_cb_set(NULL, NULL),
6260          //
6261          elm_interface_atspi_accessible_translation_domain_set(NULL),
6262          elm_interface_atspi_accessible_relationships_clear(),
6263          // TIZEN_ONLY(20160930) : endless recursion fix
6264          elm_interface_atspi_accessible_attributes_clear()
6265          //
6266          );
6267    // TIZEN_ONLY(20150709) : atspi relations api
6268    if (sd->atspi_custom_relations)
6269      elm_atspi_relation_set_free(&sd->atspi_custom_relations);
6270    //
6271    //TIZEN_ONLY(20150717) add widget name setter
6272    if (sd->name)
6273      eina_stringshare_del(sd->name);
6274    //
6275
6276    //TIZEN_ONLY(20150731) : add i18n support for name and description
6277    if (sd->atspi_translation_domain)
6278      eina_stringshare_del(sd->atspi_translation_domain);
6279    //
6280    //Tizen Only(20160728) free attribute list
6281    if (sd->attr_list)
6282    {
6283       Elm_Atspi_Attribute *attr;
6284       EINA_LIST_FREE(sd->attr_list, attr)
6285        {
6286           eina_stringshare_del(attr->key);
6287           eina_stringshare_del(attr->value);
6288           free(attr);
6289        }
6290    }
6291    //
6292
6293    eo_do_super(obj, ELM_WIDGET_CLASS, eo_destructor());
6294    sd->on_destroy = EINA_FALSE;
6295
6296    elm_interface_atspi_accessible_removed(obj);
6297 }
6298
6299 EOLIAN static Eina_Bool
6300 _elm_widget_on_focus(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item EINA_UNUSED)
6301 {
6302    if (elm_widget_can_focus_get(obj))
6303      {
6304         if (elm_widget_focus_get(obj))
6305           {
6306              if (!sd->resize_obj)
6307                evas_object_focus_set(obj, EINA_TRUE);
6308               eo_do(obj, eo_event_callback_call
6309                (ELM_WIDGET_EVENT_FOCUSED, NULL));
6310              if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6311                elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_TRUE);
6312           }
6313         else
6314           {
6315              if (!sd->resize_obj)
6316                evas_object_focus_set(obj, EINA_FALSE);
6317              eo_do(obj, eo_event_callback_call
6318                (ELM_WIDGET_EVENT_UNFOCUSED, NULL));
6319              if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6320                elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_FALSE);
6321     }
6322      }
6323    else
6324      return EINA_FALSE;
6325
6326    return EINA_TRUE;
6327 }
6328
6329 EOLIAN static Eina_Bool
6330 _elm_widget_disable(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6331 {
6332    return EINA_FALSE;
6333 }
6334
6335 EOLIAN static Eina_Bool
6336 _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)
6337 {
6338    return EINA_FALSE;
6339 }
6340
6341 EOLIAN static Eina_Bool
6342 _elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6343 {
6344    WRN("The %s widget does not implement the \"focus_next/focus_next_manager_is\" functions.",
6345        eo_class_name_get(eo_class_get(obj)));
6346    return EINA_FALSE;
6347 }
6348
6349 static Eina_Bool
6350 _elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6351 {
6352    WRN("The %s widget does not implement the \"focus_direction/focus_direction_manager_is\" functions.",
6353        eo_class_name_get(eo_class_get(obj)));
6354    return EINA_FALSE;
6355 }
6356
6357 EOLIAN static Eina_Bool
6358 _elm_widget_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Activate act EINA_UNUSED)
6359 {
6360    WRN("The %s widget does not implement the \"activate\" functions.",
6361        eo_class_name_get(eo_class_get(obj)));
6362    return EINA_TRUE;
6363 }
6364
6365 EOLIAN static void
6366 _elm_widget_class_constructor(Eo_Class *klass)
6367 {
6368    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
6369 }
6370
6371 EOLIAN static Eina_Bool
6372 _elm_widget_elm_interface_atspi_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6373 {
6374    if (elm_object_focus_allow_get(obj))
6375      {
6376        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
6377        if (!ee) return EINA_FALSE;
6378        ecore_evas_activate(ee);
6379        elm_object_focus_set(obj, EINA_TRUE);
6380        return EINA_TRUE;
6381      }
6382    return EINA_FALSE;
6383 }
6384
6385 //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
6386 void
6387 _elm_widget_showing_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
6388 {
6389    Evas_Object *parent;
6390    Evas_Coord px, py, sx, sy, sw, sh;
6391
6392    *x = 0;
6393    *y = 0;
6394    *w = 0;
6395    *h = 0;
6396
6397    if (!obj) return;
6398
6399    evas_object_geometry_get(obj, x, y, w, h);
6400
6401    if (elm_widget_is(obj))
6402      parent = elm_widget_parent_get(obj);
6403    else
6404      parent = elm_widget_parent_widget_get(obj);
6405
6406    while (parent)
6407      {
6408         if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
6409           {
6410              evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
6411              px = *x;
6412              py = *y;
6413              *x = *x > sx ? *x : sx;
6414              *y = *y > sy ? *y : sy;
6415              *w = px + *w < sx + sw ? px + *w - *x : sx + sw - *x;
6416              *h = py + *h < sy + sh ? py + *h - *y : sy + sh - *y;
6417           }
6418         parent = elm_widget_parent_get(parent);
6419      }
6420 }
6421
6422 Eina_Bool
6423 _accessible_object_on_screen_is(Eo *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool is_complete)
6424 {
6425    if(!obj) return EINA_FALSE;
6426
6427    Evas_Object *target = obj;
6428    Evas_Object *parent = NULL;
6429    Evas_Coord px, py, sx, sy, sw, sh, ox, oy, ow, oh;
6430
6431    /* uninitialized data could be read */
6432    ow = 0;
6433    oh = 0;
6434
6435    if (elm_widget_is(target))
6436      parent = elm_widget_parent_get(target);
6437    else
6438      parent = elm_widget_parent_widget_get(target);
6439
6440    while (parent)
6441      {
6442         if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
6443           {
6444              evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
6445              px = ox = x;
6446              py = oy = y;
6447              ow = w;
6448              oh = h;
6449              ox = is_complete ? ox : ox + ow;
6450              oy = is_complete ? oy : oy + oh;
6451              ox = ox > sx ? ox : sx;
6452              oy = oy > sy ? oy : sy;
6453              ow = px + ow < sx + sw ? px + ow - ox : sx + sw - ox;
6454              oh = py + oh < sy + sh ? py + oh - oy : sy + sh - oy;
6455           }
6456         if (ow <= 0 || oh <= 0)
6457           return EINA_FALSE;
6458
6459         parent = elm_widget_parent_get(parent);
6460      }
6461    return EINA_TRUE;
6462 }
6463
6464 Eina_List *
6465 _accessible_scrollable_parent_list_get(Eo *obj)
6466 {
6467    if(!obj) return NULL;
6468
6469    Evas_Object *parent = NULL;
6470    Eina_List *plist = NULL;
6471
6472    if (elm_widget_is(obj))
6473      parent = elm_widget_parent_get(obj);
6474    else
6475      parent = elm_widget_parent_widget_get(obj);
6476
6477    while (parent)
6478      {
6479         if (_elm_scrollable_is(parent))
6480           plist = eina_list_append(plist, parent);
6481
6482         parent = elm_widget_parent_get(parent);
6483    }
6484    return plist;
6485 }
6486
6487 void
6488 _accessible_highlight_region_show(Eo* obj)
6489 {
6490    if (!obj) return;
6491
6492    Evas_Object *target = obj;
6493    Evas_Object *parent = NULL;
6494    Evas_Object *parent_sub = NULL;
6495    Eina_List *plist, *plist_sub;
6496    Eina_List *l, *l2;
6497
6498    Evas_Coord target_x, target_y, target_w, target_h;
6499
6500    evas_object_geometry_get(target, &target_x, &target_y, &target_w, &target_h);
6501
6502    plist = _accessible_scrollable_parent_list_get(target);
6503    if (!plist) return;
6504
6505    EINA_LIST_FOREACH(plist, l, parent)
6506      {
6507         if(!_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_TRUE))
6508           {
6509              plist_sub = _accessible_scrollable_parent_list_get(parent);
6510              plist_sub = eina_list_prepend(plist_sub, parent);
6511              EINA_LIST_FOREACH(plist_sub, l2, parent_sub)
6512                {
6513                   Evas_Coord scroll_x = 0, scroll_y = 0;
6514                   Evas_Coord scroll_x_back = 0, scroll_y_back = 0;
6515                   Evas_Coord x, y, w, h;
6516                   Evas_Coord px, py;
6517
6518                   eo_do(parent_sub, elm_interface_scrollable_content_region_get(&scroll_x_back, &scroll_y_back, NULL, NULL));
6519                   evas_object_geometry_get(parent_sub, &px, &py, NULL, NULL);
6520                   x = target_x; y = target_y; w = target_w; h = target_h;
6521
6522                   x -= (px - scroll_x_back);
6523                   y -= (py - scroll_y_back);
6524                   switch (_elm_config->focus_autoscroll_mode)
6525                     {
6526                        case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
6527                           eo_do(parent_sub, elm_interface_scrollable_content_region_show(x, y, w, h));
6528                           break;
6529                        case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
6530                           eo_do(parent_sub, elm_interface_scrollable_region_bring_in(x, y, w, h));
6531                           break;
6532                        default:
6533                           break;
6534                     }
6535                   eo_do(parent_sub, elm_interface_scrollable_content_region_get(&scroll_x, &scroll_y, NULL, NULL));
6536
6537                   target_x -= (scroll_x - scroll_x_back);
6538                   target_y -= (scroll_y - scroll_y_back);
6539
6540                   if(_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_FALSE))
6541                     break;
6542                }
6543              eina_list_free(plist_sub);
6544           }
6545      }
6546
6547    eina_list_free(plist);
6548 }
6549 //
6550
6551 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
6552 EOLIAN static Eina_Bool
6553 _elm_widget_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6554 {
6555    if(!obj) return EINA_FALSE;
6556    if(!_elm_atspi_enabled())
6557       return EINA_FALSE;
6558
6559    //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
6560    _accessible_highlight_region_show(obj);
6561    //
6562
6563    elm_object_accessibility_highlight_set(obj, EINA_TRUE);
6564    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
6565
6566    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6567    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_HIGHLIGHTED, NULL);
6568    //
6569    return EINA_TRUE;
6570 }
6571
6572 EOLIAN static Eina_Bool
6573 _elm_widget_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6574 {
6575    if(!_elm_atspi_enabled())
6576       return EINA_FALSE;
6577    elm_object_accessibility_highlight_set(obj, EINA_FALSE);
6578    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
6579
6580    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6581    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, NULL);
6582    //
6583    return EINA_TRUE;
6584 }
6585 //
6586
6587 EOLIAN static const char*
6588 _elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Widget_Smart_Data *_pd)
6589 {
6590    //TIZEN_ONLY(20190922): add name callback, description callback.
6591    const char *ret = NULL;
6592    eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_name_get());
6593    if (ret) return ret;
6594    //
6595
6596    //TIZEN_ONLY(20150717) add widget name setter
6597    if (_pd->name)
6598      {
6599 #ifdef HAVE_GETTEXT
6600         if (_pd->atspi_translation_domain)
6601           return dgettext(_pd->atspi_translation_domain, _pd->name);
6602 #endif
6603         return _pd->name;
6604      }
6605    //
6606
6607    //TIZEN_ONLY(20170110) : Ignore text from elm_object_text_set in accessible_name_get
6608    Elm_Atspi_Role role;
6609    eo_do(obj, role = elm_interface_atspi_accessible_role_get());
6610    if(role == ELM_ATSPI_ROLE_DIALOG)
6611      return NULL;
6612    //
6613
6614    ret = elm_object_text_get(obj);
6615    if (!ret) return NULL;
6616
6617    return _elm_widget_accessible_plain_name_get(obj, ret);
6618 }
6619 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
6620 EOLIAN void
6621 _elm_widget_elm_interface_atspi_accessible_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *description)
6622 {
6623    if (_pd->description)
6624      eina_stringshare_del(_pd->description);
6625
6626    _pd->description = eina_stringshare_add(description);
6627 }
6628
6629 EOLIAN static const char*
6630 _elm_widget_elm_interface_atspi_accessible_description_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6631 {
6632    const char *ret = NULL;
6633    eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_description_get());
6634    if (ret) return ret;
6635
6636 #ifdef HAVE_GETTEXT
6637    if (_pd->atspi_translation_domain)
6638      return dgettext(_pd->atspi_translation_domain, _pd->description);
6639 #endif
6640    return _pd->description;
6641 }
6642 //
6643
6644 //TIZEN_ONLY(20150713) : add atspi name setter to widget_item
6645 EOLIAN void
6646 _elm_widget_item_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *name)
6647 {
6648    if (_pd->name)
6649      eina_stringshare_del(_pd->name);
6650
6651    _pd->name = eina_stringshare_add(name);
6652 }
6653
6654 EOLIAN const char*
6655 _elm_widget_item_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6656 {
6657    //TIZEN_ONLY(20190922): add name callback, description callback.
6658    const char *ret = NULL;
6659    eo_do_super(obj, ELM_WIDGET_ITEM_CLASS, ret = elm_interface_atspi_accessible_name_get());
6660    if (ret) return ret;
6661    //
6662
6663    if (_pd->name)
6664      {
6665 #ifdef HAVE_GETTEXT
6666         if (_pd->atspi_translation_domain)
6667           return dgettext(_pd->atspi_translation_domain, _pd->name);
6668 #endif
6669         return _pd->name;
6670      }
6671
6672    return NULL;
6673 }
6674 //
6675 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
6676 EOLIAN void
6677 _elm_widget_item_elm_interface_atspi_accessible_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *description)
6678 {
6679    if (_pd->description)
6680      eina_stringshare_del(_pd->description);
6681
6682    _pd->description = eina_stringshare_add(description);
6683 }
6684
6685 EOLIAN const char*
6686 _elm_widget_item_elm_interface_atspi_accessible_description_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6687 {
6688    const char *ret = NULL;
6689    eo_do_super(obj, ELM_WIDGET_ITEM_CLASS, ret = elm_interface_atspi_accessible_description_get());
6690    if (ret) return ret;
6691
6692 #ifdef HAVE_GETTEXT
6693    if (_pd->atspi_translation_domain)
6694      return dgettext(_pd->atspi_translation_domain, _pd->description);
6695 #endif
6696    return _pd->description;
6697 }
6698 //
6699 //TIZEN_ONLY(20150709) : spatially sort atspi children
6700 static int _sort_vertically(const void *data1, const void *data2)
6701 {
6702    Evas_Coord y1, y2;
6703    evas_object_geometry_get(data1, NULL, &y1, NULL, NULL);
6704    evas_object_geometry_get(data2, NULL, &y2, NULL, NULL);
6705
6706    return y1 < y2 ? -1 : 1;
6707 }
6708
6709 static int _sort_horizontally(const void *data1, const void *data2)
6710 {
6711    Evas_Coord x1, x2;
6712    evas_object_geometry_get(data1, &x1, NULL, NULL, NULL);
6713    evas_object_geometry_get(data2, &x2, NULL, NULL, NULL);
6714
6715    return x1 < x2 ? -1 : 1;
6716 }
6717
6718 static Eina_List *_lines_split(Eina_List *children)
6719 {
6720    Eo *c;
6721    Eina_List *lines, *line, *l;
6722    Evas_Coord yl, y, hl, h;
6723    lines = line = NULL;
6724
6725    if (!children) return NULL;
6726
6727    EINA_LIST_FOREACH(children, l, c)
6728      {
6729         evas_object_geometry_get(c, NULL, &yl, NULL, &hl);
6730
6731         /* remove child if its height == 0 */
6732         if (hl != 0) break;
6733      }
6734
6735    EINA_LIST_FREE(children, c)
6736      {
6737         evas_object_geometry_get(c, NULL, &y, NULL, &h);
6738
6739         /* remove child if its height == 0 */
6740         if (h == 0 && !eo_isa(c, ELM_ATSPI_PROXY_CLASS)) continue;
6741
6742         if ((yl + (int)(0.25 * hl)) >= y)
6743           {
6744              //same line
6745              line = eina_list_append(line,c);
6746           }
6747         else
6748           {
6749              // finish current line & start new
6750              lines = eina_list_append(lines, line);
6751              yl = y, hl = h;
6752              line = eina_list_append(NULL, c);
6753           }
6754      }
6755
6756    return eina_list_append(lines, line);
6757 }
6758 //
6759
6760 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6761 static void
6762 _proxy_widget_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6763 {
6764    Evas_Coord x, y;
6765    Eo *proxy = data;
6766
6767    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
6768    elm_atspi_bridge_utils_proxy_offset_set(proxy, x, y);
6769 }
6770 //
6771
6772 static Eina_Bool
6773 _on_widget_del(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6774 {
6775    Eo *plug = data;
6776    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6777    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
6778                                        _proxy_widget_move_cb, plug);
6779    //
6780    eo_del(plug);
6781    return EINA_TRUE;
6782 }
6783
6784 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6785 static Eina_Bool
6786 _on_proxy_connected_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6787 {
6788    Evas_Coord x, y;
6789    Evas_Object *widget = data;
6790
6791    evas_object_geometry_get(widget, &x, &y, NULL, NULL);
6792    elm_atspi_bridge_utils_proxy_offset_set(obj, x, y);
6793
6794    evas_object_event_callback_add(widget, EVAS_CALLBACK_MOVE, _proxy_widget_move_cb, obj);
6795    return EINA_TRUE;
6796 }
6797 //
6798 // TIZEN ONLY - END
6799
6800 //TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
6801 static Eo *
6802 _plug_type_proxy_get(Eo *obj, Evas_Object *widget)
6803 {
6804    Eo *proxy = NULL;
6805    const char *plug_id;
6806    char *svcname, *svcnum;
6807
6808    if ((plug_id = evas_object_data_get(widget, "___PLUGID")) != NULL)
6809      {
6810         // TIZEN_ONLY(20160930) : endless recursion fix
6811         eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id));
6812
6813         proxy = evas_object_data_get(widget, "__widget_proxy");
6814         if (proxy) return proxy;
6815
6816         if (_elm_atspi_bridge_plug_id_split(plug_id, &svcname, &svcnum))
6817           {
6818              proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
6819              evas_object_data_set(widget, "__widget_proxy", proxy);
6820              eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
6821              eo_do(proxy, eo_event_callback_add(ELM_ATSPI_PROXY_EVENT_CONNECTED, _on_proxy_connected_cb, widget));
6822              elm_atspi_bridge_utils_proxy_connect(proxy);
6823              free(svcname);
6824              free(svcnum);
6825           }
6826      }
6827
6828    return proxy;
6829 }
6830
6831 EAPI Eo *
6832 elm_widget_atspi_plug_type_proxy_get(Evas_Object *obj)
6833 {
6834    Elm_Widget_Smart_Data *wd;
6835    Evas_Object *widget;
6836    Eina_List *l;
6837
6838    wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6839    if (!wd) return NULL;
6840
6841    Eo *proxy = NULL;
6842    EINA_LIST_FOREACH(wd->subobjs, l, widget)
6843      {
6844         if (evas_object_data_get(widget, "___PLUGID"))
6845            proxy = _plug_type_proxy_get(obj, widget);
6846         if (proxy) break;
6847      }
6848    return proxy;
6849 }
6850 //
6851
6852 EOLIAN static Eina_List*
6853 _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6854 {
6855    Eina_List *l, *accs = NULL;
6856    Elm_Widget_Smart_Data *wd;
6857    Evas_Object *widget;
6858    // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6859    Eo *parent;
6860    //
6861
6862    wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6863    if (!wd) return NULL;
6864
6865    EINA_LIST_FOREACH(wd->subobjs, l, widget)
6866      {
6867         const char *type = evas_object_type_get(widget);
6868         // TIZEN ONLY
6869         // Ugly Tizen hack to integrate AT-SPI2 accessibility provided by WebKit/Chromium with elementary one.
6870         // This wrapper class should be implemented in Webkit/Chromium EFL ports
6871         if (type && (!strcmp(type, "EWebView") || !strcmp(type, "WebView"))) {
6872            elm_atspi_ewk_wrapper_a11y_init(obj, widget);
6873         }
6874      }
6875
6876    Eo *proxy = NULL;
6877    EINA_LIST_FOREACH(wd->subobjs, l, widget)
6878      {
6879         // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6880         if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) {
6881            eo_do(widget, parent = elm_interface_atspi_accessible_parent_get());
6882            if (parent && (parent != obj)) continue;
6883         }
6884
6885         // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6886         /* This assumes that only one proxy exists in obj */
6887         if (!proxy)
6888           {
6889              proxy = _plug_type_proxy_get(obj, widget);
6890              if (proxy)
6891                {
6892                   accs = eina_list_append(accs, proxy);
6893                   continue;
6894                }
6895           }
6896         //
6897         // TIZEN ONLY - END
6898         if (!elm_object_widget_check(widget)) continue;
6899         if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6900           accs = eina_list_append(accs, widget);
6901      }
6902    //TIZEN_ONLY(20150709) : spatially sort atspi children
6903    // sort children using its top-left coordinate
6904    accs = eina_list_sort(accs, -1, _sort_vertically);
6905    Eina_List *line, *lines = _lines_split(accs);
6906    accs = NULL;
6907    EINA_LIST_FREE(lines, line)
6908      accs = eina_list_merge(accs, eina_list_sort(line, -1, _sort_horizontally));
6909    //
6910
6911    if (proxy)
6912      {
6913         Eo *deputy = NULL;
6914         accs = eina_list_remove(accs, proxy);
6915         EINA_LIST_FOREACH(accs, l, widget)
6916           {
6917               if (eo_isa(widget, ELM_ACCESS_CLASS))
6918                 {
6919                    Elm_Access_Info *info = _elm_access_info_get(widget);
6920                    if (!info) continue;
6921                    if (obj == info->part_object)
6922                      {
6923                         deputy = widget;
6924                         break;
6925                      }
6926                 }
6927           }
6928
6929         if (deputy)
6930           {
6931              accs = eina_list_append_relative(accs, proxy, deputy);
6932           }
6933      }
6934    return accs;
6935 }
6936
6937 EOLIAN static Eo*
6938 _elm_widget_elm_interface_atspi_accessible_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
6939 {
6940    Eo *ret;
6941    eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_parent_get());
6942
6943    return ret ? ret : pd->parent_obj;
6944 }
6945
6946 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
6947 EAPI Eina_Bool
6948 _elm_widget_highlightable(Evas_Object *obj)
6949 {
6950    Eo *parent;
6951    Eina_Bool can_highlight;
6952
6953    Elm_Widget_Smart_Data *wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6954    if (!wd) return EINA_FALSE;
6955    if (!wd->can_highlight) return EINA_FALSE;
6956
6957    eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
6958    while (parent && !eo_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
6959      {
6960         eo_do(parent, can_highlight = elm_interface_atspi_accessible_can_highlight_get());
6961         if (!can_highlight) return EINA_FALSE;
6962         eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
6963      }
6964    return EINA_TRUE;
6965 }
6966 //
6967
6968 EOLIAN static Elm_Atspi_State_Set
6969 _elm_widget_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Widget_Smart_Data *pd)
6970 {
6971    Elm_Atspi_State_Set states = 0;
6972
6973    eo_do_super(obj, ELM_WIDGET_CLASS, states = elm_interface_atspi_accessible_state_set_get());
6974
6975    if (evas_object_visible_get(obj))
6976      {
6977         STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
6978         if (_elm_widget_onscreen_is(obj))
6979           STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
6980      }
6981    if (!elm_widget_child_can_focus_get(obj))
6982      {
6983         if (elm_object_focus_allow_get(obj))
6984           STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
6985         if (elm_object_focus_get(obj))
6986           STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
6987      }
6988    if (!elm_object_disabled_get(obj))
6989      {
6990         STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
6991         STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
6992      }
6993
6994    //TIZEN_ONLY(20170717) : expose highlight information on atspi
6995    if (_elm_widget_highlightable(obj) && _accessible_object_on_scroll_is(obj))
6996      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6997    else
6998      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6999
7000    if (_elm_object_accessibility_currently_highlighted_get() == (void*)pd->obj)
7001      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
7002    //
7003
7004    return states;
7005 }
7006
7007 //TIZEN_ONLY(20160729): attributes_get, append APIs added/updated.
7008 EOLIAN static Eina_List*
7009 _elm_widget_elm_interface_atspi_accessible_attributes_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
7010 {
7011    Eina_List *attr_list = NULL;
7012    // TIZEN_ONLY(20160930) : endless recursion fix
7013    eo_do_super(obj, MY_CLASS, attr_list = elm_interface_atspi_accessible_attributes_get());
7014    //
7015    //Add type and style information in addition.
7016    Elm_Atspi_Attribute *attr = NULL;
7017    attr = calloc(1, sizeof(Elm_Atspi_Attribute));
7018    if (attr)
7019      {
7020         attr->key = eina_stringshare_add("type");
7021         attr->value = eina_stringshare_add(elm_widget_type_get(obj));
7022         attr_list = eina_list_append(attr_list, attr);
7023      }
7024
7025    attr = calloc(1, sizeof(Elm_Atspi_Attribute));
7026    if (attr)
7027      {
7028         attr->key = eina_stringshare_add("style");
7029         attr->value = eina_stringshare_add(elm_widget_style_get(obj));
7030         attr_list = eina_list_append(attr_list, attr);
7031      }
7032
7033    return attr_list;
7034 }
7035
7036 //TIZEN_ONLY(20150709) : atspi relations api
7037 EOLIAN static Elm_Atspi_Relation_Set
7038 _elm_widget_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7039 {
7040    return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
7041 }
7042
7043 EOLIAN static Elm_Atspi_Relation_Set
7044 _elm_widget_item_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
7045 {
7046    return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
7047 }
7048
7049 EOLIAN static void
7050 _elm_widget_elm_interface_atspi_accessible_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7051 {
7052    elm_atspi_relation_set_free(&sd->atspi_custom_relations);
7053    sd->atspi_custom_relations = NULL;
7054 }
7055 //
7056
7057 EOLIAN static void
7058 _elm_widget_item_elm_interface_atspi_accessible_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
7059 {
7060    elm_atspi_relation_set_free(&sd->atspi_custom_relations);
7061    sd->atspi_custom_relations = NULL;
7062 }
7063 //
7064
7065 EOLIAN static void
7066 _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)
7067 {
7068    int ee_x, ee_y;
7069
7070    if (!sd->view)
7071      {
7072         if (x) *x = -1;
7073         if (y) *y = -1;
7074         if (w) *w = -1;
7075         if (h) *h = -1;
7076         return;
7077      }
7078
7079    evas_object_geometry_get(sd->view, x, y, w, h);
7080    if (screen_coords)
7081      {
7082         Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->view));
7083         if (!ee) return;
7084         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
7085         if (x) *x += ee_x;
7086         if (y) *y += ee_y;
7087      }
7088 }
7089
7090 EOLIAN static Eina_Bool
7091 _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)
7092 {
7093    return EINA_FALSE;
7094 }
7095
7096 EOLIAN static int
7097 _elm_widget_item_elm_interface_atspi_component_layer_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
7098 {
7099    if (!sd->view)
7100      return -1;
7101    return evas_object_layer_get(sd->view);
7102 }
7103
7104 EOLIAN static Eina_Bool
7105 _elm_widget_item_elm_interface_atspi_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7106 {
7107    elm_object_item_focus_set(obj, EINA_TRUE);
7108    return elm_object_item_focus_get(obj);
7109 }
7110
7111 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods
7112
7113 EOLIAN static Eina_Bool
7114 _elm_widget_item_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
7115 {
7116    if (!sd) return EINA_FALSE;
7117    if (!sd->view) return EINA_FALSE;
7118
7119    //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
7120    _accessible_highlight_region_show(sd->view);
7121    //
7122
7123    if (!sd->eo_obj) return EINA_FALSE;
7124    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_TRUE);
7125
7126    if (!obj) return EINA_FALSE;
7127    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
7128
7129    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
7130    evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_HIGHLIGHTED, obj);
7131    //
7132    return EINA_TRUE;
7133 }
7134
7135 EOLIAN static Eina_Bool
7136 _elm_widget_item_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
7137 {
7138    if (!obj) return EINA_FALSE;
7139    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_FALSE);
7140    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
7141
7142    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
7143    evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, obj);
7144    //
7145    return EINA_TRUE;
7146 }
7147 //
7148
7149 EOLIAN static double
7150 _elm_widget_item_elm_interface_atspi_component_alpha_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
7151 {
7152    int alpha;
7153
7154    if (!sd->view) return -1.0;
7155    evas_object_color_get(sd->view, NULL, NULL, NULL, &alpha);
7156    return (double)alpha / 255.0;
7157 }
7158
7159 //TIZEN_ONLY(20150717) add widget name setter
7160 EOLIAN void
7161 _elm_widget_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *name)
7162 {
7163    if (_pd->name)
7164      eina_stringshare_del(_pd->name);
7165
7166    _pd->name = eina_stringshare_add(name);
7167 }
7168 //
7169
7170 //TIZEN_ONLY(20160329): widget: improve accessibile_at_point getter (a8aff0423202b9a55dbb3843205875226678fbd6)
7171 static void
7172 _coordinate_system_based_point_translate(Eo *obj, Eina_Bool screen_coords, int *x, int *y)
7173 {
7174    Ecore_Evas *ee;
7175    int ee_x = 0;
7176    int ee_y = 0;
7177
7178    if (screen_coords)
7179      {
7180         ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
7181         if (!ee) return;
7182
7183         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
7184         *x -= ee_x;
7185         *y -= ee_y;
7186      }
7187 }
7188
7189 static Evas_Object *
7190 _parent_get(Evas_Object *obj)
7191 {
7192    Evas_Object *parent;
7193
7194    parent = evas_object_smart_parent_get(obj);
7195    if (!parent)
7196      {
7197         if (strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))))
7198           parent = elm_widget_parent_get(obj);
7199      }
7200
7201    return parent;
7202 }
7203
7204 static Eina_Bool
7205 _is_inside(Evas_Object *obj, int x, int y)
7206 {
7207    Eina_Bool ret = EINA_TRUE;
7208    Evas_Coord cx = 0;
7209    Evas_Coord cy = 0;
7210    Evas_Coord cw = 0;
7211    Evas_Coord ch = 0;
7212    if (eo_isa(obj, ELM_WIDGET_ITEM_CLASS))
7213      {
7214         Elm_Widget_Item_Data *id = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
7215         evas_object_geometry_get(id->view, &cx, &cy, &cw, &ch);
7216      }
7217    else
7218      evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
7219
7220    /* check the point is out of bound */
7221    if (x < cx || x > cx + cw || y < cy || y > cy + ch)
7222      {
7223         ret = EINA_FALSE;
7224      }
7225    return ret;
7226 }
7227
7228 static Eina_Bool
7229 _is_ancestor_of(Evas_Object *smart_parent, Evas_Object *obj)
7230 {
7231    Eina_Bool ret = EINA_FALSE;
7232    Evas_Object *parent = elm_widget_parent_get(obj);
7233    while (parent)
7234      {
7235         /* No need to check more, the smart_parent is parent of obj */
7236         if (smart_parent == parent)
7237           {
7238              ret = EINA_TRUE;
7239              break;
7240           }
7241         parent = elm_widget_parent_get(parent);
7242      }
7243
7244    return ret;
7245 }
7246
7247 static int _sort_by_size(const void *data1, const void *data2)
7248 {
7249    Evas_Coord w, h;
7250    Evas_Coord w2, h2;
7251
7252    evas_object_geometry_get(data1, NULL, NULL, &w, &h);
7253    evas_object_geometry_get(data2, NULL, NULL, &w2, &h2);
7254
7255    if ((w * h) > (w2 * h2)) return 1;
7256    return -1;
7257 }
7258
7259 Eina_Bool
7260 _elm_widget_atspi_role_acceptable_check(Eo *obj)
7261 {
7262    Elm_Atspi_Role role;
7263    eo_do(obj, role = elm_interface_atspi_accessible_role_get());
7264
7265    switch (role)
7266      {
7267        case ELM_ATSPI_ROLE_APPLICATION:
7268        case ELM_ATSPI_ROLE_FILLER:
7269        case ELM_ATSPI_ROLE_SCROLL_PANE:
7270        case ELM_ATSPI_ROLE_SPLIT_PANE:
7271        case ELM_ATSPI_ROLE_WINDOW:
7272        case ELM_ATSPI_ROLE_IMAGE:
7273        case ELM_ATSPI_ROLE_LIST:
7274        case ELM_ATSPI_ROLE_ICON:
7275        case ELM_ATSPI_ROLE_TOOL_BAR:
7276        case ELM_ATSPI_ROLE_REDUNDANT_OBJECT:
7277        case ELM_ATSPI_ROLE_COLOR_CHOOSER:
7278        case ELM_ATSPI_ROLE_TREE_TABLE:
7279        case ELM_ATSPI_ROLE_PAGE_TAB_LIST:
7280        case ELM_ATSPI_ROLE_PAGE_TAB:
7281        case ELM_ATSPI_ROLE_SPIN_BUTTON:
7282        case ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW:
7283        case ELM_ATSPI_ROLE_EMBEDDED:
7284        case ELM_ATSPI_ROLE_INVALID:
7285        case ELM_ATSPI_ROLE_NOTIFICATION:
7286          return EINA_FALSE;
7287        default:
7288          break;
7289      }
7290
7291    return EINA_TRUE;
7292 }
7293
7294 static Eo *
7295 _child_object_at_point_get(Eo *obj, int x, int y)
7296 {
7297    Eina_List *l, *l_next, *children, *valid_children = NULL;
7298    Eo *child;
7299    Eo *target;
7300    int count;
7301
7302    eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7303
7304    EINA_LIST_FOREACH(children, l, child)
7305      {
7306         if (_is_inside(child, x, y))
7307           valid_children = eina_list_append(valid_children, child);
7308      }
7309
7310    EINA_LIST_FOREACH_SAFE(valid_children, l, l_next, child)
7311      {
7312         eo_do(child, children = elm_interface_atspi_accessible_children_get());
7313
7314         /* do not use unacceptable leaf node */
7315         if (!_elm_widget_atspi_role_acceptable_check(child) &&
7316             eina_list_count(children) == 0)
7317           valid_children = eina_list_remove_list(valid_children, l);
7318      }
7319
7320    count = eina_list_count(valid_children);
7321    if (count > 0)
7322      {
7323         valid_children = eina_list_sort(valid_children, -1, _sort_by_size);
7324         target = eina_list_nth(valid_children, 0);
7325
7326         return _child_object_at_point_get(target, x, y);
7327      }
7328
7329    return obj;
7330 }
7331
7332 static Eina_Bool
7333 _is_acceptable_leaf(Eo *obj)
7334 {
7335    Elm_Atspi_Role role;
7336    Eina_List *children;
7337
7338    eo_do(obj, role = elm_interface_atspi_accessible_role_get());
7339    switch (role)
7340      {
7341        case ELM_ATSPI_ROLE_IMAGE:
7342        case ELM_ATSPI_ROLE_ICON:
7343          eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7344          if (!children) return EINA_FALSE;
7345          break;
7346
7347        default:
7348          break;
7349      }
7350
7351    return EINA_TRUE;
7352 }
7353
7354 static Eo *
7355 _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
7356 {
7357    Eina_List *l, *l2, *children, *valid_children = NULL;
7358    Eo *child;
7359    Evas_Object *stack_item;
7360    Eo *compare_obj;
7361    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7362    Eo *proxy;
7363    Evas_Coord px, py, pw, ph;
7364    //
7365
7366    _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
7367
7368    eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7369
7370    EINA_LIST_FOREACH(children, l2, child)
7371      {
7372         if (_is_inside(child, x, y) && _is_acceptable_leaf(child))
7373           valid_children = eina_list_append(valid_children, child);
7374      }
7375    /* Get evas_object stacked at given x,y coordinates starting from top */
7376    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
7377    /* Foreach stacked object starting from top */
7378    EINA_LIST_FOREACH(stack, l, stack_item)
7379      {
7380         /* Foreach at-spi valid children traverse stack_item evas_objects hierarchy */
7381         EINA_LIST_FOREACH(valid_children, l2, child)
7382           {
7383              Elm_Atspi_Role role;
7384              eo_do(child, role = elm_interface_atspi_accessible_role_get());
7385              if (role == ELM_ATSPI_ROLE_REDUNDANT_OBJECT)
7386                {
7387                   /* The redundant object ignores */
7388                   continue;
7389                }
7390              /* Compare object used to compare with stacked evas objects */
7391              compare_obj = child;
7392              /* In case of widget_items compare should be different then elm_widget_ item  object */
7393              if (eo_isa(child, ELM_WIDGET_ITEM_CLASS))
7394                {
7395                   Elm_Widget_Item_Data *id = eo_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
7396                   compare_obj = id->view;
7397                   if (TIZEN_PROFILE_WEARABLE)
7398                     {
7399                        Eo* it_view = evas_object_image_source_get(stack_item);
7400                        if (it_view && it_view == compare_obj)
7401                          {
7402                             eina_list_free(children);
7403                             eina_list_free(stack);
7404                             return child;
7405                          }
7406                     }
7407                }
7408              /* In case of access object compare should be 'wrapped' evas_object */
7409              if (eo_isa(child, ELM_ACCESS_CLASS))
7410                {
7411                    Elm_Access_Info *info = _elm_access_info_get(child);
7412                    if (!info) continue;
7413                    compare_obj = info->part_object;
7414                 }
7415              /* In case of widget is registerd by elm_access_object_register */
7416              Evas_Object *ao = elm_access_object_get(child);
7417              if (ao)
7418                {
7419                   eina_list_free(children);
7420                   eina_list_free(stack);
7421                   return ao;
7422                }
7423
7424              /* In case of ewk wrapper object compare with internal ewk_view evas_object */
7425              if (eo_isa(child, ELM_ATSPI_EWK_WRAPPER_CLASS))
7426                {
7427                   compare_obj = elm_atspi_ewk_wrapper_ewk_view_get(child);
7428                }
7429
7430              /* If spacial eo children do not have backing evas_object continue with search */
7431              if (!compare_obj)
7432                continue;
7433
7434              Evas_Object *smart_parent = stack_item;
7435              while (smart_parent)
7436                {
7437                    if (smart_parent == compare_obj)
7438                      {
7439                         eina_list_free(children);
7440                         eina_list_free(stack);
7441                         return child;
7442                      }
7443
7444                    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
7445                    proxy = evas_object_data_get(smart_parent, "__widget_proxy");
7446                    if (proxy)
7447                      {
7448                         evas_object_geometry_get(smart_parent, &px, &py, &pw, &ph);
7449                         if (x >= px && x <= px + pw && y >= py && y <= py +ph)
7450                           {
7451                              eina_list_free(children);
7452                              eina_list_free(stack);
7453                              return proxy;
7454                           }
7455                      }
7456                    //
7457
7458                    smart_parent = _parent_get(smart_parent);
7459                    if (_is_ancestor_of(smart_parent, obj)) break;
7460                }
7461           }
7462      }
7463
7464    eina_list_free(children);
7465    eina_list_free(stack);
7466    return NULL;
7467 }
7468
7469 static int _sort_by_repeat_events(const void *data1, const void *data2)
7470 {
7471    Evas_Object *ao1, *ao2;
7472    Eina_Bool repeat1, repeat2;
7473
7474    ao1 = elm_access_object_get(data1);
7475    ao2 = elm_access_object_get(data2);
7476
7477    repeat1 = evas_object_repeat_events_get(data1);
7478    repeat2 = evas_object_repeat_events_get(data2);
7479
7480    if (repeat1 != repeat2)
7481      {
7482         if (repeat1 && !ao1) return 1;
7483      }
7484    else
7485      {
7486         if (repeat1 && !ao1 && ao2) return 1;
7487      }
7488
7489    return -1;
7490 }
7491
7492 static Eo *_item_at_point_get(Evas_Object *obj, int x, int y)
7493 {
7494    Eo *child;
7495    Eina_List *l, *children;
7496
7497    eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7498
7499    EINA_LIST_FOREACH(children, l, child)
7500      {
7501         if (_is_inside(child, x, y)) return child;
7502      }
7503
7504    ERR("No child at point (%d, %d) on object %p", x, y, obj);
7505    return NULL;
7506 }
7507
7508 EOLIAN static Eo *
7509 _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)
7510 {
7511    Eina_List *l;
7512    Evas_Object *stack_item;
7513
7514    if(strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))))
7515      return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
7516
7517    _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
7518
7519    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
7520    stack = eina_list_sort(stack, -1, _sort_by_repeat_events);
7521
7522    EINA_LIST_FOREACH(stack, l, stack_item)
7523      {
7524         Evas_Object *smart_parent = stack_item;
7525         while (smart_parent)
7526           {
7527              Evas_Object *ao = elm_access_object_get(smart_parent);
7528              if (ao) return ao;
7529
7530              if (eo_isa(smart_parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
7531                {
7532                   Eina_Bool acceptable = EINA_FALSE;
7533                   Eo *item_child;
7534                   Elm_Atspi_Role role;
7535                   eo_do(smart_parent, role = elm_interface_atspi_accessible_role_get());
7536                   switch (role)
7537                     {
7538                      case ELM_ATSPI_ROLE_FILLER: /* ex: View of colorselector item is layout */
7539                      case ELM_ATSPI_ROLE_ICON:
7540                      case ELM_ATSPI_ROLE_IMAGE:
7541                      case ELM_ATSPI_ROLE_REDUNDANT_OBJECT:
7542                      case ELM_ATSPI_ROLE_WINDOW:
7543                        DBG("Go for parent: %s (%p)\n", evas_object_type_get(smart_parent), smart_parent);
7544                        break;
7545
7546                      case ELM_ATSPI_ROLE_LIST:
7547                        item_child = _item_at_point_get(smart_parent, x, y);
7548                        if (TIZEN_PROFILE_WEARABLE)
7549                          {
7550                             item_child = _child_object_at_point_get(item_child, x, y);
7551                             return item_child;
7552                          }
7553                        return item_child;
7554                        break;
7555
7556                      default:
7557                        acceptable = EINA_TRUE;
7558                        break;
7559                     }
7560
7561                     if (acceptable) return smart_parent;
7562                }
7563
7564              smart_parent = _parent_get(smart_parent);
7565           }
7566      }
7567    return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
7568 }
7569 //
7570
7571 //TIZEN_ONLY(20150709) add relations atpi
7572 EOLIAN static Eina_Bool
7573 _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)
7574 {
7575    return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7576 }
7577
7578 EOLIAN static void
7579 _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)
7580 {
7581    elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7582 }
7583
7584 EOLIAN static Eina_Bool
7585 _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)
7586 {
7587    return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7588 }
7589
7590 EOLIAN static void
7591 _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)
7592 {
7593    elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7594 }
7595 //
7596
7597 //TIZEN_ONLY(20150731) : add i18n support for name and description
7598 EOLIAN static void
7599 _elm_widget_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, const char *domain)
7600 {
7601    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7602 }
7603
7604 EOLIAN static const char*
7605 _elm_widget_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
7606 {
7607    return _pd->atspi_translation_domain;
7608 }
7609
7610 EOLIAN static void
7611 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, const char *domain)
7612 {
7613    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7614 }
7615
7616 EOLIAN static const char*
7617 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd)
7618 {
7619    return _pd->atspi_translation_domain;
7620 }
7621
7622 //TIZEN_ONLY(20160726): add API elm_atspi_accessible_can_highlight_set/get
7623 static Eina_Bool
7624 _children_highlight_check(Eo *obj)
7625 {
7626    Eina_List *children, *l;
7627    Eo *child;
7628
7629    if (_elm_object_accessibility_currently_highlighted_get() == (void *)obj)
7630      {
7631         eo_do(obj, elm_interface_atspi_component_highlight_clear());
7632         return EINA_TRUE;
7633      }
7634
7635    eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7636    EINA_LIST_FOREACH(children, l, child)
7637      {
7638         if (_children_highlight_check(child)) return EINA_TRUE;
7639      }
7640
7641    return EINA_FALSE;
7642 }
7643
7644 EOLIAN static void
7645 _elm_widget_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Eina_Bool can_highlight)
7646 {
7647    if (!can_highlight) _children_highlight_check(obj);
7648    _pd->can_highlight = !!can_highlight;
7649 }
7650
7651 EOLIAN static Eina_Bool
7652 _elm_widget_elm_interface_atspi_accessible_can_highlight_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7653 {
7654    return _elm_widget_highlightable(obj);
7655 }
7656
7657 EOLIAN static void
7658 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, Eina_Bool can_highlight)
7659 {
7660    if (!can_highlight) _children_highlight_check(obj);
7661    _pd->can_highlight = !!can_highlight;
7662 }
7663
7664 EOLIAN static Eina_Bool
7665 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_get(Eo *obj, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7666 {
7667    return _elm_widget_item_highlightable(obj);
7668 }
7669 //
7670
7671 //TIZEN_ONLY(20160622): Override Paragraph Direction APIs
7672 static void
7673 _elm_widget_evas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
7674 {
7675    Evas_Object *child;
7676    Eina_List *l;
7677
7678    if (sd->on_destroy) return;
7679
7680    EINA_LIST_FOREACH(sd->subobjs, l, child)
7681      {
7682         if (_elm_widget_is(child))
7683           {
7684              Elm_Widget_Smart_Data *sdc = eo_data_scope_get(child, MY_CLASS);
7685
7686              if (sdc->inherit_paragraph_direction &&
7687                  (sdc->paragraph_direction != dir))
7688                {
7689                   sdc->paragraph_direction = dir;
7690                   _elm_widget_evas_object_paragraph_direction_set_internal(child, sdc, dir);
7691                   eo_do_super(child, MY_CLASS, evas_obj_paragraph_direction_set(dir));
7692                }
7693           }
7694
7695         /* FIXME: There is no way to handle non-widget child object.
7696          * If a non-widget child object has smart parent, it will get the direction
7697          * from the smart parent. */
7698      }
7699 }
7700
7701 EOLIAN static void
7702 _elm_widget_evas_object_paragraph_direction_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
7703 {
7704    if ((!(sd->inherit_paragraph_direction) && (sd->paragraph_direction == dir)) ||
7705        (sd->inherit_paragraph_direction && (dir == EVAS_BIDI_DIRECTION_INHERIT)))
7706      return;
7707
7708    if (dir == EVAS_BIDI_DIRECTION_INHERIT)
7709      {
7710         sd->inherit_paragraph_direction = EINA_TRUE;
7711         Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
7712
7713         if (sd->parent_obj)
7714           parent_dir = evas_object_paragraph_direction_get(sd->parent_obj);
7715
7716         if (parent_dir != sd->paragraph_direction)
7717           {
7718              sd->paragraph_direction = parent_dir;
7719              _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, parent_dir);
7720           }
7721      }
7722    else
7723      {
7724         sd->inherit_paragraph_direction = EINA_FALSE;
7725         sd->paragraph_direction = dir;
7726         _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, dir);
7727      }
7728
7729    eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(dir));
7730 }
7731 //
7732
7733
7734 //TIZEN_ONLY(20161013): clean up elm color class feature
7735 void
7736 _edje_color_class_free(void *data)
7737 {
7738    Edje_Color_Class *cc = data;
7739
7740    if (cc->name) eina_stringshare_del(cc->name);
7741    free(cc);
7742 }
7743
7744 Eina_Stringshare *
7745 _elm_widget_edje_class_get(const Eo_Class *klass, const char *style, const char *part)
7746 {
7747    Eina_Strbuf *buf;
7748    Eina_Stringshare *str;
7749
7750    buf = eina_strbuf_new();
7751
7752    eina_strbuf_append(buf, strchr(eo_class_name_get(klass), '_') + 1);
7753    eina_strbuf_tolower(buf);
7754
7755    if (style)
7756      {
7757         eina_strbuf_append_printf(buf, "/%s/%s", style, part);
7758      }
7759    else
7760      {
7761         eina_strbuf_append_printf(buf, "/%s", part);
7762      }
7763
7764    str = eina_stringshare_add(eina_strbuf_string_get(buf));
7765
7766    eina_strbuf_free(buf);
7767    return str;
7768 }
7769
7770 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
7771 Eina_Bool
7772 _elm_widget_color_class_set_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
7773                                      int r, int g, int b, int a,
7774                                      int r2, int g2, int b2, int a2,
7775                                      int r3, int g3, int b3, int a3)
7776 {
7777    Eina_Bool int_ret = EINA_TRUE;
7778    Eina_Stringshare *buf;
7779    int temp_color[3][4] = { { r,  g,  b,  a },
7780                             { r2, g2, b2, a2 },
7781                             { r3, g3, b3, a3 } };
7782
7783    if (!color_class) return EINA_FALSE;
7784
7785    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
7786
7787 #define TEMP_COLOR(x, y) \
7788    ((temp_color[x][y] == -1) ? &temp_color[x][y] : NULL)
7789
7790    edje_object_color_class_get(edje, buf,
7791                                TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
7792                                TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
7793                                TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
7794
7795 #undef TEMP_COLOR
7796
7797 #define TEMP_COLOR(x, y) \
7798    ((temp_color[x][y] == -1) ? 0 : temp_color[x][y])
7799
7800    int_ret &= edje_object_color_class_set(edje, buf,
7801                                           TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
7802                                           TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
7803                                           TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
7804
7805 #undef TEMP_COLOR
7806
7807    eina_stringshare_del(buf);
7808
7809    return int_ret;
7810 }
7811
7812 Eina_Bool
7813 _elm_widget_color_class_get_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
7814                                      int *r, int *g, int *b, int *a,
7815                                      int *r2, int *g2, int *b2, int *a2,
7816                                      int *r3, int *g3, int *b3, int *a3)
7817 {
7818    Eina_Bool int_ret = EINA_TRUE;
7819    Eina_Stringshare *buf;
7820
7821    if (!color_class) return EINA_FALSE;
7822
7823    buf = _elm_widget_edje_class_get(eo_class_get(obj), elm_widget_style_get(obj), color_class);
7824
7825    int_ret &= edje_object_color_class_get(edje, buf,
7826                                           r,  g,  b,  a,
7827                                           r2, g2, b2, a2,
7828                                           r3, g3, b3, a3);
7829
7830    eina_stringshare_del(buf);
7831
7832    return int_ret;
7833 }
7834 /* END */
7835
7836 EOLIAN Eina_Bool
7837 _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)
7838 {
7839    Evas_Object *edje;
7840    Eina_Bool int_ret = EINA_TRUE;
7841
7842    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7843
7844    edje = elm_layout_edje_get(obj);
7845    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7846                                                    r, g, b, a,
7847                                                    -1, -1, -1, -1,
7848                                                    -1, -1, -1, -1);
7849
7850    return int_ret;
7851 }
7852
7853 EOLIAN Eina_Bool
7854 _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)
7855 {
7856    Evas_Object *edje;
7857    Eina_Bool int_ret = EINA_TRUE;
7858
7859    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7860
7861    edje = elm_layout_edje_get(obj);
7862    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7863                                                    r, g, b, a,
7864                                                    NULL, NULL, NULL, NULL,
7865                                                    NULL, NULL, NULL, NULL);
7866
7867    return int_ret;
7868 }
7869
7870 EOLIAN Eina_Bool
7871 _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)
7872 {
7873    Evas_Object *edje;
7874    Eina_Bool int_ret = EINA_TRUE;
7875
7876    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7877
7878    edje = elm_layout_edje_get(obj);
7879    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7880                                                    -1, -1, -1, -1,
7881                                                    r, g, b, a,
7882                                                    -1, -1, -1, -1);
7883
7884    return int_ret;
7885 }
7886
7887 EOLIAN Eina_Bool
7888 _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)
7889 {
7890    Evas_Object *edje;
7891    Eina_Bool int_ret = EINA_TRUE;
7892
7893    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7894
7895    edje = elm_layout_edje_get(obj);
7896    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7897                                                    NULL, NULL, NULL, NULL,
7898                                                    r, g, b, a,
7899                                                    NULL, NULL, NULL, NULL);
7900
7901    return int_ret;
7902 }
7903
7904 EOLIAN Eina_Bool
7905 _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)
7906 {
7907    Evas_Object *edje;
7908    Eina_Bool int_ret = EINA_TRUE;
7909
7910    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7911
7912    edje = elm_layout_edje_get(obj);
7913    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7914                                                    -1, -1, -1, -1,
7915                                                    -1, -1, -1, -1,
7916                                                    r, g, b, a);
7917
7918    return int_ret;
7919 }
7920
7921 EOLIAN Eina_Bool
7922 _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)
7923 {
7924    Evas_Object *edje;
7925    Eina_Bool int_ret = EINA_TRUE;
7926
7927    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7928
7929    edje = elm_layout_edje_get(obj);
7930    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7931                                                    NULL, NULL, NULL, NULL,
7932                                                    NULL, NULL, NULL, NULL,
7933                                                    r, g, b, a);
7934
7935    return int_ret;
7936 }
7937
7938 EOLIAN void
7939 _elm_widget_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *color_class)
7940 {
7941    Eina_Stringshare *buf;
7942
7943    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return;
7944
7945    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
7946    edje_object_color_class_del(sd->resize_obj, buf);
7947    eina_stringshare_del(buf);
7948 }
7949
7950 EOLIAN void
7951 _elm_widget_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7952 {
7953    if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return;
7954    edje_object_color_class_clear(sd->resize_obj);
7955 }
7956
7957 #define ELM_COLOR_CLASS_UPDATE(obj, hash, cond)                                  \
7958    Evas_Object *edje = NULL;                                                     \
7959    Eina_Iterator *itr;                                                           \
7960    Edje_Color_Class *cc;                                                         \
7961    Eina_Bool int_ret = EINA_TRUE;                                                \
7962    if (cond) return EINA_FALSE;                                                  \
7963    if (eo_isa(obj, ELM_LAYOUT_CLASS))                                            \
7964      edje =  elm_layout_edje_get(obj);                                           \
7965    else if (eo_isa(obj, EDJE_OBJECT_CLASS))                                      \
7966      edje = obj;                                                                 \
7967    if (!edje) return EINA_FALSE;                                                 \
7968    itr = eina_hash_iterator_data_new(hash);                                      \
7969    EINA_ITERATOR_FOREACH(itr, cc)                                                \
7970      {                                                                           \
7971         int_ret &= edje_object_color_class_set(edje, cc->name,                   \
7972                                                cc->r, cc->g, cc->b, cc->a,       \
7973                                                cc->r2, cc->g2, cc->b2, cc->a2,   \
7974                                                cc->r3, cc->g3, cc->b3, cc->a3);  \
7975      }                                                                           \
7976    eina_iterator_free(itr);                                                      \
7977    return int_ret
7978
7979
7980 #define CHECK_BOUND(x)                                                           \
7981    if (x > 0xff) x = 0xff;                                                       \
7982    else if (x < 0) x = 0
7983
7984 #define ELM_COLOR_CLASS_SET_START(obj, cr, cg, cb, ca)                           \
7985    Eina_Bool int_ret = EINA_FALSE;                                               \
7986    Edje_Color_Class *cc = NULL;                                                  \
7987    Eina_Stringshare *buf;                                                        \
7988    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);       \
7989    CHECK_BOUND(r);                                                               \
7990    CHECK_BOUND(g);                                                               \
7991    CHECK_BOUND(b);                                                               \
7992    CHECK_BOUND(a);                                                               \
7993    _elm_color_unpremul(a, &r, &g, &b);                                           \
7994    if (!sd->color_classes)                                                       \
7995      sd->color_classes = eina_hash_string_small_new(_edje_color_class_free);     \
7996    else                                                                          \
7997      cc = eina_hash_find(sd->color_classes, buf);                                \
7998    if (!cc)                                                                      \
7999      {                                                                           \
8000         cc = calloc(1, sizeof(Edje_Color_Class));                                \
8001         cc->name = eina_stringshare_add(buf);                                    \
8002         if (!cc->name)                                                           \
8003           {                                                                      \
8004              free(cc);                                                           \
8005              eina_stringshare_del(buf);                                          \
8006              return EINA_FALSE;                                                  \
8007           }                                                                      \
8008         eina_hash_direct_add(sd->color_classes, cc->name, cc);                   \
8009      }                                                                           \
8010    else if ((cc->cr == r) && (cc->cg == g) &&                                    \
8011             (cc->cb == b) && (cc->ca == a))                                      \
8012      {                                                                           \
8013         eina_stringshare_del(buf);                                               \
8014         return EINA_TRUE;                                                        \
8015      }                                                                           \
8016    cc->cr = r;                                                                   \
8017    cc->cg = g;                                                                   \
8018    cc->cb = b;                                                                   \
8019    cc->ca = a;                                                                   \
8020    int_ret = EINA_TRUE
8021
8022 #define ELM_COLOR_CLASS_SET_END()                                                \
8023    eina_stringshare_del(buf);                                                    \
8024    return int_ret
8025
8026 #define ELM_COLOR_CLASS_GET(obj, cr, cg, cb, ca)                                 \
8027    Eina_Bool int_ret = EINA_FALSE;                                               \
8028    Edje_Color_Class *cc;                                                         \
8029    Eina_Stringshare *buf;                                                        \
8030    int alpha = 0;                                                                \
8031    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);       \
8032    if ((!sd->color_classes) || !(cc = eina_hash_find(sd->color_classes, buf)))   \
8033      {                                                                           \
8034         if (r) *r = 0;                                                           \
8035         if (g) *g = 0;                                                           \
8036         if (b) *b = 0;                                                           \
8037         if (a) *a = 0;                                                           \
8038         int_ret = EINA_FALSE;                                                    \
8039      }                                                                           \
8040    else                                                                          \
8041      {                                                                           \
8042         if (r) *r = cc->cr;                                                      \
8043         if (g) *g = cc->cg;                                                      \
8044         if (b) *b = cc->cb;                                                      \
8045         if (a) *a = cc->ca;                                                      \
8046         alpha = cc->ca;                                                          \
8047         int_ret = EINA_TRUE;                                                     \
8048      }                                                                           \
8049    _elm_color_premul(alpha, r, g, b);                                            \
8050    eina_stringshare_del(buf);                                                    \
8051    return int_ret
8052
8053 Eina_Bool
8054 _elm_widget_item_color_class_update(Elm_Widget_Item_Data *sd)
8055 {
8056    ELM_COLOR_CLASS_UPDATE(sd->view, sd->color_classes, (!sd) || (!sd->color_classes) || (!sd->view));
8057 }
8058
8059 EOLIAN Eina_Bool
8060 _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)
8061 {
8062    ELM_COLOR_CLASS_SET_START(obj, r, g, b, a);
8063
8064    int_ret &= _elm_widget_item_color_class_update(sd);
8065
8066    ELM_COLOR_CLASS_SET_END();
8067 }
8068
8069 EOLIAN Eina_Bool
8070 _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)
8071 {
8072    ELM_COLOR_CLASS_GET(obj, r, g, b, a);
8073 }
8074
8075 EOLIAN Eina_Bool
8076 _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)
8077 {
8078    ELM_COLOR_CLASS_SET_START(obj, r2, g2, b2, a2);
8079
8080    int_ret &= _elm_widget_item_color_class_update(sd);
8081
8082    ELM_COLOR_CLASS_SET_END();
8083 }
8084
8085 EOLIAN Eina_Bool
8086 _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)
8087 {
8088    ELM_COLOR_CLASS_GET(obj, r2, g2, b2, a2);
8089 }
8090
8091 EOLIAN Eina_Bool
8092 _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)
8093 {
8094    ELM_COLOR_CLASS_SET_START(obj, r3, g3, b3, a3);
8095
8096    int_ret &= _elm_widget_item_color_class_update(sd);
8097
8098    ELM_COLOR_CLASS_SET_END();
8099 }
8100
8101 EOLIAN Eina_Bool
8102 _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)
8103 {
8104    ELM_COLOR_CLASS_GET(obj, r3, g3, b3, a3);
8105 }
8106
8107 static Evas_Object *
8108 _elm_widget_item_edje_get(Eo *obj, Elm_Widget_Item_Data *sd)
8109 {
8110    if (!sd)
8111      sd = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
8112
8113    if (eo_isa(sd->view, ELM_LAYOUT_CLASS))
8114      return elm_layout_edje_get(sd->view);
8115    else if (eo_isa(sd->view, EDJE_OBJECT_CLASS))
8116      return sd->view;
8117
8118    return NULL;
8119 }
8120
8121 EOLIAN void
8122 _elm_widget_item_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, const char *color_class)
8123 {
8124    Eina_Stringshare *buf;
8125    Evas_Object *edje;
8126    Edje_Color_Class *cc = NULL;
8127
8128    if (!color_class) return;
8129
8130    buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
8131    eina_hash_del(sd->color_classes, buf, cc);
8132
8133    edje = _elm_widget_item_edje_get(obj, sd);
8134    if (edje)
8135      edje_object_color_class_del(edje, buf);
8136
8137    eina_stringshare_del(buf);
8138 }
8139
8140 EOLIAN void
8141 _elm_widget_item_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
8142 {
8143    Evas_Object *edje;
8144    ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
8145
8146    edje = _elm_widget_item_edje_get(obj, sd);
8147    if (!edje) return;
8148
8149    edje_object_color_class_clear(edje);
8150 }
8151 //
8152
8153 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
8154 void
8155 _elm_widget_color_class_parent_set(Evas_Object *obj, Evas_Object *parent)
8156 {
8157    Evas_Object *edje = NULL, *parent_edje = NULL;
8158
8159    if (!obj || !parent) return;
8160
8161    if (eo_isa(obj, ELM_LAYOUT_CLASS))
8162      edje =  elm_layout_edje_get(obj);
8163    else if (eo_isa(obj, EDJE_OBJECT_CLASS))
8164      edje = obj;
8165
8166    if (eo_isa(parent, ELM_LAYOUT_CLASS))
8167      parent_edje =  elm_layout_edje_get(parent);
8168    else if (eo_isa(parent, EDJE_OBJECT_CLASS))
8169      parent_edje = parent;
8170
8171    if (!edje || !parent_edje) return;
8172
8173    edje_object_color_class_parent_set(edje, parent_edje);
8174 }
8175
8176 void
8177 _elm_widget_color_class_parent_unset(Evas_Object *obj)
8178 {
8179    Evas_Object *edje = NULL;
8180
8181    if (!obj) return;
8182
8183    if (eo_isa(obj, ELM_LAYOUT_CLASS))
8184      edje =  elm_layout_edje_get(obj);
8185    else if (eo_isa(obj, EDJE_OBJECT_CLASS))
8186      edje = obj;
8187
8188    if (!edje) return;
8189
8190    edje_object_color_class_parent_unset(edje);
8191 }
8192 /* END */
8193
8194 //TIZEN_ONLY(20160527): widget: add AtspiAction interface to all widgets and widget_items, add handlers for reading stopped/cancelled
8195 EOLIAN const Elm_Atspi_Action *
8196 _elm_widget_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
8197 {
8198    return NULL;
8199 }
8200
8201 EOLIAN const Elm_Atspi_Action *
8202 _elm_widget_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *pd EINA_UNUSED)
8203 {
8204    return NULL;
8205 }
8206 //
8207
8208 #include "elm_widget_item.eo.c"
8209 #include "elm_widget.eo.c"