efl_access_object: Support org.a11y.atspi.Value.Text property
[platform/upstream/efl.git] / src / lib / elementary / efl_ui_widget.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_COMPONENT_PROTECTED
7 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
8 #define ELM_WIDGET_PROTECTED
9 #define ELM_WIDGET_ITEM_PROTECTED
10 #define EFL_INPUT_EVENT_PROTECTED
11 #define EFL_UI_L10N_PROTECTED
12 #define EFL_UI_FOCUS_OBJECT_PROTECTED
13 #define EFL_UI_WIDGET_PART_BG_PROTECTED
14 #define EFL_PART_PROTECTED
15
16 #include <Elementary.h>
17
18 #include "elm_priv.h"
19 #include "elm_widget_container.h"
20 #include "elm_interface_scrollable.h"
21 #include "elm_pan_eo.h"
22 #include "elm_part_helper.h"
23 #include "elm_widget_combobox.h"
24
25 #define MY_CLASS EFL_UI_WIDGET_CLASS
26
27 #define MY_CLASS_NAME "Efl_Ui_Widget"
28 #define MY_CLASS_NAME_LEGACY "elm_widget"
29
30 #define API_ENTRY                                    \
31   Elm_Widget_Smart_Data *sd = NULL;                  \
32   if (!_elm_widget_is(obj) ||                        \
33       (!(sd = efl_data_scope_get(obj, MY_CLASS))))
34
35 #define INTERNAL_ENTRY                               \
36   ELM_WIDGET_DATA_GET(obj, sd);                      \
37   if (!sd) return
38
39 #define ELM_WIDGET_FOCUS_GET(obj)                                          \
40   (efl_isa(obj, EFL_UI_WIDGET_CLASS) &&                                    \
41    ((_elm_access_auto_highlight_get()) ? (elm_widget_highlight_get(obj)) : \
42                                          (efl_ui_focus_object_focus_get(obj))))
43
44 const char SIG_WIDGET_FOCUSED[] = "focused";
45 const char SIG_WIDGET_UNFOCUSED[] = "unfocused";
46 const char SIG_WIDGET_LANG_CHANGED[] = "language,changed";
47 const char SIG_WIDGET_ACCESS_CHANGED[] = "access,changed";
48
49 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
50 const char SIG_WIDGET_ATSPI_HIGHLIGHTED[] = "atspi,highlighted";
51 const char SIG_WIDGET_ATSPI_UNHIGHLIGHTED[] = "atspi,unhighlighted";
52 //
53 typedef struct _Elm_Event_Cb_Data         Elm_Event_Cb_Data;
54 typedef struct _Elm_Label_Data            Elm_Label_Data;
55 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
56
57 static Eina_Error _efl_ui_property_bind(Eo *widget, Eo *target, Efl_Ui_Widget_Data *pd,
58                                         const char *part,
59                                         const char *key, const char *property);
60
61 struct _Elm_Event_Cb_Data
62 {
63    Elm_Event_Cb func;
64    const void  *data;
65 };
66
67 struct _Elm_Label_Data
68 {
69    const char *part;
70    const char *text;
71 };
72
73 struct _Elm_Translate_String_Data
74 {
75    EINA_INLIST;
76    Eina_Stringshare *id;
77    Eina_Stringshare *domain;
78    Eina_Stringshare *string;
79    Eina_Bool   preset : 1;
80 };
81
82 // TIZEN_ONLY PROTOTYPES
83 static void _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *sd, Efl_Text_Bidirectional_Type dir);  // TIZEN_ONLY(20180117): Override Paragraph Direction APIs
84 static void _if_focused_revert(Evas_Object *obj, Eina_Bool can_focus_only); //TIZEN_ONLY(20180607): Restore legacy focus
85
86 static void _on_sub_obj_hide(void *data, const Efl_Event *event);
87
88 static inline Eina_Bool _elm_widget_focus_chain_manager_is(const Evas_Object *obj);
89 static inline Eina_Bool _internal_elm_widget_focus_direction_manager_is(const Evas_Object *obj);
90 static void _parent_focus(Evas_Object *obj, Elm_Object_Item *item);
91 static void _elm_object_focus_chain_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
92
93 static Eina_List *_lines_split(Eina_List *children);
94 static int _sort_vertically(const void *data1, const void *data2);
95 static int _sort_horizontally(const void *data1, const void *data2);
96
97 Eo * plug_type_proxy_get(const Eo *obj, Evas_Object *widget);
98
99 // TIZEN_ONLY(20200623) : apply Tizen's color_class features
100 static Eina_Bool _elm_widget_color_class_update(Eo *obj, Elm_Widget_Smart_Data *sd);
101 //
102
103 static Eina_Bool _elm_widget_can_highlight_get_by_class(Eo *obj);
104 static Eina_Bool _accessible_object_on_scroll_is(Eo* obj);
105 // TIZEN_ONLY
106
107
108
109
110 /* For keeping backward compatibility (EFL 1.18 or older versions).
111  * Since EFL 1.19 which starts to use eolian_gen2, it does not convert
112  * "." to "_" among the class name. */
113 static const char *legacy_type_table[][2] =
114 {
115      { "Efl.Ui.Bg_Legacy", "Elm_Bg" },
116      { "Efl.Ui.Button_Legacy", "Elm_Button" },
117      { "Efl.Ui.Check_Legacy", "Elm_Check" },
118      { "Efl.Ui.Clock_Legacy", "Elm_Datetime" },
119      { "Efl.Ui.Flip_Legacy", "Elm_Flip" },
120      { "Efl.Ui.Frame_Legacy", "Elm_Frame" },
121      { "Efl.Ui.Image_Legacy", "Elm_Image" },
122      { "Efl.Ui.Image_Zoomable_Legacy", "Elm_Photocam" },
123      { "Efl.Ui.Layout_Legacy", "Elm_Layout" },
124      { "Efl.Ui.Panes_Legacy", "Elm_Panes" },
125      { "Efl.Ui.Progressbar_Legacy", "Elm_Progressbar" },
126      { "Efl.Ui.Radio_Legacy", "Elm_Radio" },
127      { "Efl.Ui.Video_Legacy", "Elm_Video" },
128      { "Efl.Ui.Win_Legacy", "Elm_Win" },
129      { "Efl.Ui.Win_Socket_Legacy", "Elm_Win" },
130      { "Efl.Ui.Win_Inlined_Legacy", "Elm_Win" },
131      { "Elm.Code_Widget_Legacy", "Elm_Code_Widget" },
132      { "Elm.Ctxpopup", "Elm_Ctxpopup" },
133      { "Elm.Entry", "Elm_Entry" },
134      { "Elm.Colorselector", "Elm_Colorselector" },
135      { "Elm.List", "Elm_List" },
136      { "Elm.Photo", "Elm_Photo" },
137      { "Elm.Actionslider", "Elm_Actionslider" },
138      { "Elm.Box", "Elm_Box" },
139      { "Elm.Table", "Elm_Table" },
140      { "Elm.Thumb", "Elm_Thumb" },
141      { "Elm.Menu", "Elm_Menu" },
142      { "Elm.Icon", "Elm_Icon" },
143      { "Elm.Prefs", "Elm_Prefs" },
144      { "Elm.Map", "Elm_Map" },
145      { "Elm.Glview", "Elm_Glview" },
146      { "Elm.Web", "Elm_Web" },
147      { "Elm.Toolbar", "Elm_Toolbar" },
148      { "Elm.Grid", "Elm_Grid" },
149      { "Elm.Diskselector", "Elm_Diskselector" },
150      { "Elm.Notify", "Elm_Notify" },
151      { "Elm.Mapbuf", "Elm_Mapbuf" },
152      { "Elm.Separator", "Elm_Separator" },
153      { "Elm.Calendar", "Elm_Calendar" },
154      { "Elm.Inwin", "Elm_Inwin" },
155      { "Elm.Gengrid", "Elm_Gengrid" },
156      { "Elm.Scroller", "Elm_Scroller" },
157      { "Elm.Player", "Elm_Player" },
158      { "Elm.Segment_Control", "Elm_Segment_Control" },
159      { "Elm.Fileselector", "Elm_Fileselector" },
160      { "Elm.Fileselector_Button", "Elm_Fileselector_Button" },
161      { "Elm.Fileselector_Entry", "Elm_Fileselector_Entry" },
162      { "Elm.Flipselector", "Elm_Flipselector" },
163      { "Elm.Hoversel", "Elm_Hoversel" },
164      { "Elm.Naviframe", "Elm_Naviframe" },
165      { "Elm.Popup", "Elm_Popup" },
166      { "Elm.Bubble", "Elm_Bubble" },
167      { "Elm.Clock", "Elm_Clock" },
168      { "Elm.Conformant", "Elm_Conformant" },
169      { "Elm.Dayselector", "Elm_Dayselector" },
170      { "Elm.Genlist", "Elm_Genlist" },
171      { "Elm.Hover", "Elm_Hover" },
172      { "Elm.Index", "Elm_Index" },
173      { "Elm.Label", "Elm_Label" },
174      { "Elm.Panel", "Elm_Panel" },
175      { "Elm.Slider", "Elm_Slider" },
176      { "Elm.Slideshow", "Elm_Slideshow" },
177      { "Elm.Spinner", "Elm_Spinner" },
178      { "Elm.Plug", "Elm_Plug" },
179      { "Elm.Web.None", "Elm_Web" },
180      { "Elm.Multibuttonentry", "Elm_Multibuttonentry" },
181      /* TIZEN_ONLY(20180423): add additional class names for legacy API calls */
182      { "Efl.Ui.Bg", "Elm_Bg" },
183      { "Efl.Ui.Button", "Elm_Button" },
184      { "Efl.Ui.Check", "Elm_Check" },
185      { "Efl.Ui.Clock", "Elm_Datetime" },
186      { "Efl.Ui.Flip", "Elm_Flip" },
187      { "Efl.Ui.Frame", "Elm_Frame" },
188      { "Efl.Ui.Image", "Elm_Image" },
189      { "Efl.Ui.Image_Zoomable", "Elm_Photocam" },
190      { "Efl.Ui.Layout", "Elm_Layout" },
191      { "Efl.Ui.Multibuttonentry", "Elm_Multibuttonentry" },
192      { "Efl.Ui.Panes", "Elm_Panes" },
193      { "Efl.Ui.Progressbar", "Elm_Progressbar" },
194      { "Efl.Ui.Radio", "Elm_Radio" },
195      { "Efl.Ui.Slider", "Elm_Slider" },
196      { "Efl.Ui.Video", "Elm_Video" },
197      { "Efl.Ui.Win", "Elm_Win" },
198      { "Elm.Code_Widget", "Elm_Code_Widget" },
199      { "Elm.Gesture_Layer", "Elm_Gesture_Layer" },
200      /* END */
201      /* TIZEN_ONLY(20180504): add missing item class names and fix edje_class parse rule for legacy */
202      { "Elm.Naviframe.Item", "Elm_Naviframe_Item" },
203      { "Elm.Genlist.Item", "Elm_Genlist_Item" },
204      { "Elm.Gengrid.Item", "Elm_Gengrid_Item" },
205      { "Elm.Toolbar_Item", "Elm_Toolbar_Item" },
206      { "Elm.Multibuttonentry_Item", "Elm_Multibuttonentry_Item" },
207      { "Elm.Ctxpopup.Item", "Elm_Ctxpopup_Item" },
208      { "Elm.Hoversel.Item", "Elm_Hoversel_Item" },
209      { "Elm.Index.Item", "Elm_Index_Item" },
210      { "Elm.Popup.Item", "Elm_Popup_Item" },
211      { "Elm.List.Item", "Elm_List_Item" },
212      { "Elm.Color.Item", "Elm_Color_Item" },
213      /* END */
214      { NULL, NULL }
215 };
216
217 //TIZEN_ONLY(20180607): Restore legacy focus
218 static unsigned int focus_order = 0;
219 //
220
221 /* local subsystem globals */
222 static inline Eina_Bool
223 _elm_widget_is(const Evas_Object *obj)
224 {
225    return efl_isa(obj, MY_CLASS);
226 }
227
228 static inline Eina_Bool
229 _is_focusable(Evas_Object *obj)
230 {
231    API_ENTRY return EINA_FALSE;
232 //TIZEN_ONLY(20190312): Restore child_can_focus
233    //return sd->can_focus || (sd->logical.child_count > 0);
234    return sd->can_focus || (sd->child_can_focus);
235 //
236 }
237
238 static inline Eina_Bool
239 _is_focused(Evas_Object *obj)
240 {
241    API_ENTRY return EINA_FALSE;
242    return sd->focused;
243 }
244
245 static inline Eina_Bool
246 _elm_scrollable_is(const Evas_Object *obj)
247 {
248    INTERNAL_ENTRY EINA_FALSE;
249    if (elm_widget_is_legacy(obj))
250      return
251         efl_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
252    else
253      return
254         efl_isa(obj, EFL_UI_SCROLLABLE_INTERFACE);
255 }
256
257 static void
258 _on_sub_obj_del(void *data, const Efl_Event *event);
259 static void _propagate_event(void *data, const Efl_Event *eo_event);
260 static void _elm_widget_shadow_update(Efl_Ui_Widget *obj);
261
262 EFL_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks,
263                           //TIZEN_ONLY(20180607): Restore legacy focus
264                           { EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _on_sub_obj_hide });
265                           //
266 EFL_CALLBACKS_ARRAY_DEFINE(efl_subitems_callbacks,
267                           { EFL_EVENT_DEL, _on_sub_obj_del });
268 EFL_CALLBACKS_ARRAY_DEFINE(focus_callbacks,
269                           { EFL_EVENT_KEY_DOWN, _propagate_event },
270                           { EFL_EVENT_KEY_UP, _propagate_event },
271                           { EFL_EVENT_POINTER_WHEEL, _propagate_event });
272
273 static inline void
274 _callbacks_add(Eo *widget, void *data)
275 {
276     efl_event_callback_array_add(widget, efl_subitems_callbacks(), data);
277 }
278
279 static inline void
280 _callbacks_del(Eo *widget, void *data)
281 {
282     efl_event_callback_array_del(widget, efl_subitems_callbacks(), data);
283 }
284
285 void
286 _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *eo_it)
287 {
288    const char *str;
289
290    if (!eo_it) return;
291    if (efl_isa(eo_it, ELM_WIDGET_ITEM_CLASS))
292      {
293         Elm_Widget_Item_Data *it = efl_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
294
295         if (efl_isa(it->view, EFL_UI_LAYOUT_BASE_CLASS))
296           str = edje_object_data_get(elm_layout_edje_get(it->view), "focus_highlight");
297         else
298           str = edje_object_data_get(it->view, "focus_highlight");
299      }
300    else
301       str = edje_object_data_get(((Elm_Widget_Item_Data *)eo_it)->view, "focus_highlight");
302    if ((str) && (!strcmp(str, "on")))
303      elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
304    else
305      elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
306 }
307
308 void
309 _elm_widget_focus_highlight_start(const Evas_Object *obj)
310 {
311    Evas_Object *top = efl_provider_find(obj, EFL_UI_WIN_CLASS);
312
313    EINA_SAFETY_ON_FALSE_RETURN(efl_isa(top, EFL_UI_WIN_CLASS));
314
315    _elm_win_focus_highlight_start(top);
316 }
317
318 Evas_Object *
319 _efl_ui_widget_focus_highlight_object_get(const Evas_Object *obj)
320 {
321    Evas_Object *top = efl_provider_find(obj, EFL_UI_WIN_CLASS);
322
323    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(top, EFL_UI_WIN_CLASS), NULL);
324
325    return _elm_win_focus_highlight_object_get(top);
326 }
327
328 //TIZEN_ONLY(20200217): comment out unused function
329 /*
330 static Eina_Bool
331 _legacy_focus_eval(Eo *obj)
332 {
333    Eina_List *lst;
334    Efl_Ui_Widget *wid = obj, *top;
335    Elm_Widget_Smart_Data *wid_pd;
336
337    wid_pd = efl_data_scope_get(wid, MY_CLASS);
338    do {
339
340      top = wid;
341
342      wid = elm_widget_parent_get(wid);
343      if (!wid) break;
344      wid_pd = efl_data_scope_get(wid, MY_CLASS);
345
346      lst = wid_pd->legacy_focus.custom_chain;
347      if (lst)
348        {
349           if (!eina_list_data_find(lst, top))
350             {
351                WRN("Widget %p disabled due to custom chain of %p", top, wid);
352                return EINA_TRUE;
353             }
354        }
355
356    } while (1);
357
358    return !efl_isa(top, EFL_UI_WIN_CLASS);
359 }
360 */
361
362 static void _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd);
363 //TIZEN_ONLY(20200217): comment out unused function
364 /*
365 static Efl_Ui_Focus_Object*
366 _focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
367 {
368    Evas_Object *provider = NULL;
369    Evas_Object *parent;
370    Efl_Ui_Focus_Manager *new = NULL, *old = NULL;
371
372    parent = elm_widget_parent_get(obj);
373    if (efl_isa(parent, EFL_UI_FOCUS_MANAGER_INTERFACE))
374      {
375         new = parent;
376      }
377    else if (parent)
378      {
379         new = efl_ui_focus_object_focus_manager_get(parent);
380         provider = parent;
381      }
382
383    if (new != pd->manager.manager)
384      {
385         old = pd->manager.manager;
386
387         pd->manager.manager = new;
388         pd->manager.provider = provider;
389      }
390
391    return old;
392 }
393 */
394
395 EOLIAN static Eina_Bool
396 _efl_ui_widget_focus_state_apply(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect)
397 {
398    Eina_Bool registered = EINA_TRUE;
399
400    //shortcut for having the same configurations
401    if (current_state.manager == configured_state->manager && !current_state.manager)
402      return !!current_state.manager;
403
404    if (configured_state->logical == current_state.logical &&
405        configured_state->manager == current_state.manager &&
406        configured_state->parent == current_state.parent)
407      return !!current_state.manager;
408
409    //this thing doesnt want to be registered, but it is ...
410    if (!configured_state->manager && current_state.manager)
411      {
412         efl_ui_focus_manager_calc_unregister(current_state.manager, obj);
413         return EINA_FALSE;
414      }
415    //by that point we have always a configured manager
416
417    if (!current_state.manager) registered = EINA_FALSE;
418
419    if ((//check if we have changed the manager
420         (current_state.manager != configured_state->manager) ||
421         //check if we are already registered but in a different state
422         (current_state.logical != configured_state->logical))
423        && registered)
424      {
425         //we need to unregister here
426         efl_ui_focus_manager_calc_unregister(current_state.manager, obj);
427         registered = EINA_FALSE;
428      }
429
430    //the parent may has changed
431    if (current_state.parent != configured_state->parent && registered)
432      {
433         return efl_ui_focus_manager_calc_update_parent(current_state.manager, obj, configured_state->parent);
434      }
435
436    if (!registered)
437      {
438         if (configured_state->logical)
439           return efl_ui_focus_manager_calc_register_logical(configured_state->manager, obj, configured_state->parent, redirect);
440         else
441           return efl_ui_focus_manager_calc_register(configured_state->manager, obj, configured_state->parent, redirect);
442      }
443    ERR("Uncaught focus state consider this as unregistered (%d) \n (%p,%p,%d) \n (%p,%p,%d) ", registered,
444      configured_state->manager, configured_state->parent, configured_state->logical,
445      current_state.manager, current_state.parent, current_state.logical
446    );
447    return EINA_FALSE;
448 }
449 //TIZEN_ONLY(20200217): comment out unused function
450 /*
451 static void
452 _eval_registration_candidate(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool *should, Eina_Bool *want_full)
453 {
454    *should = *want_full = EINA_FALSE;
455
456     //can focus can be overridden by the following properties
457     if ((!pd->parent_obj) ||
458         (!evas_object_visible_get(obj)) ||
459         pd->disabled > 0 ||
460         pd->tree_unfocusable > 0)
461       return;
462
463     if (!pd->shared_win_data || ((Efl_Ui_Shared_Win_Data*)pd->shared_win_data)->legacy_focus_api_used)
464       {
465          if (_legacy_focus_eval(obj))
466            return;
467       }
468
469     if (pd->can_focus)
470       {
471          *should = *want_full = EINA_TRUE;
472       }
473     else if (pd->logical.child_count > 0)
474       {
475          *should = EINA_TRUE;
476       }
477 }
478
479 static void
480 _focus_state_eval(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool should, Eina_Bool want_full)
481 {
482    Efl_Ui_Widget_Focus_State configuration;
483
484    //this would mean we are registering again the root, we dont want that
485    if (pd->manager.manager == obj) return;
486
487    //there are two reasons to be registered, the child count is bigger than 0, or the widget is flagged to be able to handle focus
488    if (should)
489      {
490         configuration.parent = pd->logical.parent;
491         configuration.manager = pd->manager.manager;
492         configuration.logical = !want_full;
493      }
494    else
495      {
496         configuration.parent = NULL;
497         configuration.manager = NULL;
498         configuration.logical = EINA_FALSE;
499      }
500
501    if (!efl_ui_widget_focus_state_apply(obj, pd->focus, &configuration, NULL))
502      {
503         //things went wrong or this thing is unregistered. Purge the current configuration.
504         pd->focus.manager = NULL;
505         pd->focus.parent = NULL;
506         pd->focus.logical = EINA_FALSE;
507      }
508    else
509      {
510         pd->focus.parent = configuration.parent;
511         pd->focus.manager = configuration.manager;
512         pd->focus.logical = configuration.logical;
513      }
514
515 }
516
517 static Efl_Ui_Focus_Object*
518 _logical_parent_eval(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd, Eina_Bool should, Eina_Bool *state_change_to_parent)
519 {
520    Efl_Ui_Widget *parent;
521    Efl_Ui_Focus_Parent_Provider *provider;
522
523    if (!pd->shared_win_data || ((Efl_Ui_Shared_Win_Data*)pd->shared_win_data)->custom_parent_provider)
524      {
525         if (should)
526           {
527              provider = efl_provider_find(obj, EFL_UI_FOCUS_PARENT_PROVIDER_INTERFACE);
528              EINA_SAFETY_ON_NULL_RETURN_VAL(provider, NULL);
529              parent = efl_ui_focus_parent_provider_find_logical_parent(provider, obj);
530           }
531         else
532           parent = NULL;
533      }
534    else
535      {
536         parent = efl_ui_widget_parent_get(obj);
537      }
538
539
540    if (pd->logical.parent != parent)
541      {
542         Efl_Ui_Focus_Object *old = NULL;
543
544         //update old logical parent;
545         if (pd->logical.parent)
546           {
547              if (efl_isa(pd->logical.parent, EFL_UI_WIDGET_CLASS))
548                {
549                   ELM_WIDGET_DATA_GET_OR_RETURN(pd->logical.parent, logical_wd, NULL);
550                   logical_wd->logical.child_count --;
551                   if (logical_wd->logical.child_count == 0)
552                     {
553                       *state_change_to_parent = EINA_TRUE;
554                     }
555                }
556              old = pd->logical.parent;
557              efl_weak_unref(&pd->logical.parent);
558              pd->logical.parent = NULL;
559           }
560         if (parent)
561           {
562              if (efl_isa(parent, EFL_UI_WIDGET_CLASS))
563                {
564                   ELM_WIDGET_DATA_GET_OR_RETURN(parent, parent_wd, NULL);
565                   parent_wd->logical.child_count ++;
566                   if (parent_wd->logical.child_count == 1)
567                     {
568                       *state_change_to_parent = EINA_TRUE;
569                     }
570                }
571              pd->logical.parent = parent;
572              efl_weak_ref(&pd->logical.parent);
573           }
574         return old;
575      }
576    return NULL;
577 }
578 */
579
580 static void
581 //TIZEN_ONLY(20200220): add EINA_UNUSED for unused parameters
582 _full_eval(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
583 //_full_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
584 //
585 {
586    //TIZEN_ONLY(20180607): Restore legacy focus
587    return;
588    /*
589    Efl_Ui_Focus_Object *old_parent;
590    Efl_Ui_Focus_Object *old_registered_parent, *old_registered_manager;
591    Eina_Bool should, want_full, state_change_to_parent = EINA_FALSE;
592
593    _eval_registration_candidate(obj, pd, &should, &want_full);
594
595    old_parent = _logical_parent_eval(obj, pd, should, &state_change_to_parent);
596
597    if (state_change_to_parent)
598      {
599         if (efl_isa(old_parent, EFL_UI_WIDGET_CLASS))
600           {
601              //emit signal and focus eval old and new
602              ELM_WIDGET_DATA_GET(old_parent, old_pd);
603              if (old_pd) _full_eval(old_parent, old_pd);
604           }
605
606         if (efl_isa(pd->logical.parent, EFL_UI_WIDGET_CLASS))
607           {
608              ELM_WIDGET_DATA_GET(pd->logical.parent, new_pd);
609              if (new_pd) _full_eval(pd->logical.parent, new_pd);
610           }
611      }
612
613
614    _focus_manager_eval(obj, pd);
615
616    old_registered_parent = pd->focus.parent;
617    old_registered_manager = pd->focus.manager;
618
619    _focus_state_eval(obj, pd, should, want_full);
620
621    if (old_registered_parent != pd->focus.parent)
622      {
623         efl_event_callback_call(obj,
624              EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_PARENT_CHANGED, old_registered_parent);
625      }
626
627    if (old_registered_manager != pd->focus.manager)
628      {
629         _elm_widget_full_eval_children(obj, pd);
630         efl_event_callback_call(obj,
631              EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_MANAGER_CHANGED, old_registered_manager);
632      }
633     */
634    //// END
635
636 }
637
638 void
639 _elm_widget_full_eval(Eo *obj)
640 {
641    ELM_WIDGET_DATA_GET(obj, pd);
642    if (pd) _full_eval(obj, pd);
643 }
644
645 /**
646  * @internal
647  *
648  * Resets the mirrored mode from the system mirror mode for widgets that are in
649  * automatic mirroring mode. This function does not call elm_widget_theme.
650  *
651  * @param obj The widget.
652  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
653  */
654 static void
655 _elm_widget_mirrored_reload(Evas_Object *obj)
656 {
657    API_ENTRY return;
658    Eina_Bool mirrored = elm_config_mirrored_get();
659
660    if (efl_ui_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
661      {
662         sd->is_mirrored = mirrored;
663      }
664 }
665
666 static void
667 _parents_focus(Evas_Object *obj)
668 {
669    for (; obj; obj = elm_widget_parent_get(obj))
670      {
671         INTERNAL_ENTRY;
672         if (sd->focused) return;
673         sd->focused = 1;
674      }
675 }
676
677 static void
678 _parents_unfocus(Evas_Object *obj)
679 {
680    for (; obj; obj = elm_widget_parent_get(obj))
681      {
682         INTERNAL_ENTRY;
683         if (!sd->focused) return;
684         sd->focused = 0;
685      }
686 }
687 //TIZEN_ONLY(20180607): Restore legacy focus
688 static void
689 _on_sub_obj_hide(void *data EINA_UNUSED, const Efl_Event *event)
690 {
691    Eina_Bool *visible = event->info;
692    if ((*visible) == EINA_FALSE)
693      efl_ui_widget_focus_hide_handle(event->object);
694 }
695 //
696 static void
697 _on_sub_obj_del(void *data, const Efl_Event *event)
698 {
699    ELM_WIDGET_DATA_GET_OR_RETURN(data, sd);
700
701    if (_elm_widget_is(event->object))
702      {
703         if (_is_focused(event->object)) _parents_unfocus(data);
704      }
705    if (event->object == sd->resize_obj)
706      {
707         /* already dels sub object */
708         elm_widget_resize_object_set(data, NULL);
709      }
710    else if (event->object == sd->hover_obj)
711      {
712         sd->hover_obj = NULL;
713      }
714    else
715      {
716         if (!elm_widget_sub_object_del(data, event->object))
717           ERR("failed to remove sub object %p from %p\n", event->object, data);
718      }
719 }
720
721 static const Evas_Smart_Cb_Description _smart_callbacks[] =
722 {
723    {SIG_WIDGET_FOCUSED, ""},
724    {SIG_WIDGET_UNFOCUSED, ""},
725    {SIG_WIDGET_LANG_CHANGED, ""},
726    {SIG_WIDGET_ACCESS_CHANGED, ""},
727    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
728    {SIG_WIDGET_ATSPI_HIGHLIGHTED, ""},
729    {SIG_WIDGET_ATSPI_UNHIGHLIGHTED, ""},
730    //
731    {NULL, NULL}
732 };
733
734 static void
735 _obj_mouse_down(void *data,
736                 Evas *e EINA_UNUSED,
737                 Evas_Object *obj EINA_UNUSED,
738                 void *event_info)
739 {
740    Evas_Object *top;
741
742    ELM_WIDGET_DATA_GET(data, sd);
743    if (!sd) return;
744    Evas_Event_Mouse_Down *ev = event_info;
745    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
746
747    top = elm_widget_top_get(data);
748    if (top && efl_isa(top, EFL_UI_WIN_CLASS)) _elm_win_focus_auto_hide(top);
749    sd->still_in = EINA_TRUE;
750 }
751
752 static void
753 _obj_mouse_move(void *data,
754                 Evas *e EINA_UNUSED,
755                 Evas_Object *obj,
756                 void *event_info)
757 {
758    ELM_WIDGET_DATA_GET(data, sd);
759    if (!sd) return;
760    Evas_Event_Mouse_Move *ev = event_info;
761    if (!sd->still_in) return;
762
763    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
764      sd->still_in = EINA_FALSE;
765    else
766      {
767         Evas_Coord x, y, w, h;
768         evas_object_geometry_get(obj, &x, &y, &w, &h);
769         if (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y))
770           sd->still_in = EINA_FALSE;
771      }
772 }
773
774 static void
775 _obj_mouse_up(void *data,
776               Evas *e EINA_UNUSED,
777               Evas_Object *obj,
778               void *event_info)
779 {
780    ELM_WIDGET_DATA_GET(data, sd);
781    if (!sd) return;
782    Evas_Event_Mouse_Up *ev = event_info;
783
784    if (sd->still_in && (ev->flags == EVAS_BUTTON_NONE) &&
785        (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_CLICK) &&
786        !efl_invalidated_get(data))
787      elm_widget_focus_mouse_up_handle(evas_object_widget_parent_find(obj));
788
789    sd->still_in = EINA_FALSE;
790 }
791
792 static void
793 _obj_mouse_in(void *data,
794               Evas *e EINA_UNUSED,
795               Evas_Object *obj,
796               void *event_info EINA_UNUSED)
797 {
798    ELM_WIDGET_DATA_GET(data, sd);
799    if (!sd) return;
800    if (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN &&
801        !efl_invalidated_get(data))
802      elm_widget_focus_mouse_up_handle(evas_object_widget_parent_find(obj));
803 }
804
805 EOLIAN static void
806 _efl_ui_widget_efl_canvas_group_group_add(Eo *obj, Elm_Widget_Smart_Data *priv)
807 {
808    priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale
809                                           * settings */
810    priv->focus_move_policy_auto_mode = EINA_TRUE;
811    priv->focus_region_show_mode = ELM_FOCUS_REGION_SHOW_WIDGET;
812    elm_widget_can_focus_set(obj, EINA_TRUE);
813    priv->is_mirrored = elm_config_mirrored_get();
814    priv->focus_move_policy = _elm_config->focus_move_policy;
815
816    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
817                                   _obj_mouse_down, obj);
818    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
819                                   _obj_mouse_move, obj);
820    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
821                                   _obj_mouse_up, obj);
822    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_IN,
823                                   _obj_mouse_in, obj);
824 }
825
826 static Eina_Bool
827 _keep(void *data, void *gdata)
828 {
829    if (data == gdata)
830      return EINA_FALSE;
831    return EINA_TRUE;
832 }
833
834 EOLIAN static void
835 _efl_ui_widget_efl_canvas_group_group_del(Eo *obj, Elm_Widget_Smart_Data *sd)
836 {
837    Evas_Object *sobj;
838    Elm_Translate_String_Data *ts;
839    Elm_Event_Cb_Data *ecb;
840
841    if (sd->hover_obj)
842      {
843         /* detach it from us */
844         _callbacks_del(sd->hover_obj, obj);
845         sd->hover_obj = NULL;
846      }
847    while(eina_array_count(sd->children))
848      {
849         sobj = eina_array_data_get(sd->children, 0);
850
851         if (!elm_widget_sub_object_del(obj, sobj))
852           {
853              ERR("failed to remove sub object %p from %p\n", sobj, obj);
854              eina_array_remove(sd->children, _keep, sobj);
855           }
856         // FIXME: is that a legacy or a new object ?
857         evas_object_del(sobj);
858         EINA_SAFETY_ON_TRUE_RETURN(eina_array_count(sd->children) && sobj == eina_array_data_get(sd->children, 0));
859      }
860    sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
861    sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
862    while (sd->translate_strings)
863      {
864         ts = EINA_INLIST_CONTAINER_GET(sd->translate_strings,
865                                        Elm_Translate_String_Data);
866         eina_stringshare_del(ts->id);
867         eina_stringshare_del(ts->domain);
868         eina_stringshare_del(ts->string);
869         sd->translate_strings = eina_inlist_remove(sd->translate_strings,
870                                                    sd->translate_strings);
871         free(ts);
872      }
873
874    EINA_LIST_FREE(sd->event_cb, ecb)
875       free(ecb);
876
877    eina_stringshare_del(sd->klass);
878    eina_stringshare_del(sd->group);
879    eina_stringshare_del(sd->style);
880    if (sd->theme) elm_theme_free(sd->theme);
881    //TIZEN_ONLY(20180607): Restore legacy focus
882    _if_focused_revert(obj, EINA_TRUE);
883    efl_ui_widget_focus_custom_chain_unset(obj);
884    //
885    eina_stringshare_del(sd->access_info);
886    eina_stringshare_del(sd->accessible_name);
887    evas_object_smart_data_set(obj, NULL);
888    efl_canvas_group_del(efl_super(obj, MY_CLASS));
889 }
890
891 static void
892 _smart_reconfigure(Eo *obj, Elm_Widget_Smart_Data *sd)
893 {
894    Eina_Rect geom = efl_gfx_entity_geometry_get(obj);
895
896    if (sd->resize_obj)
897      {
898         efl_gfx_entity_geometry_set(sd->resize_obj, geom);
899      }
900    if (sd->hover_obj)
901      {
902         efl_gfx_entity_geometry_set(sd->hover_obj, geom);
903      }
904    if (sd->bg)
905      {
906         efl_gfx_entity_geometry_set(sd->bg, geom);
907      }
908    if (sd->has_shadow)
909      _elm_widget_shadow_update(obj);
910 }
911
912 EOLIAN static void
913 _efl_ui_widget_efl_gfx_entity_position_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Position2D pos)
914 {
915    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
916      return;
917
918    if (sd->resize_obj)
919      efl_gfx_entity_position_set(sd->resize_obj, pos);
920    if (sd->hover_obj)
921      efl_gfx_entity_position_set(sd->hover_obj, pos);
922    if (sd->bg)
923      efl_gfx_entity_position_set(sd->bg, pos);
924
925    if (sd->has_shadow)
926      _elm_widget_shadow_update(obj);
927
928    efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
929 }
930
931 EOLIAN static void
932 _efl_ui_widget_efl_gfx_entity_size_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Size2D sz)
933 {
934    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
935      return;
936
937    if (sd->resize_obj)
938      efl_gfx_entity_size_set(sd->resize_obj, sz);
939    if (sd->hover_obj)
940      efl_gfx_entity_size_set(sd->hover_obj, sz);
941    if (sd->bg)
942      efl_gfx_entity_size_set(sd->bg, sz);
943
944    if (sd->has_shadow)
945      _elm_widget_shadow_update(obj);
946
947    efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
948 }
949
950 void
951 //TIZEN_ONLY(20200220): add EINA_UNUSED for unused parameters
952 _elm_widget_full_eval_children(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED)
953 //_elm_widget_full_eval_children(Eo *obj, Elm_Widget_Smart_Data *sd)
954 //
955 {
956    //TIZEN_ONLY(20180607): Restore legacy focus
957    return;
958    /*
959    Eo *child;
960
961    _full_eval(obj, sd);
962
963    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
964      {
965         Elm_Widget_Smart_Data *sd_child;
966         child = eina_array_data_get(sd->children, i);
967
968         if (!efl_isa(child, EFL_UI_WIDGET_CLASS)) continue;
969
970         sd_child = efl_data_scope_get(child, EFL_UI_WIDGET_CLASS);
971         _elm_widget_full_eval_children(child, sd_child);
972      }
973     */
974    //// END
975 }
976
977 EOLIAN static void
978 _efl_ui_widget_efl_gfx_entity_visible_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool vis)
979 {
980    Eina_Iterator *it;
981    Evas_Object *o;
982
983    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
984      {
985         _elm_widget_full_eval_children(obj, pd);
986         return;
987      }
988
989    efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
990
991    _elm_widget_full_eval_children(obj, pd);
992
993
994    it = evas_object_smart_iterator_new(obj);
995    EINA_ITERATOR_FOREACH(it, o)
996      {
997        if (evas_object_data_get(o, "_elm_leaveme")) continue;
998        efl_gfx_entity_visible_set(o, vis);
999      }
1000    eina_iterator_free(it);
1001
1002    if (!_elm_atspi_enabled() || pd->on_destroy)
1003      return;
1004
1005    if (vis)
1006      {
1007         efl_access_added(obj);
1008         if (_elm_widget_onscreen_is(obj))
1009           efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_SHOWING, EINA_TRUE);
1010      }
1011    else
1012      {
1013         //TIZEN_ONLY(20161223) check if the parent of highlighted object is hide
1014         Eo *highlighted_obj;
1015         highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
1016         if (highlighted_obj && highlighted_obj != obj)
1017           {
1018              Eo *parent;
1019              parent = efl_provider_find(efl_parent_get(highlighted_obj), EFL_ACCESS_OBJECT_MIXIN);
1020              while (parent)
1021                {
1022                   if (parent == obj)
1023                     {
1024                        efl_access_state_changed_signal_emit(highlighted_obj, EFL_ACCESS_STATE_TYPE_SHOWING, EINA_FALSE);
1025                        efl_access_component_highlight_clear(highlighted_obj);
1026                        break;
1027                     }
1028                   parent = efl_provider_find(efl_parent_get(parent), EFL_ACCESS_OBJECT_MIXIN);
1029                }
1030           }
1031         //
1032         efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_SHOWING, EINA_FALSE);
1033      }
1034 }
1035
1036 EOLIAN static void
1037 _efl_ui_widget_efl_gfx_color_color_set(Eo *obj, Elm_Widget_Smart_Data *pd, int r, int g, int b, int a)
1038 {
1039    Eina_Iterator *it;
1040    Evas_Object *o;
1041
1042    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_COLOR_SET, 0, r, g, b, a))
1043      return;
1044
1045    efl_gfx_color_set(efl_super(obj, MY_CLASS), r, g, b, a);
1046
1047    it = evas_object_smart_iterator_new(obj);
1048    EINA_ITERATOR_FOREACH(it, o)
1049      {
1050        if (pd->bg == o) continue;
1051        if (evas_object_data_get(o, "_elm_leaveme")) continue;
1052        evas_object_color_set(o, r, g, b, a);
1053      }
1054    eina_iterator_free(it);
1055 }
1056
1057 EOLIAN static void
1058 _efl_ui_widget_efl_canvas_object_no_render_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool hide)
1059 {
1060    Eina_Iterator *it;
1061    Evas_Object *o;
1062
1063    hide = !!hide;
1064    if (efl_canvas_object_no_render_get(obj) == hide)
1065      return;
1066
1067    it = evas_object_smart_iterator_new(obj);
1068    EINA_ITERATOR_FOREACH(it, o)
1069      {
1070        if (evas_object_data_get(o, "_elm_leaveme")) continue;
1071        efl_canvas_object_no_render_set(o, hide);
1072      }
1073    eina_iterator_free(it);
1074
1075    // bypass implementation in Efl.Canvas.Group
1076    efl_canvas_object_no_render_set(efl_super(obj, EFL_CANVAS_GROUP_CLASS), hide);
1077 }
1078
1079 EOLIAN static void
1080 _efl_ui_widget_efl_canvas_object_is_frame_object_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool frame)
1081 {
1082    Evas_Object *o;
1083
1084    frame = !!frame;
1085    efl_canvas_object_is_frame_object_set(efl_super(obj, MY_CLASS), frame);
1086    for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
1087      {
1088         o = eina_array_data_get(pd->children, i);
1089
1090        if (evas_object_data_get(o, "_elm_leaveme")) continue;
1091        efl_canvas_object_is_frame_object_set(o, frame);
1092      }
1093 }
1094
1095 EOLIAN static void
1096 _efl_ui_widget_efl_canvas_object_clipper_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *clip)
1097 {
1098    Eina_Iterator *it;
1099    Evas_Object *o;
1100
1101    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_CLIP_SET, 0, clip))
1102      return;
1103
1104    efl_canvas_object_clipper_set(efl_super(obj, MY_CLASS), clip);
1105
1106    it = evas_object_smart_iterator_new(obj);
1107    EINA_ITERATOR_FOREACH(it, o)
1108      {
1109        if (evas_object_data_get(o, "_elm_leaveme")) continue;
1110        evas_object_clip_set(o, clip);
1111      }
1112    eina_iterator_free(it);
1113 }
1114
1115 EOLIAN static void
1116 _efl_ui_widget_efl_canvas_group_group_calculate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
1117 {
1118    /* a NO-OP, on the base */
1119    efl_canvas_group_need_recalculate_set(obj, EINA_FALSE);
1120 }
1121
1122 EOLIAN static void
1123 _efl_ui_widget_efl_canvas_group_group_member_add(Eo *obj, Elm_Widget_Smart_Data *pd, Evas_Object *child)
1124 {
1125    int r, g, b, a;
1126    efl_canvas_group_member_add(efl_super(obj, MY_CLASS), child);
1127
1128    if (evas_object_data_get(child, "_elm_leaveme")) return;
1129
1130    if (pd->bg != child)
1131      {
1132         evas_object_color_get(obj, &r, &g, &b, &a);
1133         evas_object_color_set(child, r, g, b, a);
1134      }
1135
1136    efl_canvas_object_no_render_set(child, efl_canvas_object_no_render_get(obj));
1137    evas_object_clip_set(child, evas_object_clip_get(obj));
1138
1139    if (evas_object_visible_get(obj))
1140      evas_object_show(child);
1141    else
1142      evas_object_hide(child);
1143 }
1144
1145 EOLIAN static void
1146 _efl_ui_widget_efl_canvas_group_group_member_remove(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
1147 {
1148    if (!evas_object_data_get(child, "_elm_leaveme"))
1149       evas_object_clip_unset(child);
1150    efl_canvas_group_member_remove(efl_super(obj, MY_CLASS), child);
1151 }
1152
1153 // internal funcs
1154 static void
1155 _propagate_x_drag_lock(Evas_Object *obj,
1156                        int dir)
1157 {
1158    INTERNAL_ENTRY;
1159    if (sd->parent_obj)
1160      {
1161         ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
1162         if (sd2)
1163           {
1164              sd2->child_drag_x_locked += dir;
1165              _propagate_x_drag_lock(sd->parent_obj, dir);
1166           }
1167      }
1168 }
1169
1170 static void
1171 _propagate_y_drag_lock(Evas_Object *obj,
1172                        int dir)
1173 {
1174    INTERNAL_ENTRY;
1175    if (sd->parent_obj)
1176      {
1177         ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
1178         if (sd2)
1179           {
1180              sd2->child_drag_y_locked += dir;
1181              _propagate_y_drag_lock(sd->parent_obj, dir);
1182           }
1183      }
1184 }
1185
1186 static Eina_Bool
1187 _propagate_event_legacy(Eo *parent, const Efl_Event *event, Eo *obj, Elm_Event_Cb_Data *ecd)
1188 {
1189    Evas_Callback_Type type;
1190    Evas_Event_Flags *event_flags, prev_flags;
1191    union {
1192       Evas_Event_Key_Down    *down;
1193       Evas_Event_Key_Up      *up;
1194       Evas_Event_Mouse_Wheel *wheel;
1195       void                   *any;
1196    } event_info;
1197
1198    if (event->desc == EFL_EVENT_KEY_DOWN)
1199      {
1200         event_info.down = efl_input_legacy_info_get(event->info);
1201         EINA_SAFETY_ON_NULL_RETURN_VAL(event_info.down, EINA_FALSE);
1202         type = EVAS_CALLBACK_KEY_DOWN;
1203         event_flags = &event_info.down->event_flags;
1204      }
1205    else if (event->desc == EFL_EVENT_KEY_UP)
1206      {
1207         event_info.up = efl_input_legacy_info_get(event->info);
1208         EINA_SAFETY_ON_NULL_RETURN_VAL(event_info.up, EINA_FALSE);
1209         type = EVAS_CALLBACK_KEY_UP;
1210         event_flags = &event_info.up->event_flags;
1211      }
1212    else if (event->desc == EFL_EVENT_POINTER_WHEEL)
1213      {
1214         event_info.wheel = efl_input_legacy_info_get(event->info);
1215         EINA_SAFETY_ON_NULL_RETURN_VAL(event_info.wheel, EINA_FALSE);
1216         type = EVAS_CALLBACK_MOUSE_WHEEL;
1217         event_flags = &event_info.wheel->event_flags;
1218      }
1219    else
1220      return EINA_FALSE;
1221
1222    prev_flags = *event_flags;
1223    if (ecd->func((void *)ecd->data, parent, obj, type, event_info.any) ||
1224        ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))
1225      {
1226         if (prev_flags != *event_flags)
1227           efl_input_event_flags_set(event->info, (Efl_Input_Flags)*event_flags);
1228         return EINA_TRUE;
1229      }
1230
1231    return EINA_FALSE;
1232 }
1233
1234 /**
1235  * @internal
1236  *
1237  * If elm_widget_focus_region_get() returns an empty rect (w or h <= 0),
1238  * this function will ignore region show action.
1239  */
1240 EAPI void
1241 elm_widget_focus_region_show(Eo *obj)
1242 {
1243    Evas_Coord ox, oy;
1244    Eina_Rect r;
1245    Evas_Object *o;
1246
1247    o = elm_widget_parent_get(obj);
1248    if (!o) return;
1249
1250    r = elm_widget_focus_region_get(obj);
1251    if (eina_rectangle_is_empty(&r.rect)) return;
1252
1253    evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
1254
1255    while (o)
1256      {
1257         Evas_Coord px, py;
1258         evas_object_geometry_get(o, &px, &py, NULL, NULL);
1259
1260         if (_elm_scrollable_is(o) && !elm_widget_disabled_get(o))
1261           {
1262              Evas_Coord sx, sy;
1263              Evas_Coord vx, vy;
1264
1265              //TIZEN_ONLY(202191209): restore legacy focus of scrollable
1266              if (elm_widget_is_legacy(o))
1267                {
1268                   elm_interface_scrollable_content_region_get(o, &sx, &sy, NULL, NULL);
1269                   elm_interface_scrollable_content_viewport_geometry_get(o, &vx, &vy, NULL, NULL);
1270                }
1271              else
1272                {
1273                   Eina_Position2D pos = efl_ui_scrollable_content_pos_get(o);
1274                   Eina_Rect rect = efl_ui_scrollable_viewport_geometry_get(o);
1275                   sx = pos.x;
1276                   sy = pos.y;
1277                   vx = rect.x;
1278                   vy = rect.y;
1279                }
1280
1281              //elm_interface_scrollable_content_region_get(o, &sx, &sy, NULL, NULL);
1282              //elm_interface_scrollable_content_viewport_geometry_get(o, &vx, &vy, NULL, NULL);
1283              //
1284
1285              // Get the object's on_focus_region position relative to the pan in the scroller.
1286              Evas_Coord rx, ry;
1287              rx = ox + r.x - vx + sx;
1288              ry = oy + r.y - vy + sy;
1289
1290              switch (_elm_config->focus_autoscroll_mode)
1291                {
1292                 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
1293                    if (elm_widget_is_legacy(o))
1294                      //TIZEN_ONLY(20200917): disable auto scroll
1295                      {
1296                        int popup_data = evas_object_data_get(o, "popup_scroll");
1297                        if (!popup_data)
1298                          elm_interface_scrollable_content_region_show(o, rx, ry, r.w, r.h);
1299                      }
1300                      //
1301                    else
1302                      efl_ui_scrollable_scroll(o, r, EINA_FALSE);
1303                    break;
1304                 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
1305                    if (elm_widget_is_legacy(o))
1306                      elm_interface_scrollable_region_bring_in(o, rx, ry, r.w, r.h);
1307                    else
1308                      efl_ui_scrollable_scroll(o, r, EINA_TRUE);
1309                    break;
1310                 default:
1311                    break;
1312                }
1313
1314              r = elm_widget_focus_region_get(o);
1315              evas_object_geometry_get(o, &ox, &oy, NULL, NULL);
1316           }
1317         else
1318           {
1319              r.x += ox - px;
1320              r.y += oy - py;
1321              ox = px;
1322              oy = py;
1323           }
1324         o = elm_widget_parent_get(o);
1325      }
1326 }
1327
1328
1329 EAPI Eina_Bool
1330 elm_widget_api_check(int ver)
1331 {
1332    if (ver != ELM_INTERNAL_API_VERSION)
1333      {
1334         CRI("Elementary widget api versions do not match");
1335         return EINA_FALSE;
1336      }
1337    return EINA_TRUE;
1338 }
1339
1340 EAPI Eina_Bool
1341 elm_widget_access(Evas_Object *obj,
1342                   Eina_Bool is_access)
1343 {
1344    Evas_Object *child;
1345    Eina_Bool ret = EINA_TRUE;
1346
1347    API_ENTRY return EINA_FALSE;
1348    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
1349      {
1350         child = eina_array_data_get(sd->children, i);
1351
1352         if (elm_widget_is(child))
1353           ret &= elm_widget_access(child, is_access);
1354      }
1355
1356    efl_ui_widget_on_access_update(obj, is_access);
1357    efl_event_callback_legacy_call(obj, EFL_UI_WIDGET_EVENT_ACCESS_CHANGED, NULL);
1358
1359    return ret;
1360 }
1361
1362 EOLIAN static void
1363 _efl_ui_widget_on_access_update(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_access EINA_UNUSED)
1364 {
1365 }
1366
1367 static void
1368 _elm_widget_theme_helper(Eina_Error err, Eina_Bool *err_default, Eina_Bool *err_generic)
1369 {
1370    if (err == EFL_UI_THEME_APPLY_ERROR_DEFAULT)
1371      *err_default = EINA_TRUE;
1372    else if (err == EFL_UI_THEME_APPLY_ERROR_GENERIC)
1373      *err_generic = EINA_TRUE;
1374 }
1375
1376 EAPI Eina_Error
1377 elm_widget_theme(Evas_Object *obj)
1378 {
1379    const Eina_List *l;
1380    Evas_Object *child;
1381    Elm_Tooltip *tt;
1382    Elm_Cursor *cur;
1383    Eina_Bool err_default = EINA_FALSE;
1384    Eina_Bool err_generic = EINA_FALSE;
1385
1386    API_ENTRY return EFL_UI_THEME_APPLY_ERROR_GENERIC;
1387    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
1388      {
1389         child = eina_array_data_get(sd->children, i);
1390         if (_elm_widget_is(child))
1391           _elm_widget_theme_helper(elm_widget_theme(child), &err_default, &err_generic);
1392      }
1393
1394    if (sd->hover_obj)
1395      _elm_widget_theme_helper(elm_widget_theme(sd->hover_obj), &err_default, &err_generic);
1396
1397    EINA_LIST_FOREACH(sd->tooltips, l, tt)
1398      elm_tooltip_theme(tt);
1399    EINA_LIST_FOREACH(sd->cursors, l, cur)
1400      elm_cursor_theme(cur);
1401
1402    _elm_widget_theme_helper(efl_ui_widget_theme_apply(obj), &err_default, &err_generic);
1403    if (err_generic) return EFL_UI_THEME_APPLY_ERROR_GENERIC;
1404    if (err_default) return EFL_UI_THEME_APPLY_ERROR_DEFAULT;
1405
1406    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
1407    if (sd->color_classes)
1408      _elm_widget_color_class_update(obj, sd);
1409    //
1410    return EFL_UI_THEME_APPLY_ERROR_NONE;
1411 }
1412
1413 EAPI void
1414 elm_widget_theme_specific(Evas_Object *obj,
1415                           Elm_Theme *th,
1416                           Eina_Bool force)
1417 {
1418    const Eina_List *l;
1419    Evas_Object *child;
1420    Elm_Tooltip *tt;
1421    Elm_Cursor *cur;
1422    Elm_Theme *th2, *thdef;
1423
1424    API_ENTRY return;
1425
1426    thdef = elm_theme_default_get();
1427    if (!th) th = thdef;
1428    if (!force)
1429      {
1430         th2 = sd->theme;
1431         if (!th2) th2 = thdef;
1432         while (th2)
1433           {
1434              if (th2 == th)
1435                {
1436                   force = EINA_TRUE;
1437                   break;
1438                }
1439              if (th2 == thdef) break;
1440              th2 = th2->ref_theme;
1441              if (!th2) th2 = thdef;
1442           }
1443      }
1444    if (!force) return;
1445    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
1446      {
1447         child = eina_array_data_get(sd->children, i);
1448         if (elm_widget_is(child))
1449           elm_widget_theme_specific(child, th, force);
1450      }
1451    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
1452    EINA_LIST_FOREACH(sd->tooltips, l, tt)
1453      elm_tooltip_theme(tt);
1454    EINA_LIST_FOREACH(sd->cursors, l, cur)
1455      elm_cursor_theme(cur);
1456    efl_ui_widget_theme_apply(obj);
1457 }
1458
1459 EOLIAN static Eina_Error
1460 _efl_ui_widget_theme_apply(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
1461 {
1462    _elm_widget_mirrored_reload(obj);
1463
1464    return EFL_UI_THEME_APPLY_ERROR_NONE;
1465 }
1466
1467 /**
1468  * @internal
1469  *
1470  * Returns the widget's mirrored mode.
1471  *
1472  * @param obj The widget.
1473  * @return mirrored mode of the object.
1474  *
1475  **/
1476 EOLIAN static Eina_Bool
1477 _efl_ui_widget_efl_ui_i18n_mirrored_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1478 {
1479    return sd->is_mirrored;
1480 }
1481
1482 /**
1483  * @internal
1484  *
1485  * Sets the widget's mirrored mode.
1486  *
1487  * @param obj The widget.
1488  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
1489  */
1490 EOLIAN static void
1491 _efl_ui_widget_efl_ui_i18n_mirrored_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool mirrored)
1492 {
1493    mirrored = !!mirrored;
1494
1495    if (sd->is_mirrored == mirrored) return;
1496
1497    sd->is_mirrored = mirrored;
1498    elm_widget_theme(obj);
1499 }
1500
1501 /**
1502  * Returns the widget's mirrored mode setting.
1503  *
1504  * @param obj The widget.
1505  * @return mirrored mode setting of the object.
1506  *
1507  **/
1508 EOLIAN static Eina_Bool
1509 _efl_ui_widget_efl_ui_i18n_mirrored_automatic_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1510 {
1511    return sd->mirrored_auto_mode;
1512 }
1513
1514 /**
1515  * @internal
1516  *
1517  * Sets the widget's mirrored mode setting.
1518  * When widget in automatic mode, it follows the system mirrored mode set by
1519  * elm_mirrored_set().
1520  * @param obj The widget.
1521  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
1522  */
1523 EOLIAN static void
1524 _efl_ui_widget_efl_ui_i18n_mirrored_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
1525 {
1526    if (sd->mirrored_auto_mode != automatic)
1527      {
1528         sd->mirrored_auto_mode = automatic;
1529
1530         if (automatic)
1531           {
1532              efl_ui_mirrored_set(obj, elm_config_mirrored_get());
1533           }
1534      }
1535 }
1536
1537 /*
1538  * @internal
1539  *
1540  * Add myself as a sub object of parent object
1541  *
1542  * @see elm_widget_sub_object_add()
1543  */
1544 EAPI Eina_Bool
1545 elm_widget_sub_object_parent_add(Evas_Object *sobj)
1546 {
1547    Eo *parent = NULL;
1548
1549    parent = efl_parent_get(sobj);
1550    if (!efl_isa(parent, EFL_UI_WIDGET_CLASS))
1551      {
1552         ERR("You passed a wrong parent parameter (%p %s). "
1553             "Elementary widget's parent should be an elementary widget.", parent, evas_object_type_get(parent));
1554         return EINA_FALSE;
1555      }
1556
1557    return elm_widget_sub_object_add(parent, sobj);
1558 }
1559
1560 static int
1561 _disabled_counter_get(Eo *widget)
1562 {
1563    ELM_WIDGET_DATA_GET_OR_RETURN(widget, pd, -1);
1564
1565    return pd->disabled;
1566 }
1567
1568 static void
1569 _mirror_disabled_state(Eo *obj, Elm_Widget_Smart_Data *pd, int disabled_delta)
1570 {
1571    int prev_disabled = pd->disabled;
1572
1573    pd->disabled = (pd->parent_obj ? _disabled_counter_get(pd->parent_obj) : 0) + disabled_delta;
1574
1575    //The current disabled state is the same as the parent
1576    //when the parent is assigned or changed, no further action is required.
1577    if (((prev_disabled > 0 && pd->disabled > 0)) ||
1578        ((prev_disabled <= 0 && pd->disabled <= 0)))
1579      return;
1580
1581    //we should not call disabled_set when things are invalidated
1582    //otherwise we will unleashe an amount of errors in efl_ui_layout
1583    if (efl_invalidated_get(obj)) return;
1584
1585    if (pd->disabled > 0)
1586      {
1587         pd->disabled --;
1588         efl_ui_widget_disabled_set(obj, EINA_TRUE);
1589      }
1590    else
1591      {
1592         pd->disabled ++;
1593         efl_ui_widget_disabled_set(obj, EINA_FALSE);
1594      }
1595 }
1596
1597 EOLIAN static void
1598 _efl_ui_widget_widget_parent_set(Eo *obj, Elm_Widget_Smart_Data *pd, Efl_Ui_Widget *parent)
1599 {
1600    Efl_Ui_Widget *old_parent;
1601    //check if we are in the subobject list of parents
1602    if (parent)
1603      {
1604         ELM_WIDGET_DATA_GET_OR_RETURN(parent, ppd);
1605         EINA_SAFETY_ON_FALSE_RETURN(eina_array_find(ppd->children, obj, NULL));
1606         if (ppd->parent_obj == parent)
1607           {
1608              CRI("ATTEMPTING TO SET CHILD OF PARENT AS PARENT OF ITS OWN PARENT. THIS IS A BUG.");
1609              return;
1610           }
1611      }
1612
1613    /* NOTE: In the following two lines, 'obj' is correct. Do not change it.
1614     * Due to elementary's scale policy, scale and prev_scale can be different in
1615     * some cases. This happens when obj's previous parent and new parent have
1616     * different scale value.
1617     * For example, if obj's previous parent's scale is 5 and new parent's scale
1618     * is 2 while obj's scale is 0. Then 'prev_pscale' is 5 and 'scale' is 2. So
1619     * we need to reset obj's scale to 5.
1620     * Note that each widget's scale is 1.0 by default.
1621     */
1622    double scale, prev_scale = efl_gfx_entity_scale_get(obj);
1623    Elm_Theme *th, *prev_th = elm_widget_theme_get(obj);
1624    int disabled_delta = pd->disabled - (pd->parent_obj ? _disabled_counter_get(pd->parent_obj) : 0);
1625
1626    old_parent = pd->parent_obj;
1627    pd->parent_obj = parent;
1628
1629    // now lets sync up all states
1630    if (pd->parent_obj)
1631      {
1632         Eina_Bool mirrored, pmirrored = efl_ui_mirrored_get(pd->parent_obj);
1633         scale = efl_gfx_entity_scale_get(obj);
1634         th = elm_widget_theme_get(obj);
1635         mirrored = efl_ui_mirrored_get(obj);
1636
1637         if (!pd->on_create)
1638           {
1639              if (!EINA_DBL_EQ(scale, prev_scale) || (th != prev_th) ||
1640                  (pmirrored != mirrored))
1641                elm_widget_theme(obj);
1642           }
1643         if (_is_focused(obj)) _parents_focus(parent);
1644         elm_widget_display_mode_set(obj, evas_object_size_hint_display_mode_get(parent));
1645         _elm_widget_top_win_focused_set(obj, _elm_widget_top_win_focused_get(parent));
1646      }
1647    _mirror_disabled_state(obj, pd, disabled_delta);
1648    _full_eval(obj, pd);
1649
1650    if (!efl_alive_get(obj)) return;
1651    if (old_parent && _elm_config->atspi_mode)
1652      {
1653         Efl_Access_Object *aparent;
1654         aparent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
1655         if (aparent)
1656            efl_access_children_changed_del_signal_emit(aparent, obj);
1657      }
1658
1659    if (pd->parent_obj && _elm_config->atspi_mode && efl_finalized_get(parent))
1660      {
1661         Efl_Access_Object *aparent;
1662         aparent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
1663         if (aparent)
1664            efl_access_children_changed_added_signal_emit(aparent, obj);
1665      }
1666 }
1667
1668 static void
1669 _widget_add_sub(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1670 {
1671    if (!sd->children) sd->children = eina_array_new(1);
1672    eina_array_push(sd->children, sobj);
1673    evas_object_data_set(sobj, "elm-parent", obj);
1674    //TIZEN_ONLY(20181024): Fix parent-children incosistencies in atspi tree
1675    if (efl_isa(sobj, EFL_ACCESS_OBJECT_MIXIN))
1676      efl_access_object_access_parent_set(sobj, obj);
1677    //
1678    _callbacks_add(sobj, obj);
1679 }
1680
1681 static void
1682 _widget_del_sub(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1683 {
1684    eina_array_remove(sd->children, _keep, sobj);
1685    evas_object_data_del(sobj, "elm-parent");
1686    _callbacks_del(sobj, obj);
1687 }
1688
1689 EOLIAN static Eina_Bool
1690 _efl_ui_widget_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1691 {
1692    Efl_Ui_Widget *parent;
1693    Eina_Bool is_widget;
1694
1695    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(sobj, EFL_GFX_ENTITY_INTERFACE), EINA_FALSE);
1696    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1697
1698    is_widget = elm_widget_is(sobj);
1699    //first make sure that we unregister the sobj from the parent
1700    if (is_widget)
1701      parent = efl_ui_widget_parent_get(sobj);
1702    else
1703      parent = evas_object_data_get(sobj, "elm-parent");
1704    if (parent == obj) return EINA_TRUE;
1705    if (parent)
1706      {
1707         if (sd->parent_obj == sobj)
1708           {
1709              CRI("ATTEMPTING TO SET CHILD OF PARENT AS PARENT OF ITS OWN PARENT. THIS IS A BUG.");
1710              return EINA_FALSE;
1711           }
1712
1713         if (!efl_ui_widget_sub_object_del(parent, sobj))
1714           return EINA_FALSE;
1715      }
1716
1717    //sobj does not have a parent here
1718    //first add it to our own children list
1719    _widget_add_sub(obj, sd, sobj);
1720
1721    //TIZEN_ONLY(20200911): restore hide callback for sub-object
1722    if (is_widget)
1723      efl_event_callback_add(sobj, EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _on_sub_obj_hide, obj);
1724    //
1725
1726    //and if it is a widget, please set the correct parent on the widget itself
1727    //the parent set method will take care of the property syncing etc.
1728    if (is_widget)
1729      efl_ui_widget_parent_set(sobj, obj);
1730
1731 //TIZEN_ONLY(20190312): Restore child_can_focus
1732    if (elm_widget_is(sobj))
1733      {
1734         /* update child focusable-ness on self and parents, now that a
1735          * focusable child got in */
1736         if (!sd->child_can_focus && (_is_focusable(sobj)))
1737           {
1738              Elm_Widget_Smart_Data *sdp = sd;
1739
1740              sdp->child_can_focus = EINA_TRUE;
1741              while (sdp->parent_obj)
1742                {
1743                   sdp = efl_data_scope_get(sdp->parent_obj, MY_CLASS);
1744
1745                   if (sdp->child_can_focus) break;
1746
1747                   sdp->child_can_focus = EINA_TRUE;
1748                }
1749           }
1750 //
1751
1752         /***********************************************************
1753          * TIZEN_ONLY(20180117): Override Paragraph Direction APIs *
1754          ***********************************************************/
1755         ELM_WIDGET_DATA_GET(sobj, sdc);
1756         if (sdc->inherit_paragraph_direction &&
1757             (sdc->paragraph_direction != efl_canvas_object_paragraph_direction_get(obj)))
1758           {
1759              sdc->paragraph_direction = efl_canvas_object_paragraph_direction_get(obj);
1760              _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1761              efl_canvas_object_paragraph_direction_set(efl_super(sobj, MY_CLASS), sdc->paragraph_direction);
1762           }
1763         /*******
1764          * END *
1765          *******/
1766      }
1767
1768    return EINA_TRUE;
1769 }
1770
1771 EOLIAN static Eina_Bool
1772 _efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1773 {
1774    Evas_Object *sobj_parent = NULL;
1775    Eina_Bool is_widget;
1776
1777    if (!sobj) return EINA_FALSE;
1778
1779    EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1780
1781    is_widget = _elm_widget_is(sobj);
1782
1783    if (!is_widget) sobj_parent = evas_object_data_del(sobj, "elm-parent");
1784
1785    //TIZEN_ONLY(20181024): Fix parent-children incosistencies in atspi tree
1786    if (efl_isa(sobj, EFL_ACCESS_OBJECT_MIXIN))
1787       efl_access_object_access_parent_set(sobj, NULL);
1788    //
1789
1790    if (sobj_parent && sobj_parent != obj)
1791      {
1792         static int abort_on_warn = -1;
1793
1794         ERR("removing sub object %p (%s) from parent %p (%s), "
1795             "but elm-parent is different %p (%s)!",
1796             sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
1797             sobj_parent, elm_widget_type_get(sobj_parent));
1798
1799         if (EINA_UNLIKELY(abort_on_warn == -1))
1800           {
1801              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1802              else abort_on_warn = 0;
1803           }
1804         if (abort_on_warn == 1) abort();
1805
1806         return EINA_FALSE;
1807      }
1808
1809    if (is_widget)
1810      {
1811         if (efl_ui_widget_parent_get(sobj) != obj)
1812           return EINA_FALSE;
1813         if (_is_focused(sobj))
1814           {
1815              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1816              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1817           }
1818
1819 //TIZEN_ONLY(20190312): Restore child_can_focus
1820         if ((sd->child_can_focus) && (_is_focusable(sobj)))
1821           {
1822              Evas_Object *parent = obj;
1823
1824              /* update child focusable-ness on self and parents, now that a
1825               * focusable child is gone */
1826              while (parent)
1827                {
1828                   Evas_Object *subobj;
1829
1830                   ELM_WIDGET_DATA_GET(parent, sdp);
1831
1832                   sdp->child_can_focus = EINA_FALSE;
1833                   for (unsigned int i = 0; i < eina_array_count(sdp->children); ++i)
1834                     {
1835                        subobj = eina_array_data_get(sdp->children, i);
1836                        if ((subobj != sobj) && (_is_focusable(subobj)))
1837                          {
1838                             sdp->child_can_focus = EINA_TRUE;
1839                             break;
1840                          }
1841                     }
1842
1843                   /* break again, child_can_focus went back to
1844                    * original value */
1845                   if (sdp->child_can_focus) break;
1846                   parent = sdp->parent_obj;
1847                }
1848           }
1849 //
1850         /***********************************************************
1851          * TIZEN_ONLY(20180117): Override Paragraph Direction APIs *
1852          ***********************************************************/
1853         ELM_WIDGET_DATA_GET(sobj, sdc);
1854         if (sdc)
1855           {
1856              if (sdc->inherit_paragraph_direction &&
1857                  (sdc->paragraph_direction != EFL_TEXT_BIDIRECTIONAL_TYPE_NEUTRAL))
1858                {
1859                   sdc->paragraph_direction = EFL_TEXT_BIDIRECTIONAL_TYPE_NEUTRAL;
1860                   _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1861                   efl_canvas_object_paragraph_direction_set(efl_super(sobj, MY_CLASS), EFL_TEXT_BIDIRECTIONAL_TYPE_NEUTRAL);
1862                }
1863           }
1864         /*******
1865          * END *
1866          *******/
1867
1868         efl_ui_widget_parent_set(sobj, NULL);
1869      }
1870
1871    if (sd->resize_obj == sobj) sd->resize_obj = NULL;
1872
1873    _widget_del_sub(obj, sd, sobj);
1874
1875    //TIZEN_ONLY(20200911): restore hide callback for sub-object
1876    if (is_widget)
1877      efl_event_callback_del(sobj, EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _on_sub_obj_hide, obj);
1878    //
1879
1880    return EINA_TRUE;
1881 }
1882
1883 /* protected function - for widget developers only */
1884 EOLIAN static void
1885 _efl_ui_widget_resize_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eo *sobj)
1886 {
1887    Evas_Object *parent;
1888
1889    if (sd->resize_obj == sobj) return;
1890    EINA_SAFETY_ON_TRUE_RETURN(sobj && !efl_isa(sobj, EFL_CANVAS_OBJECT_CLASS));
1891
1892    // orphan previous resize obj
1893    if (sd->resize_obj)
1894      {
1895         evas_object_clip_unset(sd->resize_obj);
1896         evas_object_smart_member_del(sd->resize_obj);
1897
1898         if (_elm_widget_is(sd->resize_obj))
1899           {
1900              if (_is_focused(sd->resize_obj)) _parents_unfocus(obj);
1901           }
1902         elm_widget_sub_object_del(obj, sd->resize_obj);
1903      }
1904
1905    sd->resize_obj = sobj;
1906    if (!sobj) return;
1907
1908    // orphan new resize obj
1909    parent = evas_object_data_get(sobj, "elm-parent");
1910    if (parent && parent != obj)
1911      {
1912         ELM_WIDGET_DATA_GET(parent, sdp);
1913
1914         /* should be there, just being paranoid */
1915         if (sdp)
1916           {
1917              if (sdp->resize_obj == sobj)
1918                elm_widget_resize_object_set(parent, NULL);
1919              else
1920                elm_widget_sub_object_del(parent, sobj);
1921           }
1922      }
1923
1924    elm_widget_sub_object_add(obj, sobj);
1925    evas_object_smart_member_add(sobj, obj);
1926    _smart_reconfigure(obj, sd);
1927 }
1928
1929 /*
1930  * @internal
1931  *
1932  * WARNING: the programmer is responsible, in the scenario of
1933  * exchanging a hover object, of cleaning the old hover "target"
1934  * before
1935  */
1936 EAPI void
1937 elm_widget_hover_object_set(Eo *obj, Evas_Object *sobj)
1938 {
1939    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
1940    if (!sd) return;
1941
1942    if (sd->hover_obj)
1943      {
1944         _callbacks_del(sd->hover_obj, obj);
1945      }
1946    sd->hover_obj = sobj;
1947    if (sd->hover_obj)
1948      {
1949         _callbacks_add(sobj, obj);
1950         _smart_reconfigure(obj, sd);
1951      }
1952 }
1953
1954 EOLIAN static void
1955 _efl_ui_widget_focus_allow_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool can_focus)
1956 {
1957    can_focus = !!can_focus;
1958
1959    if (sd->can_focus == can_focus) return;
1960    sd->can_focus = can_focus;
1961    if (sd->can_focus)
1962      {
1963 //TIZEN_ONLY(20190312): Restore child_can_focus
1964         /* update child_can_focus of parents */
1965         Evas_Object *o = obj;
1966
1967         for (;;)
1968           {
1969              o = elm_widget_parent_get(o);
1970              if (!o) break;
1971              ELM_WIDGET_DATA_GET(o, sdp);
1972              if (!sdp || sdp->child_can_focus) break;
1973              sdp->child_can_focus = EINA_TRUE;
1974           }
1975 //
1976
1977         efl_event_callback_array_add(obj, focus_callbacks(), NULL);
1978      }
1979    else
1980      {
1981 //TIZEN_ONLY(20190312): Restore child_can_focus
1982         // update child_can_focus of parents */
1983         Evas_Object *parent = elm_widget_parent_get(obj);
1984         while (parent)
1985           {
1986              Evas_Object *subobj;
1987
1988              ELM_WIDGET_DATA_GET(parent, sdp);
1989              if (!sdp) break;
1990
1991              sdp->child_can_focus = EINA_FALSE;
1992              for (unsigned int i = 0; i < eina_array_count(sdp->children); ++i)
1993                {
1994                   subobj = eina_array_data_get(sdp->children, i);
1995                   if (_is_focusable(subobj))
1996                     {
1997                        sdp->child_can_focus = EINA_TRUE;
1998                        break;
1999                     }
2000                }
2001              /* break again, child_can_focus went back to
2002               * original value */
2003              if (sdp->child_can_focus) break;
2004              parent = sdp->parent_obj;
2005           }
2006 //
2007         efl_event_callback_array_del(obj, focus_callbacks(), NULL);
2008      }
2009      if (efl_finalized_get(obj))
2010        _full_eval(obj, sd);
2011 }
2012
2013 EOLIAN static Eina_Bool
2014 _efl_ui_widget_focus_allow_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
2015 {
2016    return sd->can_focus;
2017 }
2018
2019 EAPI Eina_Bool
2020 elm_widget_child_can_focus_get(const Eo *obj)
2021 {
2022    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2023    if (!sd) return EINA_FALSE;
2024
2025 //TIZEN_ONLY(20190312): Restore child_can_focus
2026    //return sd->logical.child_count > 0;
2027    return sd->child_can_focus;
2028 //
2029 }
2030
2031
2032 EINA_UNUSED static int
2033 _tree_unfocusable_counter_get(Eo *widget)
2034 {
2035    ELM_WIDGET_DATA_GET_OR_RETURN(widget, pd, -1);
2036
2037    return pd->tree_unfocusable;
2038 }
2039
2040 /**
2041  * Evalulate tree number.
2042  *
2043  * This is here to support properties which are propagating through the widget tree. If this property is set to true,
2044  * every widget in the subtree, will also be automatically true.
2045  * When one of the widgets in the subtree then seperatly will be set to true, the unsetting on the original widget will not unset the flag automatically in this tree.
2046  *
2047  * The basic idea here is:
2048  * - The numeric number beeing bigger than 0, means that the property is true
2049  * - The difference between the number of the parent, and the number of the object, represents the boolean flag
2050  *   (0 means that the flag is equal to the one of the parent, 1 means that if the parent is false, this child is true).
2051  */
2052 static int
2053 _calculate_tree_number(int self_counter, int parent_counter, Eina_Bool flag)
2054 {
2055    int distance = self_counter - parent_counter;
2056
2057    if (flag)
2058      self_counter ++;
2059    else
2060      self_counter --;
2061
2062    distance = self_counter - parent_counter;
2063
2064    if ((distance < 0) || (distance > 1))
2065      {
2066         distance = MAX(MIN(flag, 1), 0);
2067         self_counter = parent_counter + distance;
2068      }
2069
2070    return self_counter;
2071 }
2072
2073 /* TIZEN_ONLY(20190821): keep legacy focus logic
2074 static void
2075 _propagate_bool_property(Elm_Widget_Smart_Data *pd, Eina_Bool flag, void (*property_setting)(Eo *obj, Eina_Bool flag))
2076 {
2077    Efl_Ui_Widget *subs;
2078    for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
2079      {
2080         subs = eina_array_data_get(pd->children, i);
2081         if (efl_isa(subs, EFL_UI_WIDGET_CLASS))
2082           property_setting(subs, flag);
2083      }
2084 }
2085 */
2086
2087 /**
2088  * @internal
2089  *
2090  * This API makes the widget object and its children to be unfocusable.
2091  *
2092  * This API can be helpful for an object to be deleted.
2093  * When an object will be deleted soon, it and its children may not
2094  * want to get focus (by focus reverting or by other focus controls).
2095  * Then, just use this API before deleting.
2096  *
2097  * @param obj The widget root of sub-tree
2098  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
2099  *
2100  * @ingroup Widget
2101  */
2102 EAPI void
2103 elm_widget_tree_unfocusable_set(Eo *obj, Eina_Bool tree_unfocusable)
2104 {
2105    /* TIZEN_ONLY(20190821): keep legacy focus logic
2106    Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
2107    EINA_SAFETY_ON_NULL_RETURN(pd);
2108    int old_tree_unfocusable;
2109
2110    old_tree_unfocusable = pd->tree_unfocusable;
2111
2112    pd->tree_unfocusable = _calculate_tree_number(pd->tree_unfocusable,
2113                                                 (pd->parent_obj ? _tree_unfocusable_counter_get(pd->parent_obj) : 0),
2114                                                 tree_unfocusable);
2115
2116    if (old_tree_unfocusable != pd->tree_unfocusable)
2117      {
2118         _full_eval(obj, pd);
2119         _propagate_bool_property(pd, tree_unfocusable, elm_widget_tree_unfocusable_set);
2120      }
2121
2122    */
2123    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2124    if (!sd) return;
2125
2126    tree_unfocusable = !!tree_unfocusable;
2127    if (sd->tree_unfocusable == tree_unfocusable) return;
2128    sd->tree_unfocusable = tree_unfocusable;
2129    efl_ui_widget_focus_tree_unfocusable_handle(obj);
2130    //
2131 }
2132
2133 /**
2134  * @internal
2135  *
2136  * This returns true, if the object sub-tree is unfocusable.
2137  *
2138  * @param obj The widget root of sub-tree
2139  * @return EINA_TRUE if the object sub-tree is unfocusable
2140  *
2141  * @ingroup Widget
2142  */
2143 EAPI Eina_Bool
2144 elm_widget_tree_unfocusable_get(const Eo *obj)
2145 {
2146    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2147    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
2148
2149    return !!sd->tree_unfocusable;
2150 }
2151
2152 //TIZEN_ONLY(20191007): Add a API to raise focus_order.
2153 /**
2154  * @internal
2155  *
2156  * Raise focus_order of @p obj. this API can be helpful to keep last focus
2157  * state of widgets which have items.
2158  *
2159  * @ingroup Widget
2160  */
2161 EAPI void
2162 elm_widget_focus_order_raise(Evas_Object *obj)
2163 {
2164    API_ENTRY return;
2165    focus_order++;
2166    sd->focus_order = focus_order;
2167 }
2168 //
2169
2170 /**
2171  * @internal
2172  *
2173  * Get the list of focusable child objects.
2174  *
2175  * This function returns list of child objects which can get focus.
2176  *
2177  * @param obj The parent widget
2178  * @return list of focusable child objects.
2179  *
2180  * @ingroup Widget
2181  */
2182 EAPI Eina_List*
2183 elm_widget_can_focus_child_list_get(const Eo *obj)
2184 {
2185    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2186    Eina_List *child_list = NULL;
2187    Evas_Object *child;
2188
2189    if (!sd) return NULL;
2190    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2191      {
2192         child = eina_array_data_get(sd->children, i);
2193         if (!_elm_widget_is(child)) continue;
2194         if ((elm_widget_can_focus_get(child)) &&
2195             (evas_object_visible_get(child)) &&
2196             (!elm_widget_disabled_get(child)))
2197           child_list = eina_list_append(child_list, child);
2198         else
2199           {
2200              Eina_List *can_focus_list;
2201              can_focus_list = elm_widget_can_focus_child_list_get(child);
2202              if (can_focus_list)
2203                child_list = eina_list_merge(child_list, can_focus_list);
2204           }
2205      }
2206
2207    return child_list;
2208 }
2209
2210 /** @internal */
2211 EAPI void
2212 elm_widget_highlight_ignore_set(Eo *obj, Eina_Bool ignore)
2213 {
2214    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2215    if (!sd) return;
2216
2217    sd->highlight_ignore = !!ignore;
2218 }
2219
2220 /** @internal */
2221 EAPI Eina_Bool
2222 elm_widget_highlight_ignore_get(const Eo *obj)
2223 {
2224    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2225    if (!sd) return EINA_FALSE;
2226
2227    return sd->highlight_ignore;
2228 }
2229
2230 /** @internal */
2231 EAPI void
2232 elm_widget_highlight_in_theme_set(Eo *obj, Eina_Bool highlight)
2233 {
2234    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2235    if (!sd) return;
2236
2237    sd->highlight_in_theme = !!highlight;
2238    /* FIXME: if focused, it should switch from one mode to the other */
2239 }
2240
2241 void
2242 _elm_widget_highlight_in_theme_update(Eo *obj)
2243 {
2244    Evas_Object *top = elm_widget_top_get(obj);
2245
2246    if (top && efl_isa(top, EFL_UI_WIN_CLASS))
2247      {
2248         _elm_win_focus_highlight_in_theme_update(
2249            top, elm_widget_highlight_in_theme_get(obj));
2250      }
2251 }
2252
2253 /** @internal */
2254 EAPI Eina_Bool
2255 elm_widget_highlight_in_theme_get(const Eo *obj)
2256 {
2257    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2258    if (!sd) return EINA_FALSE;
2259
2260    return sd->highlight_in_theme;
2261 }
2262
2263 /** @internal */
2264 EAPI void
2265 elm_widget_access_highlight_in_theme_set(Eo *obj, Eina_Bool highlight)
2266 {
2267    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2268    if (!sd) return;
2269
2270    sd->access_highlight_in_theme = !!highlight;
2271 }
2272
2273 /** @internal */
2274 EAPI Eina_Bool
2275 elm_widget_access_highlight_in_theme_get(const Eo *obj)
2276 {
2277    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2278    if (!sd) return EINA_FALSE;
2279
2280    return sd->access_highlight_in_theme;
2281 }
2282
2283 /** @internal */
2284 EAPI Eina_Bool
2285 elm_widget_highlight_get(const Eo *obj)
2286 {
2287    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2288    if (!sd) return EINA_FALSE;
2289
2290    return sd->highlighted;
2291 }
2292 //TIZEN_ONLY(20180607): Restore legacy focus
2293 EAPI Eina_Bool
2294 elm_widget_focus_get(const Eo *obj)
2295 {
2296    ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd, EINA_FALSE);
2297    return (sd->focused && sd->top_win_focused);
2298 }
2299
2300 EOLIAN static Evas_Object*
2301 _efl_ui_widget_focused_object_get(const Eo *obj, Elm_Widget_Smart_Data *sd)
2302 {
2303    const Evas_Object *subobj;
2304
2305    if (!sd->focused || !sd->top_win_focused) return NULL;
2306    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2307      {
2308         subobj = eina_array_data_get(sd->children, i);
2309         Evas_Object *fobj;
2310         if (!_elm_widget_is(subobj)) continue;
2311         fobj = efl_ui_widget_focused_object_get(subobj);
2312         if (fobj) return fobj;
2313      }
2314    return (Evas_Object *)obj;
2315 }
2316 //
2317
2318 EAPI Eina_Bool
2319 elm_widget_is(const Evas_Object *obj)
2320 {
2321    return _elm_widget_is(obj);
2322 }
2323
2324 EAPI void
2325 elm_widget_access_info_set(Efl_Ui_Widget *obj, const char *txt)
2326 {
2327    efl_ui_widget_access_info_set(obj, txt);
2328 }
2329
2330 EAPI const char *
2331 elm_widget_access_info_get(const Efl_Ui_Widget *obj)
2332 {
2333    return efl_ui_widget_access_info_get(obj);
2334 }
2335
2336 EAPI Eo *
2337 elm_widget_top_get(const Eo *obj)
2338 {
2339    Efl_Ui_Widget *parent = elm_widget_parent_get(obj);
2340    if (parent)
2341      {
2342         if (!efl_isa(parent, EFL_UI_WIDGET_CLASS)) return NULL;
2343         return elm_widget_top_get(parent);
2344      }
2345    /* XXX const */
2346    return (Evas_Object *)obj;
2347 }
2348
2349 EAPI Evas_Object *
2350 elm_widget_parent_widget_get(const Evas_Object *obj)
2351 {
2352    Evas_Object *parent;
2353
2354    if (_elm_widget_is(obj))
2355      {
2356         ELM_WIDGET_DATA_GET(obj, sd);
2357         if (!sd) return NULL;
2358         parent = sd->parent_obj;
2359      }
2360    else
2361      {
2362         parent = evas_object_data_get(obj, "elm-parent");
2363         if (!parent) parent = evas_object_smart_parent_get(obj);
2364      }
2365
2366    while (parent)
2367      {
2368         Evas_Object *elm_parent;
2369         if (_elm_widget_is(parent)) break;
2370         elm_parent = evas_object_data_get(parent, "elm-parent");
2371         if (elm_parent) parent = elm_parent;
2372         else parent = evas_object_smart_parent_get(parent);
2373      }
2374    return parent;
2375 }
2376
2377 EAPI void
2378 elm_widget_event_callback_add(Eo *obj, Elm_Event_Cb func, const void *data)
2379 {
2380    API_ENTRY return;
2381    EINA_SAFETY_ON_NULL_RETURN(func);
2382
2383    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
2384    if (!ecb)
2385      {
2386         ERR("Failed to allocate memory");
2387         return;
2388      }
2389    ecb->func = func;
2390    ecb->data = data;
2391    sd->event_cb = eina_list_append(sd->event_cb, ecb);
2392 }
2393
2394 EAPI void *
2395 elm_widget_event_callback_del(Eo *obj, Elm_Event_Cb func, const void *data)
2396 {
2397    API_ENTRY return NULL;
2398    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
2399    Eina_List *l;
2400    Elm_Event_Cb_Data *ecd;
2401
2402    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
2403      if ((ecd->func == func) && (ecd->data == data))
2404        {
2405           free(ecd);
2406           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
2407           return (void *)data;
2408        }
2409
2410    return NULL;
2411 }
2412
2413 static void
2414 _propagate_event(void *data EINA_UNUSED, const Efl_Event *eo_event)
2415 {
2416    Evas_Object *obj = eo_event->object;
2417    Evas_Object *parent = obj;
2418    Elm_Event_Cb_Data *ecd;
2419    Eina_List *l, *l_prev;
2420
2421    if ((evas_focus_get(evas_object_evas_get(obj)) != elm_widget_top_get(obj)) &&
2422        efl_isa(obj, EFL_UI_WIN_CLASS))
2423      return;
2424
2425    while (parent && !efl_input_processed_get(eo_event->info))
2426      {
2427         Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(parent, MY_CLASS);
2428         if (!sd) return;
2429
2430         if (elm_widget_disabled_get(obj))
2431           {
2432              parent = sd->parent_obj;
2433              continue;
2434           }
2435
2436         if (efl_ui_widget_input_event_handler(parent, eo_event, obj))
2437           return;
2438
2439         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
2440           {
2441              if (_propagate_event_legacy(parent, eo_event, obj, ecd))
2442                return;
2443           }
2444
2445         parent = sd->parent_obj;
2446      }
2447 }
2448
2449 double
2450 _elm_widget_focus_direction_weight_get(const Evas_Object *obj1,
2451                       const Evas_Object *obj2,
2452                       double degree)
2453 {
2454    Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
2455    double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
2456    double ax, ay, cx, cy;
2457    double weight = -1.0, g = 0.0;
2458    // TIZEN_ONLY(20171129): add second_level for weight calculate
2459    Eina_Bool second_level = EINA_FALSE;
2460    //
2461
2462    if (obj1 == obj2) return 0.0;
2463
2464    degree -= 90.0;
2465    while (degree >= 360.0)
2466      degree -= 360.0;
2467    while (degree < 0.0)
2468      degree += 360.0;
2469
2470    evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
2471    cx = obj_x1 + (w1 / 2.0);
2472    cy = obj_y1 + (h1 / 2.0);
2473    evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
2474
2475    /* For overlapping cases. */
2476    if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2))
2477      return 0.0;
2478
2479    /* Change all points to relative one. */
2480    x1 = obj_x1 - cx;
2481    xx1 = x1 + w1;
2482    yy1 = obj_y1 - cy;
2483    yyy1 = yy1 + h1;
2484    x2 = obj_x2 - cx;
2485    xx2 = x2 + w2;
2486    yy2 = obj_y2 - cy;
2487    yyy2 = yy2 + h2;
2488
2489    /* Get crossing points (ax, ay) between obj1 and a line extending
2490     * to the direction of current degree. */
2491    if (degree == 0.0)
2492      {
2493         ax = xx1;
2494         ay = 0.0;
2495      }
2496    else if (degree == 90.0)
2497      {
2498         ax = 0.0;
2499         ay = yyy1;
2500      }
2501    else if (degree == 180.0)
2502      {
2503         ax = x1;
2504         ay = 0.0;
2505      }
2506    else if (degree == 270.0)
2507      {
2508         ax = 0.0;
2509         ay = yy1;
2510      }
2511    else
2512      {
2513         g = tan(degree * (M_PI / 180.0));
2514         if ((degree > 0.0) && (degree < 90.0))
2515           {
2516              ay = g * xx1;
2517              if (ay <= yyy1) ax = xx1;
2518              else
2519                {
2520                   ax = yyy1 / g;
2521                   ay = yyy1;
2522                }
2523           }
2524         else if ((degree > 90.0) && (degree < 180.0))
2525           {
2526              ay = g * x1;
2527              if (ay <= yyy1) ax = x1;
2528              else
2529                {
2530                   ax = yyy1 / g;
2531                   ay = yyy1;
2532                }
2533           }
2534         else if ((degree > 180.0) && (degree < 270.0))
2535           {
2536              ay = g * x1;
2537              if (ay >= yy1) ax = x1;
2538              else
2539                {
2540                   ax = yy1 / g;
2541                   ay = yy1;
2542                }
2543           }
2544         else
2545           {
2546              ay = g * xx1;
2547              if (ay >= yy1) ax = xx1;
2548              else
2549                {
2550                   ax = yy1 / g;
2551                   ay = yy1;
2552                }
2553           }
2554      }
2555
2556    /* Filter obj2, if it is not in the specific derection. */
2557    int i = 0;
2558    double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
2559    double t1, t2, u1, v1, u2, v2;
2560
2561    if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) ||
2562        (degree == 315.0))
2563      {
2564         u1 = 1.0;
2565         v1 = 0.0;
2566         u2 = 0.0;
2567         v2 = 1.0;
2568      }
2569    else
2570      {
2571         double g2 = tan((degree + 45.0) * (M_PI / 180.0));
2572         u1 = (-1.0 * g2);
2573         u2 = (1.0 / g2);
2574         v1 = v2 = 1.0;
2575      }
2576    t1 = (u1 * ax) + (v1 * ay);
2577    t2 = (u2 * ax) + (v2 * ay);
2578
2579 #define _R(x) (int)((x + 0.05) * 10.0)
2580
2581    if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) +
2582                                                             (v2 * yy2))) > 0))
2583      {
2584         rx[i] = x2;
2585         ry[i++] = yy2;
2586      }
2587    if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) +
2588                                                              (v2 * yyy2))) > 0))
2589      {
2590         rx[i] = x2;
2591         ry[i++] = yyy2;
2592      }
2593    if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) +
2594                                                              (v2 * yy2))) > 0))
2595      {
2596         rx[i] = xx2;
2597         ry[i++] = yy2;
2598      }
2599    if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) &&
2600        (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
2601      {
2602         rx[i] = xx2;
2603         ry[i++] = yyy2;
2604      }
2605    if (i == 0)
2606      {
2607         if (degree == 0.0)
2608           {
2609              // TIZEN_ONLY(20171129): add second_level for weight calculate
2610              //if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2611              if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0))
2612                {
2613                   if (xx1 <= x2) second_level = EINA_TRUE;
2614                   else return 0.0;
2615                }
2616              //
2617           }
2618         else if (degree == 90.0)
2619           {
2620              // TIZEN_ONLY(20171129): add second_level for weight calculate
2621              //if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2622              if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0))
2623                {
2624                   if (yyy1 <= yy2) second_level = EINA_TRUE;
2625                   else return 0.0;
2626                }
2627              //
2628           }
2629         else if (degree == 180.0)
2630           {
2631              // TIZEN_ONLY(20171129): add second_level for weight calculate
2632              //if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2633              if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0))
2634                {
2635                   if (x1 >= xx2) second_level = EINA_TRUE;
2636                   else return 0.0;
2637                }
2638              //
2639           }
2640         else if (degree == 270.0)
2641           {
2642              // TIZEN_ONLY(20171129): add second_level for weight calculate
2643              //if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2644              if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0))
2645                {
2646                   if (yy1 >= yyy2) second_level = EINA_TRUE;
2647                   else return 0.0;
2648                }
2649              //
2650           }
2651         else
2652           {
2653              if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
2654                {
2655                   if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0)))
2656                     return 0.0;
2657                }
2658              else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
2659                {
2660                   if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0)))
2661                     return 0.0;
2662                }
2663              else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2)
2664                                                            <= _R(xx2)))
2665                {
2666                   if (!((_R(ax * ((1.0 / g) * yy2)) > 0)
2667                         && (_R(ay * yy2) > 0)))
2668                     return 0.0;
2669                }
2670              else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) &&
2671                       (_R((1.0 / g) * yyy2) <= _R(xx2)))
2672                {
2673                   if (!((_R(ax * ((1.0 / g) * yyy2)) > 0)
2674                         && (_R(ay * yyy2) > 0))) return 0.0;
2675                }
2676              else return 0.0;
2677           }
2678      }
2679
2680    /* Calculate the weight for obj2. */
2681    if (degree == 0.0)
2682      {
2683         if (_R(xx1) > _R(x2)) weight = -1.0;
2684         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2685           weight = (x2 - xx1) * (x2 - xx1);
2686         else if (_R(yy2) > 0)
2687           weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
2688         else if (_R(yyy2) < 0)
2689           weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
2690         else weight = (x2 - xx1) * (x2 - xx1);
2691      }
2692    else if (degree == 90.0)
2693      {
2694         if (_R(yyy1) > _R(yy2)) weight = -1.0;
2695         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2696           weight = (yy2 - yyy1) * (yy2 - yyy1);
2697         else if (_R(x2) > 0)
2698           weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
2699         else if (_R(xx2) < 0)
2700           weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
2701         else weight = (yy2 - yyy1) * (yy2 - yyy1);
2702      }
2703    else if (degree == 180.0)
2704      {
2705         if (_R(x1) < _R(xx2)) weight = -1.0;
2706         else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2707           weight = (x1 - xx2) * (x1 - xx2);
2708         else if (_R(yy2) > 0)
2709           weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
2710         else if (_R(yyy2) < 0)
2711           weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
2712         else weight = (x1 - xx2) * (x1 - xx2);
2713      }
2714    else if (degree == 270.0)
2715      {
2716         if (_R(yy1) < _R(yyy2)) weight = -1.0;
2717         else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2718           weight = (yy1 - yyy2) * (yy1 - yyy2);
2719         else if (_R(x2) > 0)
2720           weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
2721         else if (_R(xx2) < 0)
2722           weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
2723         else weight = (yy1 - yyy2) * (yy1 - yyy2);
2724      }
2725    else
2726      {
2727         int j = 0, k = 0;
2728         double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
2729         double t_weight[4] = {-1.0, -1.0, -1.0, -1.0};
2730         if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
2731           {
2732              sx[j] = x2;
2733              sy[j] = g * x2;
2734              t_weight[j++] = ((ax - x2) * (ax - x2)) +
2735                ((ay - (g * x2)) * (ay - (g * x2)));
2736           }
2737         if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
2738           {
2739              sx[j] = xx2;
2740              sy[j] = g * xx2;
2741              t_weight[j++] = ((ax - xx2) * (ax - xx2)) +
2742                ((ay - (g * xx2)) * (ay - (g * xx2)));
2743           }
2744         if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
2745           {
2746              sx[j] = (1.0 / g) * yy2;
2747              sy[j] = yy2;
2748              t_weight[j++] =
2749                ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) +
2750                ((ay - yy2) * (ay - yy2));
2751           }
2752         if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2)
2753                                                  <= _R(xx2)))
2754           {
2755              sx[j] = (1.0 / g) * yyy2;
2756              sy[j] = yyy2;
2757              t_weight[j++] =
2758                ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) +
2759                ((ay - yyy2) * (ay - yyy2));
2760           }
2761
2762         if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) ||
2763                                      (_R(sy[0]) != _R(sy[1])))))
2764           {
2765              for (; k < j; k++)
2766                {
2767                   if (_R(t_weight[k]) == 0) return -1.0;
2768                   if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
2769                }
2770           }
2771         else
2772           {
2773              for (; k < i; k++)
2774                {
2775                   double ccx, ccy, t1_weight, x_diff, y_diff;
2776                   ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
2777                   ccy = g * ccx;
2778                   x_diff = rx[k] - ccx;
2779                   if (x_diff < 0) x_diff *= -1.0;
2780                   y_diff = ry[k] - ccy;
2781                   if (y_diff < 0) y_diff *= -1.0;
2782                   t1_weight =
2783                     (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
2784                     ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
2785                   if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
2786                     weight = t1_weight;
2787                }
2788           }
2789      }
2790    /* Return the current object's weight. */
2791    if (weight == -1.0) return 0.0;
2792    if (_R(weight) == 0) return -1.0;
2793
2794 #undef _R
2795
2796    // TIZEN_ONLY(20171129): add second_level for weight calculate
2797    if (second_level) return 1.0 / (weight * 1000000.0);
2798    //
2799
2800    return 1.0 / weight;
2801 }
2802
2803 /** @internal */
2804 EAPI void
2805 elm_widget_parent_highlight_set(Eo *obj, Eina_Bool highlighted)
2806 {
2807    Elm_Widget_Smart_Data *sd =efl_data_scope_safe_get(obj, MY_CLASS);
2808    if (!sd) return;
2809
2810    highlighted = !!highlighted;
2811
2812    Evas_Object *o = elm_widget_parent_get(obj);
2813
2814    if (o) elm_widget_parent_highlight_set(o, highlighted);
2815
2816    sd->highlighted = highlighted;
2817 }
2818
2819 EOLIAN static Evas_Object*
2820 _efl_ui_widget_widget_parent_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
2821 {
2822    return sd->parent_obj;
2823 }
2824
2825 void
2826 _elm_widget_focus_auto_show(Evas_Object *obj)
2827 {
2828    Evas_Object *top = elm_widget_top_get(obj);
2829    if (top && efl_isa(top, EFL_UI_WIN_CLASS)) _elm_win_focus_auto_show(top);
2830 }
2831
2832 void
2833 _elm_widget_top_win_focused_set(Evas_Object *obj,
2834                                 Eina_Bool top_win_focused)
2835 {
2836    Evas_Object *child;
2837    API_ENTRY return;
2838
2839    if (sd->top_win_focused == top_win_focused) return;
2840    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2841      {
2842         child = eina_array_data_get(sd->children, i);
2843         if (elm_widget_is(child))
2844           _elm_widget_top_win_focused_set(child, top_win_focused);
2845      }
2846    sd->top_win_focused = top_win_focused;
2847
2848    if (sd->focused && !sd->top_win_focused)
2849      efl_ui_focus_object_on_focus_update(obj);
2850 }
2851
2852 Eina_Bool
2853 _elm_widget_top_win_focused_get(const Evas_Object *obj)
2854 {
2855    API_ENTRY return EINA_FALSE;
2856    return sd->top_win_focused;
2857 }
2858
2859 EOLIAN static void
2860 _efl_ui_widget_disabled_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd, Eina_Bool disabled)
2861 {
2862    Efl_Ui_Widget *subs;
2863    int old_state;
2864
2865    old_state = pd->disabled;
2866
2867    pd->disabled = _calculate_tree_number(pd->disabled, (pd->parent_obj ? _disabled_counter_get(pd->parent_obj) : 0), disabled);
2868    if (old_state != pd->disabled)
2869      {
2870         //TIZEN_ONLY(20191028): Restore focus revert in disabled_set
2871         efl_ui_widget_focus_disabled_handle(obj);
2872         //
2873         if (efl_finalized_get(obj))
2874           _full_eval(obj, pd);
2875         for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
2876           {
2877              subs = eina_array_data_get(pd->children, i);
2878              //TIZEN_ONLY(20180607): Restore legacy focus
2879              if (elm_widget_is(subs))
2880                efl_ui_widget_focus_disabled_handle((Evas_Object *)subs);
2881              //
2882              if (efl_isa(subs, EFL_UI_WIDGET_CLASS))
2883                efl_ui_widget_disabled_set(subs, disabled);
2884           }
2885      }
2886 }
2887
2888 EOLIAN static Eina_Bool
2889 _efl_ui_widget_disabled_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
2890 {
2891    return pd->disabled > 0;
2892 }
2893
2894 /**
2895  * @internal
2896  *
2897  * Get the focus region of the given widget.
2898  *
2899  * @return The region to show. If it's not a valid rectangle it will not show.
2900  *
2901  * The focus region is the area of a widget that should brought into the
2902  * visible area when the widget is focused. Mostly used to show the part of
2903  * an entry where the cursor is, for example. The area returned is relative
2904  * to the object @p obj.
2905  *
2906  * @param obj The widget object
2907  * @return The region to show, in relative coordinates. If it's not a valid
2908  *         rectangle (i.e. w or h <= 0) it will be ignored.
2909  *
2910  * @ingroup Widget
2911  */
2912 EOLIAN static Eina_Rect
2913 _efl_ui_widget_interest_region_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
2914 {
2915    Eina_Rect r = {};
2916    r.size = efl_gfx_entity_size_get(obj);
2917    return r;
2918 }
2919
2920 EOLIAN static void
2921 _efl_ui_widget_scroll_hold_push(Eo *obj, Elm_Widget_Smart_Data *sd)
2922 {
2923    sd->scroll_hold++;
2924    if (sd->scroll_hold == 1)
2925      {
2926         if (_elm_scrollable_is(obj))
2927           {
2928              if (elm_widget_is_legacy(obj))
2929                elm_interface_scrollable_hold_set(obj, EINA_TRUE);
2930              else
2931                efl_ui_scrollable_scroll_hold_set(obj, EINA_TRUE);
2932           }
2933         else
2934           {
2935              Evas_Object *child;
2936
2937              for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2938                {
2939                   child = eina_array_data_get(sd->children, i);
2940                   if (elm_widget_is(child) && _elm_scrollable_is(child))
2941                     {
2942                        if (elm_widget_is_legacy(child))
2943                          elm_interface_scrollable_hold_set(child, EINA_TRUE);
2944                        else
2945                          efl_ui_scrollable_scroll_hold_set(child, EINA_TRUE);
2946                     }
2947                }
2948           }
2949      }
2950    if (sd->parent_obj) efl_ui_widget_scroll_hold_push(sd->parent_obj);
2951    // FIXME: on delete/reparent hold pop
2952 }
2953
2954 EOLIAN static void
2955 _efl_ui_widget_scroll_hold_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
2956 {
2957    sd->scroll_hold--;
2958    if (!sd->scroll_hold)
2959      {
2960         if (_elm_scrollable_is(obj))
2961           {
2962              if (elm_widget_is_legacy(obj))
2963                elm_interface_scrollable_hold_set(obj, EINA_FALSE);
2964              else
2965                efl_ui_scrollable_scroll_hold_set(obj, EINA_FALSE);
2966           }
2967         else
2968           {
2969              Evas_Object *child;
2970
2971              for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
2972                {
2973                   child = eina_array_data_get(sd->children, i);
2974                   if (elm_widget_is(child) && _elm_scrollable_is(child))
2975                     {
2976                        if (elm_widget_is_legacy(child))
2977                          elm_interface_scrollable_hold_set(child, EINA_FALSE);
2978                        else
2979                          efl_ui_scrollable_scroll_hold_set(child, EINA_FALSE);
2980                     }
2981                }
2982           }
2983      }
2984    if (sd->parent_obj) efl_ui_widget_scroll_hold_pop(sd->parent_obj);
2985    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2986 }
2987
2988 EAPI int
2989 elm_widget_scroll_hold_get(const Eo *obj)
2990 {
2991    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
2992
2993    if (!sd) return 0;
2994    return sd->scroll_hold;
2995 }
2996
2997 EOLIAN static void
2998 _efl_ui_widget_scroll_freeze_push(Eo *obj, Elm_Widget_Smart_Data *sd)
2999 {
3000    sd->scroll_freeze++;
3001    if (sd->scroll_freeze == 1)
3002      {
3003         if (_elm_scrollable_is(obj))
3004           {
3005              if (elm_widget_is_legacy(obj))
3006                elm_interface_scrollable_freeze_set(obj, EINA_TRUE);
3007              else
3008                efl_ui_scrollable_scroll_freeze_set(obj, EINA_TRUE);
3009           }
3010         else
3011           {
3012              Evas_Object *child;
3013
3014              for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
3015                {
3016                   child = eina_array_data_get(sd->children, i);
3017                   if (elm_widget_is(child) && _elm_scrollable_is(child))
3018                     {
3019                        if (elm_widget_is_legacy(child))
3020                          elm_interface_scrollable_freeze_set(child, EINA_TRUE);
3021                        else
3022                          efl_ui_scrollable_scroll_freeze_set(child, EINA_TRUE);
3023                     }
3024                }
3025           }
3026      }
3027    if (sd->parent_obj) efl_ui_widget_scroll_freeze_push(sd->parent_obj);
3028    // FIXME: on delete/reparent freeze pop
3029 }
3030
3031 EOLIAN static void
3032 _efl_ui_widget_scroll_freeze_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
3033 {
3034    sd->scroll_freeze--;
3035    if (!sd->scroll_freeze)
3036      {
3037         if (_elm_scrollable_is(obj))
3038           {
3039              if (elm_widget_is_legacy(obj))
3040                elm_interface_scrollable_freeze_set(obj, EINA_FALSE);
3041              else
3042                efl_ui_scrollable_scroll_freeze_set(obj, EINA_FALSE);
3043           }
3044         else
3045           {
3046              Evas_Object *child;
3047
3048              for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
3049                {
3050                   child = eina_array_data_get(sd->children, i);
3051
3052                   if (elm_widget_is(child) && _elm_scrollable_is(child))
3053                     {
3054                        if (elm_widget_is_legacy(child))
3055                          elm_interface_scrollable_freeze_set(child, EINA_FALSE);
3056                        else
3057                          efl_ui_scrollable_scroll_freeze_set(child, EINA_FALSE);
3058                     }
3059                }
3060           }
3061      }
3062    if (sd->parent_obj) efl_ui_widget_scroll_freeze_pop(sd->parent_obj);
3063    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
3064 }
3065
3066 EAPI int
3067 elm_widget_scroll_freeze_get(const Eo *obj)
3068 {
3069    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3070
3071    if (!sd) return 0;
3072    return sd->scroll_freeze;
3073 }
3074
3075 EOLIAN static void
3076 _efl_ui_widget_efl_gfx_entity_scale_set(Eo *obj, Elm_Widget_Smart_Data *sd, double scale)
3077 {
3078    if (scale < 0.0) scale = 0.0;
3079    if (!EINA_DBL_EQ(sd->scale, scale))
3080      {
3081         sd->scale = scale;
3082         elm_widget_theme(obj);
3083      }
3084 }
3085
3086 EOLIAN static double
3087 _efl_ui_widget_efl_gfx_entity_scale_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3088 {
3089    // FIXME: save walking up the tree by storing/caching parent scale
3090    if (EINA_DBL_EQ(sd->scale, 0.0))
3091      {
3092         if (sd->parent_obj)
3093           {
3094              return efl_gfx_entity_scale_get(sd->parent_obj);
3095           }
3096         else
3097           {
3098              return 1.0;
3099           }
3100      }
3101    return sd->scale;
3102 }
3103
3104 EAPI void
3105 elm_widget_theme_set(Evas_Object *obj, Elm_Theme *th)
3106 {
3107    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3108    if (!sd) return;
3109
3110    Eina_Bool apply = EINA_FALSE;
3111    if (sd->theme != th)
3112      {
3113         if (elm_widget_theme_get(obj) != th) apply = EINA_TRUE;
3114         if (sd->theme) elm_theme_free(sd->theme);
3115         sd->theme = th;
3116         if (th) efl_ref(th->eo_theme);
3117         if (apply) elm_widget_theme(obj);
3118      }
3119 }
3120
3121 EAPI void
3122 elm_widget_part_text_set(Eo *obj, const char *part, const char *label)
3123 {
3124    /* legacy support: combobox was special (internal entry is text object). */
3125    //TIZEN_ONLY(20180426):stop creating unused class.
3126    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
3127      elm_layout_text_set(obj, part, label);
3128    else if (efl_isa(obj, ELM_COMBOBOX_CLASS))
3129      _elm_combobox_part_text_set(obj, part, label);
3130    //
3131 }
3132
3133 EAPI const char*
3134 elm_widget_part_text_get(const Eo *obj, const char *part)
3135 {
3136    /* legacy support: combobox was special (internal entry is text object). */
3137    //TIZEN_ONLY(20180426):stop creating unused class.
3138    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
3139      return elm_layout_text_get(obj, part);
3140    else if (efl_isa(obj, ELM_COMBOBOX_CLASS))
3141      return _elm_combobox_part_text_get(obj, part);
3142    //
3143
3144    return NULL;
3145 }
3146
3147 static Elm_Translate_String_Data *
3148 _translate_string_data_get(Eina_Inlist *translate_strings, const char *part)
3149 {
3150    Elm_Translate_String_Data *ts;
3151    Eina_Stringshare *str;
3152
3153    if (!translate_strings) return NULL;
3154
3155    str = eina_stringshare_add(part);
3156    EINA_INLIST_FOREACH(translate_strings, ts)
3157      {
3158         if (ts->id == str) break;
3159      }
3160
3161    eina_stringshare_del(str);
3162
3163    return ts;
3164 }
3165
3166 static Elm_Translate_String_Data *
3167 _part_text_translatable_set(Eina_Inlist **translate_strings, const char *part, Eina_Bool translatable, Eina_Bool preset)
3168 {
3169    Eina_Inlist *t;
3170    Elm_Translate_String_Data *ts;
3171    t = *translate_strings;
3172    ts = _translate_string_data_get(t, part);
3173
3174    if (translatable)
3175      {
3176         if (!ts)
3177           {
3178              ts = ELM_NEW(Elm_Translate_String_Data);
3179              if (!ts) return NULL;
3180
3181              ts->id = eina_stringshare_add(part);
3182              t = eina_inlist_append(t, (Eina_Inlist*) ts);
3183           }
3184         if (preset) ts->preset = EINA_TRUE;
3185      }
3186    //Delete this exist one if this part has been not preset.
3187    //see elm_widget_part_text_translatable_set()
3188    else if (ts && ((preset) || (!ts->preset)))
3189      {
3190         t = eina_inlist_remove(t, EINA_INLIST_GET(ts));
3191         eina_stringshare_del(ts->id);
3192         eina_stringshare_del(ts->domain);
3193         eina_stringshare_del(ts->string);
3194         ELM_SAFE_FREE(ts, free);
3195      }
3196
3197    *translate_strings = t;
3198
3199    return ts;
3200 }
3201
3202 /* internal */
3203 void
3204 elm_widget_part_translatable_text_set(Eo *obj, const char *part, const char *label, const char *domain)
3205 {
3206    Elm_Translate_String_Data *ts;
3207    Elm_Widget_Smart_Data *sd;
3208
3209    sd = efl_data_scope_safe_get(obj, MY_CLASS);
3210    if (!sd) return;
3211
3212    if (!label)
3213      {
3214         _part_text_translatable_set(&sd->translate_strings, part, EINA_FALSE,
3215                                     EINA_FALSE);
3216      }
3217    else
3218      {
3219         ts = _part_text_translatable_set(&sd->translate_strings, part,
3220                                          EINA_TRUE, EINA_FALSE);
3221         if (!ts) return;
3222         if (!ts->string) ts->string = eina_stringshare_add(label);
3223         else eina_stringshare_replace(&ts->string, label);
3224         if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3225         else eina_stringshare_replace(&ts->domain, domain);
3226 #ifdef HAVE_GETTEXT
3227         if (label[0]) label = dgettext(domain, label);
3228 #endif
3229      }
3230
3231    sd->on_translate = EINA_TRUE;
3232    elm_widget_part_text_set(obj, part, label);
3233    sd->on_translate = EINA_FALSE;
3234 }
3235
3236 /* legacy only */
3237 EAPI void
3238 elm_widget_domain_part_text_translatable_set(Eo *obj, const char *part, const char *domain, Eina_Bool translatable)
3239 {
3240    Elm_Translate_String_Data *ts;
3241    Elm_Widget_Smart_Data *sd;
3242    const char *text = NULL;
3243
3244    sd = efl_data_scope_safe_get(obj, MY_CLASS);
3245    if (!sd) return;
3246
3247    ts = _part_text_translatable_set(&sd->translate_strings, part,
3248                                     translatable, EINA_TRUE);
3249    if (!ts) return;
3250    if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3251    else eina_stringshare_replace(&ts->domain, domain);
3252
3253    text = elm_widget_part_text_get(obj, part);
3254    if (!text || !text[0]) return;
3255
3256    if (!ts->string) ts->string = eina_stringshare_add(text);
3257
3258 //Try to translate text since we don't know the text is already translated.
3259 #ifdef HAVE_GETTEXT
3260    text = dgettext(domain, text);
3261 #endif
3262    sd->on_translate = EINA_TRUE;
3263    elm_widget_part_text_set(obj, part, text);
3264    sd->on_translate = EINA_FALSE;
3265 }
3266
3267 /* internal */
3268 const char *
3269 elm_widget_part_translatable_text_get(const Eo *obj, const char *part, const char **domain)
3270 {
3271    Elm_Widget_Smart_Data *sd;
3272    Elm_Translate_String_Data *ts;
3273
3274    if (domain) *domain = NULL;
3275
3276    sd = efl_data_scope_safe_get(obj, MY_CLASS);
3277    if (!sd) return NULL;
3278
3279    ts = _translate_string_data_get(sd->translate_strings, part);
3280    if (!ts) return NULL;
3281
3282    if (domain) *domain = ts->domain;
3283    return ts->string;
3284 }
3285
3286 EOLIAN static void
3287 _efl_ui_widget_efl_ui_l10n_translation_update(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3288 {
3289    Evas_Object *child;
3290
3291    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
3292      {
3293         child = eina_array_data_get(sd->children, i);
3294         if (elm_widget_is(child))
3295           efl_ui_l10n_translation_update(child);
3296
3297      }
3298
3299    if (sd->hover_obj) efl_ui_l10n_translation_update(sd->hover_obj);
3300
3301 #ifdef HAVE_GETTEXT
3302    Elm_Translate_String_Data *ts;
3303    EINA_INLIST_FOREACH(sd->translate_strings, ts)
3304      {
3305         if (!ts->string) continue;
3306         const char *s = dgettext(ts->domain, ts->string);
3307         sd->on_translate = EINA_TRUE;
3308         elm_widget_part_text_set(obj, ts->id, s);
3309         sd->on_translate = EINA_FALSE;
3310      }
3311 #endif
3312    efl_event_callback_legacy_call(obj, EFL_UI_WIDGET_EVENT_LANGUAGE_CHANGED, NULL);
3313 }
3314
3315 EOLIAN static void
3316 _efl_ui_widget_access_info_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *txt)
3317 {
3318    eina_stringshare_replace(&sd->access_info, txt);
3319 }
3320
3321 EOLIAN static const char*
3322 _efl_ui_widget_access_info_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3323 {
3324    return sd->access_info;
3325 }
3326
3327 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
3328 //register/unregister access objects accordingly.
3329 EAPI Eina_Bool
3330 elm_widget_screen_reader(Evas_Object *obj,
3331                   Eina_Bool is_screen_reader)
3332 {
3333    Evas_Object *child;
3334    Eina_Bool ret = EINA_TRUE;
3335
3336    API_ENTRY return EINA_FALSE;
3337    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
3338      {
3339         child = eina_array_data_get(sd->children, i);
3340         if (elm_widget_is(child))
3341           ret &= elm_widget_screen_reader(child, is_screen_reader);
3342      }
3343    efl_ui_widget_screen_reader(obj, is_screen_reader);
3344
3345    return ret;
3346 }
3347
3348 EOLIAN static void
3349 _efl_ui_widget_screen_reader(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_screen_reader EINA_UNUSED)
3350 {
3351 }
3352 //
3353
3354 //TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
3355 EAPI Eina_Bool
3356 elm_widget_atspi(Evas_Object *obj, Eina_Bool is_atspi)
3357 {
3358    Eina_List *l, *children;
3359    Evas_Object *child;
3360    Eina_Bool ret = EINA_TRUE;
3361
3362    API_ENTRY return EINA_FALSE;
3363    children = efl_access_object_access_children_get(obj);
3364    EINA_LIST_FOREACH(children, l, child)
3365      {
3366         ret &= elm_widget_atspi(child, is_atspi);
3367      }
3368    efl_ui_widget_atspi(obj, is_atspi);
3369
3370    return ret;
3371 }
3372
3373 EOLIAN static void
3374 _efl_ui_widget_atspi(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_atspi EINA_UNUSED)
3375 {
3376 }
3377 //
3378 //
3379
3380 EAPI void
3381 elm_widget_scroll_hold_push(Efl_Ui_Widget *obj)
3382 {
3383    efl_ui_widget_scroll_hold_push(obj);
3384 }
3385
3386 EAPI void
3387 elm_widget_scroll_hold_pop(Efl_Ui_Widget *obj)
3388 {
3389    efl_ui_widget_scroll_hold_pop(obj);
3390 }
3391
3392 EAPI void
3393 elm_widget_scroll_freeze_push(Efl_Ui_Widget *obj)
3394 {
3395    efl_ui_widget_scroll_freeze_push(obj);
3396 }
3397
3398 EAPI void
3399 elm_widget_scroll_freeze_pop(Efl_Ui_Widget *obj)
3400 {
3401    efl_ui_widget_scroll_freeze_pop(obj);
3402 }
3403
3404 EAPI Elm_Theme *
3405 elm_widget_theme_get(const Evas_Object *obj)
3406 {
3407    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3408    if (!sd) return NULL;
3409
3410    if (!sd->theme)
3411      {
3412         if (sd->parent_obj)
3413            return elm_widget_theme_get(sd->parent_obj);
3414         else return NULL;
3415      }
3416    return sd->theme;
3417 }
3418
3419 EOLIAN static Eina_Error
3420 _efl_ui_widget_style_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *style)
3421 {
3422    if (!elm_widget_is_legacy(obj) && efl_finalized_get(obj))
3423      {
3424         ERR("Efl.Ui.Widget.style can only be set before finalize!");
3425         return EFL_UI_THEME_APPLY_ERROR_GENERIC;
3426      }
3427
3428    if (eina_stringshare_replace(&sd->style, style))
3429       return elm_widget_theme(obj);
3430
3431    return EFL_UI_THEME_APPLY_ERROR_NONE;
3432 }
3433
3434 EOLIAN static const char*
3435 _efl_ui_widget_style_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3436 {
3437    const char *ret;
3438    ret = "default";
3439    if (sd->style) ret = sd->style;
3440
3441    return ret;
3442 }
3443
3444 EAPI void
3445 elm_widget_tooltip_add(Eo *obj, Elm_Tooltip *tt)
3446 {
3447    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3448    if (!sd) return;
3449
3450    sd->tooltips = eina_list_append(sd->tooltips, tt);
3451 }
3452
3453 EAPI void
3454 elm_widget_tooltip_del(Eo *obj, Elm_Tooltip *tt)
3455 {
3456    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3457    if (!sd) return;
3458
3459    sd->tooltips = eina_list_remove(sd->tooltips, tt);
3460 }
3461
3462 EAPI void
3463 elm_widget_cursor_add(Eo *obj, Elm_Cursor *cur)
3464 {
3465    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3466    if (!sd) return;
3467
3468    sd->cursors = eina_list_append(sd->cursors, cur);
3469 }
3470
3471 EAPI void
3472 elm_widget_cursor_del(Eo *obj, Elm_Cursor *cur)
3473 {
3474    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3475    if (!sd) return;
3476
3477    sd->cursors = eina_list_remove(sd->cursors, cur);
3478 }
3479
3480 EAPI void
3481 elm_widget_scroll_lock_set(Eo *obj, Efl_Ui_Layout_Orientation block)
3482 {
3483    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3484    Eina_Bool lx, ly;
3485
3486    if (!sd) return;
3487    lx = !!(block & EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL);
3488    ly = !!(block & EFL_UI_LAYOUT_ORIENTATION_VERTICAL);
3489    if (sd->scroll_x_locked != lx)
3490      {
3491         sd->scroll_x_locked = lx;
3492         _propagate_x_drag_lock(obj, lx ? 1 : -1);
3493      }
3494    if (sd->scroll_y_locked != ly)
3495      {
3496         sd->scroll_y_locked = ly;
3497         _propagate_y_drag_lock(obj, ly ? 1 : -1);
3498      }
3499 }
3500
3501 EAPI Efl_Ui_Layout_Orientation
3502 elm_widget_scroll_lock_get(const Eo *obj)
3503 {
3504    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3505    Efl_Ui_Layout_Orientation block = EFL_UI_LAYOUT_ORIENTATION_DEFAULT;
3506
3507    if (!sd) return block;
3508    if (sd->scroll_x_locked) block |= EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL;
3509    if (sd->scroll_y_locked) block |= EFL_UI_LAYOUT_ORIENTATION_VERTICAL;
3510
3511    return block;
3512 }
3513
3514 EAPI int
3515 elm_widget_scroll_child_locked_x_get(const Eo *obj)
3516 {
3517    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3518    if (!sd) return EINA_FALSE;
3519    return sd->child_drag_x_locked;
3520 }
3521
3522 EAPI int
3523 elm_widget_scroll_child_locked_y_get(const Eo *obj)
3524 {
3525    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3526    if (!sd) return EINA_FALSE;
3527    return sd->child_drag_y_locked;
3528 }
3529
3530 EAPI Eina_Error
3531 elm_widget_theme_object_set(Evas_Object *obj, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle)
3532 {
3533    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
3534    if (!sd) return EFL_UI_THEME_APPLY_ERROR_GENERIC;
3535
3536    if (eina_streq(welement, "base"))
3537      welement = NULL;
3538    if (eina_streq(wstyle, "default"))
3539      wstyle = NULL;
3540    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
3541 }
3542
3543 static void
3544 _convert(Efl_Dbg_Info *info, Eina_Iterator *ptr_list)
3545 {
3546    void *p;
3547    int i = 0;
3548
3549    EINA_ITERATOR_FOREACH(ptr_list, p)
3550      {
3551         char name[100];
3552
3553         snprintf(name, sizeof(name), "Candidate %d", i);
3554
3555         EFL_DBG_INFO_APPEND(info, name, EINA_VALUE_TYPE_UINT64, p);
3556         i++;
3557      }
3558
3559    eina_iterator_free(ptr_list);
3560 }
3561
3562 EOLIAN static void
3563 _efl_ui_widget_efl_object_dbg_info_get(Eo *eo_obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Dbg_Info *root)
3564 {
3565    efl_dbg_info_get(efl_super(eo_obj, MY_CLASS), root);
3566    Efl_Ui_Focus_Relations *rel = NULL;
3567    Efl_Dbg_Info *focus, *group = EFL_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
3568
3569    EFL_DBG_INFO_APPEND(group, "Wid-Type", EINA_VALUE_TYPE_STRING, elm_widget_type_get(eo_obj));
3570    EFL_DBG_INFO_APPEND(group, "Style", EINA_VALUE_TYPE_STRING, elm_widget_style_get(eo_obj));
3571    EFL_DBG_INFO_APPEND(group, "Layer", EINA_VALUE_TYPE_INT,
3572          (int) evas_object_layer_get(eo_obj));
3573    EFL_DBG_INFO_APPEND(group, "Scale", EINA_VALUE_TYPE_DOUBLE,
3574          evas_object_scale_get(eo_obj));
3575    EFL_DBG_INFO_APPEND(group, "Has focus", EINA_VALUE_TYPE_CHAR,
3576          elm_object_focus_get(eo_obj));
3577    EFL_DBG_INFO_APPEND(group, "Can focus", EINA_VALUE_TYPE_CHAR,
3578          elm_widget_can_focus_get(eo_obj));
3579    EFL_DBG_INFO_APPEND(group, "Disabled", EINA_VALUE_TYPE_CHAR,
3580          elm_widget_disabled_get(eo_obj));
3581    EFL_DBG_INFO_APPEND(group, "Mirrored", EINA_VALUE_TYPE_CHAR,
3582          efl_ui_mirrored_get(eo_obj));
3583    EFL_DBG_INFO_APPEND(group, "Tree Unfocusable", EINA_VALUE_TYPE_CHAR,
3584          elm_widget_tree_unfocusable_get(eo_obj));
3585    EFL_DBG_INFO_APPEND(group, "Automatic mirroring", EINA_VALUE_TYPE_CHAR,
3586          efl_ui_mirrored_automatic_get(eo_obj));
3587
3588    rel = efl_ui_focus_manager_fetch(_pd->focus.manager, eo_obj);
3589    if (rel)
3590      {
3591         focus = EFL_DBG_INFO_LIST_APPEND(group, "Focus");
3592
3593         EFL_DBG_INFO_APPEND(focus, "logical", EINA_VALUE_TYPE_CHAR, rel->logical );
3594         EFL_DBG_INFO_APPEND(focus, "manager", EINA_VALUE_TYPE_UINT64, _pd->focus.manager);
3595         EFL_DBG_INFO_APPEND(focus, "parent", EINA_VALUE_TYPE_UINT64, rel->parent);
3596         EFL_DBG_INFO_APPEND(focus, "next", EINA_VALUE_TYPE_UINT64 , rel->next);
3597         EFL_DBG_INFO_APPEND(focus, "prev", EINA_VALUE_TYPE_UINT64 , rel->prev);
3598
3599         EFL_DBG_INFO_APPEND(focus, "redirect", EINA_VALUE_TYPE_UINT64 , rel->redirect);
3600
3601 #define ADD_PTR_LIST(name) \
3602         Efl_Dbg_Info* name = EFL_DBG_INFO_LIST_APPEND(focus, ""#name""); \
3603         _convert(name, rel->name);
3604
3605         ADD_PTR_LIST(top)
3606         ADD_PTR_LIST(down)
3607         ADD_PTR_LIST(right)
3608         ADD_PTR_LIST(left)
3609
3610 #undef ADD_PTR_LIST
3611
3612      }
3613
3614    //if that's a focus manager, give useful information like the border elements
3615    if (efl_isa(eo_obj, EFL_UI_FOCUS_MANAGER_INTERFACE))
3616      {
3617         Efl_Dbg_Info *border;
3618
3619         focus = EFL_DBG_INFO_LIST_APPEND(group, "Focus Manager");
3620         border = EFL_DBG_INFO_LIST_APPEND(focus, "Border Elements");
3621
3622         _convert(border,
3623           efl_ui_focus_manager_border_elements_get(eo_obj)
3624         );
3625
3626         EFL_DBG_INFO_APPEND(focus, "redirect", EINA_VALUE_TYPE_UINT64,
3627           efl_ui_focus_manager_redirect_get(eo_obj));
3628      }
3629 }
3630
3631 EAPI Eina_Bool
3632 elm_widget_is_check(const Evas_Object *obj)
3633 {
3634    static int abort_on_warn = -1;
3635    if (elm_widget_is(obj))
3636      return EINA_TRUE;
3637
3638    ERR("Passing Object: %p.", obj);
3639    if (abort_on_warn == -1)
3640      {
3641         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3642         else abort_on_warn = 0;
3643      }
3644    if (abort_on_warn == 1) abort();
3645    return EINA_FALSE;
3646 }
3647
3648 /* If you changed a legacy widget's class name,
3649  * please update the "legacy_type_table". */
3650 EAPI const char *
3651 elm_widget_type_get(const Evas_Object *obj)
3652 {
3653    const char *ret;
3654    int i;
3655
3656    API_ENTRY return NULL;
3657
3658    ret = efl_class_name_get(efl_class_get(obj));
3659
3660    /* If the given widget is created for legacy,
3661     * convert type name to legacy. */
3662    if (elm_widget_is_legacy(obj))
3663      {
3664         for (i = 0; legacy_type_table[i][0] ; i++)
3665           {
3666              if (eina_streq(ret, legacy_type_table[i][0]))
3667                return legacy_type_table[i][1];
3668           }
3669      }
3670
3671    return ret;
3672 }
3673
3674 EAPI Eina_Bool
3675 elm_widget_type_check(const Evas_Object *obj,
3676                       const char *type,
3677                       const char *func)
3678 {
3679    const char *provided, *expected = "(unknown)";
3680    static int abort_on_warn = -1;
3681
3682    provided = elm_widget_type_get(obj);
3683    /* TODO: eventually migrate to check_ptr version */
3684    if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
3685    if (type) expected = type;
3686    if ((!provided) || (!provided[0]))
3687      {
3688         provided = evas_object_type_get(obj);
3689         if ((!provided) || (!provided[0]))
3690           provided = "(unknown)";
3691      }
3692    ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
3693        " type: '%s'", obj, func, provided, expected);
3694    if (abort_on_warn == -1)
3695      {
3696         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
3697         else abort_on_warn = 0;
3698      }
3699    if (abort_on_warn == 1) abort();
3700    return EINA_FALSE;
3701 }
3702
3703 /** @internal */
3704 EAPI Evas_Object *
3705 elm_widget_name_find(const Eo *obj, const char *name, int recurse)
3706 {
3707    Evas_Object *child;
3708    const char *s;
3709    INTERNAL_ENTRY NULL;
3710
3711    if (!name) return NULL;
3712    if (!_elm_widget_is(obj)) return NULL;
3713
3714    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
3715      {
3716         child = eina_array_data_get(sd->children, i);
3717         s = evas_object_name_get(child);
3718         if ((s) && (!strcmp(s, name))) return child;
3719         if ((recurse != 0) &&
3720             ((child = elm_widget_name_find(child, name, recurse - 1))))
3721           return child;
3722      }
3723    if (sd->hover_obj)
3724      {
3725         s = evas_object_name_get(sd->hover_obj);
3726         if ((s) && (!strcmp(s, name))) return sd->hover_obj;
3727         if ((recurse != 0) &&
3728             ((child = elm_widget_name_find(sd->hover_obj, name, recurse - 1))))
3729           return child;
3730      }
3731    return NULL;
3732 }
3733
3734 /**
3735  * @internal
3736  *
3737  * Split string in words
3738  *
3739  * @param str Source string
3740  * @return List of const words
3741  *
3742  * @see elm_widget_stringlist_free()
3743  * @ingroup Widget
3744  */
3745 EAPI Eina_List *
3746 elm_widget_stringlist_get(const char *str)
3747 {
3748    Eina_List *list = NULL;
3749    const char *s, *b;
3750    if (!str) return NULL;
3751    for (b = s = str; 1; s++)
3752      {
3753         if ((*s == ' ') || (!*s))
3754           {
3755              char *t = malloc(s - b + 1);
3756              if (t)
3757                {
3758                   strncpy(t, b, s - b);
3759                   t[s - b] = 0;
3760                   list = eina_list_append(list, eina_stringshare_add(t));
3761                   free(t);
3762                }
3763              b = s + 1;
3764           }
3765         if (!*s) break;
3766      }
3767    return list;
3768 }
3769
3770 EAPI void
3771 elm_widget_stringlist_free(Eina_List *list)
3772 {
3773    const char *s;
3774    EINA_LIST_FREE(list, s)
3775      eina_stringshare_del(s);
3776 }
3777 //TIZEN_ONLY(20180607): Restore legacy focus
3778 EOLIAN static void
3779 _efl_ui_widget_focus_hide_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3780 {
3781    if (!_elm_widget_is(obj))
3782      return;
3783    _if_focused_revert(obj, EINA_TRUE);
3784 }
3785 //
3786 /* internal */
3787 EAPI void
3788 elm_widget_focus_mouse_up_handle(Eo *obj)
3789 {
3790    if (!_is_focusable(obj)) return;
3791
3792    /* TIZEN_ONLY(20180607): Restore legacy focus
3793    Elm_Widget_Smart_Data *pd = efl_data_scope_get(obj, MY_CLASS);
3794    if (pd->focus.manager && !pd->focus.logical)
3795      {
3796         efl_ui_focus_util_focus(obj);
3797      }
3798    */
3799    Evas_Object *o = obj;
3800    do
3801      {
3802         if (_elm_widget_is(o)) break;
3803         o = evas_object_smart_parent_get(o);
3804      }
3805    while (o);
3806
3807    efl_ui_widget_focus_mouse_up_handle(o);
3808 }
3809
3810 // TIZEN_ONLY(20190821): keep legacy focus logic
3811 EOLIAN static void
3812 _efl_ui_widget_focus_tree_unfocusable_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3813 {
3814    if (!elm_widget_parent_get(obj))
3815      efl_ui_widget_focused_object_clear(obj);
3816    else
3817      _if_focused_revert(obj, EINA_TRUE);
3818 }
3819 //
3820
3821
3822 /*
3823  * @internal
3824  *
3825  * Get the focus highlight geometry of a widget.
3826  *
3827  * @param obj Widget object for the focus highlight
3828  * @param x Focus highlight x coordinate
3829  * @param y Focus highlight y coordinate
3830  * @param w Focus highlight object width
3831  * @param h Focus highlight object height
3832  * @param is_next @c EINA_TRUE if this request is for the new focused object,
3833  * @c EINA_FALSE if this request is for the previously focused object. This
3834  * information becomes important when the focus highlight is changed inside one
3835  * widget.
3836  *
3837  * @ingroup Widget
3838  */
3839 /*
3840  * @internal
3841  *
3842  * Get the 'focus_part' geometry if there is any
3843  *
3844  * This queries if there is a 'focus_part' request from the edc style. If edc
3845  * style offers 'focus_part' edje data item, this function requests for the
3846  * geometry of a specific part which is described in 'focus_part' edje data.
3847  *
3848  * @param obj Widget object for the focus highlight
3849  * @param x Focus highlight x coordinate
3850  * @param y Focus highlight y coordinate
3851  * @param w Focus highlight object width
3852  * @param h Focus highlight object height
3853  *
3854  * x, y, w, h already contain the object's geometry. If there is a 'focus_part'
3855  * support, these values will be updated accordingly or the values will be
3856  * remained as they were.
3857  *
3858  * @ingroup Widget
3859  */
3860 EAPI void
3861 elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj,
3862                                                    Evas_Coord *x,
3863                                                    Evas_Coord *y,
3864                                                    Evas_Coord *w,
3865                                                    Evas_Coord *h)
3866 {
3867    Evas_Coord tx = 0, ty = 0, tw = 0, th = 0;
3868    const char *target_hl_part = NULL;
3869    const Evas_Object *edje_obj = NULL;
3870
3871    if (obj && efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))
3872      {
3873         edje_obj = obj;
3874         if (!(target_hl_part = edje_object_data_get(edje_obj, "focus_part")))
3875           return;
3876      }
3877    else if (obj && efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
3878      {
3879         edje_obj = elm_layout_edje_get(obj);
3880         if (!(target_hl_part = elm_layout_data_get(obj, "focus_part")))
3881           return;
3882      }
3883    else
3884      return;
3885
3886   edje_object_part_geometry_get(edje_obj, target_hl_part,
3887                                 &tx, &ty, &tw, &th);
3888   *x += tx;
3889   *y += ty;
3890   if (tw != *w) *w = tw;
3891   if (th != *h) *h = th;
3892 }
3893
3894 EOLIAN static Eina_Rect
3895 _efl_ui_widget_focus_highlight_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *sd)
3896 {
3897    Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
3898    Evas_Object *scroller = (Evas_Object *)obj;
3899    Eina_Rect r = {};
3900
3901    evas_object_geometry_get(obj, &r.x, &r.y, &r.w, &r.h);
3902    elm_widget_focus_highlight_focus_part_geometry_get(sd->resize_obj, &r.x, &r.y, &r.w, &r.h);
3903
3904    if (_elm_config->focus_autoscroll_mode != ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN)
3905      return r;
3906
3907    while (scroller)
3908      {
3909         if (_elm_scrollable_is(scroller))
3910           {
3911              elm_interface_scrollable_content_viewport_geometry_get(scroller, &ox, &oy, &ow, &oh);
3912
3913              if (r.y < oy)
3914                r.y = oy;
3915              else if ((oy + oh) < (r.y + r.h))
3916                r.y = (oy + oh - r.h);
3917              else if (r.x < ox)
3918                r.x = ox;
3919              else if ((ox + ow) < (r.x + r.w))
3920                r.x = (ox + ow - r.w);
3921
3922              break;
3923           }
3924         scroller = elm_widget_parent_get(scroller);
3925      }
3926
3927    return r;
3928 }
3929
3930 EAPI void
3931 elm_widget_activate(Evas_Object *obj, Efl_Ui_Activate act)
3932 {
3933    Evas_Object *parent;
3934    Eina_Bool ret;
3935
3936    ELM_WIDGET_CHECK(obj);
3937
3938    ret = EINA_FALSE;
3939
3940    ret = efl_ui_widget_on_access_activate(obj, act);
3941
3942    if (ret) return;
3943
3944    parent = elm_widget_parent_get(obj);
3945    if (parent)
3946      elm_widget_activate(parent, act);
3947
3948    return;
3949 }
3950
3951 /**
3952  * @internal
3953  *
3954  * Sets the widget and child widget's Evas_Display_Mode.
3955  *
3956  * @param obj The widget.
3957  * @param dispmode Evas_Display_Mode to set widget's mode.
3958  *
3959  * Widgets are resized by several reasons.
3960  * Evas_Display_Mode can help for widgets to get one more reason of resize.
3961  * For example, elm conform widget resizes it's contents when keypad state changed.
3962  * After keypad showing, conform widget can change child's Evas_Display_Mode.
3963  * @ingroup Widget
3964  */
3965 /* Legacy only */
3966 EAPI void
3967 elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode)
3968 {
3969    Evas_Display_Mode prev_dispmode;
3970    Evas_Object *child;
3971
3972    API_ENTRY return;
3973    prev_dispmode = evas_object_size_hint_display_mode_get(obj);
3974
3975    if ((prev_dispmode == dispmode) ||
3976        (prev_dispmode == EVAS_DISPLAY_MODE_DONT_CHANGE)) return;
3977
3978    evas_object_size_hint_display_mode_set(obj, dispmode);
3979
3980    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
3981      {
3982         child = eina_array_data_get(sd->children, i);
3983         if (elm_widget_is(child))
3984           elm_widget_display_mode_set(child, dispmode);
3985      }
3986 }
3987
3988 /**
3989  * @internal
3990  *
3991  * Returns the widget's focus move policy.
3992  *
3993  * @param obj The widget.
3994  * @return focus move policy of the object.
3995  *
3996  **/
3997 EOLIAN static Efl_Ui_Focus_Move_Policy
3998 _efl_ui_widget_focus_move_policy_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3999 {
4000    return (Efl_Ui_Focus_Move_Policy)sd->focus_move_policy;
4001 }
4002
4003 /**
4004  * @internal
4005  *
4006  * Sets the widget's focus move policy.
4007  *
4008  * @param obj The widget.
4009  * @param policy Elm_Focus_Move_Policy to set object's focus move policy.
4010  */
4011
4012 EOLIAN static void
4013 _efl_ui_widget_focus_move_policy_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Ui_Focus_Move_Policy policy)
4014 {
4015    if (sd->focus_move_policy == (Elm_Focus_Move_Policy)policy) return;
4016    sd->focus_move_policy = (Elm_Focus_Move_Policy)policy;
4017 }
4018
4019 /**
4020  * Returns the widget's focus_move_policy mode setting.
4021  *
4022  * @param obj The widget.
4023  * @return focus_move_policy mode setting of the object.
4024  *
4025  **/
4026 EOLIAN static Eina_Bool
4027 _efl_ui_widget_focus_move_policy_automatic_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4028 {
4029    return sd->focus_move_policy_auto_mode;
4030 }
4031
4032 /**
4033  * @internal
4034  *
4035  * Sets the widget's focus_move_policy mode setting.
4036  * When widget in automatic mode, it follows the system focus_move_policy mode set by
4037  * elm_config_focus_move_policy_set().
4038  * @param obj The widget.
4039  * @param automatic EINA_TRUE for auto focus_move_policy mode. EINA_FALSE for manual.
4040  */
4041 EOLIAN static void
4042 _efl_ui_widget_focus_move_policy_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
4043 {
4044    if (sd->focus_move_policy_auto_mode != automatic)
4045      {
4046         sd->focus_move_policy_auto_mode = automatic;
4047
4048         if (automatic)
4049           {
4050              efl_ui_widget_focus_move_policy_set
4051                (obj, (Efl_Ui_Focus_Move_Policy)elm_config_focus_move_policy_get());
4052           }
4053      }
4054 }
4055
4056 /**
4057  * @internal
4058  *
4059  * Sets the klass name of a widget.
4060  * @param obj The widget.
4061  * @param name Name of the klass to use.
4062  * @return Whether the name was different and thus replaced.
4063  */
4064 EAPI Eina_Bool
4065 elm_widget_theme_klass_set(Evas_Object *obj, const char *name)
4066 {
4067    Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
4068    if (!pd) return EINA_FALSE;
4069
4070    return eina_stringshare_replace(&(pd->klass), name);
4071 }
4072
4073 /**
4074  * @internal
4075  *
4076  * Gets the klass name of a widget.
4077  * @param obj The widget.
4078  * @return The current klass name of internal canvas object.
4079  */
4080 EAPI const char *
4081 elm_widget_theme_klass_get(const Evas_Object *obj)
4082 {
4083    Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
4084    if (!pd) return NULL;
4085
4086    return (const char *)pd->klass;
4087 }
4088
4089 /**
4090  * @internal
4091  *
4092  * Sets the element name of a widget.
4093  *
4094  * @param obj The widget.
4095  * @param name Name of the element to use.
4096  * @return Whether the name was different and thus replaced.
4097  */
4098 EAPI Eina_Bool
4099 elm_widget_theme_element_set(Evas_Object *obj, const char *name)
4100 {
4101    Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
4102    if (!pd) return EINA_FALSE;
4103
4104    if (eina_streq(name, "base"))
4105      name = NULL;
4106
4107    return eina_stringshare_replace(&(pd->group), name);
4108 }
4109
4110 /**
4111  * @internal
4112  *
4113  * Gets the element name of a widget.
4114  * @param obj The widget.
4115  * @return The current element name of internal canvas object.
4116  */
4117 EAPI const char *
4118 elm_widget_theme_element_get(const Evas_Object *obj)
4119 {
4120    Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
4121    if (!pd) return NULL;
4122
4123    return (const char *)pd->group;
4124 }
4125
4126 /**
4127  * @internal
4128  *
4129  * Sets the style name of a widget.
4130  *
4131  * @param obj The widget.
4132  * @param name Name of the style to use.
4133  * @return Whether the name was different and thus replaced.
4134  */
4135 EAPI Eina_Bool
4136 elm_widget_theme_style_set(Evas_Object *obj, const char *name)
4137 {
4138    Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
4139    if (!pd) return EINA_FALSE;
4140
4141    if (eina_streq(name, "default"))
4142      name = NULL;
4143
4144    return eina_stringshare_replace(&(pd->style), name);
4145 }
4146
4147 /**
4148  * @internal
4149  *
4150  * Gets the style name of a widget.
4151  * @param obj The widget.
4152  * @return The current style name of internal canvas object.
4153  */
4154 EAPI const char *
4155 elm_widget_theme_style_get(const Evas_Object *obj)
4156 {
4157    Elm_Widget_Smart_Data *pd = efl_data_scope_safe_get(obj, MY_CLASS);
4158    if (!pd) return NULL;
4159
4160    return (const char *)pd->style;
4161 }
4162
4163 /**
4164  * @internal
4165  *
4166  * Register sub object as a group of a widget and re-apply its theme.
4167  * @param obj The widget.
4168  * @param component A sub object to be added as an element of the widget.
4169  * @param name An element name of sub object.
4170  * @return Whether the style was successfully applied or not.
4171  */
4172 EAPI Eina_Error
4173 elm_widget_element_update(Evas_Object *obj, Evas_Object *component, const char *name)
4174 {
4175    Eina_Error ret = EFL_UI_THEME_APPLY_ERROR_NONE;
4176    Eina_Bool changed = EINA_FALSE;
4177    const char *obj_group;
4178    Eina_Stringshare *group;
4179
4180    obj_group = elm_widget_theme_element_get(obj);
4181    if (!obj_group)
4182      group = eina_stringshare_add(name);
4183    else
4184      group = eina_stringshare_printf("%s/%s", elm_widget_theme_element_get(obj), name);
4185    if (efl_isa(component, EFL_UI_WIDGET_CLASS))
4186      {
4187         changed |= elm_widget_theme_klass_set(component, elm_widget_theme_klass_get(obj));
4188         changed |= elm_widget_theme_element_set(component, (const char *)group);
4189         changed |= elm_widget_theme_style_set(component, elm_widget_theme_style_get(obj));
4190         if (changed)
4191           ret = efl_ui_widget_theme_apply(component);
4192      }
4193    else
4194      {
4195         ret = elm_widget_theme_object_set(obj, component,
4196                                    elm_widget_theme_klass_get(obj),
4197                                    (const char *)group,
4198                                    elm_widget_theme_style_get(obj));
4199      }
4200    eina_stringshare_del(group);
4201
4202    return ret;
4203 }
4204
4205 static void
4206 _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
4207
4208 static void
4209 _track_obj_update(Evas_Object *track, Evas_Object *obj)
4210 {
4211    //Geometry
4212    Evas_Coord x, y, w, h;
4213    evas_object_geometry_get(obj, &x, &y, &w, &h);
4214    evas_object_move(track, x, y);
4215    evas_object_resize(track, w, h);
4216
4217    //Visibility
4218    if (evas_object_visible_get(obj)) evas_object_show(track);
4219    else evas_object_hide(track);
4220 }
4221
4222 static void
4223 _track_obj_view_update(void *data, const Efl_Event *event)
4224 {
4225    Elm_Widget_Item_Data *item = data;
4226    _track_obj_update(item->track_obj, event->object);
4227 }
4228
4229 static void
4230 _track_obj_view_del(void *data, const Efl_Event *event);
4231
4232 EFL_CALLBACKS_ARRAY_DEFINE(tracker_callbacks,
4233                           { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _track_obj_view_update },
4234                           { EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _track_obj_view_update },
4235                           { EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _track_obj_view_update },
4236                           { EFL_EVENT_DEL, _track_obj_view_del });
4237
4238 static void
4239 _track_obj_view_del(void *data, const Efl_Event *event EINA_UNUSED)
4240 {
4241    Elm_Widget_Item_Data *item = data;
4242
4243    while (evas_object_ref_get(item->track_obj) > 0)
4244      evas_object_unref(item->track_obj);
4245
4246    evas_object_event_callback_del(item->track_obj, EVAS_CALLBACK_DEL,
4247                                   _track_obj_del);
4248    evas_object_del(item->track_obj);
4249    item->track_obj = NULL;
4250 }
4251
4252 static void
4253 _track_obj_del(void *data, Evas *e EINA_UNUSED,
4254                     Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
4255 {
4256    Elm_Widget_Item_Data *item = data;
4257    item->track_obj = NULL;
4258
4259    if (!item->view) return;
4260
4261    efl_event_callback_array_del(item->view, tracker_callbacks(), item);
4262 }
4263
4264 static void
4265 _elm_widget_item_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission,
4266                            const char *source)
4267 {
4268    Elm_Widget_Item_Signal_Data *wisd = data;
4269    wisd->func(wisd->data, wisd->item, emission, source);
4270 }
4271
4272 static void *
4273 _elm_widget_item_signal_callback_list_get(Elm_Widget_Item_Data *item, Eina_List *position)
4274 {
4275    Elm_Widget_Item_Signal_Data *wisd = eina_list_data_get(position);
4276    void *data;
4277
4278    item->signals = eina_list_remove_list(item->signals, position);
4279    data = wisd->data;
4280
4281    if (_elm_widget_is(item->view))
4282      elm_object_signal_callback_del(item->view,
4283                                     wisd->emission, wisd->source,
4284                                     _elm_widget_item_signal_cb);
4285    else if (efl_isa(item->view, EFL_CANVAS_LAYOUT_CLASS))
4286      edje_object_signal_callback_del_full(item->view,
4287                                           wisd->emission, wisd->source,
4288                                           _elm_widget_item_signal_cb, wisd);
4289
4290    eina_stringshare_del(wisd->emission);
4291    eina_stringshare_del(wisd->source);
4292    free(wisd);
4293
4294    return data;
4295 }
4296
4297 #define ERR_NOT_SUPPORTED(item, method)  ERR("%s does not support %s API.", elm_widget_type_get(item->widget), method);
4298
4299 static void
4300 _efl_del_cb(void *data EINA_UNUSED, const Efl_Event *event)
4301 {
4302    Elm_Widget_Item_Data *item = efl_data_scope_get(event->object, ELM_WIDGET_ITEM_CLASS);
4303    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4304    if (item->del_func)
4305       item->del_func((void *) WIDGET_ITEM_DATA_GET(event->object), item->widget, item->eo_obj);
4306 }
4307
4308 /**
4309  * @internal
4310  *
4311  * Allocate a new Elm_Widget_Item-derived structure.
4312  *
4313  * The goal of this structure is to provide common ground for actions
4314  * that a widget item have, such as the owner widget, callback to
4315  * notify deletion, data pointer and maybe more.
4316  *
4317  * @param widget the owner widget that holds this item, must be an elm_widget!
4318  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
4319  *        be used to allocate memory.
4320  *
4321  * @return allocated memory that is already zeroed out, or NULL on errors.
4322  *
4323  * @see elm_widget_item_new() convenience macro.
4324  * @see elm_widget_item_del() to release memory.
4325  * @ingroup Widget
4326  */
4327 EOLIAN static Eo *
4328 _elm_widget_item_efl_object_constructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4329 {
4330    Evas_Object *widget;
4331    widget = efl_parent_get(eo_item);
4332
4333    if (!_elm_widget_is(widget))
4334      {
4335         ERR("Failed");
4336         return NULL;
4337      }
4338
4339    eo_item = efl_constructor(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
4340
4341    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
4342
4343    item->widget = widget;
4344    item->eo_obj = eo_item;
4345    //TIZEN_ONLY(20170717) : expose highlight information on atspi
4346    item->can_highlight = EINA_TRUE;
4347    //
4348    efl_event_callback_add(eo_item, EFL_EVENT_DEL, _efl_del_cb, NULL);
4349
4350    return eo_item;
4351 }
4352
4353 EOLIAN static void
4354 _elm_widget_item_efl_object_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4355 {
4356    Elm_Translate_String_Data *ts;
4357
4358    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4359
4360    eina_stringshare_del(item->style);
4361    eina_stringshare_del(item->access_info);
4362    eina_stringshare_del(item->accessible_name);
4363
4364    while (item->signals)
4365      _elm_widget_item_signal_callback_list_get(item, item->signals);
4366
4367    while (item->translate_strings)
4368      {
4369         ts = EINA_INLIST_CONTAINER_GET(item->translate_strings,
4370                                        Elm_Translate_String_Data);
4371         eina_stringshare_del(ts->id);
4372         eina_stringshare_del(ts->domain);
4373         eina_stringshare_del(ts->string);
4374         item->translate_strings = eina_inlist_remove(item->translate_strings,
4375                                                      item->translate_strings);
4376         free(ts);
4377      }
4378    eina_hash_free(item->labels);
4379
4380    //TIZEN_ONLY : elm_widget_item: add at-spi name setter
4381    efl_access_object_description_set(eo_item, NULL);
4382    efl_access_object_i18n_name_set(eo_item, NULL);
4383
4384    efl_access_object_description_cb_set(eo_item, NULL, NULL);
4385    efl_access_object_name_cb_set(eo_item, NULL, NULL);
4386    //
4387    //TIZEN_ONLY(20230414): Support org.a11y.atspi.Value.Text property.
4388    efl_access_object_value_text_set(eo_item, NULL);
4389    efl_access_object_value_text_cb_set(eo_item, NULL, NULL);
4390    //
4391    //TIZEN_ONLY(20170405) Add gesture method to accessible interface
4392    efl_access_object_gesture_cb_set(eo_item, NULL, NULL);
4393    //
4394    //TIZEN_ONLY : elm_widget_item: add at-spi name setter
4395    efl_access_object_translation_domain_set(eo_item, NULL);
4396    efl_access_object_relationships_clear(eo_item);
4397    //
4398
4399    efl_access_object_attributes_clear(eo_item);
4400
4401    // TIZEN_ONLY(20150709) : atspi relations api
4402    if (item->atspi_custom_relations)
4403      efl_access_relation_set_free(&item->atspi_custom_relations);
4404    //
4405
4406    //TIZEN_ONLY(20150731) : add i18n support for name and description
4407    if (item->atspi_translation_domain)
4408      eina_stringshare_del(item->atspi_translation_domain);
4409    ///
4410
4411    //TIZEN_ONLY(20150713) : add widget_item name setter
4412    if (item->name)
4413      eina_stringshare_del(item->name);
4414    //
4415
4416    /***********************************************************************************
4417     * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *
4418     ***********************************************************************************/
4419    if (item->color_classes)
4420      ELM_SAFE_FREE(item->color_classes, eina_hash_free);
4421    /*******
4422     * END *
4423     *******/
4424
4425    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
4426
4427    efl_destructor(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
4428 }
4429
4430 /**
4431  * @internal
4432  *
4433  * Releases widget item memory, calling back item_del_pre_hook() and
4434  * item_del_cb() if they exist.
4435  *
4436  * @param item a valid #Elm_Widget_Item to be deleted.
4437  *
4438  * If there is an Elm_Widget_Item::del_cb, then it will be called prior
4439  * to memory release. Note that elm_widget_item_pre_notify_del() calls
4440  * this function and then unset it, thus being useful for 2 step
4441  * cleanup whenever the del_cb may use any of the data that must be
4442  * deleted from item.
4443  *
4444  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
4445  * is presented!
4446  *
4447  * Note that if item_del_pre_hook() returns @c EINA_TRUE, item free will be
4448  * deferred, or item will be freed here if it returns @c EINA_FALSE.
4449  *
4450  * @see elm_widget_item_del() convenience macro.
4451  * @ingroup Widget
4452  */
4453 EOLIAN static void
4454 _elm_widget_item_efl_object_invalidate(Eo *eo_item, Elm_Widget_Item_Data *item)
4455 {
4456    Evas_Object *view;
4457
4458    //Widget item delete callback
4459    elm_wdg_item_del_pre(item->eo_obj);
4460
4461    // TIZEN_ONLY(20200109): if item deletion process need to be intercepted for
4462    // provide animation on the view object, widget need to add efl_del_intercept_set()
4463    // and clear the view after all animation processed.
4464    if (!efl_del_intercept_get(eo_item))
4465      {
4466         view = item->view;
4467         if (item->view) efl_wref_del(item->view, &item->view);
4468         // FIXME: Is view an Efl.Ui or a legacy object ?
4469         evas_object_del(view);
4470         item->view = NULL;
4471      }
4472
4473    efl_invalidate(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
4474 }
4475
4476 EOLIAN static void
4477 _elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4478 {
4479 }
4480
4481 /**
4482  * @internal
4483  *
4484  * Notify object will be deleted without actually deleting it.
4485  *
4486  * This function will callback Elm_Widget_Item::del_cb if it is set
4487  * and then unset it so it is not called twice (ie: from
4488  * elm_widget_item_del()).
4489  *
4490  * @param item a valid #Elm_Widget_Item to be notified
4491  * @see elm_widget_item_pre_notify_del() convenience macro.
4492  * @ingroup Widget
4493  */
4494 EOLIAN static void
4495 _elm_widget_item_pre_notify_del(Eo *eo_item, Elm_Widget_Item_Data *item)
4496 {
4497    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4498    if (!item->del_func) return;
4499    item->del_func((void *)WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4500    item->del_func = NULL;
4501 }
4502
4503 /**
4504  * @internal
4505  *
4506  * Set the function to notify when item is being deleted.
4507  *
4508  * This function will complain if there was a callback set already,
4509  * however it will set the new one.
4510  *
4511  * The callback will be called from elm_widget_item_pre_notify_del()
4512  * or elm_widget_item_del() will be called with:
4513  *   - data: the Elm_Widget_Item::data value.
4514  *   - obj: the Elm_Widget_Item::widget evas object.
4515  *   - event_info: the item being deleted.
4516  *
4517  * @param item a valid #Elm_Widget_Item to be notified
4518  * @see elm_widget_item_del_cb_set() convenience macro.
4519  * @ingroup Widget
4520  */
4521 EOLIAN static void
4522 _elm_widget_item_del_cb_set(Eo *eo_item EINA_UNUSED,
4523                             Elm_Widget_Item_Data *item,
4524                             Evas_Smart_Cb func)
4525 {
4526    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4527    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4528
4529    if ((item->del_func) && (item->del_func != func))
4530      WRN("You're replacing a previously set del_cb %p of item %p with %p",
4531          item->del_func, item->eo_obj, func);
4532
4533    item->del_func = func;
4534 }
4535
4536 /**
4537  * @internal
4538  *
4539  * Get owner widget of this item.
4540  *
4541  * @param item a valid #Elm_Widget_Item to get data from.
4542  * @return owner widget of this item.
4543  * @ingroup Widget
4544  */
4545 EOLIAN static Evas_Object *
4546 _elm_widget_item_widget_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4547 {
4548    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4549    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4550
4551    return item->widget;
4552 }
4553
4554 EAPI Eina_Bool
4555 _elm_widget_onscreen_is(const Evas_Object *widget)
4556 {
4557    Evas_Object *parent = (Evas_Object *)widget;
4558    Eina_Rectangle r1, r2;
4559
4560    Evas *evas = evas_object_evas_get(widget);
4561    if (!evas) return EINA_FALSE;
4562
4563    evas_object_geometry_get(widget, &r1.x, &r1.y, &r1.w, &r1.h);
4564    if (eina_rectangle_is_empty(&r1))
4565      return EINA_FALSE;
4566
4567    // window does not have to check viewport and geometry
4568    if (efl_isa(widget, EFL_UI_WIN_CLASS))
4569       return EINA_TRUE;
4570
4571    // check if on canvas
4572    evas_output_viewport_get(evas, &r2.x, &r2.y, &r2.w, &r2.h);
4573    if (!eina_rectangles_intersect(&r1, &r2))
4574      return EINA_FALSE;
4575
4576    // check if inside scrollable parent viewport
4577    do {
4578       parent = elm_widget_parent_get(parent);
4579       if (parent && !evas_object_visible_get(parent))
4580         return EINA_FALSE;
4581       if (parent && efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4582         {
4583            evas_object_geometry_get(parent, &r2.x, &r2.y, &r2.w, &r2.h);
4584            if (!eina_rectangles_intersect(&r1, &r2))
4585              return EINA_FALSE;
4586         }
4587    } while (parent && (parent != elm_widget_top_get(widget)));
4588
4589    return EINA_TRUE;
4590 }
4591
4592 EAPI Eina_Bool
4593 _elm_widget_item_onscreen_is(const Elm_Object_Item *item)
4594 {
4595    Eina_Rectangle r1, r2;
4596    Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4597    if (!id || !id->view) return EINA_FALSE;
4598
4599    if (!evas_object_visible_get(id->view))
4600      return EINA_FALSE;
4601
4602    if (!_elm_widget_onscreen_is(id->widget))
4603      return EINA_FALSE;
4604
4605    evas_object_geometry_get(id->view, &r1.x, &r1.y, &r1.w, &r1.h);
4606    if (eina_rectangle_is_empty(&r1))
4607      return EINA_FALSE;
4608
4609    evas_object_geometry_get(id->widget, &r2.x, &r2.y, &r2.w, &r2.h);
4610    if (!eina_rectangles_intersect(&r1, &r2))
4611      return EINA_FALSE;
4612
4613    return EINA_TRUE;
4614 }
4615
4616 const char*
4617 _elm_widget_accessible_plain_name_get(const Evas_Object *obj, const char* name)
4618 {
4619    char *accessible_plain_name;
4620
4621    API_ENTRY return NULL;
4622
4623    accessible_plain_name = _elm_util_mkup_to_text(name);
4624    eina_stringshare_del(sd->accessible_name);
4625    sd->accessible_name =  eina_stringshare_add(accessible_plain_name);
4626    free(accessible_plain_name);
4627    return sd->accessible_name;
4628 }
4629
4630 const char*
4631 _elm_widget_item_accessible_plain_name_get(const Elm_Object_Item *item, const char* name)
4632 {
4633    char *accessible_plain_name;
4634
4635    Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4636    if (!id) return NULL;
4637
4638    accessible_plain_name = _elm_util_mkup_to_text(name);
4639    eina_stringshare_del(id->accessible_name);
4640    id->accessible_name =  eina_stringshare_add(accessible_plain_name);
4641    free(accessible_plain_name);
4642    return id->accessible_name;
4643 }
4644
4645 EOLIAN static Efl_Access_State_Set
4646 _elm_widget_item_efl_access_object_state_set_get(const Eo *eo_item, Elm_Widget_Item_Data *item)
4647 {
4648    Efl_Access_State_Set states = 0;
4649
4650    // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
4651    // //TIZEN_ONLY(20171108): bring HIGHLIGHT related changes
4652    // Evas_Object *win = elm_widget_top_get(item->widget);
4653    // if (win && efl_isa(win, EFL_UI_WIN_CLASS))
4654    //   {
4655    //      if (_elm_win_accessibility_highlight_get(win) == item->view)
4656    //        STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
4657    //   }
4658    // STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
4659    // //
4660    //
4661
4662    STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSABLE);
4663
4664    if (elm_object_item_focus_get(eo_item))
4665      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSED);
4666    if (!elm_object_item_disabled_get(eo_item))
4667      {
4668         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_ENABLED);
4669         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SENSITIVE);
4670         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
4671      }
4672    if (_elm_widget_item_onscreen_is(eo_item))
4673      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SHOWING);
4674
4675    //TIZEN_ONLY(20170207) : [ATSPI] enhance expose highlight information on atspi
4676    /* unrealized genlist item does not have item->view,
4677       and item cannot change its visibility, only widget can change the visibility */
4678    if (evas_object_visible_get(item->widget))
4679      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
4680    //
4681
4682    //TIZEN_ONLY(20170717) : expose highlight information on atspi
4683    if (_elm_widget_item_highlightable((Eo *)eo_item) && _accessible_object_on_scroll_is(item->view))
4684      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
4685    else
4686      STATE_TYPE_UNSET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
4687
4688    if (_elm_object_accessibility_currently_highlighted_get() == (void*)item->eo_obj)
4689      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED);
4690    //
4691    return states;
4692 }
4693
4694 EAPI void
4695 elm_object_item_data_set(Elm_Object_Item *it, void *data)
4696 {
4697    WIDGET_ITEM_DATA_SET(it, data);
4698 }
4699
4700 EAPI void *
4701 elm_object_item_data_get(const Elm_Object_Item *it)
4702 {
4703    return (void *) WIDGET_ITEM_DATA_GET(it);
4704 }
4705
4706 EOLIAN static void
4707 _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED,
4708                               Elm_Widget_Item_Data *item,
4709                               Eina_Bool disabled)
4710 {
4711    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4712    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4713
4714    if (item->disabled == disabled) return;
4715    item->disabled = !!disabled;
4716    elm_wdg_item_disable(item->eo_obj);
4717 }
4718
4719 EOLIAN static Eina_Bool
4720 _elm_widget_item_disabled_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4721 {
4722    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4723    return item->disabled;
4724 }
4725
4726 EOLIAN static void
4727 _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style)
4728 {
4729    eina_stringshare_replace(&item->style, style);
4730 }
4731
4732 EOLIAN static const char *
4733 _elm_widget_item_style_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4734 {
4735    return item->style;
4736 }
4737
4738 EOLIAN static void
4739 _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4740 {
4741 }
4742
4743 EOLIAN static void
4744 _elm_widget_item_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED)
4745 {
4746    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set");
4747 }
4748
4749 EOLIAN static Eina_Bool
4750 _elm_widget_item_item_focus_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4751 {
4752    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get");
4753    return EINA_FALSE;
4754 }
4755
4756 EOLIAN static void
4757 _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED,
4758                                                    Elm_Widget_Item_Data *item,
4759                                                    const char *part,
4760                                                    const char *domain,
4761                                                    const char *label)
4762 {
4763    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4764    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4765    Elm_Translate_String_Data *ts;
4766
4767    if (!label)
4768      {
4769         _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE,
4770                                     EINA_FALSE);
4771      }
4772    else
4773      {
4774         ts = _part_text_translatable_set(&item->translate_strings, part,
4775                                          EINA_TRUE, EINA_FALSE);
4776         if (!ts) return;
4777         if (!ts->string) ts->string = eina_stringshare_add(label);
4778         else eina_stringshare_replace(&ts->string, label);
4779         if (!ts->domain) ts->domain = eina_stringshare_add(domain);
4780         else eina_stringshare_replace(&ts->domain, domain);
4781 #ifdef HAVE_GETTEXT
4782         if (label[0]) label = dgettext(domain, label);
4783 #endif
4784      }
4785    item->on_translate = EINA_TRUE;
4786    elm_wdg_item_part_text_set(item->eo_obj, part, label);
4787    item->on_translate = EINA_FALSE;
4788 }
4789
4790 EOLIAN static const char *
4791 _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED,
4792                                             Elm_Widget_Item_Data *item,
4793                                             const char *part)
4794 {
4795    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4796    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4797
4798    Elm_Translate_String_Data *ts;
4799    ts = _translate_string_data_get(item->translate_strings, part);
4800    if (ts) return ts->string;
4801    return NULL;
4802 }
4803
4804 EOLIAN static void
4805 _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED,
4806                                                    Elm_Widget_Item_Data *item,
4807                                                    const char *part,
4808                                                    const char *domain,
4809                                                    Eina_Bool translatable)
4810 {
4811    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4812    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4813    Elm_Translate_String_Data *ts;
4814    const char *text;
4815
4816    ts = _part_text_translatable_set(&item->translate_strings, part,
4817                                     translatable, EINA_TRUE);
4818    if (!ts) return;
4819    if (!ts->domain) ts->domain = eina_stringshare_add(domain);
4820    else eina_stringshare_replace(&ts->domain, domain);
4821
4822    text = elm_wdg_item_part_text_get(item->eo_obj, part);
4823
4824    if (!text || !text[0]) return;
4825
4826    if (!ts->string) ts->string = eina_stringshare_add(text);
4827
4828 //Try to translate text since we don't know the text is already translated.
4829 #ifdef HAVE_GETTEXT
4830    text = dgettext(domain, text);
4831 #endif
4832    item->on_translate = EINA_TRUE;
4833    elm_wdg_item_part_text_set(item->eo_obj, part, text);
4834    item->on_translate = EINA_FALSE;
4835 }
4836
4837 EOLIAN static void
4838 _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4839 {
4840    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4841    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4842
4843    if (!item->track_obj) return;
4844
4845    while (evas_object_ref_get(item->track_obj) > 0)
4846      evas_object_unref(item->track_obj);
4847
4848    evas_object_del(item->track_obj);
4849 }
4850
4851 EOLIAN static Evas_Object *
4852 _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4853 {
4854    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4855    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4856
4857    if (item->track_obj)
4858      {
4859         evas_object_ref(item->track_obj);
4860         return item->track_obj;
4861      }
4862
4863    if (!item->view)
4864      {
4865         WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item);
4866         return NULL;
4867      }
4868
4869    Evas_Object *track =
4870       evas_object_rectangle_add(evas_object_evas_get(item->widget));
4871    evas_object_color_set(track, 0, 0, 0, 0);
4872    evas_object_pass_events_set(track, EINA_TRUE);
4873    _track_obj_update(track, item->view);
4874    evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del,
4875                                   item);
4876
4877    efl_event_callback_array_add(item->view, tracker_callbacks(), item);
4878
4879    evas_object_ref(track);
4880
4881    item->track_obj = track;
4882
4883    return track;
4884 }
4885
4886 EOLIAN static void
4887 _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4888 {
4889    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4890    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4891
4892    if (!item->track_obj) return;
4893    evas_object_unref(item->track_obj);
4894
4895    if (evas_object_ref_get(item->track_obj) == 0)
4896      evas_object_del(item->track_obj);
4897 }
4898
4899 EOLIAN static int
4900 _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4901 {
4902    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0);
4903    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0);
4904
4905    if (!item->track_obj) return 0;
4906    return evas_object_ref_get(item->track_obj);
4907 }
4908
4909 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
4910
4911 struct _Elm_Widget_Item_Tooltip
4912 {
4913    Elm_Widget_Item_Data       *item;
4914    Elm_Tooltip_Item_Content_Cb func;
4915    Evas_Smart_Cb               del_cb;
4916    const void                 *data;
4917 };
4918
4919 static Evas_Object *
4920 _elm_widget_item_tooltip_label_create(void *data,
4921                                       Evas_Object *obj EINA_UNUSED,
4922                                       Evas_Object *tooltip,
4923                                       void *item EINA_UNUSED)
4924 {
4925    Evas_Object *label = elm_label_add(tooltip);
4926    if (!label)
4927      return NULL;
4928    elm_object_style_set(label, "tooltip");
4929    elm_object_text_set(label, data);
4930    return label;
4931 }
4932
4933 static Evas_Object *
4934 _elm_widget_item_tooltip_trans_label_create(void *data,
4935                                             Evas_Object *obj EINA_UNUSED,
4936                                             Evas_Object *tooltip,
4937                                             void *item EINA_UNUSED)
4938 {
4939    Evas_Object *label = elm_label_add(tooltip);
4940    if (!label)
4941      return NULL;
4942    elm_object_style_set(label, "tooltip");
4943    elm_object_translatable_text_set(label, data);
4944    return label;
4945 }
4946
4947 static void
4948 _elm_widget_item_tooltip_label_del_cb(void *data,
4949                                       Evas_Object *obj EINA_UNUSED,
4950                                       void *event_info EINA_UNUSED)
4951 {
4952    eina_stringshare_del(data);
4953 }
4954
4955 /**
4956  * @internal
4957  *
4958  * Set the text to be shown in the widget item.
4959  *
4960  * @param item Target item
4961  * @param text The text to set in the content
4962  *
4963  * Setup the text as tooltip to object. The item can have only one tooltip,
4964  * so any previous tooltip data is removed.
4965  *
4966  * @ingroup Widget
4967  */
4968 EOLIAN static void
4969 _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED,
4970                                   Elm_Widget_Item_Data *item EINA_UNUSED,
4971                                   const char *text)
4972 {
4973    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4974    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4975    EINA_SAFETY_ON_NULL_RETURN(text);
4976
4977    text = eina_stringshare_add(text);
4978    elm_wdg_item_tooltip_content_cb_set(item->eo_obj, _elm_widget_item_tooltip_label_create, text, _elm_widget_item_tooltip_label_del_cb);
4979 }
4980
4981 EOLIAN static void
4982 _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED,
4983                                                Elm_Widget_Item_Data *item EINA_UNUSED,
4984                                                const char *text)
4985 {
4986    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4987    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4988    EINA_SAFETY_ON_NULL_RETURN(text);
4989
4990    text = eina_stringshare_add(text);
4991    elm_wdg_item_tooltip_content_cb_set(item->eo_obj, _elm_widget_item_tooltip_trans_label_create, text, _elm_widget_item_tooltip_label_del_cb);
4992 }
4993
4994 static Evas_Object *
4995 _elm_widget_item_tooltip_create(void *data,
4996                                 Evas_Object *obj,
4997                                 Evas_Object *tooltip)
4998 {
4999    Elm_Widget_Item_Tooltip *wit = data;
5000    return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj);
5001 }
5002
5003 static void
5004 _elm_widget_item_tooltip_del_cb(void *data,
5005                                 Evas_Object *obj,
5006                                 void *event_info EINA_UNUSED)
5007 {
5008    Elm_Widget_Item_Tooltip *wit = data;
5009    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj);
5010    free(wit);
5011 }
5012
5013 /**
5014  * @internal
5015  *
5016  * Set the content to be shown in the tooltip item
5017  *
5018  * Setup the tooltip to item. The item can have only one tooltip,
5019  * so any previous tooltip data is removed. @p func(with @p data) will
5020  * be called every time that need show the tooltip and it should
5021  * return a valid Evas_Object. This object is then managed fully by
5022  * tooltip system and is deleted when the tooltip is gone.
5023  *
5024  * @param item the widget item being attached a tooltip.
5025  * @param func the function used to create the tooltip contents.
5026  * @param data what to provide to @a func as callback data/context.
5027  * @param del_cb called when data is not needed anymore, either when
5028  *        another callback replaces @func, the tooltip is unset with
5029  *        elm_widget_item_tooltip_unset() or the owner @a item
5030  *        dies. This callback receives as the first parameter the
5031  *        given @a data, and @c event_info is the item.
5032  *
5033  * @ingroup Widget
5034  */
5035 EOLIAN static void
5036 _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED,
5037                                         Elm_Widget_Item_Data *item,
5038                                         Elm_Tooltip_Item_Content_Cb func,
5039                                         const void *data,
5040                                         Evas_Smart_Cb del_cb)
5041 {
5042    Elm_Widget_Item_Tooltip *wit;
5043
5044    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
5045    //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem);
5046
5047    if (!func)
5048      {
5049         elm_wdg_item_tooltip_unset(item->eo_obj);
5050         return;
5051      }
5052
5053    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
5054    if (!wit) goto error;
5055    wit->item = item;
5056    wit->func = func;
5057    wit->data = data;
5058    wit->del_cb = del_cb;
5059
5060    elm_object_sub_tooltip_content_cb_set
5061      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
5062      _elm_widget_item_tooltip_del_cb);
5063
5064    return;
5065
5066 error_noitem:
5067    if (del_cb) del_cb((void *)data, NULL, item);
5068    return;
5069 error:
5070    if (del_cb) del_cb((void *)data, item->widget, item);
5071 }
5072
5073 /**
5074  * @internal
5075  *
5076  * Unset tooltip from item
5077  *
5078  * @param item widget item to remove previously set tooltip.
5079  *
5080  * Remove tooltip from item. The callback provided as del_cb to
5081  * elm_widget_item_tooltip_content_cb_set() will be called to notify
5082  * it is not used anymore.
5083  *
5084  * @see elm_widget_item_tooltip_content_cb_set()
5085  *
5086  * @ingroup Widget
5087  */
5088 EOLIAN static void
5089 _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5090 {
5091    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5092    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5093
5094    elm_object_tooltip_unset(item->view);
5095 }
5096
5097 /**
5098  * @internal
5099  *
5100  * Sets a different style for this item tooltip.
5101  *
5102  * @note before you set a style you should define a tooltip with
5103  *       elm_widget_item_tooltip_content_cb_set() or
5104  *       elm_widget_item_tooltip_text_set()
5105  *
5106  * @param item widget item with tooltip already set.
5107  * @param style the theme style to use (default, transparent, ...)
5108  *
5109  * @ingroup Widget
5110  */
5111 EOLIAN static void
5112 _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED,
5113                                    Elm_Widget_Item_Data *item,
5114                                    const char *style)
5115 {
5116    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5117    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5118
5119    elm_object_tooltip_style_set(item->view, style);
5120 }
5121
5122 EOLIAN static Eina_Bool
5123 _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED,
5124                                          Elm_Widget_Item_Data *item,
5125                                          Eina_Bool disable)
5126 {
5127    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5128    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5129
5130    return elm_object_tooltip_window_mode_set(item->view, disable);
5131 }
5132
5133 EOLIAN static Eina_Bool
5134 _elm_widget_item_tooltip_window_mode_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5135 {
5136    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5137    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5138
5139    return elm_object_tooltip_window_mode_get(item->view);
5140 }
5141
5142 /**
5143  * @internal
5144  *
5145  * Get the style for this item tooltip.
5146  *
5147  * @param item widget item with tooltip already set.
5148  * @return style the theme style in use, defaults to "default". If the
5149  *         object does not have a tooltip set, then NULL is returned.
5150  *
5151  * @ingroup Widget
5152  */
5153 EOLIAN static const char *
5154 _elm_widget_item_tooltip_style_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5155 {
5156    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5157
5158    return elm_object_tooltip_style_get(item->view);
5159 }
5160
5161 EOLIAN static void
5162 _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED,
5163                             Elm_Widget_Item_Data *item,
5164                             const char *cursor)
5165 {
5166    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5167    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5168
5169    elm_object_sub_cursor_set(item->view, item->widget, cursor);
5170 }
5171
5172 EOLIAN static const char *
5173 _elm_widget_item_cursor_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5174 {
5175    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5176    return elm_object_sub_cursor_get(item->view);
5177 }
5178
5179 EOLIAN static void
5180 _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5181 {
5182    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5183    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5184
5185    elm_object_cursor_unset(item->view);
5186 }
5187
5188 /**
5189  * @internal
5190  *
5191  * Sets a different style for this item cursor.
5192  *
5193  * @note before you set a style you should define a cursor with
5194  *       elm_widget_item_cursor_set()
5195  *
5196  * @param item widget item with cursor already set.
5197  * @param style the theme style to use (default, transparent, ...)
5198  *
5199  * @ingroup Widget
5200  */
5201 EOLIAN static void
5202 _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED,
5203                                   Elm_Widget_Item_Data *item,
5204                                   const char *style)
5205 {
5206    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5207    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5208
5209    elm_object_sub_cursor_style_set(item->view, style);
5210 }
5211
5212 /**
5213  * @internal
5214  *
5215  * Get the style for this item cursor.
5216  *
5217  * @param item widget item with cursor already set.
5218  * @return style the theme style in use, defaults to "default". If the
5219  *         object does not have a cursor set, then NULL is returned.
5220  *
5221  * @ingroup Widget
5222  */
5223 EOLIAN static const char *
5224 _elm_widget_item_cursor_style_get(const Eo *eo_item EINA_UNUSED,
5225                                   Elm_Widget_Item_Data *item)
5226 {
5227    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5228    return elm_object_sub_cursor_style_get(item->view);
5229 }
5230
5231 /**
5232  * @internal
5233  *
5234  * Set if the cursor set should be searched on the theme or should use
5235  * the provided by the engine, only.
5236  *
5237  * @note before you set if should look on theme you should define a cursor
5238  * with elm_object_cursor_set(). By default it will only look for cursors
5239  * provided by the engine.
5240  *
5241  * @param item widget item with cursor already set.
5242  * @param engine_only boolean to define it cursors should be looked only
5243  * between the provided by the engine or searched on widget's theme as well.
5244  *
5245  * @ingroup Widget
5246  */
5247 EOLIAN static void
5248 _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED,
5249                                         Elm_Widget_Item_Data *item,
5250                                         Eina_Bool engine_only)
5251 {
5252    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5253    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5254
5255    elm_object_sub_cursor_theme_search_enabled_set(item->view, !engine_only);
5256 }
5257
5258 /**
5259  * @internal
5260  *
5261  * Get the cursor engine only usage for this item cursor.
5262  *
5263  * @param item widget item with cursor already set.
5264  * @return engine_only boolean to define it cursors should be looked only
5265  * between the provided by the engine or searched on widget's theme as well. If
5266  *         the object does not have a cursor set, then EINA_FALSE is returned.
5267  *
5268  * @ingroup Widget
5269  */
5270 EOLIAN static Eina_Bool
5271 _elm_widget_item_cursor_engine_only_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5272 {
5273    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5274    return !elm_object_sub_cursor_theme_search_enabled_get(item->view);
5275 }
5276
5277 EOLIAN static void
5278 _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED,
5279                                   Elm_Widget_Item_Data *item,
5280                                   const char *part EINA_UNUSED,
5281                                   Evas_Object *content EINA_UNUSED)
5282 {
5283    ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()");
5284 }
5285
5286 EOLIAN static Evas_Object *
5287 _elm_widget_item_part_content_get(const Eo *eo_item EINA_UNUSED,
5288                                   Elm_Widget_Item_Data *item,
5289                                   const char *part EINA_UNUSED)
5290 {
5291    ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()");
5292    return NULL;
5293 }
5294
5295 EOLIAN static Evas_Object *
5296 _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED,
5297                                     Elm_Widget_Item_Data *item,
5298                                     const char *part EINA_UNUSED)
5299 {
5300    ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()");
5301    return NULL;
5302 }
5303
5304 EOLIAN static void
5305 _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
5306                                Elm_Widget_Item_Data *item,
5307                                const char *part EINA_UNUSED,
5308                                const char *label EINA_UNUSED)
5309 {
5310    ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()");
5311 }
5312
5313 EOLIAN static const char *
5314 _elm_widget_item_part_text_get(const Eo *eo_item EINA_UNUSED,
5315                                Elm_Widget_Item_Data *item,
5316                                const char *part EINA_UNUSED)
5317 {
5318    ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()");
5319    return NULL;
5320 }
5321
5322 static void
5323 _elm_widget_item_part_text_custom_free(void *data)
5324 {
5325    Elm_Label_Data *label;
5326    label = data;
5327    eina_stringshare_del(label->part);
5328    eina_stringshare_del(label->text);
5329    free(label);
5330 }
5331
5332 EOLIAN static void
5333 _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED,
5334                                       Elm_Widget_Item_Data *item,
5335                                       const char *part,
5336                                       const char *text)
5337 {
5338    Elm_Label_Data *label;
5339    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5340    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5341
5342    if (!item->labels)
5343      item->labels =
5344         eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free);
5345    label = eina_hash_find(item->labels, part);
5346    if (!label)
5347      {
5348         label = malloc(sizeof(Elm_Label_Data));
5349         if (!label)
5350           {
5351              ERR("Failed to allocate memory");
5352              return;
5353           }
5354         label->part = eina_stringshare_add(part);
5355         label->text = eina_stringshare_add(text);
5356         eina_hash_add(item->labels, part, label);
5357      }
5358    else
5359      eina_stringshare_replace(&label->text, text);
5360 }
5361
5362 EOLIAN static const char *
5363 _elm_widget_item_part_text_custom_get(const Eo *eo_item EINA_UNUSED,
5364                                       Elm_Widget_Item_Data *item,
5365                                       const char *part)
5366 {
5367    Elm_Label_Data *label;
5368    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5369    label = eina_hash_find(item->labels, part);
5370    return label ? label->text : NULL;
5371 }
5372
5373 static Eina_Bool
5374 _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED,
5375                                           const void *key EINA_UNUSED,
5376                                           void *data,
5377                                           void *func_data)
5378 {
5379    Elm_Label_Data *label;
5380    Elm_Widget_Item_Data *item;
5381    label = data;
5382    item = func_data;
5383
5384    elm_wdg_item_part_text_set(item->eo_obj, label->part, label->text);
5385
5386    return EINA_TRUE;
5387 }
5388
5389 EOLIAN static void
5390 _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5391 {
5392    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5393    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5394    if (item->labels)
5395      eina_hash_foreach(item->labels,
5396                        _elm_widget_item_part_text_custom_foreach, item);
5397 }
5398
5399 EOLIAN static void
5400 _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
5401                              Elm_Widget_Item_Data *item EINA_UNUSED,
5402                              const char *emission EINA_UNUSED,
5403                              const char *source EINA_UNUSED)
5404 {
5405
5406 }
5407
5408 EOLIAN static void
5409 _elm_widget_item_signal_callback_add(Eo *eo_item,
5410                                      Elm_Widget_Item_Data *item,
5411                                      const char *emission,
5412                                      const char *source,
5413                                      Elm_Object_Item_Signal_Cb func,
5414                                      void *data)
5415 {
5416    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5417    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5418    EINA_SAFETY_ON_NULL_RETURN(func);
5419
5420    Elm_Widget_Item_Signal_Data *wisd;
5421
5422    wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
5423    if (!wisd) return;
5424
5425    wisd->item = eo_item;
5426    wisd->func = (Elm_Widget_Item_Signal_Cb)func;
5427    wisd->data = data;
5428    wisd->emission = eina_stringshare_add(emission);
5429    wisd->source = eina_stringshare_add(source);
5430
5431    if (_elm_widget_is(item->view))
5432      elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5433    else if (efl_isa(item->view, EFL_CANVAS_LAYOUT_CLASS))
5434      edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5435    else
5436      {
5437         WRN("The %s widget item doesn't support signal callback add!",
5438             efl_class_name_get(efl_class_get(item->widget)));
5439         free(wisd);
5440         return;
5441      }
5442
5443    item->signals = eina_list_append(item->signals, wisd);
5444 }
5445
5446 EOLIAN static void *
5447 _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED,
5448                                      Elm_Widget_Item_Data *item,
5449                                      const char *emission,
5450                                      const char *source,
5451                                      Elm_Object_Item_Signal_Cb func)
5452 {
5453    Elm_Widget_Item_Signal_Data *wisd;
5454    Eina_List *l;
5455
5456    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5457    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5458    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
5459
5460    EINA_LIST_FOREACH(item->signals, l, wisd)
5461      {
5462         if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) &&
5463             !strcmp(wisd->emission, emission) &&
5464             !strcmp(wisd->source, source))
5465           return _elm_widget_item_signal_callback_list_get(item, l);
5466      }
5467
5468    return NULL;
5469 }
5470
5471
5472
5473 EOLIAN static void
5474 _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED,
5475                                  Elm_Widget_Item_Data *item,
5476                                  const char *txt)
5477 {
5478    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5479    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5480
5481    eina_stringshare_del(item->access_info);
5482    if (!txt) item->access_info = NULL;
5483    else item->access_info = eina_stringshare_add(txt);
5484 }
5485
5486 EOLIAN static void
5487 _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5488 {
5489    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5490    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5491
5492 #ifdef HAVE_GETTEXT
5493    Elm_Translate_String_Data *ts;
5494    EINA_INLIST_FOREACH(item->translate_strings, ts)
5495      {
5496         if (!ts->string) continue;
5497         const char *s = dgettext(ts->domain, ts->string);
5498         item->on_translate = EINA_TRUE;
5499         elm_wdg_item_part_text_set(item->eo_obj, ts->id, s);
5500         item->on_translate = EINA_FALSE;
5501      }
5502 #endif
5503 }
5504
5505 EOLIAN static void
5506 _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED,
5507                                   Elm_Widget_Item_Data *item,
5508                                   Eina_List *objs)
5509 {
5510    _elm_access_widget_item_access_order_set(item, objs);
5511 }
5512
5513 EOLIAN static const Eina_List *
5514 _elm_widget_item_access_order_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5515 {
5516    return _elm_access_widget_item_access_order_get(item);
5517 }
5518
5519 EOLIAN static void
5520 _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5521 {
5522    _elm_access_widget_item_access_order_unset(item);
5523 }
5524
5525 EOLIAN static Evas_Object*
5526 _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5527 {
5528    _elm_access_widget_item_register(item);
5529    return item->access_obj;
5530 }
5531
5532 EOLIAN static void
5533 _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5534 {
5535    _elm_access_widget_item_unregister(item);
5536 }
5537
5538 EOLIAN static Evas_Object*
5539 _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5540 {
5541    return item->access_obj;
5542 }
5543
5544 EOLIAN static Evas_Object *
5545 _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5546 {
5547    Evas_Object *ret = NULL;
5548
5549    if (dir == ELM_FOCUS_PREVIOUS)
5550      ret = item->focus_previous;
5551    else if (dir == ELM_FOCUS_NEXT)
5552      ret = item->focus_next;
5553    else if (dir == ELM_FOCUS_UP)
5554      ret = item->focus_up;
5555    else if (dir == ELM_FOCUS_DOWN)
5556      ret = item->focus_down;
5557    else if (dir == ELM_FOCUS_RIGHT)
5558      ret = item->focus_right;
5559    else if (dir == ELM_FOCUS_LEFT)
5560      ret = item->focus_left;
5561
5562    return ret;
5563 }
5564
5565 EOLIAN static void
5566 _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir)
5567 {
5568    if (dir == ELM_FOCUS_PREVIOUS)
5569      item->focus_previous = next;
5570    else if (dir == ELM_FOCUS_NEXT)
5571      item->focus_next = next;
5572    else if (dir == ELM_FOCUS_UP)
5573      item->focus_up = next;
5574    else if (dir == ELM_FOCUS_DOWN)
5575      item->focus_down = next;
5576    else if (dir == ELM_FOCUS_RIGHT)
5577      item->focus_right = next;
5578    else if (dir == ELM_FOCUS_LEFT)
5579      item->focus_left = next;
5580 }
5581
5582 EOLIAN static Elm_Object_Item*
5583 _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5584 {
5585    Elm_Object_Item *ret = NULL;
5586
5587    if (dir == ELM_FOCUS_PREVIOUS)
5588      ret = item->item_focus_previous;
5589    else if (dir == ELM_FOCUS_NEXT)
5590      ret = item->item_focus_next;
5591    else if (dir == ELM_FOCUS_UP)
5592      ret = item->item_focus_up;
5593    else if (dir == ELM_FOCUS_DOWN)
5594      ret = item->item_focus_down;
5595    else if (dir == ELM_FOCUS_RIGHT)
5596      ret = item->item_focus_right;
5597    else if (dir == ELM_FOCUS_LEFT)
5598      ret = item->item_focus_left;
5599
5600    return ret;
5601 }
5602
5603 EOLIAN static void
5604 _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)
5605 {
5606    if (dir == ELM_FOCUS_PREVIOUS)
5607      item->item_focus_previous = next_item;
5608    else if (dir == ELM_FOCUS_NEXT)
5609      item->item_focus_next = next_item;
5610    else if (dir == ELM_FOCUS_UP)
5611      item->item_focus_up = next_item;
5612    else if (dir == ELM_FOCUS_DOWN)
5613      item->item_focus_down = next_item;
5614    else if (dir == ELM_FOCUS_RIGHT)
5615      item->item_focus_right = next_item;
5616    else if (dir == ELM_FOCUS_LEFT)
5617      item->item_focus_left = next_item;
5618 }
5619
5620 /* happy debug functions */
5621 #ifdef ELM_DEBUG
5622 static void
5623 _sub_obj_tree_dump(const Evas_Object *obj,
5624                    int lvl)
5625 {
5626    int i;
5627
5628    for (i = 0; i < lvl * 3; i++)
5629      putchar(' ');
5630
5631    if (_elm_widget_is(obj))
5632      {
5633         Eina_List *l;
5634         INTERNAL_ENTRY;
5635         DBG("+ %s(%p)\n",
5636             elm_widget_type_get(obj),
5637             obj);
5638        for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
5639          {
5640             obj = eina_array_data_get(sd->children, i);
5641           _sub_obj_tree_dump(obj, lvl + 1);
5642          }
5643      }
5644    else
5645      DBG("+ %s(%p)\n", evas_object_type_get(obj), obj);
5646 }
5647
5648 static void
5649 _sub_obj_tree_dot_dump(const Evas_Object *obj,
5650                        FILE *output)
5651 {
5652    if (!_elm_widget_is(obj))
5653      return;
5654    INTERNAL_ENTRY;
5655
5656    Eina_Bool visible = evas_object_visible_get(obj);
5657    Eina_Bool disabled = elm_widget_disabled_get(obj);
5658    Eina_Bool focused = efl_ui_focus_object_focus_get(obj);
5659    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
5660
5661    if (sd->parent_obj)
5662      {
5663         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
5664
5665         if (focused)
5666           fprintf(output, ", style=bold");
5667
5668         if (!visible)
5669           fprintf(output, ", color=gray28");
5670
5671         fprintf(output, " ];\n");
5672      }
5673
5674    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
5675                    "disabled: %d|focused: %d/%d|focus order:%d}\"",
5676            obj, obj, elm_widget_type_get(obj),
5677            evas_object_name_get(obj), visible, disabled, focused, can_focus,
5678            sd->focus_order);
5679
5680    if (focused)
5681      fprintf(output, ", style=bold");
5682
5683    if (!visible)
5684      fprintf(output, ", fontcolor=gray28");
5685
5686    if ((disabled) || (!visible))
5687      fprintf(output, ", color=gray");
5688
5689    fprintf(output, " ];\n");
5690
5691    Eina_List *l;
5692    Evas_Object *o;
5693
5694    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
5695      {
5696         o = eina_array_data_get(sd->children, i);
5697         _sub_obj_tree_dot_dump(o, output);
5698      }
5699 }
5700
5701 #endif
5702
5703 EAPI void
5704 elm_widget_tree_dump(const Evas_Object *top)
5705 {
5706 #ifdef ELM_DEBUG
5707    if (!_elm_widget_is(top))
5708      return;
5709    _sub_obj_tree_dump(top, 0);
5710 #else
5711    (void)top;
5712    return;
5713 #endif
5714 }
5715
5716 EAPI void
5717 elm_widget_tree_dot_dump(const Evas_Object *top,
5718                          FILE *output)
5719 {
5720 #ifdef ELM_DEBUG
5721    if (!_elm_widget_is(top))
5722      return;
5723    fprintf(output, "graph " " { node [shape=record];\n");
5724    _sub_obj_tree_dot_dump(top, output);
5725    fprintf(output, "}\n");
5726 #else
5727    (void)top;
5728    (void)output;
5729    return;
5730 #endif
5731 }
5732
5733 EINA_UNUSED static void
5734 _focus_event_changed(void *data EINA_UNUSED, const Efl_Event *event)
5735 {
5736    if (efl_ui_focus_object_focus_get(event->object))
5737      evas_object_smart_callback_call(event->object, "focused", NULL);
5738    else
5739      evas_object_smart_callback_call(event->object, "unfocused", NULL);
5740 }
5741
5742 EOLIAN static Eo *
5743 _efl_ui_widget_efl_object_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
5744 {
5745    Eo *parent = efl_parent_get(obj);
5746    sd->on_create = EINA_TRUE;
5747
5748    sd->window = efl_provider_find(efl_parent_get(obj), EFL_UI_WIN_CLASS);
5749    if (!efl_isa(obj, EFL_UI_WIN_CLASS))
5750      {
5751         if (!efl_isa(parent, EFL_UI_WIDGET_CLASS))
5752           {
5753              ERR("You passed a wrong parent parameter (%p %s). "
5754                  "Elementary widget's parent should be an elementary widget.",
5755                  parent, evas_object_type_get(parent));
5756           }
5757         else
5758           {
5759              ELM_WIDGET_DATA_GET(parent, parent_sd);
5760              if (parent_sd)
5761                sd->shared_win_data = parent_sd->shared_win_data;
5762           }
5763      }
5764    else
5765      {
5766         sd->shared_win_data = efl_ui_win_shared_data_get(obj);
5767      }
5768
5769    _efl_ui_focus_event_redirector(obj, obj);
5770    efl_canvas_group_clipped_set(obj, EINA_FALSE);
5771    obj = efl_constructor(efl_super(obj, MY_CLASS));
5772    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
5773    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
5774
5775    if (!efl_isa(obj, EFL_UI_WIN_CLASS) && efl_isa(parent, EFL_UI_WIDGET_CLASS))
5776      efl_ui_widget_sub_object_add(parent, obj);
5777
5778    sd->on_create = EINA_FALSE;
5779
5780    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_UNKNOWN);
5781    //TIZEN_ONLY(20170717) : expose highlight information on atspi
5782    sd->can_highlight = EINA_TRUE;
5783    //
5784    /***********************************************************
5785     * TIZEN_ONLY(20180117): Override Paragraph Direction APIs *
5786     ***********************************************************/
5787    sd->inherit_paragraph_direction = EINA_TRUE;
5788
5789    if (efl_isa(parent, EFL_CANVAS_OBJECT_CLASS))
5790      {
5791         if (sd->paragraph_direction != efl_canvas_object_paragraph_direction_get(parent))
5792           {
5793              sd->paragraph_direction = efl_canvas_object_paragraph_direction_get(parent);
5794              _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(obj, sd, sd->paragraph_direction);
5795              efl_canvas_object_paragraph_direction_set(efl_super(obj, MY_CLASS), sd->paragraph_direction);
5796           }
5797      }
5798    /*******
5799     * END *
5800     *******/
5801
5802    if (!elm_widget_is_legacy(obj))
5803      EINA_SAFETY_ON_NULL_RETURN_VAL(sd->shared_win_data, NULL);
5804
5805    return obj;
5806 }
5807
5808 EOLIAN static Efl_Object*
5809 _efl_ui_widget_efl_object_finalize(Eo *obj, Elm_Widget_Smart_Data *pd)
5810 {
5811   Eo *eo;
5812
5813   eo = efl_finalize(efl_super(obj, MY_CLASS));
5814
5815   _full_eval(obj, pd);
5816
5817   return eo;
5818 }
5819
5820
5821 EOLIAN static void
5822 _efl_ui_widget_efl_object_destructor(Eo *obj, Elm_Widget_Smart_Data *sd)
5823 {
5824    if (sd->manager.provider)
5825      {
5826         sd->manager.provider = NULL;
5827      }
5828
5829    //TIZEN_ONLY : elm_widget_item: add at-spi name setter
5830    efl_access_object_description_set(obj, NULL);
5831    efl_access_object_i18n_name_set(obj, NULL);
5832
5833    efl_access_object_description_cb_set(obj, NULL, NULL);
5834    efl_access_object_name_cb_set(obj, NULL, NULL);
5835    //
5836    //TIZEN_ONLY(20230414): Support org.a11y.atspi.Value.Text property.
5837    efl_access_object_value_text_set(obj, NULL);
5838    efl_access_object_value_text_cb_set(obj, NULL, NULL);
5839    //
5840    //TIZEN_ONLY(20170405) Add gesture method to accessible interface
5841    efl_access_object_gesture_cb_set(obj, NULL, NULL);
5842    //
5843    //TIZEN_ONLY : elm_widget_item: add at-spi name setter
5844    efl_access_object_translation_domain_set(obj, NULL);
5845    efl_access_object_relationships_clear(obj);
5846    //
5847
5848    efl_access_object_attributes_clear(obj);
5849    if (sd->logical.parent)
5850      {
5851         efl_weak_unref(&sd->logical.parent);
5852         sd->logical.parent = NULL;
5853      }
5854
5855    // TIZEN_ONLY(20150709) : atspi relations api
5856    if (sd->atspi_custom_relations)
5857      efl_access_relation_set_free(&sd->atspi_custom_relations);
5858    //
5859
5860    //TIZEN_ONLY(20150717) add widget name setter
5861    if (sd->name)
5862      eina_stringshare_del(sd->name);
5863    //
5864
5865    //TIZEN_ONLY(20150731) : add i18n support for name and description
5866    if (sd->atspi_translation_domain)
5867      eina_stringshare_del(sd->atspi_translation_domain);
5868    ///
5869
5870    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
5871    if (sd->color_classes)
5872      ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
5873    //
5874
5875    if (sd->children)
5876      {
5877         eina_array_free(sd->children);
5878         sd->children = NULL;
5879      }
5880
5881    sd->on_destroy = EINA_TRUE;
5882    efl_destructor(efl_super(obj, EFL_UI_WIDGET_CLASS));
5883    sd->on_destroy = EINA_FALSE;
5884 }
5885
5886 /* internal eo */
5887
5888 EOLIAN static void
5889 _efl_ui_widget_efl_object_debug_name_override(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Strbuf *sb)
5890 {
5891    const char *focus = "";
5892
5893    if (efl_ui_focus_object_focus_get(obj)) focus = ":focused";
5894    efl_debug_name_override(efl_super(obj, MY_CLASS), sb);
5895    eina_strbuf_append_printf(sb, "%s", focus);
5896 }
5897
5898 EOLIAN static Eina_Bool
5899 _efl_ui_widget_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_Widget_Smart_Data *sd)
5900 {
5901    Eina_Bool focused;
5902
5903    if (!elm_widget_can_focus_get(obj))
5904      return EINA_FALSE;
5905
5906    focused = efl_ui_focus_object_focus_get(obj);
5907
5908    if (!sd->resize_obj)
5909      evas_object_focus_set(obj, focused);
5910
5911    //TIZEN_ONLY(20180607): Restore legacy focus
5912    if (focused)
5913      evas_object_smart_callback_call(obj, "focused", NULL);
5914    else
5915      evas_object_smart_callback_call(obj, "unfocused", NULL);
5916    //
5917
5918    if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
5919      efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_FOCUSED, focused);
5920
5921    return EINA_TRUE;
5922 }
5923
5924 EOLIAN static Eina_Bool
5925 _efl_ui_widget_widget_input_event_handler(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Efl_Event *eo_event EINA_UNUSED, Evas_Object *source EINA_UNUSED)
5926 {
5927    return EINA_FALSE;
5928 }
5929
5930 EOLIAN static Eina_Bool
5931 _efl_ui_widget_on_access_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Ui_Activate act EINA_UNUSED)
5932 {
5933    WRN("The %s widget does not implement the \"activate\" functions.",
5934        efl_class_name_get(efl_class_get(obj)));
5935    return EINA_TRUE;
5936 }
5937
5938 EOLIAN static void
5939 _efl_ui_widget_class_constructor(Efl_Class *klass)
5940 {
5941    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
5942 }
5943
5944 EOLIAN static Eina_Bool
5945 _efl_ui_widget_efl_access_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
5946 {
5947    if (elm_object_focus_allow_get(obj))
5948      {
5949        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
5950        if (!ee) return EINA_FALSE;
5951        ecore_evas_activate(ee);
5952        elm_object_focus_set(obj, EINA_TRUE);
5953        return EINA_TRUE;
5954      }
5955    return EINA_FALSE;
5956 }
5957
5958
5959 EOLIAN static const char*
5960 _efl_ui_widget_efl_access_object_i18n_name_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
5961 {
5962    const char *ret, *name;
5963    name = efl_access_object_i18n_name_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
5964
5965    if (name) return name;
5966
5967    //TIZEN_ONLY(20150717) add widget name setter
5968    if (_pd->name)
5969      {
5970 #ifdef HAVE_GETTEXT
5971         if (_pd->atspi_translation_domain)
5972           return dgettext(_pd->atspi_translation_domain, _pd->name);
5973 #endif
5974         return _pd->name;
5975      }
5976    //
5977
5978    //TIZEN_ONLY(20170110) : Ignore text from elm_object_text_set in accessible_name_get
5979    Efl_Access_Role role;
5980    role = efl_access_object_role_get(obj);
5981    if(role == EFL_ACCESS_ROLE_DIALOG || role == EFL_ACCESS_ROLE_PASSWORD_TEXT)
5982      return NULL;
5983    //
5984
5985    ret = elm_object_text_get(obj);
5986    if (!ret) return NULL;
5987
5988    return _elm_widget_accessible_plain_name_get(obj, ret);
5989 }
5990
5991 EOLIAN static Eina_List*
5992 _efl_ui_widget_efl_access_object_access_children_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
5993 {
5994    Eina_List *l, *accs = NULL;
5995    Evas_Object *widget;
5996    Eo *proxy = NULL;
5997
5998    /* this is for webapp which is using window only */
5999    if (efl_access_object_role_get(obj) == EFL_ACCESS_ROLE_WINDOW)
6000      {
6001         if (evas_object_data_get(obj, "__PlugID"))
6002           elm_atspi_ewk_wrapper_a11y_init((Eo *)obj, (Eo *)obj);
6003      }
6004
6005    for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
6006      {
6007         widget = eina_array_data_get(pd->children, i);
6008         const char *type = evas_object_type_get(widget);
6009         // TIZEN ONLY
6010         // Ugly Tizen hack to integrate AT-SPI2 accessibility provided by WebKit/Chromium with elementary one.
6011         // This wrapper class should be implemented in Webkit/Chromium EFL ports
6012         if (type && (!strcmp(type, "EWebView") || !strcmp(type, "WebView")))
6013           {
6014              elm_atspi_ewk_wrapper_a11y_init((Eo *)obj, widget);
6015           }
6016      }
6017    for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
6018      {
6019         widget = eina_array_data_get(pd->children, i);
6020
6021         // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6022         /* This assumes that only one proxy exists in obj */
6023         if (!proxy)
6024           {
6025              proxy = plug_type_proxy_get(obj, widget);
6026              if (proxy)
6027                {
6028                   accs = eina_list_append(accs, proxy);
6029                   continue;
6030                }
6031           }
6032         //
6033         // TIZEN ONLY - END
6034         if (!elm_object_widget_check(widget)) continue;
6035         if (!efl_isa(widget, EFL_ACCESS_OBJECT_MIXIN)) continue;
6036         accs = eina_list_append(accs, widget);
6037      }
6038    //TIZEN_ONLY(20150709) : spatially sort atspi children
6039    // sort children using its top-left coordinate
6040    accs = eina_list_sort(accs, -1, _sort_vertically);
6041    Eina_List *line, *lines = _lines_split(accs);
6042    accs = NULL;
6043    EINA_LIST_FREE(lines, line)
6044      accs = eina_list_merge(accs, eina_list_sort(line, -1, _sort_horizontally));
6045    //
6046
6047   if (proxy)
6048     {
6049        Eo *deputy = NULL;
6050        accs = eina_list_remove(accs, proxy);
6051        EINA_LIST_FOREACH(accs, l, widget)
6052          {
6053              if (efl_isa(widget, ELM_ACCESS_CLASS))
6054                {
6055                   Elm_Access_Info *info = _elm_access_info_get(widget);
6056                   if (!info) continue;
6057                   if (obj == info->part_object)
6058                     {
6059                        deputy = widget;
6060                        break;
6061                     }
6062                }
6063          }
6064
6065        if (deputy)
6066          {
6067             accs = eina_list_append_relative(accs, proxy, deputy);
6068          }
6069     }
6070
6071    return accs;
6072 }
6073
6074 /* Legacy APIs */
6075
6076 EOLIAN static Efl_Access_State_Set
6077 _efl_ui_widget_efl_access_object_state_set_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6078 {
6079    Efl_Access_State_Set states = 0;
6080
6081    states = efl_access_object_state_set_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
6082
6083    // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
6084    // //TIZEN_ONLY(20171108): bring HIGHLIGHT related changes
6085    // Evas_Object *win = elm_widget_top_get(obj);
6086    // if (win && efl_isa(win, EFL_UI_WIN_CLASS))
6087    //   {
6088    //      if (_elm_win_accessibility_highlight_get(win) == obj)
6089    //        STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
6090    //   }
6091    // STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6092    // //
6093    //
6094
6095    if (evas_object_visible_get(obj))
6096      {
6097         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
6098         if (_elm_widget_onscreen_is(obj))
6099           STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SHOWING);
6100      }
6101    if (!elm_widget_child_can_focus_get(obj))
6102      {
6103         if (elm_object_focus_allow_get(obj))
6104           STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSABLE);
6105         if (elm_object_focus_get(obj))
6106           STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSED);
6107      }
6108    if (!elm_object_disabled_get(obj))
6109      {
6110         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_ENABLED);
6111         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SENSITIVE);
6112      }
6113
6114    //TIZEN_ONLY(20170717) : expose highlight information on atspi
6115    if (_elm_widget_highlightable(obj))
6116      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
6117    else
6118      STATE_TYPE_UNSET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
6119
6120    if (_elm_object_accessibility_currently_highlighted_get() == (void*)obj)
6121      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED);
6122    //
6123
6124    return states;
6125 }
6126
6127 EOLIAN static Eina_List*
6128 _efl_ui_widget_efl_access_object_attributes_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6129 {
6130    const char *type = NULL;
6131    const char *style = NULL;
6132    Eina_List *attr_list = NULL;
6133    Efl_Access_Attribute *attr = NULL;
6134
6135    attr_list = efl_access_object_attributes_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
6136
6137    //Add type and style information in addition.
6138    type = elm_widget_type_get(obj);
6139    if (type)
6140      {
6141         attr = calloc(1, sizeof(Efl_Access_Attribute));
6142         if (attr)
6143           {
6144              attr->key = eina_stringshare_add("type");
6145              attr->value = eina_stringshare_add(type);
6146              attr_list = eina_list_append(attr_list, attr);
6147            }
6148      }
6149
6150    style = elm_widget_style_get(obj);
6151    if (style)
6152      {
6153         attr = calloc(1, sizeof(Efl_Access_Attribute));
6154         if (attr)
6155           {
6156              attr->key = eina_stringshare_add("style");
6157              attr->value = eina_stringshare_add(style);
6158              attr_list = eina_list_append(attr_list, attr);
6159           }
6160      }
6161
6162    return attr_list;
6163 }
6164
6165 EOLIAN static Eina_List *
6166 _elm_widget_item_efl_access_object_attributes_get(const Eo *eo_item, Elm_Widget_Item_Data *pd  EINA_UNUSED)
6167 {
6168    const char *style = NULL;
6169    Eina_List *attr_list = NULL;
6170    Efl_Access_Attribute *attr = NULL;
6171
6172    attr_list = efl_access_object_attributes_get(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
6173
6174    style = elm_object_item_style_get(eo_item);
6175    if (style)
6176      {
6177         attr = calloc(1, sizeof(Efl_Access_Attribute));
6178         if (attr)
6179           {
6180              attr->key = eina_stringshare_add("style");
6181              attr->value = eina_stringshare_add(style);
6182              attr_list = eina_list_append(attr_list, attr);
6183           }
6184      }
6185    return attr_list;
6186 }
6187
6188 EOLIAN static Eina_Rect
6189 _elm_widget_item_efl_access_component_extents_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords)
6190 {
6191    Eina_Rect r = EINA_RECT(-1, -1, -1, -1);
6192
6193    if (!sd->view) return r;
6194
6195    r = efl_gfx_entity_geometry_get(sd->view);
6196    if (screen_coords)
6197      {
6198         r = _efl_access_component_screen_coords_extents_get(obj, r);
6199      }
6200    return r;
6201 }
6202
6203 EOLIAN static Eina_Bool
6204 _elm_widget_item_efl_access_component_extents_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords EINA_UNUSED, Eina_Rect r EINA_UNUSED)
6205 {
6206    return EINA_FALSE;
6207 }
6208
6209 EOLIAN static Eina_Bool
6210 _elm_widget_item_efl_access_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6211 {
6212    elm_object_item_focus_set(obj, EINA_TRUE);
6213    return elm_object_item_focus_get(obj);
6214 }
6215
6216 EOLIAN static Efl_Object *
6217 _efl_ui_widget_efl_object_provider_find(const Eo *obj, Elm_Widget_Smart_Data *pd, const Efl_Object *klass)
6218 {
6219    Efl_Object *lookup = NULL;
6220
6221    if ((klass == EFL_CONFIG_INTERFACE) || (klass == EFL_CONFIG_GLOBAL_CLASS))
6222      return _efl_config_obj;
6223
6224    if (klass == EFL_UI_WIN_CLASS)
6225      {
6226         if (pd->window)
6227           return pd->window;
6228         //let the parent_obj lookup handle this
6229      }
6230
6231    if (klass == EFL_ACCESS_OBJECT_MIXIN)
6232      return (Eo*)obj;
6233
6234    if (pd->provider_lookup) return NULL;
6235    pd->provider_lookup = EINA_TRUE;
6236
6237    lookup = efl_provider_find(efl_super(obj, MY_CLASS), klass);
6238    if (!lookup && pd->parent_obj) lookup = efl_provider_find(pd->parent_obj, klass);
6239
6240    pd->provider_lookup = EINA_FALSE;
6241
6242    return lookup;
6243 }
6244
6245 //TIZEN_ONLY(20191205): fix build warnings of focus_manager functions
6246 #pragma GCC diagnostic push
6247 #pragma GCC diagnostic ignored "-Wunused-function"
6248 //
6249
6250 EOLIAN static Efl_Ui_Focus_Manager*
6251 _efl_ui_widget_efl_ui_focus_object_focus_parent_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6252 {
6253    return pd->focus.parent;
6254 }
6255
6256 EOLIAN static Efl_Ui_Focus_Manager*
6257 _efl_ui_widget_efl_ui_focus_object_focus_manager_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6258 {
6259    return pd->focus.manager;
6260 }
6261
6262 EOLIAN static Eina_Rect
6263 _efl_ui_widget_efl_ui_focus_object_focus_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6264 {
6265    return efl_gfx_entity_geometry_get(obj);
6266 }
6267
6268 EOLIAN static void
6269 _efl_ui_widget_efl_ui_focus_object_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool focus)
6270 {
6271    pd->focused = focus;
6272
6273    efl_ui_focus_object_focus_set(efl_super(obj, MY_CLASS), focus);
6274
6275    efl_ui_focus_object_on_focus_update(obj);
6276 }
6277
6278 EOLIAN static Efl_Ui_Focus_Manager*
6279 _efl_ui_widget_focus_manager_create(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root EINA_UNUSED)
6280 {
6281    ERR("No manager presented");
6282    return NULL;
6283 }
6284
6285 //TIZEN_ONLY(20191205): fix build warnings of focus_manager functions
6286 #pragma GCC diagnostic pop
6287 //
6288
6289 //TIZEN_ONLY(20160726): add API elm_object_part_access_object_get
6290 EOLIAN static Evas_Object*
6291 _efl_ui_widget_part_access_object_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part EINA_UNUSED)
6292 {
6293    WRN("The %s widget does not implement the \"part_access_object_get\" functions.",
6294        efl_class_name_get(efl_class_get(obj)));
6295    return NULL;
6296 }
6297 //
6298
6299 /* Legacy APIs */
6300
6301 EAPI void
6302 elm_widget_on_show_region_hook_set(Eo *obj, void *data, Elm_Widget_On_Show_Region_Cb func, Eina_Free_Cb func_free_cb)
6303 {
6304    ELM_WIDGET_DATA_GET(obj, sd);
6305
6306    if (!sd) return;
6307    if ((sd->on_show_region_data == data) && (sd->on_show_region == func))
6308      return;
6309
6310    if (sd->on_show_region_data && sd->on_show_region_data_free)
6311      sd->on_show_region_data_free(sd->on_show_region_data);
6312
6313    sd->on_show_region = func;
6314    sd->on_show_region_data = data;
6315    sd->on_show_region_data_free = func_free_cb;
6316 }
6317
6318 EAPI void
6319 elm_widget_show_region_set(Eo *obj, Eina_Rect sr, Eina_Bool forceshow)
6320 {
6321    Evas_Object *parent_obj, *child_obj;
6322    Evas_Coord px, py, cx, cy, nx = 0, ny = 0;
6323
6324    ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd);
6325
6326    /*****************************************************************************
6327     * TIZEN_ONLY_FEATURE: Fix entry size/cursor/region calculation for Tizen UX *
6328     *****************************************************************************
6329     * Move this code to the below to update show region geometry properly.
6330    evas_smart_objects_calculate(evas_object_evas_get(obj));
6331     */
6332    /*******
6333     * END *
6334     *******/
6335
6336    if (!forceshow && eina_rectangle_equal(&sr.rect, &sd->show_region.rect)) return;
6337
6338    sd->show_region = sr;
6339
6340    /*****************************************************************************
6341     * TIZEN_ONLY_FEATURE: Fix entry size/cursor/region calculation for Tizen UX *
6342     *****************************************************************************/
6343    /* Block nested call for evas_smart_objects_calculate() and region showing works */
6344    if (sd->on_show_region_set) return;
6345
6346    sd->on_show_region_set = EINA_TRUE;
6347
6348    evas_smart_objects_calculate(evas_object_evas_get(obj));
6349
6350    sd->on_show_region_set = EINA_FALSE;
6351
6352    /* show_region geometry could be changed during processing elm_widget_show_region_set().
6353       evas_smart_objects_calculate() can trigger nested show_region_set calls */
6354    sr = sd->show_region;
6355    /*******
6356     * END *
6357     *******/
6358
6359    if (sd->on_show_region)
6360      {
6361         sd->on_show_region(sd->on_show_region_data, obj, sr);
6362
6363         if (_elm_scrollable_is(obj))
6364           {
6365              if (elm_widget_is_legacy(obj))
6366                {
6367                   elm_interface_scrollable_content_pos_get(obj, &nx, &ny);
6368                   sr.x -= nx;
6369                   sr.y -= ny;
6370                }
6371              else
6372                {
6373                   Eina_Position2D pos;
6374                   pos = efl_ui_scrollable_content_pos_get(obj);
6375                   sr.x -= pos.x;
6376                   sr.y -= pos.y;
6377                }
6378           }
6379      }
6380    child_obj = obj;
6381    do
6382      {
6383         parent_obj = sd->parent_obj;
6384         if ((!parent_obj)) break;
6385         sd = efl_data_scope_get(parent_obj, MY_CLASS);
6386         if (!sd) break;
6387
6388         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
6389         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
6390
6391         sr.x += (cx - px);
6392         sr.y += (cy - py);
6393         sd->show_region = sr;
6394
6395         if (sd->on_show_region)
6396           sd->on_show_region(sd->on_show_region_data, parent_obj, sr);
6397         child_obj = parent_obj;
6398      }
6399    while (parent_obj);
6400 }
6401
6402 EAPI Eina_Rect
6403 elm_widget_show_region_get(const Eo *obj)
6404 {
6405    ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd, EINA_RECT_EMPTY());
6406    return (Eina_Rect) sd->show_region;
6407 }
6408 /* elm_object_content_xxx APIs are supposed to work on all objects for which
6409  * elm_object_widget_check() returns true. The below checks avoid printing out
6410  * undesired ERR messages. */
6411 EAPI void
6412 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
6413 {
6414    ELM_WIDGET_CHECK(obj);
6415    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6416      {
6417         elm_layout_content_set(obj, part, content);
6418         return;
6419      }
6420    if (!efl_isa(obj, EFL_PART_INTERFACE)) return;
6421    if (!part)
6422      {
6423         part = efl_ui_widget_default_content_part_get(obj);
6424         if (!part) return;
6425      }
6426    efl_content_set(efl_part(obj, part), content);
6427 }
6428
6429 EAPI Evas_Object *
6430 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
6431 {
6432    ELM_WIDGET_CHECK(obj) NULL;
6433    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6434      return elm_layout_content_get(obj, part);
6435    if (!efl_isa(obj, EFL_PART_INTERFACE)) return NULL;
6436    if (!part)
6437      {
6438         part = efl_ui_widget_default_content_part_get(obj);
6439         if (!part) return NULL;
6440      }
6441    return efl_content_get(efl_part(obj, part));
6442 }
6443
6444 EAPI Evas_Object *
6445 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
6446 {
6447    ELM_WIDGET_CHECK(obj) NULL;
6448    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6449      return elm_layout_content_unset(obj, part);
6450    if (!efl_isa(obj, EFL_PART_INTERFACE)) return NULL;
6451    if (!part)
6452      {
6453         part = efl_ui_widget_default_content_part_get(obj);
6454         if (!part) return NULL;
6455      }
6456    return efl_content_unset(efl_part(obj, part));
6457 }
6458
6459 EAPI void
6460 elm_widget_signal_emit(Eo *obj, const char *emission, const char *source)
6461 {
6462    ELM_WIDGET_CHECK(obj);
6463
6464    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6465      elm_layout_signal_emit(obj, emission, source);
6466    else if (evas_object_smart_type_check(obj, "elm_icon"))
6467      {
6468         WRN("Deprecated function. This functionality on icon objects"
6469             " will be dropped on a next release.");
6470         _elm_icon_signal_emit(obj, emission, source);
6471      }
6472 }
6473
6474 EAPI void
6475 elm_widget_signal_callback_add(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
6476 {
6477    ELM_WIDGET_CHECK(obj);
6478    EINA_SAFETY_ON_NULL_RETURN(func);
6479    if (evas_object_smart_type_check(obj, "elm_layout"))
6480      elm_layout_signal_callback_add(obj, emission, source, func, data);
6481    else if (evas_object_smart_type_check(obj, "elm_icon"))
6482      {
6483         WRN("Deprecated function. This functionality on icon objects"
6484             " will be dropped on a next release.");
6485
6486         _elm_icon_signal_callback_add(obj, emission, source, func, data);
6487      }
6488 }
6489
6490 EAPI void *
6491 elm_widget_signal_callback_del(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func)
6492 {
6493    void *data = NULL;
6494
6495    ELM_WIDGET_CHECK(obj) NULL;
6496    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
6497    if (evas_object_smart_type_check(obj, "elm_layout"))
6498      data = elm_layout_signal_callback_del(obj, emission, source, func);
6499    else if (evas_object_smart_type_check(obj, "elm_icon"))
6500      {
6501         WRN("Deprecated function. This functionality on icon objects"
6502             " will be dropped on a next release.");
6503
6504         data = _elm_icon_signal_callback_del(obj, emission, source, func);
6505      }
6506
6507    return data;
6508 }
6509
6510
6511 /* Widget Shadow Begin */
6512
6513 typedef struct _Widget_Shadow
6514 {
6515    Eo *widget;
6516    Eo *surface;
6517    struct {
6518       double rx, ry, ox, oy, grow;
6519       int r, g, b, a;
6520    } props;
6521    Eina_Stringshare *code, *name;
6522 } Widget_Shadow;
6523
6524 static void _widget_shadow_update(Widget_Shadow *shadow);
6525
6526 static void
6527 _widget_shadow_del_cb(void *data, const Efl_Event *ev EINA_UNUSED)
6528 {
6529    Widget_Shadow *shadow = data;
6530
6531    efl_del(shadow->surface);
6532    free(shadow);
6533 }
6534
6535 static void
6536 _widget_shadow_event_cb(void *data, const Efl_Event *ev EINA_UNUSED)
6537 {
6538    Widget_Shadow *shadow = data;
6539    _widget_shadow_update(shadow);
6540 }
6541
6542 EFL_CALLBACKS_ARRAY_DEFINE(widget_shadow_cb,
6543 { EFL_EVENT_DEL, _widget_shadow_del_cb },
6544 { EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _widget_shadow_event_cb },
6545 { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _widget_shadow_event_cb },
6546 { EFL_GFX_ENTITY_EVENT_STACKING_CHANGED, _widget_shadow_event_cb },
6547 { EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _widget_shadow_event_cb });
6548
6549 static Widget_Shadow *
6550 _widget_shadow_part_get(const Eo *part_obj)
6551 {
6552    Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS);
6553    Widget_Shadow *shadow;
6554    Eo *widget = pd->obj;
6555
6556    shadow = efl_key_data_get(widget, "__elm_shadow");
6557    if (!shadow)
6558      {
6559         shadow = calloc(1, sizeof(*shadow));
6560         if (!shadow) return NULL;
6561         shadow->widget = pd->obj;
6562         efl_key_data_set(widget, "__elm_shadow", shadow);
6563         efl_event_callback_array_add(widget, widget_shadow_cb(), shadow);
6564      }
6565    return shadow;
6566 }
6567
6568 static void
6569 _widget_shadow_update(Widget_Shadow *ws)
6570 {
6571    int l = 0, r = 0, t = 0, b = 0;
6572    Eina_Rect srect, wrect;
6573    char filter[1024];
6574
6575 #define FILTER_FMT \
6576    "a = buffer { 'alpha' }" \
6577    "grow { %f, dst = a, alphaonly = true }" \
6578    "blur { src = a, rx = %f, ry = %f, color = color(%d,%d,%d,%d) }"
6579
6580    if (!ws->surface)
6581      {
6582         ws->surface = efl_add(EFL_CANVAS_PROXY_CLASS, ws->widget);
6583         efl_gfx_fill_auto_set(ws->surface, 1);
6584         efl_canvas_proxy_source_clip_set(ws->surface, EINA_FALSE);
6585         efl_canvas_proxy_source_events_set(ws->surface, EINA_FALSE);
6586         efl_canvas_proxy_source_set(ws->surface, ws->widget);
6587      }
6588
6589    if (!ws->code)
6590      {
6591         snprintf(filter, sizeof(filter), FILTER_FMT,
6592                  ws->props.grow, ws->props.rx, ws->props.ry,
6593                  ws->props.r, ws->props.g, ws->props.b, ws->props.a);
6594      }
6595
6596    efl_gfx_filter_program_set(ws->surface,
6597                               ws->code ? ws->code : filter,
6598                               ws->name ? ws->name : "shadow");
6599    efl_gfx_filter_padding_get(ws->surface, &l, &r, &t, &b);
6600
6601    wrect = efl_gfx_entity_geometry_get(ws->widget);
6602    srect.x = wrect.x + (int) (-l + ws->props.ox);
6603    srect.y = wrect.y + (int) (-t + ws->props.oy);
6604    srect.w = wrect.w + (int) (l + r);
6605    srect.h = wrect.h + (int) (t + b);
6606
6607    if ((!ws->props.a && !ws->code) ||
6608        !efl_gfx_entity_visible_get(ws->widget))
6609      {
6610         efl_gfx_entity_visible_set(ws->surface, EINA_FALSE);
6611         return;
6612      }
6613
6614    efl_canvas_object_clipper_set(ws->surface, efl_canvas_object_clipper_get(ws->widget));
6615    efl_canvas_group_member_add(efl_canvas_object_render_parent_get(ws->widget), ws->surface);
6616    efl_gfx_entity_geometry_set(ws->surface, srect);
6617    efl_gfx_stack_below(ws->surface, ws->widget);
6618    efl_gfx_entity_visible_set(ws->surface, EINA_TRUE);
6619 }
6620
6621 static void
6622 _elm_widget_shadow_update(Efl_Ui_Widget *obj)
6623 {
6624    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6625    _widget_shadow_update(shadow);
6626 }
6627
6628 EOLIAN static void
6629 _efl_ui_widget_part_shadow_efl_gfx_blur_offset_set(Eo *obj, void *_pd EINA_UNUSED, double ox, double oy)
6630 {
6631    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6632    shadow->props.ox = ox;
6633    shadow->props.oy = oy;
6634    _widget_shadow_update(shadow);
6635 }
6636
6637 EOLIAN static void
6638 _efl_ui_widget_part_shadow_efl_gfx_blur_offset_get(const Eo *obj, void *_pd EINA_UNUSED, double *ox, double *oy)
6639 {
6640    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6641    if (ox) *ox = shadow->props.ox;
6642    if (oy) *oy = shadow->props.oy;
6643 }
6644
6645 EOLIAN static void
6646 _efl_ui_widget_part_shadow_efl_gfx_blur_radius_set(Eo *obj, void *_pd EINA_UNUSED, double rx, double ry)
6647 {
6648    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6649    shadow->props.rx = rx;
6650    shadow->props.ry = ry;
6651    _widget_shadow_update(shadow);
6652 }
6653
6654 EOLIAN static void
6655 _efl_ui_widget_part_shadow_efl_gfx_blur_radius_get(const Eo *obj, void *_pd EINA_UNUSED, double *rx, double *ry)
6656 {
6657    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6658    if (rx) *rx = shadow->props.rx;
6659    if (ry) *ry = shadow->props.ry;
6660 }
6661
6662 EOLIAN static void
6663 _efl_ui_widget_part_shadow_efl_gfx_color_color_set(Eo *obj, void *_pd EINA_UNUSED, int r, int g, int b, int a)
6664 {
6665    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6666    shadow->props.r = r;
6667    shadow->props.g = g;
6668    shadow->props.b = b;
6669    shadow->props.a = a;
6670    _widget_shadow_update(shadow);
6671 }
6672
6673 EOLIAN static void
6674 _efl_ui_widget_part_shadow_efl_gfx_color_color_get(const Eo *obj, void *_pd EINA_UNUSED, int *r, int *g, int *b, int *a)
6675 {
6676    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6677    if (r) *r = shadow->props.r;
6678    if (g) *g = shadow->props.g;
6679    if (b) *b = shadow->props.b;
6680    if (a) *a = shadow->props.a;
6681 }
6682
6683 EOLIAN static void
6684 _efl_ui_widget_part_shadow_efl_gfx_blur_grow_set(Eo *obj, void *_pd EINA_UNUSED, double radius)
6685 {
6686    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6687    shadow->props.grow = radius;
6688    _widget_shadow_update(shadow);
6689 }
6690
6691 EOLIAN static double
6692 _efl_ui_widget_part_shadow_efl_gfx_blur_grow_get(const Eo *obj, void *_pd EINA_UNUSED)
6693 {
6694    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6695    return shadow->props.grow;
6696 }
6697
6698 EOLIAN static void
6699 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_set(Eo *obj, void *_pd EINA_UNUSED, const char *code, const char *name)
6700 {
6701    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6702    eina_stringshare_replace(&ws->code, code);
6703    eina_stringshare_replace(&ws->name, name);
6704    _widget_shadow_update(ws);
6705 }
6706
6707 EOLIAN static void
6708 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_get(const Eo *obj, void *_pd EINA_UNUSED, const char **code, const char **name)
6709 {
6710    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6711    efl_gfx_filter_program_get(ws->surface, code, name);
6712 }
6713
6714 EOLIAN static void
6715 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, Efl_Gfx_Entity *source)
6716 {
6717    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6718    _widget_shadow_update(ws);
6719    efl_gfx_filter_source_set(ws->surface, name, source);
6720 }
6721
6722 EOLIAN static Efl_Gfx_Entity *
6723 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_get(const Eo *obj, void *_pd EINA_UNUSED, const char *name)
6724 {
6725    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6726    return efl_gfx_filter_source_get(ws->surface, name);
6727 }
6728
6729 EOLIAN static void
6730 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, const char *value, Eina_Bool execute)
6731 {
6732    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6733    _widget_shadow_update(ws);
6734    efl_gfx_filter_data_set(ws->surface, name, value, execute);
6735 }
6736
6737 EOLIAN static void
6738 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_data_get(const Eo *obj, void *_pd EINA_UNUSED, const char *name, const char **value, Eina_Bool *execute)
6739 {
6740    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6741    efl_gfx_filter_data_get(ws->surface, name, value, execute);
6742 }
6743
6744 EOLIAN static void
6745 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_padding_get(const Eo *obj, void *_pd EINA_UNUSED, int *l, int *r, int *t, int *b)
6746 {
6747    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6748    efl_gfx_filter_padding_get(ws->surface, l, r, t, b);
6749 }
6750
6751 EOLIAN static void
6752 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_set(Eo *obj, void *_pd EINA_UNUSED, const char *cur_state, double cur_val, const char *next_state, double next_val, double pos)
6753 {
6754    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6755    efl_gfx_filter_state_set(ws->surface, cur_state, cur_val, next_state, next_val, pos);
6756 }
6757
6758 EOLIAN static void
6759 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_state_get(const Eo *obj, void *_pd EINA_UNUSED, const char **cur_state, double *cur_val, const char **next_state, double *next_val, double *pos)
6760 {
6761    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6762    efl_gfx_filter_state_get(ws->surface, cur_state, cur_val, next_state, next_val, pos);
6763 }
6764
6765 #include "efl_ui_widget_part_shadow.eo.c"
6766
6767 /* Widget Shadow End */
6768
6769
6770 /* Efl.Part implementation */
6771
6772 EOLIAN static Efl_Object *
6773 _efl_ui_widget_efl_part_part_get(const Eo *obj, Elm_Widget_Smart_Data *wd EINA_UNUSED, const char *part)
6774 {
6775    if (eina_streq(part, "background"))
6776      return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_BG_CLASS, obj, part);
6777    else if (eina_streq(part, "shadow"))
6778      return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_SHADOW_CLASS, obj, part);
6779    return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_CLASS, obj, part);
6780 }
6781
6782 EOLIAN static void \
6783 _efl_ui_widget_part_efl_object_destructor(Eo *obj, Elm_Part_Data *pd)
6784 {
6785    ELM_PART_HOOK;
6786    eina_tmpstr_del(pd->part);
6787    efl_destructor(efl_super(obj, EFL_UI_WIDGET_PART_CLASS));
6788 }
6789
6790 static Efl_Canvas_Layout_Part_Type
6791 _efl_ui_widget_part_efl_canvas_layout_part_type_provider_part_type_get(const Eo *obj EINA_UNUSED, Elm_Part_Data *pd)
6792 {
6793    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(pd->obj, MY_CLASS);
6794    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EFL_CANVAS_LAYOUT_PART_TYPE_NONE);
6795    return efl_canvas_layout_part_type_get(efl_part(sd->resize_obj, pd->part));
6796 }
6797
6798 static Eina_Rect
6799 _efl_ui_widget_part_efl_gfx_entity_geometry_get(const Eo *obj EINA_UNUSED, Elm_Part_Data *pd)
6800 {
6801    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(pd->obj, MY_CLASS);
6802    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_RECT_EMPTY());
6803    return efl_gfx_entity_geometry_get(efl_part(sd->resize_obj, pd->part));
6804 }
6805
6806 static Eina_Error
6807 _efl_ui_widget_part_efl_ui_property_bind_property_bind(Eo *obj, Elm_Part_Data *ppd,
6808                                                        const char *key, const char *property)
6809 {
6810    Efl_Ui_Widget_Data *pd;
6811    Eo *widget;
6812
6813    widget = efl_parent_get(obj);
6814    pd = efl_data_scope_get(widget, EFL_UI_WIDGET_CLASS);
6815
6816    return _efl_ui_property_bind(widget, obj, pd, ppd->part, key, property);
6817 }
6818
6819 #include "efl_ui_widget_part.eo.c"
6820
6821 /* Efl.Part end */
6822
6823 /* Efl.Part Bg implementation */
6824
6825 Efl_Canvas_Object *
6826 _efl_ui_widget_bg_get(const Efl_Ui_Widget *obj)
6827 {
6828    Elm_Widget_Smart_Data *sd = efl_data_scope_get(obj, MY_CLASS);
6829    Evas_Object *bg_obj = sd->bg;
6830
6831    if (!bg_obj)
6832      {
6833         bg_obj = efl_add(EFL_UI_BG_CLASS, (Eo *)obj);
6834         EINA_SAFETY_ON_NULL_RETURN_VAL(bg_obj, NULL);
6835         sd->bg = bg_obj;
6836         efl_canvas_group_member_add((Eo *)obj, sd->bg);
6837         evas_object_stack_below(sd->bg, sd->resize_obj);
6838         _smart_reconfigure((Eo*)obj, sd);
6839      }
6840
6841    return bg_obj;
6842 }
6843
6844 static inline Efl_Canvas_Object *
6845 efl_ui_widget_part_bg_get(const Eo *part_obj)
6846 {
6847    Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS);
6848    return _efl_ui_widget_bg_get(pd->obj);
6849 }
6850
6851 EOLIAN static Eina_Error
6852 _efl_ui_widget_part_bg_efl_file_load(Eo *obj, void *pd EINA_UNUSED)
6853 {
6854    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6855
6856    return efl_file_load(bg_obj);
6857 }
6858
6859 EOLIAN static void
6860 _efl_ui_widget_part_bg_efl_file_unload(Eo *obj, void *pd EINA_UNUSED)
6861 {
6862    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6863
6864    efl_file_unload(bg_obj);
6865 }
6866
6867 EOLIAN static const char *
6868 _efl_ui_widget_part_bg_efl_file_file_get(const Eo *obj, void *pd EINA_UNUSED)
6869 {
6870    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6871
6872    return efl_file_get(bg_obj);
6873 }
6874
6875 EOLIAN static Eina_Error
6876 _efl_ui_widget_part_bg_efl_file_file_set(Eo *obj, void *pd EINA_UNUSED, const char *file)
6877 {
6878    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6879
6880    return efl_file_set(bg_obj, file);
6881 }
6882
6883 EOLIAN static const char *
6884 _efl_ui_widget_part_bg_efl_file_key_get(const Eo *obj, void *pd EINA_UNUSED)
6885 {
6886    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6887
6888    return efl_file_key_get(bg_obj);
6889 }
6890
6891 EOLIAN static void
6892 _efl_ui_widget_part_bg_efl_file_key_set(Eo *obj, void *pd EINA_UNUSED, const char *key)
6893 {
6894    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6895
6896    efl_file_key_set(bg_obj, key);
6897 }
6898
6899 EOLIAN static const Eina_File *
6900 _efl_ui_widget_part_bg_efl_file_mmap_get(const Eo *obj, void *pd EINA_UNUSED)
6901 {
6902    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6903
6904    return efl_file_mmap_get(bg_obj);
6905 }
6906
6907 EOLIAN static Eina_Error
6908 _efl_ui_widget_part_bg_efl_file_mmap_set(Eo *obj, void *pd EINA_UNUSED, const Eina_File *file)
6909 {
6910    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6911
6912    return efl_file_mmap_set(bg_obj, file);
6913 }
6914
6915 EOLIAN static void
6916 _efl_ui_widget_part_bg_efl_gfx_color_color_set(Eo *obj, void *pd EINA_UNUSED, int r, int g, int b, int a)
6917 {
6918    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6919
6920    efl_gfx_color_set(bg_obj, r, g, b, a);
6921 }
6922
6923 EOLIAN static void
6924 _efl_ui_widget_part_bg_efl_gfx_color_color_get(const Eo *obj, void *pd EINA_UNUSED, int *r, int *g, int *b, int *a)
6925 {
6926    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6927
6928    efl_gfx_color_get(bg_obj, r, g, b, a);
6929 }
6930
6931 EOLIAN static Efl_Object*
6932 _efl_ui_widget_part_bg_efl_object_finalize(Eo *obj, void *pd EINA_UNUSED)
6933 {
6934    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6935
6936    efl_composite_attach(obj, bg_obj);
6937
6938    return efl_finalize(efl_super(obj, EFL_UI_WIDGET_PART_BG_CLASS));
6939 }
6940
6941
6942 typedef struct _Efl_Ui_Property_Bound Efl_Ui_Property_Bound;
6943 struct _Efl_Ui_Property_Bound
6944 {
6945    Eina_Stringshare *part; // Optional part to apply the property on
6946    Eina_Stringshare *key; // Local object property
6947    Eina_Stringshare *property; // Model property
6948    Eina_Future *f;
6949 };
6950
6951 static void
6952 _efl_ui_property_bind_free(void *data)
6953 {
6954    Efl_Ui_Property_Bound *prop = data;
6955
6956    eina_stringshare_del(prop->part);
6957    eina_stringshare_del(prop->key);
6958    eina_stringshare_del(prop->property);
6959    free(prop);
6960 }
6961
6962 static void
6963 _efl_ui_property_bind_clean(Eo *obj EINA_UNUSED,
6964                             void *data,
6965                             const Eina_Future *f EINA_UNUSED)
6966 {
6967    Efl_Ui_Property_Bound *prop = data;
6968
6969    prop->f = NULL;
6970 }
6971
6972 static void
6973 _efl_ui_property_bind_get(Eo *obj, Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
6974 {
6975    Eina_Value *value;
6976    Eina_Future *f;
6977    Eina_Error err;
6978    Eo *target;
6979
6980    // If there is no model set yet, no need to try anything
6981    if (!pd->properties.model) return ;
6982
6983    value = efl_model_property_get(pd->properties.model, prop->property);
6984    target = prop->part ? efl_part(obj, prop->part) : obj;
6985
6986    err = efl_property_reflection_set(target, prop->key, eina_value_reference_copy(value));
6987    eina_value_free(value);
6988
6989    if (!err) return ;
6990
6991    // Report back the error to the model
6992    if (prop->f) eina_future_cancel(prop->f);
6993    f = efl_model_property_set(pd->properties.model, prop->property,
6994                               eina_value_error_new(err));
6995    prop->f = efl_future_then(obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
6996 }
6997
6998 static void
6999 _efl_ui_property_bind_set(Eo *obj, Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
7000 {
7001    Eina_Value value;
7002    Eina_Future *f;
7003    Eo *target;
7004
7005    target = prop->part ? efl_part(obj, prop->part) : obj;
7006    value = efl_property_reflection_get(target, prop->key);
7007
7008    if (prop->f) eina_future_cancel(prop->f);
7009    f = efl_model_property_set(pd->properties.model, prop->property, eina_value_dup(&value));
7010    prop->f = efl_future_then(obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
7011    eina_value_flush(&value);
7012 }
7013
7014 static void
7015 _efl_ui_model_property_bind_changed(void *data, const Efl_Event *event)
7016 {
7017    Efl_Model_Property_Event *evt = event->info;
7018    ELM_WIDGET_DATA_GET(data, pd);
7019    Eina_Array_Iterator it;
7020    const char *prop;
7021    unsigned int i;
7022
7023    if (!pd) return;
7024    EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
7025      {
7026         Efl_Ui_Property_Bound *lookup;
7027
7028         lookup = eina_hash_find(pd->properties.model_lookup, prop);
7029         if (lookup) _efl_ui_property_bind_get(data, pd, lookup);
7030      }
7031 }
7032
7033 static void
7034 _efl_ui_view_property_bind_changed(void *data, const Efl_Event *event)
7035 {
7036    Efl_Ui_Property_Event *evt = event->info;
7037    ELM_WIDGET_DATA_GET(data, pd);
7038    Eina_Array_Iterator it;
7039    Eina_Stringshare *prop;
7040    unsigned int i;
7041
7042    if (!pd) return;
7043    EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
7044      {
7045         Efl_Ui_Property_Bound *lookup;
7046
7047         lookup = eina_hash_find(pd->properties.view_lookup, prop);
7048         if (lookup) _efl_ui_property_bind_set(data, pd, lookup);
7049      }
7050 }
7051
7052 static void
7053 _efl_ui_widget_model_update(Eo *obj, Efl_Ui_Widget_Data *pd)
7054 {
7055    Efl_Ui_Property_Bound *property;
7056    Eina_Iterator *it;
7057
7058    it = eina_hash_iterator_data_new(pd->properties.model_lookup);
7059    EINA_ITERATOR_FOREACH(it, property)
7060      _efl_ui_property_bind_get(obj, pd, property);
7061    eina_iterator_free(it);
7062 }
7063
7064 static void _efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event EINA_UNUSED);
7065 static void _efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED);
7066
7067 EFL_CALLBACKS_ARRAY_DEFINE(efl_ui_widget_model_provider_callbacks,
7068                            { EFL_EVENT_INVALIDATE, _efl_ui_widget_model_provider_invalidate },
7069                            { EFL_UI_VIEW_EVENT_MODEL_CHANGED, _efl_ui_widget_model_provider_model_change });
7070
7071 static void
7072 _efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event)
7073 {
7074    ELM_WIDGET_DATA_GET(data, pd);
7075
7076    if (!pd) return;
7077    efl_replace(&pd->properties.model,
7078                efl_ui_view_model_get(pd->properties.provider));
7079    _efl_ui_widget_model_update(data, pd);
7080
7081    efl_event_callback_call(data, EFL_UI_VIEW_EVENT_MODEL_CHANGED, event->info);
7082 }
7083
7084 static void
7085 _efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED)
7086 {
7087    ELM_WIDGET_DATA_GET(data, pd);
7088
7089    if (!pd) return;
7090    efl_event_callback_array_del(pd->properties.provider,
7091                                 efl_ui_widget_model_provider_callbacks(),
7092                                 data);
7093    efl_replace(&pd->properties.provider, NULL);
7094    efl_replace(&pd->properties.model, NULL);
7095    pd->properties.callback_to_provider = EINA_FALSE;
7096 }
7097
7098 static void
7099 _efl_ui_widget_model_register(Eo *obj, Efl_Ui_Widget_Data *pd)
7100 {
7101    if (pd->properties.registered) return ;
7102
7103    if (!pd->properties.model)
7104      {
7105         Efl_Model_Changed_Event ev;
7106
7107         efl_replace(&pd->properties.provider,
7108                     efl_provider_find(obj, EFL_MODEL_PROVIDER_CLASS));
7109         if (!pd->properties.provider) return ;
7110         if (!pd->properties.callback_to_provider)
7111           efl_event_callback_array_add(pd->properties.provider,
7112                                        efl_ui_widget_model_provider_callbacks(),
7113                                        obj);
7114         pd->properties.callback_to_provider = EINA_TRUE;
7115         efl_replace(&pd->properties.model,
7116                     efl_ui_view_model_get(pd->properties.provider));
7117
7118         if (!pd->properties.model) return ;
7119
7120         ev.current = pd->properties.model;
7121         ev.previous = NULL;
7122         efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
7123      }
7124
7125    if (!pd->properties.model) return ;
7126    if (!pd->properties.model_lookup) return ;
7127
7128    efl_event_callback_add(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
7129                           _efl_ui_model_property_bind_changed, obj);
7130    efl_event_callback_add(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
7131                           _efl_ui_view_property_bind_changed, obj);
7132    pd->properties.registered = EINA_TRUE;
7133 }
7134
7135 static void
7136 _efl_ui_widget_model_unregister(Eo *obj, Efl_Ui_Widget_Data *pd)
7137 {
7138    if (pd->properties.registered)
7139      {
7140         // Remove any existing handler that might exist for any reason
7141         efl_event_callback_del(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
7142                                _efl_ui_model_property_bind_changed, obj);
7143         efl_event_callback_del(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
7144                                _efl_ui_view_property_bind_changed, obj);
7145
7146         pd->properties.registered = EINA_FALSE;
7147      }
7148    // Invalidate must be called before setting a new model and even if no model is registered
7149    if (pd->properties.provider)
7150      _efl_ui_widget_model_provider_invalidate(obj, NULL);
7151 }
7152
7153 static Eina_Error
7154 _efl_ui_property_bind(Eo *widget, Eo *target, Efl_Ui_Widget_Data *pd,
7155                       const char *part, const char *key, const char *property)
7156 {
7157    Efl_Ui_Property_Bound *prop;
7158
7159    // Always check for a model and fetch a provider in case a bound property
7160    // is provided by a class down the hierarchy, but they still need to be notified
7161    // when a model change
7162    _efl_ui_widget_model_register(widget, pd);
7163
7164    // Check if the property is available from the reflection table of the object.
7165    if (!efl_property_reflection_exist(target, key)) return EFL_PROPERTY_ERROR_INVALID_KEY;
7166
7167    if (!pd->properties.model_lookup)
7168      {
7169         pd->properties.model_lookup = eina_hash_stringshared_new(_efl_ui_property_bind_free);
7170         pd->properties.view_lookup = eina_hash_stringshared_new(NULL);
7171      }
7172
7173    prop = calloc(1, sizeof (Efl_Ui_Property_Bound));
7174    if (!prop) return ENOMEM;
7175    prop->part = eina_stringshare_add(part);
7176    prop->key = eina_stringshare_add(key);
7177    prop->property = eina_stringshare_add(property);
7178
7179    eina_hash_direct_add(pd->properties.model_lookup, prop->property, prop);
7180    eina_hash_direct_add(pd->properties.view_lookup, prop->key, prop);
7181
7182    _efl_ui_property_bind_get(widget, pd, prop);
7183
7184    efl_event_callback_call(widget, EFL_UI_PROPERTY_BIND_EVENT_PROPERTY_BOUND, (void*) prop->key);
7185    // In case of part, we emit it also on the part so that the part too can act on it
7186    if (target)
7187      efl_event_callback_call(target, EFL_UI_PROPERTY_BIND_EVENT_PROPERTY_BOUND, (void*) prop->key);
7188
7189    return 0;
7190 }
7191
7192 static Eina_Error
7193 _efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *pd,
7194                                                   const char *key, const char *property)
7195 {
7196    return _efl_ui_property_bind(obj, obj, pd, NULL, key, property);
7197 }
7198
7199 static void
7200 _efl_ui_widget_efl_ui_view_model_set(Eo *obj,
7201                                      Efl_Ui_Widget_Data *pd,
7202                                      Efl_Model *model)
7203 {
7204    Efl_Model_Changed_Event ev;
7205
7206    ev.current = efl_ref(model);
7207    ev.previous = efl_ref(pd->properties.model);
7208
7209    _efl_ui_widget_model_unregister(obj, pd);
7210
7211    efl_replace(&pd->properties.model, model);
7212
7213    // Set the properties handler just in case
7214    _efl_ui_widget_model_register(obj, pd);
7215
7216    // In case the model set was NULL, but we did found a model provider
7217    // we shouldn't emit a second event. Otherwise we should.
7218    if (ev.current == pd->properties.model)
7219      efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
7220
7221    if (pd->properties.model) _efl_ui_widget_model_update(obj, pd);
7222
7223    efl_unref(ev.current);
7224    efl_unref(ev.previous);
7225 }
7226
7227 static Efl_Model *
7228 _efl_ui_widget_efl_ui_view_model_get(const Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *pd)
7229 {
7230    return pd->properties.model;
7231 }
7232
7233 static void
7234 _efl_ui_widget_efl_object_invalidate(Eo *obj, Efl_Ui_Widget_Data *pd)
7235 {
7236    efl_invalidate(efl_super(obj, EFL_UI_WIDGET_CLASS));
7237
7238    _efl_ui_widget_model_unregister(obj, pd);
7239    efl_replace(&pd->properties.model, NULL);
7240
7241    if (pd->properties.view_lookup) eina_hash_free(pd->properties.view_lookup);
7242    pd->properties.view_lookup = NULL;
7243    if (pd->properties.model_lookup) eina_hash_free(pd->properties.model_lookup);
7244    pd->properties.model_lookup = NULL;
7245 }
7246
7247 #include "efl_ui_widget_part_bg.eo.c"
7248
7249 EAPI void
7250 efl_ui_widget_internal_set(Eo *obj, Eina_Bool b)
7251 {
7252    ELM_WIDGET_DATA_GET(obj, pd);
7253    EINA_SAFETY_ON_NULL_RETURN(pd);
7254
7255    pd->internal = b;
7256 }
7257
7258 EAPI Eina_Bool
7259 efl_ui_widget_internal_get(Eo *obj)
7260 {
7261    ELM_WIDGET_DATA_GET(obj, pd);
7262    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
7263
7264    return pd->internal;
7265 }
7266
7267 /* Efl.Part Bg end */
7268
7269
7270 /* Internal EO APIs and hidden overrides */
7271
7272 EFL_FUNC_BODY_CONST(efl_ui_widget_default_content_part_get, const char *, NULL)
7273 EFL_FUNC_BODY_CONST(efl_ui_widget_default_text_part_get, const char *, NULL)
7274
7275 ELM_PART_CONTENT_DEFAULT_GET(efl_ui_widget, NULL)
7276 ELM_PART_TEXT_DEFAULT_GET(efl_ui_widget, NULL)
7277
7278 /***********************************************************************************
7279  * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *
7280  ***********************************************************************************/
7281 /* Internal EO APIs and hidden overrides */
7282 EAPI EFL_FUNC_BODYV(elm_widget_class_color_set, Eina_Bool, EINA_FALSE,
7283                     EFL_FUNC_CALL(color_class, r, g, b, a),
7284                     const char *color_class, int r, int g, int b, int a)
7285 EAPI EFL_FUNC_BODYV(elm_widget_class_color_get, Eina_Bool, EINA_FALSE,
7286                     EFL_FUNC_CALL(color_class, r, g, b, a),
7287                     const char *color_class, int *r, int *g, int *b, int *a)
7288 EAPI EFL_FUNC_BODYV(elm_widget_class_color2_set, Eina_Bool, EINA_FALSE,
7289                     EFL_FUNC_CALL(color_class, r, g, b, a),
7290                     const char *color_class, int r, int g, int b, int a)
7291 EAPI EFL_FUNC_BODYV(elm_widget_class_color2_get, Eina_Bool, EINA_FALSE,
7292                     EFL_FUNC_CALL(color_class, r, g, b, a),
7293                     const char *color_class, int *r, int *g, int *b, int *a)
7294 EAPI EFL_FUNC_BODYV(elm_widget_class_color3_set, Eina_Bool, EINA_FALSE,
7295                     EFL_FUNC_CALL(color_class, r, g, b, a),
7296                     const char *color_class, int r, int g, int b, int a)
7297 EAPI EFL_FUNC_BODYV(elm_widget_class_color3_get, Eina_Bool, EINA_FALSE,
7298                     EFL_FUNC_CALL(color_class, r, g, b, a),
7299                     const char *color_class, int *r, int *g, int *b, int *a)
7300 EAPI EFL_VOID_FUNC_BODYV(elm_widget_class_color_del,
7301                          EFL_FUNC_CALL(color_class),
7302                          const char *color_class)
7303 EAPI EFL_VOID_FUNC_BODY(elm_widget_class_color_clear)
7304
7305 static Eina_Bool _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);
7306 static Eina_Bool _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);
7307 static Eina_Bool _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);
7308 static Eina_Bool _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);
7309 static Eina_Bool _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);
7310 static Eina_Bool _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);
7311 static void _elm_widget_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *color_class);
7312 static void _elm_widget_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd);
7313 /*******
7314  * END *
7315  *******/
7316
7317
7318 #define EFL_UI_WIDGET_EXTRA_OPS \
7319    EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_widget), \
7320    ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_widget), \
7321    ELM_PART_TEXT_DEFAULT_OPS(efl_ui_widget), \
7322    EFL_OBJECT_OP_FUNC(efl_canvas_object_is_frame_object_set, _efl_ui_widget_efl_canvas_object_is_frame_object_set), \
7323    EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_ui_widget_efl_object_dbg_info_get), \
7324 /***********************************************************************************  \
7325  * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *  \
7326  ***********************************************************************************/ \
7327    EFL_OBJECT_OP_FUNC(elm_widget_class_color_set, _elm_widget_class_color_set), \
7328    EFL_OBJECT_OP_FUNC(elm_widget_class_color_get, _elm_widget_class_color_get), \
7329    EFL_OBJECT_OP_FUNC(elm_widget_class_color2_set, _elm_widget_class_color2_set), \
7330    EFL_OBJECT_OP_FUNC(elm_widget_class_color2_get, _elm_widget_class_color2_get), \
7331    EFL_OBJECT_OP_FUNC(elm_widget_class_color3_set, _elm_widget_class_color3_set), \
7332    EFL_OBJECT_OP_FUNC(elm_widget_class_color3_get, _elm_widget_class_color3_get), \
7333    EFL_OBJECT_OP_FUNC(elm_widget_class_color_del, _elm_widget_class_color_del), \
7334    EFL_OBJECT_OP_FUNC(elm_widget_class_color_clear, _elm_widget_class_color_clear)
7335
7336 /*******
7337  * END *
7338  *******/
7339
7340 // TIZEN_ONLY(20150709) : atspi relations api
7341 EOLIAN static Efl_Access_Relation_Set
7342 _efl_ui_widget_efl_access_object_relation_set_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7343 {
7344    return efl_access_relation_set_clone(&sd->atspi_custom_relations);
7345 }
7346 EOLIAN static Eina_Bool
7347 _efl_ui_widget_efl_access_object_relationship_append(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Access_Relation_Type type, const Eo *relation_obj)
7348 {
7349    return efl_access_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7350 }
7351
7352 EOLIAN static void
7353 _efl_ui_widget_efl_access_object_relationship_remove(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Access_Relation_Type type, const Eo *relation_obj)
7354 {
7355    efl_access_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7356 }
7357
7358 EOLIAN static void
7359 _efl_ui_widget_efl_access_object_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7360 {
7361    efl_access_relation_set_free(&sd->atspi_custom_relations);
7362    sd->atspi_custom_relations = NULL;
7363 }
7364
7365 EOLIAN static Elm_Atspi_Relation_Set
7366 _elm_widget_item_efl_access_object_relation_set_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
7367 {
7368    return efl_access_relation_set_clone(&sd->atspi_custom_relations);
7369 }
7370
7371 EOLIAN static Eina_Bool
7372 _elm_widget_item_efl_access_object_relationship_append(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, Efl_Access_Relation_Type type, const Eo *relation_obj)
7373 {
7374    return efl_access_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7375 }
7376
7377 EOLIAN static void
7378 _elm_widget_item_efl_access_object_relationship_remove(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, Efl_Access_Relation_Type type, const Eo *relation_obj)
7379 {
7380    efl_access_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7381 }
7382
7383 EOLIAN static void
7384 _elm_widget_item_efl_access_object_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
7385 {
7386    efl_access_relation_set_free(&sd->atspi_custom_relations);
7387    sd->atspi_custom_relations = NULL;
7388 }
7389 //////////////////////////////
7390
7391 //TIZEN_ONLY(20160726): add API elm_atspi_accessible_can_highlight_set/get
7392 static Eina_Bool
7393 _children_highlight_check(Eo *obj)
7394 {
7395    Eina_List *children, *l;
7396    Eo *child;
7397
7398    if (_elm_object_accessibility_currently_highlighted_get() == (void *)obj)
7399      {
7400         efl_access_component_highlight_clear(obj);
7401         return EINA_TRUE;
7402      }
7403
7404    children = efl_access_object_access_children_get(obj);
7405    EINA_LIST_FOREACH(children, l, child)
7406      {
7407         if (_children_highlight_check(child)) return EINA_TRUE;
7408      }
7409
7410    return EINA_FALSE;
7411 }
7412
7413 EOLIAN static void
7414 _efl_ui_widget_efl_access_object_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Eina_Bool can_highlight)
7415 {
7416    if (!can_highlight) _children_highlight_check(obj);
7417    _pd->can_highlight = !!can_highlight;
7418 }
7419
7420 EOLIAN static Eina_Bool
7421 _efl_ui_widget_efl_access_object_can_highlight_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7422 {
7423    return _elm_widget_highlightable(obj);
7424 }
7425
7426 EOLIAN static void
7427 _elm_widget_item_efl_access_object_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, Eina_Bool can_highlight)
7428 {
7429    if (!can_highlight) _children_highlight_check(obj);
7430    _pd->can_highlight = !!can_highlight;
7431 }
7432
7433 EOLIAN static Eina_Bool
7434 _elm_widget_item_efl_access_object_can_highlight_get(const Eo *obj, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7435 {
7436    return _elm_widget_item_highlightable((Eo *)obj);
7437 }
7438 //
7439
7440 // TIZEN_ONLY(20150705): Genlist item align feature
7441 EAPI void
7442 elm_widget_scroll_item_align_enabled_set(Evas_Object *obj,
7443                                         Eina_Bool scroll_item_align_enable)
7444 {
7445    API_ENTRY return;
7446    if (sd->scroll_item_align_enable == scroll_item_align_enable) return;
7447    sd->scroll_item_align_enable = scroll_item_align_enable;
7448 }
7449
7450 EAPI Eina_Bool
7451 elm_widget_scroll_item_align_enabled_get(const Evas_Object *obj)
7452 {
7453    API_ENTRY return EINA_FALSE;
7454    return sd->scroll_item_align_enable;
7455 }
7456
7457
7458 //TIZEN_ONLY(20150717) add widget name setter
7459 EOLIAN void
7460 _efl_ui_widget_efl_access_object_i18n_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *name)
7461 {
7462    //TIZEN_ONLY(20220826): Remove markup from accessible name
7463    char *text;
7464
7465    text = _elm_util_mkup_to_text(name); // NULL is OK
7466    eina_stringshare_replace(&_pd->name, text);
7467    free(text);
7468    //
7469 }
7470 //
7471
7472 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
7473 EOLIAN void
7474 _efl_ui_widget_efl_access_object_description_set(Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data* _pd, const char *description)
7475 {
7476    if (_pd->description)
7477      eina_stringshare_del(_pd->description);
7478
7479    _pd->description = eina_stringshare_add(description);
7480 }
7481
7482 EOLIAN static const char*
7483 _efl_ui_widget_efl_access_object_description_get(const Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *_pd EINA_UNUSED)
7484 {
7485    const char *ret = NULL;
7486    ret = efl_access_object_description_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
7487    if (ret) return ret;
7488
7489 #ifdef HAVE_GETTEXT
7490    if (_pd->atspi_translation_domain)
7491      return dgettext(_pd->atspi_translation_domain, _pd->description);
7492 #endif
7493    return _pd->description;
7494 }
7495 //
7496
7497 //TIZEN_ONLY(20171108): make atspi_proxy work
7498 static void
7499 _proxy_widget_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
7500 {
7501    Evas_Coord x, y;
7502    Eo *proxy = data;
7503
7504    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
7505    elm_atspi_bridge_utils_proxy_offset_set(proxy, x, y);
7506 }
7507
7508 static void
7509 _on_widget_del(void *data, const Efl_Event *event)
7510 {
7511    Eo *plug = data;
7512    evas_object_event_callback_del_full(event->object, EVAS_CALLBACK_MOVE,
7513                                        _proxy_widget_move_cb, plug);
7514    efl_access_object_attribute_del(event->object, "child_bus");
7515    efl_del(plug);
7516 }
7517
7518 static void
7519 _on_proxy_connected_cb(void *data, const Efl_Event *event)
7520 {
7521    Evas_Coord x, y;
7522    Evas_Object *widget = data;
7523
7524    evas_object_geometry_get(widget, &x, &y, NULL, NULL);
7525    elm_atspi_bridge_utils_proxy_offset_set(event->object, x, y);
7526
7527    evas_object_event_callback_add(widget, EVAS_CALLBACK_MOVE, _proxy_widget_move_cb, event->object);
7528 }
7529 //
7530
7531 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
7532 EOLIAN void
7533 _elm_widget_item_efl_access_object_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *description)
7534 {
7535    if (_pd->description)
7536      eina_stringshare_del(_pd->description);
7537
7538    _pd->description = eina_stringshare_add(description);
7539 }
7540
7541 EOLIAN const char*
7542 _elm_widget_item_efl_access_object_description_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7543 {
7544    const char *ret = NULL;
7545    ret = efl_access_object_description_get(efl_super(obj, ELM_WIDGET_ITEM_CLASS));
7546    if (ret) return ret;
7547
7548 #ifdef HAVE_GETTEXT
7549    if (_pd->atspi_translation_domain)
7550      return dgettext(_pd->atspi_translation_domain, _pd->description);
7551 #endif
7552    return _pd->description;
7553 }
7554 //
7555
7556 //TIZEN_ONLY(20150713) : add atspi name setter to widget_item
7557 EOLIAN void
7558 _elm_widget_item_efl_access_object_i18n_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *name)
7559 {
7560    //TIZEN_ONLY(20220826): Remove markup from accessible name
7561    char *text;
7562
7563    text = _elm_util_mkup_to_text(name); // NULL is OK
7564    eina_stringshare_replace(&_pd->name, text);
7565    free(text);
7566    //
7567 }
7568
7569 EOLIAN const char*
7570 _elm_widget_item_efl_access_object_i18n_name_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7571 {
7572    //TIZEN_ONLY(20190922): add name callback, description callback.
7573    const char *ret = NULL;
7574    ret = efl_access_object_i18n_name_get(efl_super(obj, ELM_WIDGET_ITEM_CLASS));
7575    if (ret) return ret;
7576    //
7577
7578    if (_pd->name)
7579      {
7580 #ifdef HAVE_GETTEXT
7581         if (_pd->atspi_translation_domain)
7582           return dgettext(_pd->atspi_translation_domain, _pd->name);
7583 #endif
7584         return _pd->name;
7585      }
7586
7587    return NULL;
7588 }
7589 ///
7590
7591 //TIZEN_ONLY(20150731) : add i18n support for name and description
7592 EOLIAN static void
7593 _efl_ui_widget_efl_access_object_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, const char *domain)
7594 {
7595    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7596 }
7597
7598 EOLIAN static const char*
7599 _efl_ui_widget_efl_access_object_translation_domain_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
7600 {
7601    return _pd->atspi_translation_domain;
7602 }
7603
7604 EOLIAN static void
7605 _elm_widget_item_efl_access_object_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, const char *domain)
7606 {
7607    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7608 }
7609
7610 EOLIAN static const char*
7611 _elm_widget_item_efl_access_object_translation_domain_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd)
7612 {
7613    return _pd->atspi_translation_domain;
7614 }
7615 ///
7616
7617 static int _sort_vertically(const void *data1, const void *data2)
7618 {
7619    Evas_Coord y1, y2;
7620    evas_object_geometry_get(data1, NULL, &y1, NULL, NULL);
7621    evas_object_geometry_get(data2, NULL, &y2, NULL, NULL);
7622
7623    return y1 < y2 ? -1 : 1;
7624 }
7625
7626 static int _sort_horizontally(const void *data1, const void *data2)
7627 {
7628    Evas_Coord x1, x2;
7629    evas_object_geometry_get(data1, &x1, NULL, NULL, NULL);
7630    evas_object_geometry_get(data2, &x2, NULL, NULL, NULL);
7631
7632    return x1 < x2 ? -1 : 1;
7633 }
7634
7635 static Eina_List *_lines_split(Eina_List *children)
7636 {
7637    Eo *c;
7638    Eina_List *lines, *line, *l;
7639    Evas_Coord yl, y, hl, h;
7640    lines = line = NULL;
7641
7642    if (!children) return NULL;
7643
7644    EINA_LIST_FOREACH(children, l, c)
7645      {
7646         evas_object_geometry_get(c, NULL, &yl, NULL, &hl);
7647
7648         /* remove child if its height == 0 */
7649         if (hl != 0) break;
7650      }
7651
7652    EINA_LIST_FREE(children, c)
7653      {
7654         evas_object_geometry_get(c, NULL, &y, NULL, &h);
7655
7656         /* remove child if its height == 0 */
7657         if (h == 0) continue;
7658
7659         if ((yl + (int)(0.25 * hl)) >= y)
7660           {
7661              //same line
7662              line = eina_list_append(line,c);
7663           }
7664         else
7665           {
7666              // finish current line & start new
7667              lines = eina_list_append(lines, line);
7668              yl = y, hl = h;
7669              line = eina_list_append(NULL, c);
7670           }
7671      }
7672
7673    return eina_list_append(lines, line);
7674 }
7675 //
7676
7677 //TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
7678 Eo *
7679 plug_type_proxy_get(const Eo *obj, Evas_Object *widget)
7680 {
7681    Eo *proxy = NULL;
7682    const char *plug_id;
7683    char *svcname, *svcnum;
7684
7685    if ((plug_id = evas_object_data_get(widget, "___PLUGID")) != NULL)
7686      {
7687         // TIZEN_ONLY(20160930) : endless recursion fix
7688         efl_access_object_attribute_append(efl_super(obj, MY_CLASS), "___PlugID", plug_id);
7689         efl_access_object_role_set((Eo *)obj, EFL_ACCESS_ROLE_EMBEDDED);
7690
7691         proxy = evas_object_data_get(widget, "__widget_proxy");
7692         // TIZEN_ONLY(20171109) : fix for invalid proxy object, when at-spi has been restarted
7693         if (proxy)
7694           {
7695             if (!evas_object_data_get(proxy, "__proxy_invalid")) return proxy;
7696             evas_object_data_del(widget, "__widget_proxy");
7697           }
7698         //
7699
7700         if (_elm_atspi_bridge_plug_id_split(plug_id, &svcname, &svcnum))
7701           {
7702              proxy = _elm_atspi_bridge_utils_proxy_create((Eo *)obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
7703              evas_object_data_set(widget, "__widget_proxy", proxy);
7704              efl_event_callback_add(widget, EFL_EVENT_DEL, _on_widget_del, proxy);
7705              efl_event_callback_add(proxy, ELM_ATSPI_PROXY_EVENT_CONNECTED, _on_proxy_connected_cb, widget);
7706              elm_atspi_bridge_utils_proxy_connect(proxy);
7707              free(svcname);
7708              free(svcnum);
7709           }
7710      }
7711
7712    return proxy;
7713 }
7714
7715 EAPI Eo *
7716 elm_widget_atspi_plug_type_proxy_get(Evas_Object *obj)
7717 {
7718    Elm_Widget_Smart_Data *wd;
7719    Evas_Object *widget;
7720
7721    wd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
7722    if (!wd) return NULL;
7723
7724    Eo *proxy = NULL;
7725    for (unsigned int i = 0; i < eina_array_count(wd->children); ++i)
7726      {
7727         widget = eina_array_data_get(wd->children, i);
7728         proxy = plug_type_proxy_get(obj, widget);
7729         if (proxy) break;
7730      }
7731    return proxy;
7732 }
7733 //
7734
7735
7736 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
7737 EAPI Eina_Bool
7738 _elm_widget_highlightable(const Evas_Object *obj)
7739 {
7740    Eo *parent;
7741
7742    Elm_Widget_Smart_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
7743    if (!wd) return EINA_FALSE;
7744    if (!wd->can_highlight) return EINA_FALSE;
7745
7746    parent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
7747    while (parent && !efl_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
7748      {
7749         //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
7750         if (!_elm_widget_can_highlight_get_by_class(parent)) return EINA_FALSE;
7751         //
7752         parent = efl_provider_find(efl_parent_get(parent), EFL_ACCESS_OBJECT_MIXIN);
7753      }
7754    return EINA_TRUE;
7755 }
7756 //
7757
7758 EAPI void
7759 elm_widget_scroll_item_valign_set(Evas_Object *obj,
7760                                   const char *scroll_item_valign)
7761 {
7762    API_ENTRY return;
7763    if (sd->scroll_item_valign) eina_stringshare_del(sd->scroll_item_valign);
7764    if (!scroll_item_valign) sd->scroll_item_valign = NULL;
7765    else sd->scroll_item_valign = eina_stringshare_add(scroll_item_valign);
7766 }
7767
7768 EAPI const char*
7769 elm_widget_scroll_item_valign_get(const Evas_Object *obj)
7770 {
7771    API_ENTRY return NULL;
7772    return sd->scroll_item_valign;
7773 }
7774 //
7775
7776 /* TIZEN_ONLY(20180504): add missing item class names and fix edje_class parse rule for legacy */
7777 const char *
7778 _elm_widget_item_legacy_type_get(const Evas_Object *obj)
7779 {
7780    const char *ret;
7781    int i;
7782
7783    ret = efl_class_name_get(efl_class_get(obj));
7784
7785    /* If the given widget is created for legacy,
7786     * convert type name to legacy. */
7787    for (i = 0; legacy_type_table[i][0] ; i++)
7788      {
7789         if (eina_streq(ret, legacy_type_table[i][0]))
7790           return legacy_type_table[i][1];
7791      }
7792
7793    return ret;
7794 }
7795 /* END */
7796
7797 EOLIAN static void
7798 _efl_ui_widget_focus_disabled_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7799 {
7800    efl_ui_widget_focus_tree_unfocusable_handle(obj);
7801 }
7802
7803 EOLIAN static unsigned int
7804 _efl_ui_widget_focus_order_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7805 {
7806    return sd->focus_order;
7807 }
7808
7809 EOLIAN static Evas_Object*
7810 _efl_ui_widget_newest_focus_order_get(const Eo *obj, Elm_Widget_Smart_Data *sd, unsigned int *newest_focus_order, Eina_Bool can_focus_only)
7811 {
7812    Evas_Object *child, *cur, *best;
7813
7814    if (!evas_object_visible_get(obj)
7815        || (elm_widget_disabled_get(obj))
7816        || (elm_widget_tree_unfocusable_get(obj)))
7817      return NULL;
7818
7819    best = NULL;
7820    if (*newest_focus_order < sd->focus_order)
7821      {
7822         if (!can_focus_only || elm_widget_can_focus_get(obj))
7823           {
7824              *newest_focus_order = sd->focus_order;
7825              best = (Evas_Object *)obj;
7826           }
7827      }
7828    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
7829      {
7830         child = eina_array_data_get(sd->children, i);
7831         if (!_elm_widget_is(child)) continue;
7832
7833         cur = efl_ui_widget_newest_focus_order_get
7834            (child, newest_focus_order, can_focus_only);
7835         if (!cur) continue;
7836         best = cur;
7837      }
7838    return best;
7839 }
7840
7841 EOLIAN static Eina_Bool
7842 _efl_ui_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7843 {
7844    WRN("The %s widget does not implement the \"focus_next/focus_next_manager_is\" functions.",
7845        efl_class_name_get(efl_class_get(obj)));
7846    return EINA_FALSE;
7847 }
7848
7849 static Eina_Bool
7850 _efl_ui_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7851 {
7852    WRN("The %s widget does not implement the \"focus_direction/focus_direction_manager_is\" functions.",
7853        efl_class_name_get(efl_class_get(obj)));
7854    return EINA_FALSE;
7855 }
7856 //
7857 //TIZEN_ONLY(20180607): Restore legacy focus
7858 EOLIAN static void
7859 _efl_ui_widget_focus_mouse_up_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7860 {
7861    if (!obj) return;
7862    if (!_is_focusable(obj)) return;
7863
7864    efl_ui_widget_focus_steal(obj, NULL);
7865 }
7866
7867 //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
7868 static Eina_Bool
7869 _elm_widget_can_highlight_get_by_class(Eo *obj)
7870 {
7871    if (efl_isa(obj, ELM_WIDGET_ITEM_CLASS))
7872      {
7873         Elm_Widget_Item_Data *id = efl_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
7874         if (!id) return EINA_FALSE;
7875         if (!id->can_highlight) return EINA_FALSE;
7876      }
7877    else
7878      {
7879         Elm_Widget_Smart_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
7880         if (!wd) return EINA_FALSE;
7881         if (!wd->can_highlight) return EINA_FALSE;
7882      }
7883    return EINA_TRUE;
7884 }
7885 //
7886
7887 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
7888 EAPI Eina_Bool
7889 _elm_widget_item_highlightable(Elm_Object_Item *item)
7890 {
7891    Eo *parent;
7892
7893    Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
7894    if (!id) return EINA_FALSE;
7895    if (!id->can_highlight) return EINA_FALSE;
7896
7897    parent = efl_provider_find(efl_parent_get(item), EFL_ACCESS_OBJECT_MIXIN);
7898    while (parent && !efl_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
7899      {
7900         //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
7901         if (!_elm_widget_can_highlight_get_by_class(parent)) return EINA_FALSE;
7902         //
7903         parent = efl_provider_find(efl_parent_get(parent), EFL_ACCESS_OBJECT_MIXIN);
7904      }
7905    return EINA_TRUE;
7906 }
7907 //
7908
7909 //TIZEN_ONLY(20170206): Add check the object is in the scroller content size
7910 static Eina_Bool
7911 _accessible_object_on_scroll_is(Eo* obj)
7912 {
7913    /* in case of genlist item, the item->view is NULL if item is unrealized.
7914       this function is used to check if obj could have HIGHLIGHTABLE or not.
7915       the unrealized genlist item should have HIGHLIGHTABLE state.
7916       so if obj is NULL return EINA_TRUE */
7917    if(!obj) return EINA_TRUE;
7918
7919    Evas_Object *target = obj;
7920    Evas_Object *parent = NULL;
7921    Evas_Coord x, y, w, h, wx, wy, ww = 0, wh = 0, nx = 0, ny = 0;
7922
7923    evas_object_geometry_get(target, &x, &y ,&w, &h);
7924
7925    if (elm_widget_is(target))
7926      parent = elm_widget_parent_get(target);
7927    else
7928      parent = elm_widget_parent_widget_get(target);
7929
7930    while (parent)
7931      {
7932         if (efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
7933           {
7934              evas_object_geometry_get(parent, &wx, &wy, NULL, NULL);
7935              elm_interface_scrollable_content_size_get(parent, &ww, &wh);
7936              elm_interface_scrollable_content_pos_get(parent, &nx, &ny);
7937
7938              /* widget implements scrollable interface but does not use scoller
7939                 in this case, use widget geometry */
7940              if (ww == 0 || wh == 0)
7941                {
7942                   INF("%s is zero sized scrollable content", efl_class_name_get(efl_class_get(parent)));
7943                   evas_object_geometry_get(parent, NULL, NULL, &ww, &wh);
7944                }
7945
7946              wx -= nx;
7947              wy -= ny;
7948
7949              if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
7950                  ((wy < y) && (wy + wh < y)) || ((wy > y + h) && (wy + wh > y + h)))
7951                return EINA_FALSE;
7952
7953              break;
7954           }
7955         parent = elm_widget_parent_get(parent);
7956      }
7957
7958    return EINA_TRUE;
7959 }
7960 //
7961
7962 //TIZEN_ONLY(20180607): Restore legacy focus
7963 /**
7964  * @internal
7965  *
7966  * Resets the focus_move_policy mode from the system one
7967  * for widgets that are in automatic mode.
7968  *
7969  * @param obj The widget.
7970  *
7971  */
7972 static void
7973 _elm_widget_focus_move_policy_reload(Evas_Object *obj)
7974 {
7975    API_ENTRY return;
7976    Elm_Focus_Move_Policy focus_move_policy = elm_config_focus_move_policy_get();
7977
7978    if (efl_ui_widget_focus_move_policy_automatic_get(obj) &&
7979        (sd->focus_move_policy != focus_move_policy))
7980      {
7981         sd->focus_move_policy = focus_move_policy;
7982      }
7983 }
7984
7985 EOLIAN static void
7986 _efl_ui_widget_focus_reconfigure(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7987 {
7988    Evas_Object *child;
7989    API_ENTRY return;
7990
7991    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
7992      {
7993         child = eina_array_data_get(sd->children, i);
7994         if (elm_widget_is(child))
7995           efl_ui_widget_focus_reconfigure(child);
7996      }
7997
7998    if (sd->hover_obj) efl_ui_widget_focus_reconfigure(sd->hover_obj);
7999
8000    _elm_widget_focus_move_policy_reload(obj);
8001 }
8002 //
8003
8004 //TIZEN_ONLY(20160329): widget: improve accessible_at_point getter (a8aff0423202b9a55dbb3843205875226678fbd6)
8005 static void
8006 _coordinate_system_based_point_translate(const Eo *obj, Eina_Bool screen_coords, int *x, int *y)
8007 {
8008    Ecore_Evas *ee;
8009    int ee_x = 0;
8010    int ee_y = 0;
8011
8012    if (screen_coords)
8013      {
8014         ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
8015         if (!ee) return;
8016
8017         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
8018         *x -= ee_x;
8019         *y -= ee_y;
8020      }
8021 }
8022
8023 static Evas_Object *
8024 _parent_get(Evas_Object *obj)
8025 {
8026    Evas_Object *parent;
8027
8028    parent = evas_object_smart_parent_get(obj);
8029    if (!parent)
8030      {
8031         if (strcmp("Efl_Ui_Win", efl_class_name_get(efl_class_get(obj))))
8032           parent = elm_widget_parent_get(obj);
8033      }
8034
8035    return parent;
8036 }
8037
8038 static Eina_Bool
8039 _is_inside(Evas_Object *obj, int x, int y)
8040 {
8041    Eina_Bool ret = EINA_TRUE;
8042    Evas_Coord cx = 0;
8043    Evas_Coord cy = 0;
8044    Evas_Coord cw = 0;
8045    Evas_Coord ch = 0;
8046    if (efl_isa(obj, ELM_WIDGET_ITEM_CLASS))
8047      {
8048         Elm_Widget_Item_Data *id = efl_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
8049         evas_object_geometry_get(id->view, &cx, &cy, &cw, &ch);
8050      }
8051    else
8052      evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
8053
8054    /* check the point is out of bound */
8055    if (x < cx || x > cx + cw || y < cy || y > cy + ch)
8056      {
8057         ret = EINA_FALSE;
8058      }
8059    return ret;
8060 }
8061
8062 static Eina_Bool
8063 _is_ancestor_of(Evas_Object *smart_parent, const Evas_Object *obj)
8064 {
8065    Eina_Bool ret = EINA_FALSE;
8066    Evas_Object *parent = elm_widget_parent_get(obj);
8067    while (parent)
8068      {
8069         /* No need to check more, the smart_parent is parent of obj */
8070         if (smart_parent == parent)
8071           {
8072              ret = EINA_TRUE;
8073              break;
8074           }
8075         parent = elm_widget_parent_get(parent);
8076      }
8077
8078    return ret;
8079 }
8080
8081 static Eina_Bool
8082 _acceptable_child_is(Eo *obj)
8083 {
8084    Efl_Access_Role role;
8085    Eina_List *children;
8086    Efl_Access_State_Set ss;
8087
8088    role = efl_access_object_role_get(obj);
8089    switch (role)
8090      {
8091        case EFL_ACCESS_ROLE_IMAGE:
8092        case EFL_ACCESS_ROLE_ICON:
8093        case EFL_ACCESS_ROLE_REDUNDANT_OBJECT:
8094        /* remove unacceptable leaf node */
8095          children = efl_access_object_access_children_get(obj);
8096          if (!children) return EINA_FALSE;
8097          break;
8098
8099        case EFL_ACCESS_ROLE_PANEL:
8100          /* remove closed panel fron children list */
8101          ss = efl_access_object_state_set_get(obj);
8102          if (!STATE_TYPE_GET(ss, EFL_ACCESS_STATE_TYPE_SHOWING)) return EINA_FALSE;
8103          break;
8104
8105        default:
8106          break;
8107      }
8108
8109    return EINA_TRUE;
8110 }
8111
8112 static int _sort_by_size(const void *data1, const void *data2)
8113 {
8114    Evas_Coord w, h;
8115    Evas_Coord w2, h2;
8116
8117    evas_object_geometry_get(data1, NULL, NULL, &w, &h);
8118    evas_object_geometry_get(data2, NULL, NULL, &w2, &h2);
8119
8120    if ((w * h) > (w2 * h2)) return 1;
8121    return -1;
8122 }
8123
8124 Eina_Bool
8125 _elm_widget_atspi_role_acceptable_check(Eo *obj)
8126 {
8127    Efl_Access_Role role;
8128    role = efl_access_object_role_get(obj);
8129
8130    switch (role)
8131      {
8132        case EFL_ACCESS_ROLE_APPLICATION:
8133        case EFL_ACCESS_ROLE_FILLER:
8134        case EFL_ACCESS_ROLE_SCROLL_PANE:
8135        case EFL_ACCESS_ROLE_SPLIT_PANE:
8136        case EFL_ACCESS_ROLE_WINDOW:
8137        case EFL_ACCESS_ROLE_IMAGE:
8138        case EFL_ACCESS_ROLE_LIST:
8139        case EFL_ACCESS_ROLE_ICON:
8140        case EFL_ACCESS_ROLE_TOOL_BAR:
8141        case EFL_ACCESS_ROLE_REDUNDANT_OBJECT:
8142        case EFL_ACCESS_ROLE_COLOR_CHOOSER:
8143        case EFL_ACCESS_ROLE_TREE_TABLE:
8144        case EFL_ACCESS_ROLE_PAGE_TAB_LIST:
8145        case EFL_ACCESS_ROLE_PAGE_TAB:
8146        case EFL_ACCESS_ROLE_SPIN_BUTTON:
8147        case EFL_ACCESS_ROLE_INPUT_METHOD_WINDOW:
8148        case EFL_ACCESS_ROLE_EMBEDDED:
8149        case EFL_ACCESS_ROLE_INVALID:
8150        case EFL_ACCESS_ROLE_NOTIFICATION:
8151          return EINA_FALSE;
8152        default:
8153          break;
8154      }
8155
8156    return EINA_TRUE;
8157 }
8158
8159 static Eo *
8160 _child_object_at_point_get(const Eo *obj, int x, int y)
8161 {
8162    Eina_List *l, *l_next, *children, *valid_children = NULL;
8163    Eo *child;
8164    Eo *target;
8165    int count;
8166
8167    children = efl_access_object_access_children_get(obj);
8168
8169    EINA_LIST_FOREACH(children, l, child)
8170      {
8171         if (_is_inside(child, x, y))
8172           valid_children = eina_list_append(valid_children, child);
8173      }
8174
8175    EINA_LIST_FOREACH_SAFE(valid_children, l, l_next, child)
8176      {
8177         children = efl_access_object_access_children_get(child);
8178
8179         /* do not use unacceptable leaf node */
8180         if (!_elm_widget_atspi_role_acceptable_check(child) &&
8181             eina_list_count(children) == 0)
8182           valid_children = eina_list_remove_list(valid_children, l);
8183      }
8184
8185    count = eina_list_count(valid_children);
8186    if (count > 0)
8187      {
8188         valid_children = eina_list_sort(valid_children, -1, _sort_by_size);
8189         target = eina_list_nth(valid_children, 0);
8190
8191         //TIZEN_ONLY(20191209):Do not accept children with unacceptable role
8192         //return _child_object_at_point_get(target, x, y);
8193         Eo *ret = (Eo *)_child_object_at_point_get(target, x, y);
8194         if (ret) return ret;
8195         //
8196      }
8197
8198    //TIZEN_ONLY(20191209):Do not accept children with unacceptable role
8199    //return obj;
8200    return _elm_widget_atspi_role_acceptable_check((Eo *)obj) ? (Eo *)obj : NULL;
8201    //
8202 }
8203
8204
8205 static Eo *
8206 _accessible_at_point_top_down_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
8207 {
8208    Eina_List *l, *l2, *children, *valid_children = NULL;
8209    Eo *child;
8210    Evas_Object *stack_item;
8211    Eo *compare_obj;
8212    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
8213    Eo *proxy;
8214    Evas_Coord px, py, pw, ph;
8215    //
8216
8217    _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
8218
8219    children = efl_access_object_access_children_get(obj);
8220
8221    EINA_LIST_FOREACH(children, l2, child)
8222      {
8223         if (_is_inside(child, x, y) && _acceptable_child_is(child))
8224           valid_children = eina_list_append(valid_children, child);
8225      }
8226
8227    /* If there is only one valid child at point, then return it.
8228       The evas_tree_objects_at_xy_get could not find proper object,
8229       if application does not have well aligned objects. */
8230    if (eina_list_count(valid_children) == 1)
8231      {
8232         eina_list_free(children);
8233         child = eina_list_nth(valid_children, 0);
8234         return child;
8235      }
8236
8237    /* Get evas_object stacked at given x,y coordinates starting from top */
8238    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
8239    /* Foreach stacked object starting from top */
8240    EINA_LIST_FOREACH(stack, l, stack_item)
8241      {
8242         /* Foreach at-spi valid children traverse stack_item evas_objects hierarchy */
8243         EINA_LIST_FOREACH(valid_children, l2, child)
8244           {
8245              Efl_Access_Role role;
8246              role = efl_access_object_role_get(child);
8247              if (role == EFL_ACCESS_ROLE_REDUNDANT_OBJECT)
8248                {
8249                   /* The redundant object ignores */
8250                   continue;
8251                }
8252              /* Compare object used to compare with stacked evas objects */
8253              compare_obj = child;
8254              /* In case of widget_items compare should be different then elm_widget_ item  object */
8255              if (efl_isa(child, ELM_WIDGET_ITEM_CLASS))
8256                {
8257                   Elm_Widget_Item_Data *id = efl_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
8258                   compare_obj = id->view;
8259                   if (TIZEN_PROFILE_WEARABLE)
8260                     {
8261                        Eo* it_view = evas_object_image_source_get(stack_item);
8262                        if (it_view && it_view == compare_obj)
8263                          {
8264                             eina_list_free(children);
8265                             eina_list_free(stack);
8266                             return child;
8267                          }
8268                     }
8269                }
8270              /* In case of access object compare should be 'wrapped' evas_object */
8271              if (efl_isa(child, ELM_ACCESS_CLASS))
8272                {
8273                    Elm_Access_Info *info = _elm_access_info_get(child);
8274                    if (!info) continue;
8275                    compare_obj = info->part_object;
8276                 }
8277              /* In case of widget is registerd by elm_access_object_register */
8278              Evas_Object *ao = elm_access_object_get(child);
8279              if (ao)
8280                {
8281                   eina_list_free(children);
8282                   eina_list_free(stack);
8283                   return ao;
8284                }
8285
8286              /* In case of ewk wrapper object compare with internal ewk_view evas_object */
8287              if (efl_isa(child, ELM_ATSPI_EWK_WRAPPER_CLASS))
8288                {
8289                   compare_obj = elm_atspi_ewk_wrapper_ewk_view_get(child);
8290                }
8291
8292              /* If spacial eo children do not have backing evas_object continue with search */
8293              if (!compare_obj)
8294                continue;
8295
8296              Evas_Object *smart_parent = stack_item;
8297              while (smart_parent)
8298                {
8299                    if (smart_parent == compare_obj)
8300                      {
8301                         eina_list_free(children);
8302                         eina_list_free(stack);
8303                         return child;
8304                      }
8305
8306                    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
8307                    proxy = evas_object_data_get(smart_parent, "__widget_proxy");
8308                    if (proxy)
8309                      {
8310                         // TIZEN_ONLY(20171109) : fix for invalid proxy object, when at-spi has been restarted
8311                         Eo *parent;
8312                         parent = efl_provider_find(efl_parent_get(smart_parent), EFL_ACCESS_OBJECT_MIXIN);
8313                         proxy = plug_type_proxy_get(parent, smart_parent);
8314                         //
8315                         evas_object_geometry_get(smart_parent, &px, &py, &pw, &ph);
8316                         if (x >= px && x <= px + pw && y >= py && y <= py +ph)
8317                           {
8318                              eina_list_free(children);
8319                              eina_list_free(stack);
8320                              return proxy;
8321                           }
8322                      }
8323                    //
8324
8325                    smart_parent = _parent_get(smart_parent);
8326                    if (_is_ancestor_of(smart_parent, obj)) break;
8327                }
8328           }
8329      }
8330
8331    eina_list_free(children);
8332    eina_list_free(stack);
8333    return NULL;
8334 }
8335
8336 static int _sort_by_repeat_events(const void *data1, const void *data2)
8337 {
8338    Evas_Object *ao1, *ao2;
8339    Eina_Bool repeat1, repeat2;
8340
8341    ao1 = elm_access_object_get(data1);
8342    ao2 = elm_access_object_get(data2);
8343
8344    repeat1 = evas_object_repeat_events_get(data1);
8345    repeat2 = evas_object_repeat_events_get(data2);
8346
8347    if (repeat1 != repeat2)
8348      {
8349         if (repeat1 && !ao1) return 1;
8350      }
8351    else
8352      {
8353         if (repeat1 && !ao1 && ao2) return 1;
8354      }
8355
8356    return -1;
8357 }
8358
8359 static Eo *_item_at_point_get(Evas_Object *obj, int x, int y)
8360 {
8361    Eo *child;
8362    Eina_List *l, *children;
8363
8364    children = efl_access_object_access_children_get(obj);
8365
8366    EINA_LIST_FOREACH(children, l, child)
8367      {
8368         if (_is_inside(child, x, y)) return child;
8369      }
8370
8371    ERR("No child at point (%d, %d) on object %p", x, y, obj);
8372    return NULL;
8373 }
8374
8375 //TIZEN_ONLY(20171108): bring HIGHLIGHT related changes
8376 EOLIAN static Eo *
8377 _efl_ui_widget_efl_access_component_accessible_at_point_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
8378 {
8379    Elm_Atspi_Role role;
8380    Eina_List *l;
8381    Evas_Object *stack_item;
8382
8383    role = efl_access_object_role_get(obj);
8384
8385    switch (role)
8386      {
8387       case ELM_ATSPI_ROLE_WINDOW:
8388         /* this is for webapp which is using window only */
8389         if (evas_object_data_get(obj, "__PlugID"))
8390           {
8391              Eina_List *children;
8392              Evas_Object *child;
8393              children = efl_access_object_access_children_get(obj);
8394              EINA_LIST_FOREACH(children, l, child)
8395                {
8396                   if (efl_access_object_role_get(child) == EFL_ACCESS_ROLE_EMBEDDED)
8397                     return child;
8398                }
8399           }
8400         DBG("Find accessible from bottom");
8401         break;
8402       case ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW:
8403       case ELM_ATSPI_ROLE_DIALOG:
8404       case ELM_ATSPI_ROLE_PAGE_TAB:
8405       //TIZEN_ONLY(20220915): Use top-down at-point search for POPUP_MENU
8406       //case ELM_ATSPI_ROLE_POPUP_MENU: // Bottom-up search would find buttons absent from the AT-SPI tree in case of CtxPopup
8407       //
8408       case ELM_ATSPI_ROLE_PANEL:
8409         DBG("Find accessible from bottom");
8410         break;
8411
8412       default:
8413         return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
8414      }
8415
8416    _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
8417
8418    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
8419    stack = eina_list_sort(stack, -1, _sort_by_repeat_events);
8420
8421    EINA_LIST_FOREACH(stack, l, stack_item)
8422      {
8423         Evas_Object *smart_parent = stack_item;
8424         while (smart_parent)
8425           {
8426              /* If parent equals to obj, it is not necessary to go upper.
8427                 So the top down logic would be better than NULL return. */
8428              if (smart_parent == obj)
8429                return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
8430
8431              Evas_Object *ao = elm_access_object_get(smart_parent);
8432              if (ao) return ao;
8433
8434              if (efl_isa(smart_parent, EFL_ACCESS_OBJECT_MIXIN))
8435                {
8436                   Eina_Bool acceptable = EINA_FALSE;
8437                   Eo *item_child;
8438                   role = efl_access_object_role_get(smart_parent);
8439                   switch (role)
8440                     {
8441                        case EFL_ACCESS_ROLE_FILLER: /* ex: View of colorselector item is layout */
8442                        case EFL_ACCESS_ROLE_ICON:
8443                        case EFL_ACCESS_ROLE_IMAGE:
8444                        case EFL_ACCESS_ROLE_REDUNDANT_OBJECT:
8445                        case EFL_ACCESS_ROLE_WINDOW:
8446                          DBG("Go for parent: %s (%p)\n", evas_object_type_get(smart_parent), smart_parent);
8447                          break;
8448                        case EFL_ACCESS_ROLE_LIST:
8449                            item_child = _item_at_point_get(smart_parent, x, y);
8450                            if (TIZEN_PROFILE_WEARABLE)
8451                              {
8452                                 item_child = _child_object_at_point_get(item_child, x, y);
8453                                 return item_child;
8454                              }
8455                            return item_child;
8456                          break;
8457                        default:
8458                          acceptable = EINA_TRUE;
8459                          break;
8460                     }
8461
8462                   if (acceptable) return smart_parent;
8463                }
8464
8465              smart_parent = _parent_get(smart_parent);
8466           }
8467      }
8468
8469    eina_list_free(stack);
8470    return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
8471 }
8472 // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
8473 // EOLIAN static Eina_Bool
8474 // _elm_widget_item_efl_access_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
8475 // {
8476 //    Evas_Object *win = elm_widget_top_get(sd->widget);
8477 //    if (win && efl_isa(win, EFL_UI_WIN_CLASS))
8478 //      {
8479 //         _elm_win_accessibility_highlight_set(win, sd->view);
8480 //         efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8481 //         return EINA_TRUE;
8482 //      }
8483 //    return EINA_FALSE;
8484 // }
8485 //
8486 //
8487 // EOLIAN static Eina_Bool
8488 // _elm_widget_item_efl_access_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
8489 // {
8490 //    Evas_Object *win = elm_widget_top_get(sd->widget);
8491 //    if (win && efl_isa(win, EFL_UI_WIN_CLASS))
8492 //      {
8493 //         if (_elm_win_accessibility_highlight_get(win) != sd->view)
8494 //           return EINA_TRUE;
8495 //
8496 //         _elm_win_accessibility_highlight_set(win, NULL);
8497 //         efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_FALSE);
8498 //         return EINA_TRUE;
8499 //      }
8500 //    return EINA_FALSE;
8501 // }
8502 //
8503
8504 //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
8505 void
8506 _elm_widget_showing_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
8507 {
8508    Evas_Object *parent;
8509    Evas_Coord px, py, sx, sy, sw, sh;
8510
8511    *x = 0;
8512    *y = 0;
8513    *w = 0;
8514    *h = 0;
8515    if (!obj) return;
8516
8517    evas_object_geometry_get(obj, x, y, w, h);
8518
8519    if (elm_widget_is(obj))
8520      parent = elm_widget_parent_get(obj);
8521    else
8522      parent = elm_widget_parent_widget_get(obj);
8523
8524    while (parent)
8525      {
8526         if (efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
8527           {
8528              evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
8529              px = *x;
8530              py = *y;
8531              *x = *x > sx ? *x : sx;
8532              *y = *y > sy ? *y : sy;
8533              *w = px + *w < sx + sw ? px + *w - *x : sx + sw - *x;
8534              *h = py + *h < sy + sh ? py + *h - *y : sy + sh - *y;
8535           }
8536         parent = elm_widget_parent_get(parent);
8537      }
8538 }
8539
8540 Eina_Bool
8541 _accessible_object_on_screen_is(Eo *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool is_complete)
8542 {
8543    if(!obj) return EINA_FALSE;
8544
8545    Evas_Object *target = obj;
8546    Evas_Object *parent = NULL;
8547    Evas_Coord px, py, sx, sy, sw, sh, ox, oy, ow, oh;
8548
8549    /* uninitialized data could be read */
8550    ow = 0;
8551    oh = 0;
8552
8553    if (elm_widget_is(target))
8554      parent = elm_widget_parent_get(target);
8555    else
8556      parent = elm_widget_parent_widget_get(target);
8557
8558    while (parent)
8559      {
8560         if (efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
8561           {
8562              evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
8563              px = ox = x;
8564              py = oy = y;
8565              ow = w;
8566              oh = h;
8567              ox = is_complete ? ox : ox + ow;
8568              oy = is_complete ? oy : oy + oh;
8569              ox = ox > sx ? ox : sx;
8570              oy = oy > sy ? oy : sy;
8571              ow = px + ow < sx + sw ? px + ow - ox : sx + sw - ox;
8572              oh = py + oh < sy + sh ? py + oh - oy : sy + sh - oy;
8573           }
8574         if (ow <= 0 || oh <= 0)
8575           return EINA_FALSE;
8576
8577         parent = elm_widget_parent_get(parent);
8578      }
8579    return EINA_TRUE;
8580 }
8581
8582 Eina_List *
8583 _accessible_scrollable_parent_list_get(const Eo *obj)
8584 {
8585    if(!obj) return NULL;
8586
8587    Evas_Object *parent = NULL;
8588    Eina_List *plist = NULL;
8589
8590    if (elm_widget_is(obj))
8591      parent = elm_widget_parent_get(obj);
8592    else
8593      parent = elm_widget_parent_widget_get(obj);
8594
8595    while (parent)
8596      {
8597         if (_elm_scrollable_is(parent))
8598           plist = eina_list_append(plist, parent);
8599
8600         parent = elm_widget_parent_get(parent);
8601    }
8602    return plist;
8603 }
8604
8605 void
8606 _accessible_highlight_region_show(Eo* obj)
8607 {
8608    if (!obj) return ;
8609
8610    Evas_Object *target = obj;
8611    Evas_Object *parent = NULL;
8612    Evas_Object *parent_sub = NULL;
8613    Eina_List *plist, *plist_sub;
8614    Eina_List *l, *l2;
8615
8616    Evas_Coord target_x, target_y, target_w, target_h;
8617
8618    evas_object_geometry_get(target, &target_x, &target_y, &target_w, &target_h);
8619
8620    plist = _accessible_scrollable_parent_list_get(target);
8621    if (!plist) return ;
8622    EINA_LIST_FOREACH(plist, l, parent)
8623      {
8624         if(!_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_TRUE))
8625           {
8626              plist_sub = _accessible_scrollable_parent_list_get(parent);
8627              plist_sub = eina_list_prepend(plist_sub, parent);
8628              EINA_LIST_FOREACH(plist_sub, l2, parent_sub)
8629                {
8630                   Evas_Coord scroll_x = 0, scroll_y = 0;
8631                   Evas_Coord scroll_x_back = 0, scroll_y_back = 0;
8632                   Evas_Coord x, y, w, h;
8633                   Evas_Coord px, py;
8634
8635                   elm_interface_scrollable_content_region_get(parent_sub, &scroll_x_back, &scroll_y_back, NULL, NULL);
8636                   evas_object_geometry_get(parent_sub, &px, &py, NULL, NULL);
8637                   x = target_x; y = target_y; w = target_w; h = target_h;
8638
8639                   x -= (px - scroll_x_back);
8640                   y -= (py - scroll_y_back);
8641                   switch (_elm_config->focus_autoscroll_mode)
8642                     {
8643                        case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
8644                           elm_interface_scrollable_content_region_show(parent_sub, x, y, w, h);
8645                           break;
8646                        case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
8647                           elm_interface_scrollable_region_bring_in(parent_sub, x, y, w, h);
8648                           break;
8649                        default:
8650                           break;
8651                     }
8652                   elm_interface_scrollable_content_region_get(parent_sub, &scroll_x, &scroll_y, NULL, NULL);
8653
8654                   target_x -= (scroll_x - scroll_x_back);
8655                   target_y -= (scroll_y - scroll_y_back);
8656
8657                   if(_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_FALSE))
8658                     break;
8659                }
8660              eina_list_free(plist_sub);
8661           }
8662      }
8663
8664    eina_list_free(plist);
8665 }
8666 //
8667
8668 //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8669 static Eo *_highlight_grabbing_object = NULL;
8670
8671 Eina_Bool
8672 _elm_widget_accessibility_highlight_grabbing_get(Eo *obj)
8673 {
8674   return _highlight_grabbing_object == obj;
8675 }
8676
8677 void
8678 _elm_widget_accessibility_highlight_grabbing_set(Eo *obj, Eina_Bool grabbing)
8679 {
8680    if (grabbing)
8681      {
8682        if (!_highlight_grabbing_object)
8683            _highlight_grabbing_object = obj;
8684        else if (_highlight_grabbing_object == obj)
8685            ERR("trying to set grabbing for %p, but it's already set to this object", obj);
8686        else
8687            ERR("trying to set grabbing for %p, but it's already set to %p", obj, _highlight_grabbing_object);
8688      }
8689    else
8690      {
8691        if (_highlight_grabbing_object != obj)
8692            ERR("trying to clear grabbing for %p, but it's set to %p", obj, _highlight_grabbing_object);
8693        else
8694            _highlight_grabbing_object = NULL;
8695      }
8696 }
8697 //
8698
8699 EOLIAN static Eina_Bool
8700 _efl_ui_widget_efl_access_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
8701 {
8702    if(!obj) return EINA_FALSE;
8703    if(!_elm_atspi_enabled())
8704       return EINA_FALSE;
8705
8706    // TIZEN_ONLY(20171020) : atspi : Do not send signal, if current object and highlight object are same
8707    if (_elm_object_accessibility_currently_highlighted_get() == obj)
8708       return EINA_FALSE;
8709    //
8710
8711    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8712    _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_TRUE);
8713    //
8714
8715    //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
8716    _accessible_highlight_region_show(obj);
8717    //
8718
8719    elm_object_accessibility_highlight_set(obj, EINA_TRUE);
8720    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8721
8722    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
8723    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_HIGHLIGHTED, NULL);
8724    //
8725
8726    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8727    _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_FALSE);
8728    //
8729    return EINA_TRUE;
8730 }
8731
8732 EOLIAN static Eina_Bool
8733 _efl_ui_widget_efl_access_component_highlight_clear(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
8734 {
8735    if (!obj) return EINA_FALSE;
8736    if (!_elm_atspi_enabled())
8737       return EINA_FALSE;
8738
8739    elm_object_accessibility_highlight_set(obj, EINA_FALSE);
8740    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_FALSE);
8741    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
8742    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, NULL);
8743    //
8744    return EINA_TRUE;
8745 }
8746 //
8747
8748 // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
8749 EOLIAN static Eina_Bool
8750 _elm_widget_item_efl_access_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
8751 {
8752    // TIZEN_ONLY(20171117) Accessibility Highlight frame support for items
8753    // Evas_Object *win = elm_widget_top_get(sd->widget);
8754    // if (win && efl_isa(win, EFL_UI_WIN_CLASS))
8755    //   {
8756    //      elm_object_accessibility_highlight_set(sd->view, EINA_TRUE);
8757    //      efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8758    //      return EINA_TRUE;
8759    //   }
8760    // return EINA_FALSE;
8761
8762    if (!sd) return EINA_FALSE;
8763    if (!sd->view) return EINA_FALSE;
8764    if (!_elm_atspi_enabled())
8765       return EINA_FALSE;
8766
8767    // TIZEN_ONLY(20171020) : atspi : Do not send signal, if current object and highlight object are same
8768    if (_elm_object_accessibility_currently_highlighted_get() == obj)
8769       return EINA_FALSE;
8770    //
8771
8772    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8773    _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_TRUE);
8774    //
8775
8776    //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
8777    _accessible_highlight_region_show(sd->view);
8778    //
8779
8780    if (!sd->eo_obj) return EINA_FALSE;
8781    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_TRUE);
8782
8783    if (!obj) return EINA_FALSE;
8784    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8785    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
8786    evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_HIGHLIGHTED, obj);
8787    //
8788
8789    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8790     _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_FALSE);
8791     //
8792
8793    return EINA_TRUE;
8794    //
8795 }
8796
8797 EOLIAN static Eina_Bool
8798 _elm_widget_item_efl_access_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
8799 {
8800    if (!obj) return EINA_FALSE;
8801    if (!_elm_atspi_enabled())
8802      return EINA_FALSE;
8803
8804    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_FALSE);
8805    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_FALSE);
8806    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
8807    evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, obj);
8808    //
8809    return EINA_TRUE;
8810 }
8811 //
8812
8813 //TIZEN_ONLY(20160527): widget: add AtspiAction interface to all widgets and widget_items, add handlers for reading stopped/cancelled
8814 EOLIAN const Efl_Access_Action_Data *
8815 _efl_ui_widget_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
8816 {
8817    return NULL;
8818 }
8819
8820 EOLIAN const Efl_Access_Action_Data *
8821 _elm_widget_item_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *pd EINA_UNUSED)
8822 {
8823    return NULL;
8824 }
8825
8826 /***********************************************************
8827  * TIZEN_ONLY(20180117): Override Paragraph Direction APIs *
8828  ***********************************************************/
8829 static void
8830 _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *sd, Efl_Text_Bidirectional_Type dir)
8831 {
8832    Evas_Object *child;
8833
8834    if (sd->on_destroy) return;
8835
8836    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
8837      {
8838         child = eina_array_data_get(sd->children, i);
8839         if (_elm_widget_is(child))
8840           {
8841              Efl_Ui_Widget_Data *sdc = efl_data_scope_get(child, MY_CLASS);
8842
8843              if (sdc->inherit_paragraph_direction &&
8844                  (sdc->paragraph_direction != dir))
8845                {
8846                   sdc->paragraph_direction = dir;
8847                   _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(child, sdc, dir);
8848                   efl_canvas_object_paragraph_direction_set(efl_super(child, MY_CLASS), dir);
8849                }
8850           }
8851
8852         /* FIXME: There is no way to handle non-widget child object.
8853          * If a non-widget child object has smart parent, it will get the direction
8854          * from the smart parent. */
8855      }
8856 }
8857
8858 EOLIAN static void
8859 _efl_ui_widget_efl_canvas_object_paragraph_direction_set(Eo *obj, Efl_Ui_Widget_Data *sd, Efl_Text_Bidirectional_Type dir)
8860 {
8861    if ((!(sd->inherit_paragraph_direction) && (sd->paragraph_direction == dir)) ||
8862        (sd->inherit_paragraph_direction && (dir == EFL_TEXT_BIDIRECTIONAL_TYPE_INHERIT)))
8863      return;
8864
8865    if (dir == EFL_TEXT_BIDIRECTIONAL_TYPE_INHERIT)
8866      {
8867         sd->inherit_paragraph_direction = EINA_TRUE;
8868         Evas_BiDi_Direction parent_dir = EFL_TEXT_BIDIRECTIONAL_TYPE_NEUTRAL;
8869
8870         if (sd->parent_obj)
8871           parent_dir = efl_canvas_object_paragraph_direction_get(sd->parent_obj);
8872
8873         if (parent_dir != sd->paragraph_direction)
8874           {
8875              sd->paragraph_direction = parent_dir;
8876              _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(obj, sd, parent_dir);
8877           }
8878      }
8879    else
8880      {
8881         sd->inherit_paragraph_direction = EINA_FALSE;
8882         sd->paragraph_direction = dir;
8883         _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(obj, sd, dir);
8884      }
8885
8886    efl_canvas_object_paragraph_direction_set(efl_super(obj, MY_CLASS), dir);
8887 }
8888 /*******
8889  * END *
8890  *******/
8891
8892 /***********************************************************************************
8893  * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *
8894  ***********************************************************************************/
8895 void
8896 _elm_widget_color_class_parent_set(Evas_Object *obj, Evas_Object *parent)
8897 {
8898    Evas_Object *edje = NULL, *parent_edje = NULL;
8899
8900    if (!obj || !parent) return;
8901
8902    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
8903      edje =  elm_layout_edje_get(obj);
8904    else if (efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))
8905      edje = obj;
8906
8907    if (efl_isa(parent, EFL_UI_LAYOUT_BASE_CLASS))
8908      parent_edje =  elm_layout_edje_get(parent);
8909    else if (efl_isa(parent, EFL_CANVAS_LAYOUT_CLASS))
8910      parent_edje = parent;
8911
8912    if (!edje || !parent_edje) return;
8913
8914    edje_object_color_class_parent_set(edje, parent_edje);
8915 }
8916
8917 void
8918 _elm_widget_color_class_parent_unset(Evas_Object *obj)
8919 {
8920    Evas_Object *edje = NULL;
8921
8922    if (!obj) return;
8923
8924    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
8925      edje =  elm_layout_edje_get(obj);
8926    else if (efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))
8927      edje = obj;
8928
8929    if (!edje) return;
8930
8931    edje_object_color_class_parent_unset(edje);
8932 }
8933
8934 void
8935 _edje_color_class_free(void *data)
8936 {
8937    Edje_Color_Class *cc = data;
8938
8939    if (cc->name) eina_stringshare_del(cc->name);
8940    free(cc);
8941 }
8942
8943 Eina_Stringshare *
8944 _elm_widget_edje_class_get(const Evas_Object *obj, const char *style, const char *part)
8945 {
8946    Eina_Strbuf *buf;
8947    Eina_Stringshare *str;
8948    const char *klass_name = NULL;
8949    Eina_Bool is_legacy = EINA_FALSE;
8950    Eina_Bool is_item = efl_isa(obj, ELM_WIDGET_ITEM_CLASS);
8951
8952    if (is_item)
8953      is_legacy = elm_widget_is_legacy(elm_object_item_widget_get(obj));
8954    else
8955      is_legacy = elm_widget_is_legacy(obj);
8956
8957    buf = eina_strbuf_new();
8958
8959    if (is_legacy)
8960      {
8961         if (is_item)
8962           klass_name = _elm_widget_item_legacy_type_get(obj);
8963         else
8964           klass_name = elm_widget_type_get(obj);
8965      }
8966    else
8967      {
8968         klass_name = efl_class_name_get(efl_class_get(obj));
8969      }
8970
8971    if (klass_name)
8972      {
8973         if (is_legacy && strchr(klass_name, '_'))
8974           {
8975              eina_strbuf_append(buf, strchr(klass_name, '_') + 1);
8976              eina_strbuf_tolower(buf);
8977           }
8978         else
8979           {
8980              /* Get the last word from the given klass name */
8981              char *temp, *temp_orig, *temp_ret, *last_ret = NULL;
8982              const char *delim = NULL;
8983
8984              temp_orig = temp = strdup(klass_name);
8985
8986              /* If "." is not used for word serperator,
8987               * it assume the given klass name is legacy.
8988               * And legacy klass name was made with "_" as its word seperator. */
8989              if (strchr(klass_name, '.'))
8990                delim = ".";
8991              else
8992                delim = "_";
8993
8994              while ((temp_ret = strsep(&temp, delim)) != NULL)
8995                {
8996                   if (strcmp(temp_ret, ""))
8997                     last_ret = temp_ret;
8998                }
8999
9000              if (last_ret)
9001                {
9002                   eina_strbuf_append(buf, last_ret);
9003                   eina_strbuf_tolower(buf);
9004                }
9005
9006              free(temp_orig);
9007           }
9008      }
9009
9010    if (style)
9011      {
9012         eina_strbuf_append_printf(buf, "/%s/%s", style, part);
9013      }
9014    else
9015      {
9016         eina_strbuf_append_printf(buf, "/%s", part);
9017      }
9018
9019    str = eina_stringshare_add(eina_strbuf_string_get(buf));
9020
9021    eina_strbuf_free(buf);
9022    return str;
9023 }
9024
9025 Eina_Bool
9026 _elm_widget_color_class_set_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
9027                                      int r, int g, int b, int a,
9028                                      int r2, int g2, int b2, int a2,
9029                                      int r3, int g3, int b3, int a3)
9030 {
9031    Eina_Bool int_ret = EINA_TRUE;
9032    Eina_Stringshare *buf;
9033    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9034    Edje_Color_Class *cc = NULL;
9035    API_ENTRY return EINA_FALSE;
9036    //
9037    int temp_color[3][4] = { { r,  g,  b,  a },
9038                             { r2, g2, b2, a2 },
9039                             { r3, g3, b3, a3 } };
9040
9041    if (!color_class) return EINA_FALSE;
9042
9043    buf = _elm_widget_edje_class_get(obj, NULL, color_class);
9044
9045 #define TEMP_COLOR(x, y) \
9046    ((temp_color[x][y] == -1) ? &temp_color[x][y] : NULL)
9047
9048    edje_object_color_class_get(edje, buf,
9049                                TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
9050                                TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
9051                                TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
9052
9053 #undef TEMP_COLOR
9054
9055 #define TEMP_COLOR(x, y) \
9056    ((temp_color[x][y] == -1) ? 0 : temp_color[x][y])
9057
9058    int_ret &= edje_object_color_class_set(edje, buf,
9059                                           TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
9060                                           TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
9061                                           TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
9062
9063 #undef TEMP_COLOR
9064
9065    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9066    if (int_ret)
9067      {
9068         if (!sd->color_classes)
9069           sd->color_classes = eina_hash_string_small_new(_edje_color_class_free);
9070         else
9071           cc = eina_hash_find(sd->color_classes, buf);
9072         if (!cc)
9073           {
9074              cc = calloc(1, sizeof(Edje_Color_Class));
9075              if (!cc) goto on_error;
9076              cc->name = eina_stringshare_add(buf);
9077              eina_hash_direct_add(sd->color_classes, cc->name, cc);
9078           }
9079         cc->r = r; cc->g = g; cc->b = b; cc->a = a;
9080         cc->r2 = r2; cc->g2 = g2; cc->b2 = b2; cc->a2 = a2;
9081         cc->r3 = r3; cc->g3 = g3; cc->b3 = b3; cc->a3 = a3;
9082      }
9083    //
9084
9085 on_error:
9086    eina_stringshare_del(buf);
9087
9088    return int_ret;
9089 }
9090
9091 Eina_Bool
9092 _elm_widget_color_class_get_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
9093                                      int *r, int *g, int *b, int *a,
9094                                      int *r2, int *g2, int *b2, int *a2,
9095                                      int *r3, int *g3, int *b3, int *a3)
9096 {
9097    Eina_Bool int_ret = EINA_TRUE;
9098    Eina_Stringshare *buf;
9099
9100    if (!color_class) return EINA_FALSE;
9101
9102    buf = _elm_widget_edje_class_get(obj, elm_widget_style_get(obj), color_class);
9103
9104    int_ret &= edje_object_color_class_get(edje, buf,
9105                                           r,  g,  b,  a,
9106                                           r2, g2, b2, a2,
9107                                           r3, g3, b3, a3);
9108
9109    eina_stringshare_del(buf);
9110
9111    return int_ret;
9112 }
9113
9114 /* Internal EO API */
9115 static Eina_Bool
9116 _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)
9117 {
9118    Evas_Object *edje;
9119    Eina_Bool int_ret = EINA_TRUE;
9120
9121    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9122
9123    edje = elm_layout_edje_get(obj);
9124    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
9125                                                    r, g, b, a,
9126                                                    -1, -1, -1, -1,
9127                                                    -1, -1, -1, -1);
9128
9129    return int_ret;
9130 }
9131
9132 /* Internal EO API */
9133 static Eina_Bool
9134 _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)
9135 {
9136    Evas_Object *edje;
9137    Eina_Bool int_ret = EINA_TRUE;
9138
9139    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9140
9141    edje = elm_layout_edje_get(obj);
9142    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
9143                                                    r, g, b, a,
9144                                                    NULL, NULL, NULL, NULL,
9145                                                    NULL, NULL, NULL, NULL);
9146
9147    return int_ret;
9148 }
9149
9150 /* Internal EO API */
9151 static Eina_Bool
9152 _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)
9153 {
9154    Evas_Object *edje;
9155    Eina_Bool int_ret = EINA_TRUE;
9156
9157    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9158
9159    edje = elm_layout_edje_get(obj);
9160    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
9161                                                    -1, -1, -1, -1,
9162                                                    r, g, b, a,
9163                                                    -1, -1, -1, -1);
9164
9165    return int_ret;
9166 }
9167
9168 /* Internal EO API */
9169 static Eina_Bool
9170 _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)
9171 {
9172    Evas_Object *edje;
9173    Eina_Bool int_ret = EINA_TRUE;
9174
9175    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9176
9177    edje = elm_layout_edje_get(obj);
9178    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
9179                                                    NULL, NULL, NULL, NULL,
9180                                                    r, g, b, a,
9181                                                    NULL, NULL, NULL, NULL);
9182
9183    return int_ret;
9184 }
9185
9186 /* Internal EO API */
9187 static Eina_Bool
9188 _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)
9189 {
9190    Evas_Object *edje;
9191    Eina_Bool int_ret = EINA_TRUE;
9192
9193    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9194
9195    edje = elm_layout_edje_get(obj);
9196    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
9197                                                    -1, -1, -1, -1,
9198                                                    -1, -1, -1, -1,
9199                                                    r, g, b, a);
9200
9201    return int_ret;
9202 }
9203
9204 /* Internal EO API */
9205 static Eina_Bool
9206 _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)
9207 {
9208    Evas_Object *edje;
9209    Eina_Bool int_ret = EINA_TRUE;
9210
9211    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9212
9213    edje = elm_layout_edje_get(obj);
9214    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
9215                                                    NULL, NULL, NULL, NULL,
9216                                                    NULL, NULL, NULL, NULL,
9217                                                    r, g, b, a);
9218
9219    return int_ret;
9220 }
9221
9222 /* Internal EO API */
9223 static void
9224 _elm_widget_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *color_class)
9225 {
9226    Eina_Stringshare *buf;
9227    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9228    Edje_Color_Class *cc = NULL;
9229    //
9230
9231    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return;
9232
9233    buf = _elm_widget_edje_class_get(obj, NULL, color_class);
9234    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9235    eina_hash_del(sd->color_classes, buf, cc);
9236    //
9237    edje_object_color_class_del(sd->resize_obj, buf);
9238    eina_stringshare_del(buf);
9239 }
9240
9241 /* Internal EO API */
9242 static void
9243 _elm_widget_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
9244 {
9245    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return;
9246    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9247    ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
9248    //
9249    edje_object_color_class_clear(sd->resize_obj);
9250 }
9251
9252 #define ELM_COLOR_CLASS_UPDATE(obj, hash, cond)                                  \
9253    Evas_Object *edje = NULL;                                                     \
9254    Eina_Iterator *itr;                                                           \
9255    Edje_Color_Class *cc;                                                         \
9256    Eina_Bool int_ret = EINA_TRUE;                                                \
9257    if (cond) return EINA_FALSE;                                                  \
9258    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))                                            \
9259      edje =  elm_layout_edje_get(obj);                                           \
9260    else if (efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))                                      \
9261      edje = obj;                                                                 \
9262    if (!edje) return EINA_FALSE;                                                 \
9263    itr = eina_hash_iterator_data_new(hash);                                      \
9264    EINA_ITERATOR_FOREACH(itr, cc)                                                \
9265      {                                                                           \
9266         int_ret &= edje_object_color_class_set(edje, cc->name,                   \
9267                                                cc->r, cc->g, cc->b, cc->a,       \
9268                                                cc->r2, cc->g2, cc->b2, cc->a2,   \
9269                                                cc->r3, cc->g3, cc->b3, cc->a3);  \
9270      }                                                                           \
9271    eina_iterator_free(itr);                                                      \
9272    return int_ret
9273
9274 static Eina_Bool
9275 _elm_widget_color_class_update(Eo *obj, Elm_Widget_Smart_Data *sd)
9276 {
9277    ELM_COLOR_CLASS_UPDATE(obj, sd->color_classes, (!sd) || (!sd->color_classes) || (!obj));
9278 }
9279
9280 #define CHECK_BOUND(x)                                                           \
9281    if (x > 0xff) x = 0xff;                                                       \
9282    else if (x < 0) x = 0
9283
9284 #define ELM_COLOR_CLASS_SET_START(obj, cr, cg, cb, ca)                           \
9285    Eina_Bool int_ret = EINA_FALSE;                                               \
9286    Edje_Color_Class *cc = NULL;                                                  \
9287    Eina_Stringshare *buf;                                                        \
9288    buf = _elm_widget_edje_class_get(obj, NULL, color_class);       \
9289    CHECK_BOUND(r);                                                               \
9290    CHECK_BOUND(g);                                                               \
9291    CHECK_BOUND(b);                                                               \
9292    CHECK_BOUND(a);                                                               \
9293    _elm_color_unpremul(a, &r, &g, &b);                                           \
9294    if (!sd->color_classes)                                                       \
9295      sd->color_classes = eina_hash_string_small_new(_edje_color_class_free);     \
9296    else                                                                          \
9297      cc = eina_hash_find(sd->color_classes, buf);                                \
9298    if (!cc)                                                                      \
9299      {                                                                           \
9300         cc = calloc(1, sizeof(Edje_Color_Class));                                \
9301         cc->name = eina_stringshare_add(buf);                                    \
9302         if (!cc->name)                                                           \
9303           {                                                                      \
9304              free(cc);                                                           \
9305              eina_stringshare_del(buf);                                          \
9306              return EINA_FALSE;                                                  \
9307           }                                                                      \
9308         eina_hash_direct_add(sd->color_classes, cc->name, cc);                   \
9309      }                                                                           \
9310    else if ((cc->cr == r) && (cc->cg == g) &&                                    \
9311             (cc->cb == b) && (cc->ca == a))                                      \
9312      {                                                                           \
9313         eina_stringshare_del(buf);                                               \
9314         return EINA_TRUE;                                                        \
9315      }                                                                           \
9316    cc->cr = r;                                                                   \
9317    cc->cg = g;                                                                   \
9318    cc->cb = b;                                                                   \
9319    cc->ca = a;                                                                   \
9320    int_ret = EINA_TRUE
9321
9322 #define ELM_COLOR_CLASS_SET_END()                                                \
9323    eina_stringshare_del(buf);                                                    \
9324    return int_ret
9325
9326 #define ELM_COLOR_CLASS_GET(obj, cr, cg, cb, ca)                                 \
9327    Eina_Bool int_ret = EINA_FALSE;                                               \
9328    Edje_Color_Class *cc;                                                         \
9329    Eina_Stringshare *buf;                                                        \
9330    int alpha = 0;                                                                \
9331    buf = _elm_widget_edje_class_get(obj, NULL, color_class);       \
9332    if ((!sd->color_classes) || !(cc = eina_hash_find(sd->color_classes, buf)))   \
9333      {                                                                           \
9334         if (r) *r = 0;                                                           \
9335         if (g) *g = 0;                                                           \
9336         if (b) *b = 0;                                                           \
9337         if (a) *a = 0;                                                           \
9338         int_ret = EINA_FALSE;                                                    \
9339      }                                                                           \
9340    else                                                                          \
9341      {                                                                           \
9342         if (r) *r = cc->cr;                                                      \
9343         if (g) *g = cc->cg;                                                      \
9344         if (b) *b = cc->cb;                                                      \
9345         if (a) *a = cc->ca;                                                      \
9346         alpha = cc->ca;                                                          \
9347         int_ret = EINA_TRUE;                                                     \
9348      }                                                                           \
9349    _elm_color_premul(alpha, r, g, b);                                            \
9350    eina_stringshare_del(buf);                                                    \
9351    return int_ret
9352
9353 Eina_Bool
9354 _elm_widget_item_color_class_update(Elm_Widget_Item_Data *sd)
9355 {
9356    ELM_COLOR_CLASS_UPDATE(sd->view, sd->color_classes, (!sd) || (!sd->color_classes) || (!sd->view));
9357 }
9358
9359 /* Internal EO API */
9360 static Eina_Bool
9361 _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)
9362 {
9363    ELM_COLOR_CLASS_SET_START(obj, r, g, b, a);
9364
9365    int_ret &= _elm_widget_item_color_class_update(sd);
9366
9367    ELM_COLOR_CLASS_SET_END();
9368 }
9369
9370 /* Internal EO API */
9371 static Eina_Bool
9372 _elm_widget_item_class_color_get(const Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
9373 {
9374    ELM_COLOR_CLASS_GET(obj, r, g, b, a);
9375 }
9376
9377 /* Internal EO API */
9378 static Eina_Bool
9379 _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)
9380 {
9381    ELM_COLOR_CLASS_SET_START(obj, r2, g2, b2, a2);
9382
9383    int_ret &= _elm_widget_item_color_class_update(sd);
9384
9385    ELM_COLOR_CLASS_SET_END();
9386 }
9387
9388 /* Internal EO API */
9389 static Eina_Bool
9390 _elm_widget_item_class_color2_get(const Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
9391 {
9392    ELM_COLOR_CLASS_GET(obj, r2, g2, b2, a2);
9393 }
9394
9395 /* Internal EO API */
9396 static Eina_Bool
9397 _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)
9398 {
9399    ELM_COLOR_CLASS_SET_START(obj, r3, g3, b3, a3);
9400
9401    int_ret &= _elm_widget_item_color_class_update(sd);
9402
9403    ELM_COLOR_CLASS_SET_END();
9404 }
9405
9406 /* Internal EO API */
9407 static Eina_Bool
9408 _elm_widget_item_class_color3_get(const Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
9409 {
9410    ELM_COLOR_CLASS_GET(obj, r3, g3, b3, a3);
9411 }
9412
9413 /* Internal EO API */
9414 static Evas_Object *
9415 _elm_widget_item_edje_get(const Eo *obj, Elm_Widget_Item_Data *sd)
9416 {
9417    if (!sd)
9418      sd = efl_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
9419
9420    if (efl_isa(sd->view, EFL_UI_LAYOUT_BASE_CLASS))
9421      return elm_layout_edje_get(sd->view);
9422    else if (efl_isa(sd->view, EFL_CANVAS_LAYOUT_CLASS))
9423      return sd->view;
9424
9425    return NULL;
9426 }
9427
9428 /* Internal EO API */
9429 static void
9430 _elm_widget_item_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, const char *color_class)
9431 {
9432    Eina_Stringshare *buf;
9433    Evas_Object *edje;
9434    Edje_Color_Class *cc = NULL;
9435
9436    if (!color_class) return;
9437
9438    buf = _elm_widget_edje_class_get(obj, NULL, color_class);
9439    eina_hash_del(sd->color_classes, buf, cc);
9440
9441    edje = _elm_widget_item_edje_get(obj, sd);
9442    if (edje)
9443      edje_object_color_class_del(edje, buf);
9444
9445    eina_stringshare_del(buf);
9446 }
9447
9448 /* Internal EO API */
9449 static void
9450 _elm_widget_item_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
9451 {
9452    Evas_Object *edje;
9453    ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
9454
9455    edje = _elm_widget_item_edje_get(obj, sd);
9456    if (!edje) return;
9457
9458    edje_object_color_class_clear(edje);
9459 }
9460
9461 /* Internal EO APIs and hidden overrides */
9462 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color_set, Eina_Bool, EINA_FALSE,
9463                     EFL_FUNC_CALL(color_class, r, g, b, a),
9464                     const char *color_class, int r, int g, int b, int a)
9465 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color_get, Eina_Bool, EINA_FALSE,
9466                     EFL_FUNC_CALL(color_class, r, g, b, a),
9467                     const char *color_class, int *r, int *g, int *b, int *a)
9468 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color2_set, Eina_Bool, EINA_FALSE,
9469                     EFL_FUNC_CALL(color_class, r, g, b, a),
9470                     const char *color_class, int r, int g, int b, int a)
9471 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color2_get, Eina_Bool, EINA_FALSE,
9472                     EFL_FUNC_CALL(color_class, r, g, b, a),
9473                     const char *color_class, int *r, int *g, int *b, int *a)
9474 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color3_set, Eina_Bool, EINA_FALSE,
9475                     EFL_FUNC_CALL(color_class, r, g, b, a),
9476                     const char *color_class, int r, int g, int b, int a)
9477 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color3_get, Eina_Bool, EINA_FALSE,
9478                     EFL_FUNC_CALL(color_class, r, g, b, a),
9479                     const char *color_class, int *r, int *g, int *b, int *a)
9480 EAPI EFL_VOID_FUNC_BODYV(elm_widget_item_class_color_del,
9481                          EFL_FUNC_CALL(color_class),
9482                          const char *color_class)
9483 EAPI EFL_VOID_FUNC_BODY(elm_widget_item_class_color_clear)
9484
9485 #define ELM_WIDGET_ITEM_EXTRA_OPS \
9486    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_set, _elm_widget_item_class_color_set), \
9487    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_get, _elm_widget_item_class_color_get), \
9488    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color2_set, _elm_widget_item_class_color2_set), \
9489    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color2_get, _elm_widget_item_class_color2_get), \
9490    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color3_set, _elm_widget_item_class_color3_set), \
9491    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color3_get, _elm_widget_item_class_color3_get), \
9492    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_del, _elm_widget_item_class_color_del), \
9493    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_clear, _elm_widget_item_class_color_clear)
9494
9495 /*******
9496  * END *
9497  *******/
9498
9499 //TIZEN_ONLY(20180607): Restore legacy focus
9500 static void
9501 _if_focused_revert(Evas_Object *obj,
9502                    Eina_Bool can_focus_only)
9503 {
9504    Evas_Object *top;
9505    Evas_Object *newest = NULL;
9506    unsigned int newest_focus_order = 0;
9507
9508    INTERNAL_ENTRY;
9509
9510    if (!sd->focused) return;
9511    if (!sd->parent_obj) return;
9512
9513    top = elm_widget_top_get(sd->parent_obj);
9514    if (top)
9515      {
9516         newest = efl_ui_widget_newest_focus_order_get
9517            (top, &newest_focus_order, can_focus_only);
9518         if (newest)
9519           {
9520              if (newest == top)
9521                {
9522                   ELM_WIDGET_DATA_GET(newest, sd2);
9523                   if (!sd2) return;
9524
9525                   if (!_is_focused(newest))
9526                     efl_ui_widget_focus_steal(newest, NULL);
9527                   else
9528                     {
9529                        if (sd2->resize_obj && _is_focused(sd2->resize_obj))
9530                          efl_ui_widget_focused_object_clear(sd2->resize_obj);
9531                        else
9532                          {
9533                             Evas_Object *child;
9534                             for (unsigned int i = 0; i < eina_array_count(sd2->children); ++i)
9535                               {
9536                                  child = eina_array_data_get(sd2->children, i);
9537                                  if (!_elm_widget_is(child)) continue;
9538                                  if (_is_focused(child))
9539                                    {
9540                                       efl_ui_widget_focused_object_clear(child);
9541                                       break;
9542                                    }
9543                               }
9544                          }
9545                     }
9546                   evas_object_focus_set(newest, EINA_TRUE);
9547                }
9548              else
9549                {
9550                   if (_is_focused(newest))
9551                     efl_ui_widget_focused_object_clear(newest);
9552                   elm_object_focus_set(newest, EINA_TRUE);
9553                }
9554           }
9555      }
9556 }
9557
9558 /**
9559  * @internal
9560  *
9561  * Set custom focus chain.
9562  *
9563  * This function i set one new and overwrite any previous custom focus chain
9564  * with the list of objects. The previous list will be deleted and this list
9565  * will be managed. After setted, don't modity it.
9566  *
9567  * @note On focus cycle, only will be evaluated children of this container.
9568  *
9569  * @param obj The container widget
9570  * @param objs Chain of objects to pass focus
9571  * @ingroup Widget
9572  */
9573 EOLIAN static void
9574 _efl_ui_widget_focus_custom_chain_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_List *objs)
9575 {
9576    if (!_elm_widget_focus_chain_manager_is(obj)) return;
9577
9578    efl_ui_widget_focus_custom_chain_unset(obj);
9579
9580    Eina_List *l;
9581    Evas_Object *o;
9582
9583    EINA_LIST_FOREACH(objs, l, o)
9584      {
9585         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
9586                                        _elm_object_focus_chain_del_cb, obj);
9587      }
9588
9589    sd->focus_chain = objs;
9590 }
9591
9592 /**
9593  * @internal
9594  *
9595  * Get custom focus chain
9596  *
9597  * @param obj The container widget
9598  * @ingroup Widget
9599  */
9600 EOLIAN static const Eina_List*
9601 _efl_ui_widget_focus_custom_chain_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
9602 {
9603    return (const Eina_List *)sd->focus_chain;
9604 }
9605
9606 /**
9607  * @internal
9608  *
9609  * Unset custom focus chain
9610  *
9611  * @param obj The container widget
9612  * @ingroup Widget
9613  */
9614 EOLIAN static void
9615 _efl_ui_widget_focus_custom_chain_unset(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
9616 {
9617    Eina_List *l, *l_next;
9618    Evas_Object *o;
9619
9620    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
9621      {
9622         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
9623                                             _elm_object_focus_chain_del_cb, obj);
9624         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
9625      }
9626 }
9627
9628 /**
9629  * @internal
9630  *
9631  * Append object to custom focus chain.
9632  *
9633  * @note If relative_child equal to NULL or not in custom chain, the object
9634  * will be added in end.
9635  *
9636  * @note On focus cycle, only will be evaluated children of this container.
9637  *
9638  * @param obj The container widget
9639  * @param child The child to be added in custom chain
9640  * @param relative_child The relative object to position the child
9641  * @ingroup Widget
9642  */
9643 EOLIAN static void
9644 _efl_ui_widget_focus_custom_chain_append(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
9645 {
9646    EINA_SAFETY_ON_NULL_RETURN(child);
9647
9648    if (!_elm_widget_focus_chain_manager_is(obj)) return;
9649
9650    evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
9651                                   _elm_object_focus_chain_del_cb, obj);
9652
9653    if (!relative_child)
9654      sd->focus_chain = eina_list_append(sd->focus_chain, child);
9655    else
9656      sd->focus_chain = eina_list_append_relative(sd->focus_chain,
9657                                                  child, relative_child);
9658 }
9659
9660 /**
9661  * @internal
9662  *
9663  * Prepend object to custom focus chain.
9664  *
9665  * @note If relative_child equal to NULL or not in custom chain, the object
9666  * will be added in begin.
9667  *
9668  * @note On focus cycle, only will be evaluated children of this container.
9669  *
9670  * @param obj The container widget
9671  * @param child The child to be added in custom chain
9672  * @param relative_child The relative object to position the child
9673  * @ingroup Widget
9674  */
9675 EOLIAN static void
9676 _efl_ui_widget_focus_custom_chain_prepend(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
9677 {
9678    EINA_SAFETY_ON_NULL_RETURN(child);
9679
9680    if (!_elm_widget_focus_chain_manager_is(obj)) return;
9681
9682    evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
9683                                   _elm_object_focus_chain_del_cb, obj);
9684
9685    if (!relative_child)
9686      sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
9687    else
9688      sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
9689                                                   child, relative_child);
9690 }
9691
9692 /**
9693  * @internal
9694  *
9695  * Give focus to next object in object tree.
9696  *
9697  * Give focus to next object in focus chain of one object sub-tree.
9698  * If the last object of chain already have focus, the focus will go to the
9699  * first object of chain.
9700  *
9701  * @param obj The widget root of sub-tree
9702  * @param dir Direction to cycle the focus
9703  *
9704  * @ingroup Widget
9705  */
9706 EOLIAN static void
9707 _efl_ui_widget_focus_cycle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Ui_Focus_Direction dir)
9708 {
9709    Evas_Object *target = NULL;
9710    Elm_Object_Item *target_item = NULL;
9711    if (!_elm_widget_is(obj))
9712      return;
9713    efl_ui_widget_focus_next_get(obj, dir, &target, &target_item);
9714    if (target)
9715      {
9716         /* access */
9717         if (_elm_config->access_mode)
9718           {
9719              /* highlight cycle does not steal a focus, only after window gets
9720                 the ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE message,
9721                 target will steal focus, or focus its own job. */
9722              if (!_elm_access_auto_highlight_get())
9723                efl_ui_widget_focus_steal(target, target_item);
9724
9725              _elm_access_highlight_set(target);
9726              elm_widget_focus_region_show(target);
9727           }
9728         else efl_ui_widget_focus_steal(target, target_item);
9729      }
9730 }
9731
9732 /**
9733  * @internal
9734  *
9735  * Give focus to near object(in object tree) in one direction.
9736  *
9737  * Give focus to near object(in object tree) in direction of current
9738  * focused object.  If none focusable object in given direction or
9739  * none focused object in object tree, the focus will not change.
9740  *
9741  * @param obj The reference widget
9742  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
9743  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
9744  * @return EINA_TRUE if focus is moved.
9745  *
9746  * @ingroup Widget
9747  */
9748 EOLIAN static Eina_Bool
9749 _efl_ui_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, double degree)
9750 {
9751    Evas_Object *target = NULL;
9752    Elm_Object_Item *target_item = NULL;
9753    Evas_Object *current_focused = NULL;
9754    double weight = 0.0;
9755
9756    if (!_elm_widget_is(obj)) return EINA_FALSE;
9757    if (!_is_focused(obj)) return EINA_FALSE;
9758
9759    current_focused = efl_ui_widget_focused_object_get(obj);
9760
9761    if (efl_ui_widget_focus_direction_get
9762          (obj, current_focused, degree, &target, &target_item, &weight))
9763      {
9764         efl_ui_widget_focus_steal(target, NULL);
9765         return EINA_TRUE;
9766      }
9767
9768    return EINA_FALSE;
9769 }
9770
9771 /**
9772  * @internal
9773  *
9774  * Get near object in one direction of base object.
9775  *
9776  * Get near object(in the object sub-tree) in one direction of
9777  * base object. Return the near object by reference.
9778  * By initializing weight, you can filter objects locating far
9779  * from base object. If object is in the specific direction,
9780  * weight is (1/(distance^2)). If object is not exactly in one
9781  * direction, some penalty will be added.
9782  *
9783  * @param obj The widget root of sub-tree
9784  * @param base The base object of the direction
9785  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
9786  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
9787  * @param direction The near object in one direction
9788  * @param weight The weight is bigger when the object is located near
9789  * @return EINA_TRUE if near object is updated.
9790  *
9791  * @ingroup Widget
9792  */
9793
9794 EOLIAN static Eina_Bool
9795 _efl_ui_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)
9796 {
9797    double c_weight;
9798
9799    /* -1 means the best was already decided. Don't need any more searching. */
9800    if (!direction || !weight || !base || (obj == base))
9801      return EINA_FALSE;
9802
9803    /* Ignore if disabled */
9804    if ((!evas_object_visible_get(obj))
9805        || (elm_widget_disabled_get(obj))
9806        || (elm_widget_tree_unfocusable_get(obj)))
9807      return EINA_FALSE;
9808
9809    /* Try use hook */
9810    if (_internal_elm_widget_focus_direction_manager_is(obj))
9811      {
9812         Eina_Bool int_ret = EINA_FALSE;
9813         int_ret = efl_ui_widget_focus_direction((Eo *)obj, base, degree, direction, direction_item, weight);
9814         return int_ret;
9815      }
9816
9817    if (!elm_widget_can_focus_get(obj) || _is_focused((Eo *)obj))
9818      return EINA_FALSE;
9819
9820    c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree);
9821    if ((c_weight == -1.0) ||
9822        ((c_weight != 0.0) && (*weight != -1.0) &&
9823         ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
9824      {
9825         if (*direction &&
9826             ((int)(*weight * 1000000) == (int)(c_weight * 1000000)))
9827           {
9828              ELM_WIDGET_DATA_GET(*direction, sd1);
9829              if (sd1)
9830                {
9831                   if (sd->focus_order <= sd1->focus_order)
9832                     return EINA_FALSE;
9833                }
9834           }
9835         *direction = (Evas_Object *)obj;
9836         *weight = c_weight;
9837         return EINA_TRUE;
9838      }
9839
9840    return EINA_FALSE;
9841 }
9842
9843 /**
9844  * @internal
9845  *
9846  * Get near object in one direction of base object in list.
9847  *
9848  * Get near object in one direction of base object in the specific
9849  * object list. Return the near object by reference.
9850  * By initializing weight, you can filter objects locating far
9851  * from base object. If object is in the specific direction,
9852  * weight is (1/(distance^2)). If object is not exactly in one
9853  * direction, some penalty will be added.
9854  *
9855  * @param obj The widget root of sub-tree
9856  * @param base The base object of the direction
9857  * @param items list with ordered objects
9858  * @param list_data_get function to get the object from one item of list
9859  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
9860  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
9861  * @param direction The near object in one direction
9862  * @param weight The weight is bigger when the object is located near
9863  * @return EINA_TRUE if near object is updated.
9864  *
9865  * @ingroup Widget
9866  */
9867 EOLIAN static Eina_Bool
9868 _efl_ui_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, void* list_data_get, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight)
9869 {
9870    if (!direction || !weight || !base || !items)
9871      return EINA_FALSE;
9872
9873    const Eina_List *l = items;
9874    Evas_Object *current_best = *direction;
9875
9876    for (; l; l = eina_list_next(l))
9877      {
9878         Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
9879         if (cur && _elm_widget_is(cur))
9880           efl_ui_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight);
9881      }
9882    if (current_best != *direction) return EINA_TRUE;
9883
9884    return EINA_FALSE;
9885 }
9886
9887 /**
9888  * @internal
9889  *
9890  * Get next object in focus chain of object tree.
9891  *
9892  * Get next object in focus chain of one object sub-tree.
9893  * Return the next object by reference. If don't have any candidate to receive
9894  * focus before chain end, the first candidate will be returned.
9895  *
9896  * @param obj The widget root of sub-tree
9897  * @param dir Direction of focus chain
9898  * @param next The next object in focus chain
9899  * @return EINA_TRUE if don't need focus chain restart/loop back
9900  *         to use 'next' obj.
9901  *
9902  * @ingroup Widget
9903  */
9904 EOLIAN static Eina_Bool
9905 _efl_ui_widget_focus_next_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Efl_Ui_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
9906 {
9907    Elm_Access_Info *ac;
9908
9909    if (!next)
9910      return EINA_FALSE;
9911    *next = NULL;
9912
9913    /* Ignore if disabled */
9914    if (_elm_config->access_mode && _elm_access_auto_highlight_get())
9915      {
9916         if (!evas_object_visible_get(obj)
9917             || (elm_widget_tree_unfocusable_get(obj)))
9918           return EINA_FALSE;
9919      }
9920    else
9921      {
9922         if ((!evas_object_visible_get(obj))
9923             || (elm_widget_disabled_get(obj))
9924             || (elm_widget_tree_unfocusable_get(obj)))
9925           return EINA_FALSE;
9926      }
9927
9928    /* Try use hook */
9929    if (_elm_widget_focus_chain_manager_is(obj))
9930      {
9931         Eina_Bool int_ret = EINA_FALSE;
9932         int_ret = efl_ui_widget_focus_next((Eo *)obj, dir, next, next_item);
9933         if (!int_ret && _is_focused((Eo *)obj))
9934           {
9935              Evas_Object *o = NULL;
9936              if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
9937                *next_item = sd->item_focus_previous;
9938              else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
9939                *next_item = sd->item_focus_next;
9940              else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
9941                *next_item = sd->item_focus_up;
9942              else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
9943                *next_item = sd->item_focus_down;
9944              else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
9945                *next_item = sd->item_focus_right;
9946              else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
9947                *next_item = sd->item_focus_left;
9948              if (*next_item)
9949                o = elm_object_item_widget_get(*next_item);
9950
9951              if (!o)
9952                {
9953                   if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
9954                     o = sd->focus_previous;
9955                   else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
9956                     o = sd->focus_next;
9957                   else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
9958                     o = sd->focus_up;
9959                   else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
9960                     o = sd->focus_down;
9961                   else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
9962                     o = sd->focus_right;
9963                   else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
9964                     o = sd->focus_left;
9965                }
9966
9967              if (o)
9968                {
9969                   *next = o;
9970                   return EINA_TRUE;
9971                }
9972           }
9973         return int_ret;
9974      }
9975
9976    /* access object does not check sd->can_focus, because an object could
9977       have highlight even though the object is not focusable. */
9978    if (_elm_config->access_mode && _elm_access_auto_highlight_get())
9979      {
9980         ac = _elm_access_info_get(obj);
9981         if (!ac) return EINA_FALSE;
9982
9983         /* check whether the hover object is visible or not */
9984         if (!evas_object_visible_get(ac->hoverobj))
9985           return EINA_FALSE;
9986      }
9987    else if (!elm_widget_can_focus_get(obj))
9988      return EINA_FALSE;
9989
9990    if (_is_focused((Eo *)obj))
9991      {
9992         if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
9993           *next_item = sd->item_focus_previous;
9994         else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
9995           *next_item = sd->item_focus_next;
9996         else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
9997           *next_item = sd->item_focus_up;
9998         else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
9999           *next_item = sd->item_focus_down;
10000         else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10001           *next_item = sd->item_focus_right;
10002         else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10003           *next_item = sd->item_focus_left;
10004         if (*next_item) *next = elm_object_item_widget_get(*next_item);
10005
10006         if (!(*next))
10007           {
10008              if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10009                *next = sd->focus_previous;
10010              else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10011                *next = sd->focus_next;
10012              else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10013                *next = sd->focus_up;
10014              else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10015                *next = sd->focus_down;
10016              else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10017                *next = sd->focus_right;
10018              else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10019                *next = sd->focus_left;
10020           }
10021
10022         if (*next) return EINA_TRUE;
10023      }
10024
10025    /* Return */
10026    *next = (Evas_Object *)obj;
10027    return !ELM_WIDGET_FOCUS_GET(obj);
10028 }
10029
10030 /**
10031  * @internal
10032  *
10033  * Get next object in focus chain of object tree in list.
10034  *
10035  * Get next object in focus chain of one object sub-tree ordered by one list.
10036  * Return the next object by reference. If don't have any candidate to receive
10037  * focus before list end, the first candidate will be returned.
10038  *
10039  * @param obj The widget root of sub-tree
10040  * @param items list with ordered objects
10041  * @param list_data_get function to get the object from one item of list
10042  * @param dir Direction of focus chain
10043  * @param next The next object in focus chain
10044  * @return EINA_TRUE if don't need focus chain restart/loop back
10045  *         to use 'next' obj.
10046  *
10047  * @ingroup Widget
10048  */
10049 EOLIAN static Eina_Bool
10050 _efl_ui_widget_focus_list_next_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Eina_List *items, void * list_data_get, Efl_Ui_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
10051 {
10052    Eina_List *(*list_next)(const Eina_List *list) = NULL;
10053    Evas_Object *focused_object = NULL;
10054
10055    if (!next)
10056      return EINA_FALSE;
10057    *next = NULL;
10058
10059    if (!_elm_widget_is(obj))
10060      return EINA_FALSE;
10061
10062    if (!items)
10063      return EINA_FALSE;
10064
10065    /* When Up, Down, Right, or Left, try direction_get first. */
10066    focused_object = efl_ui_widget_focused_object_get(obj);
10067    if (focused_object)
10068      {
10069         if ((dir == EFL_UI_FOCUS_DIRECTION_UP)
10070            || (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10071            || (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10072            || (dir == EFL_UI_FOCUS_DIRECTION_LEFT))
10073           {
10074              *next_item = efl_ui_widget_focus_next_item_get(focused_object, dir);
10075              if (*next_item)
10076                *next = elm_object_item_widget_get(*next_item);
10077              else
10078                *next = efl_ui_widget_focus_next_object_get(focused_object, dir);
10079              if (*next) return EINA_TRUE;
10080              else
10081                {
10082                   Evas_Object *n = NULL;
10083                   Elm_Object_Item *n_item = NULL;
10084                   double degree = 0;
10085                   double weight = 0.0;
10086
10087                   if (dir == EFL_UI_FOCUS_DIRECTION_UP) degree = 0.0;
10088                   else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN) degree = 180.0;
10089                   else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT) degree = 90.0;
10090                   else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT) degree = 270.0;
10091
10092                   if (efl_ui_widget_focus_list_direction_get(obj, focused_object,
10093                                                           items, list_data_get,
10094                                                           degree, &n, &n_item,
10095                                                           &weight))
10096                     {
10097                        *next_item = n_item;
10098                        *next = n;
10099                        return EINA_TRUE;
10100                     }
10101                }
10102           }
10103      }
10104
10105    /* Direction */
10106    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10107      {
10108         items = eina_list_last(items);
10109         list_next = eina_list_prev;
10110      }
10111    else if ((dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10112             || (dir == EFL_UI_FOCUS_DIRECTION_UP)
10113             || (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10114             || (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10115             || (dir == EFL_UI_FOCUS_DIRECTION_LEFT))
10116      list_next = eina_list_next;
10117    else
10118      return EINA_FALSE;
10119
10120    const Eina_List *l = items;
10121
10122    /* Recovery last focused sub item */
10123    if (ELM_WIDGET_FOCUS_GET(obj))
10124      {
10125         for (; l; l = list_next(l))
10126           {
10127              Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
10128              if (ELM_WIDGET_FOCUS_GET(cur)) break;
10129           }
10130
10131          /* Focused object, but no focused sub item */
10132          if (!l) l = items;
10133      }
10134
10135    const Eina_List *start = l;
10136    Evas_Object *to_focus = NULL;
10137    Elm_Object_Item *to_focus_item = NULL;
10138
10139    /* Iterate sub items */
10140    /* Go to the end of list */
10141    for (; l; l = list_next(l))
10142      {
10143         Evas_Object *tmp = NULL;
10144         Elm_Object_Item *tmp_item = NULL;
10145         Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
10146
10147         if (!cur) continue;
10148         if (!_elm_widget_is(cur)) continue;
10149         if (elm_widget_parent_get(cur) != obj)
10150           continue;
10151
10152         /* Try Focus cycle in subitem */
10153         if (efl_ui_widget_focus_next_get(cur, dir, &tmp, &tmp_item))
10154           {
10155              *next = tmp;
10156              *next_item = tmp_item;
10157              return EINA_TRUE;
10158           }
10159         else if ((dir == EFL_UI_FOCUS_DIRECTION_UP)
10160                  || (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10161                  || (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10162                  || (dir == EFL_UI_FOCUS_DIRECTION_LEFT))
10163           {
10164              if (tmp && _is_focused(cur))
10165                {
10166                   *next = tmp;
10167                   *next_item = tmp_item;
10168                   return EINA_FALSE;
10169                }
10170           }
10171         else if ((tmp) && (!to_focus))
10172           {
10173              to_focus = tmp;
10174              to_focus_item = tmp_item;
10175           }
10176      }
10177
10178    l = items;
10179
10180    /* Get First possible */
10181    for (; l != start; l = list_next(l))
10182      {
10183         Evas_Object *tmp = NULL;
10184         Elm_Object_Item *tmp_item = NULL;
10185         Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
10186
10187         if (elm_widget_parent_get(cur) != obj)
10188           continue;
10189
10190         /* Try Focus cycle in subitem */
10191         efl_ui_widget_focus_next_get(cur, dir, &tmp, &tmp_item);
10192         if (tmp)
10193           {
10194              *next = tmp;
10195              *next_item = tmp_item;
10196              return EINA_FALSE;
10197           }
10198      }
10199
10200    *next = to_focus;
10201    *next_item = to_focus_item;
10202    return EINA_FALSE;
10203 }
10204
10205 /**
10206  * @internal
10207  *
10208  * Get next object which was set with specific focus direction.
10209  *
10210  * Get next object which was set by elm_widget_focus_next_object_set
10211  * with specific focus directioin.
10212  *
10213  * @param obj The widget
10214  * @param dir Direction of focus
10215  * @return Widget which was registered with sepecific focus direction.
10216  *
10217  * @ingroup Widget
10218  */
10219 EOLIAN static Evas_Object*
10220 _efl_ui_widget_focus_next_object_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Ui_Focus_Direction dir)
10221 {
10222    Evas_Object *ret = NULL;
10223
10224    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10225      ret = sd->focus_previous;
10226    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10227      ret = sd->focus_next;
10228    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10229      ret = sd->focus_up;
10230    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10231      ret = sd->focus_down;
10232    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10233      ret = sd->focus_right;
10234    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10235      ret = sd->focus_left;
10236
10237    return ret;
10238 }
10239
10240 /**
10241  * @internal
10242  *
10243  * Set next object with specific focus direction.
10244  *
10245  * When a widget is set with specific focus direction, this widget will be
10246  * the first candidate when finding the next focus object.
10247  * Focus next object can be registered with six directions that are previous,
10248  * next, up, down, right, and left.
10249  *
10250  * @param obj The widget
10251  * @param next Next focus object
10252  * @param dir Direction of focus
10253  *
10254  * @ingroup Widget
10255  */
10256 EOLIAN static void
10257 _efl_ui_widget_focus_next_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *next, Efl_Ui_Focus_Direction dir)
10258 {
10259
10260    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10261      sd->focus_previous = next;
10262    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10263      sd->focus_next = next;
10264    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10265      sd->focus_up = next;
10266    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10267      sd->focus_down = next;
10268    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10269      sd->focus_right = next;
10270    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10271      sd->focus_left = next;
10272
10273 }
10274
10275 EOLIAN static Elm_Object_Item*
10276 _efl_ui_widget_focus_next_item_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Ui_Focus_Direction dir)
10277 {
10278    Elm_Object_Item *ret = NULL;
10279
10280    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10281      ret = sd->item_focus_previous;
10282    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10283      ret = sd->item_focus_next;
10284    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10285      ret = sd->item_focus_up;
10286    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10287      ret = sd->item_focus_down;
10288    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10289      ret = sd->item_focus_right;
10290    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10291      ret = sd->item_focus_left;
10292
10293    return ret;
10294
10295 }
10296
10297 EOLIAN static void
10298 _efl_ui_widget_focus_next_item_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Object_Item *next_item, Efl_Ui_Focus_Direction dir)
10299 {
10300    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10301      sd->item_focus_previous = next_item;
10302    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10303      sd->item_focus_next = next_item;
10304    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10305      sd->item_focus_up = next_item;
10306    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10307      sd->item_focus_down = next_item;
10308    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10309      sd->item_focus_right = next_item;
10310    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10311      sd->item_focus_left = next_item;
10312 }
10313
10314 EAPI void
10315 elm_widget_focus_set(Eo *obj, Eina_Bool focus)
10316 {
10317    ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd);
10318    if (!sd->focused)
10319      {
10320         focus_order++;
10321         sd->focus_order = focus_order;
10322         sd->focused = EINA_TRUE;
10323         efl_ui_focus_object_on_focus_update(obj);
10324      }
10325
10326    if (focus)
10327      {
10328         if ((_is_focusable(sd->resize_obj)) &&
10329             (!elm_widget_disabled_get(sd->resize_obj)))
10330           {
10331              elm_widget_focus_set(sd->resize_obj, focus);
10332           }
10333         else
10334           {
10335              Evas_Object *child;
10336
10337              for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
10338                {
10339                   child = eina_array_data_get(sd->children, i);
10340                   if (!_elm_widget_is(child)) continue;
10341                   if ((_is_focusable(child)) &&
10342                        (!elm_widget_disabled_get(child)))
10343                       {
10344                          elm_widget_focus_set(child, focus);
10345                          break;
10346                       }
10347                }
10348           }
10349      }
10350    else
10351      {
10352         Evas_Object *child;
10353         unsigned int i = eina_array_count(sd->children);
10354
10355         while (i >= 1)
10356           {
10357              i--;
10358              child = eina_array_data_get(sd->children, i);
10359              if (!_elm_widget_is(child)) continue;
10360              if ((_is_focusable(child)) &&
10361                  (!elm_widget_disabled_get(child)))
10362                {
10363                   elm_widget_focus_set(child, focus);
10364                   break;
10365                }
10366              if (i == 0) break;
10367           }
10368      }
10369 }
10370
10371 static void
10372 _focused_object_clear(Elm_Widget_Smart_Data *sd)
10373 {
10374    if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
10375        _is_focused(sd->resize_obj))
10376      {
10377         efl_ui_widget_focused_object_clear(sd->resize_obj);
10378      }
10379    else
10380      {
10381         Evas_Object *child;
10382         for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
10383           {
10384              child = eina_array_data_get(sd->children, i);
10385              if (_elm_widget_is(child) && _is_focused(child))
10386                {
10387                   efl_ui_widget_focused_object_clear(child);
10388                   break;
10389                }
10390           }
10391      }
10392 }
10393
10394 EOLIAN static void
10395 _efl_ui_widget_focused_object_clear(Eo *obj, Elm_Widget_Smart_Data *sd)
10396 {
10397    if (!sd->focused) return;
10398    _focused_object_clear(sd);
10399    sd->focused = EINA_FALSE;
10400    if (sd->top_win_focused)
10401      efl_ui_focus_object_on_focus_update(obj);
10402 }
10403
10404 EOLIAN static void
10405 _efl_ui_widget_focus_steal(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item)
10406 {
10407    Evas_Object *parent, *parent2, *o;
10408
10409    if (sd->focused) return;
10410    if (sd->disabled) return;
10411    if (!sd->can_focus) return;
10412    if (sd->tree_unfocusable) return;
10413    parent = obj;
10414    for (;; )
10415      {
10416         o = elm_widget_parent_get(parent);
10417         if (!o) break;
10418         sd = efl_data_scope_get(o, MY_CLASS);
10419         if (sd->disabled || sd->tree_unfocusable) return;
10420         if (sd->focused) break;
10421         parent = o;
10422      }
10423    if ((!elm_widget_parent_get(parent)))
10424      efl_ui_widget_focused_object_clear(parent);
10425    else
10426      {
10427         parent2 = elm_widget_parent_get(parent);
10428         parent = parent2;
10429         sd = efl_data_scope_get(parent, MY_CLASS);
10430         if (sd) _focused_object_clear(sd);
10431      }
10432    _parent_focus(obj, item);
10433    elm_widget_focus_region_show(obj);
10434    return;
10435 }
10436
10437 static void
10438 _parents_on_focus(Evas_Object *obj)
10439 {
10440    API_ENTRY return;
10441    if (!sd->focused || !sd->top_win_focused) return;
10442
10443    Evas_Object *o = elm_widget_parent_get(obj);
10444    if (o) _parents_on_focus(o);
10445    efl_ui_focus_object_on_focus_update(obj);
10446 }
10447
10448 EOLIAN static void
10449 _efl_ui_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
10450 {
10451    Evas_Object *newest = NULL;
10452    unsigned int newest_focus_order = 0;
10453
10454    newest = efl_ui_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
10455    if (newest)
10456      _parents_on_focus(newest);
10457 }
10458
10459 /**
10460  * @internal
10461  *
10462  * Check if the widget has its own focus next function.
10463  *
10464  * @param obj The widget.
10465  * @return focus next function is implemented/unimplemented.
10466  * (@c EINA_TRUE = implemented/@c EINA_FALSE = unimplemented.)
10467  */
10468 static inline Eina_Bool
10469 _elm_widget_focus_chain_manager_is(const Evas_Object *obj)
10470 {
10471    ELM_WIDGET_CHECK(obj) EINA_FALSE;
10472
10473    Eina_Bool manager_is = EINA_FALSE;
10474    manager_is = efl_ui_widget_focus_next_manager_is((Eo *)obj);
10475    return manager_is;
10476 }
10477
10478 static inline Eina_Bool
10479 _internal_elm_widget_focus_direction_manager_is(const Evas_Object *obj)
10480 {
10481    ELM_WIDGET_CHECK(obj) EINA_FALSE;
10482
10483    Eina_Bool manager_is = EINA_FALSE;
10484    manager_is = efl_ui_widget_focus_direction_manager_is((Eo *)obj);
10485    return manager_is;
10486 }
10487
10488 static void
10489 _parent_focus(Evas_Object *obj, Elm_Object_Item *item)
10490 {
10491    API_ENTRY return;
10492
10493    if (sd->focused) return;
10494
10495    Evas_Object *o = elm_widget_parent_get(obj);
10496    sd->focus_order_on_calc = EINA_TRUE;
10497
10498    if (o) _parent_focus(o, item);
10499
10500    if (!sd->focus_order_on_calc)
10501      return;  /* we don't want to override it if by means of any of the
10502                  callbacks below one gets to calculate our order
10503                  first. */
10504
10505    focus_order++;
10506    sd->focus_order = focus_order;
10507    sd->focused = EINA_TRUE;
10508
10509    if (sd->top_win_focused)
10510      efl_ui_focus_object_on_focus_update(obj);
10511    sd->focus_order_on_calc = EINA_FALSE;
10512
10513    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
10514      _elm_access_highlight_set(obj);
10515 }
10516
10517 static void
10518 _elm_object_focus_chain_del_cb(void *data,
10519                                Evas *e EINA_UNUSED,
10520                                Evas_Object *obj,
10521                                void *event_info EINA_UNUSED)
10522 {
10523    ELM_WIDGET_DATA_GET(data, sd);
10524
10525    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
10526 }
10527
10528 //TIZEN_ONLY(20200117): transition duration factor for widget transition customize
10529 EOLIAN static Eina_Bool
10530 _efl_ui_widget_transition_duration_factor_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd , double duration)
10531 {
10532    pd->transition_duration = duration;
10533    // the value need to be $true when widget have transition effect.
10534    return EINA_FALSE;
10535 }
10536
10537 EOLIAN static double
10538 _efl_ui_widget_transition_duration_factor_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
10539 {
10540    return pd->transition_duration;
10541 }
10542 //
10543
10544 //TIZEN_ONLT(20191218): efl_ui_widget: add widget_focus property to handle focus
10545 EOLIAN static Eina_Bool
10546 _efl_ui_widget_widget_focus_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
10547 {
10548    return elm_object_focus_get(obj);
10549 }
10550
10551 EOLIAN static void
10552 _efl_ui_widget_widget_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED, Eina_Bool focus)
10553 {
10554    focus = !!focus;
10555    elm_object_focus_set(obj, focus);
10556 }
10557 //
10558
10559 #include "elm_widget_item_eo.c"
10560 #include "elm_widget_item_container_eo.c"
10561 #include "efl_ui_widget.eo.c"
10562 #include "efl_ui_widget_eo.legacy.c"
10563
10564 /* Others */
10565 #include "efl_ui_l10n.eo.c"