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