430b8d41456379b4ae417c59d084405d1d37fd94
[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(20170405) Add gesture method to accessible interface
4388    efl_access_object_gesture_cb_set(eo_item, NULL, NULL);
4389    //
4390    //TIZEN_ONLY : elm_widget_item: add at-spi name setter
4391    efl_access_object_translation_domain_set(eo_item, NULL);
4392    efl_access_object_relationships_clear(eo_item);
4393    //
4394
4395    efl_access_object_attributes_clear(eo_item);
4396
4397    // TIZEN_ONLY(20150709) : atspi relations api
4398    if (item->atspi_custom_relations)
4399      efl_access_relation_set_free(&item->atspi_custom_relations);
4400    //
4401
4402    //TIZEN_ONLY(20150731) : add i18n support for name and description
4403    if (item->atspi_translation_domain)
4404      eina_stringshare_del(item->atspi_translation_domain);
4405    ///
4406
4407    //TIZEN_ONLY(20150713) : add widget_item name setter
4408    if (item->name)
4409      eina_stringshare_del(item->name);
4410    //
4411
4412    /***********************************************************************************
4413     * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *
4414     ***********************************************************************************/
4415    if (item->color_classes)
4416      ELM_SAFE_FREE(item->color_classes, eina_hash_free);
4417    /*******
4418     * END *
4419     *******/
4420
4421    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
4422
4423    efl_destructor(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
4424 }
4425
4426 /**
4427  * @internal
4428  *
4429  * Releases widget item memory, calling back item_del_pre_hook() and
4430  * item_del_cb() if they exist.
4431  *
4432  * @param item a valid #Elm_Widget_Item to be deleted.
4433  *
4434  * If there is an Elm_Widget_Item::del_cb, then it will be called prior
4435  * to memory release. Note that elm_widget_item_pre_notify_del() calls
4436  * this function and then unset it, thus being useful for 2 step
4437  * cleanup whenever the del_cb may use any of the data that must be
4438  * deleted from item.
4439  *
4440  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
4441  * is presented!
4442  *
4443  * Note that if item_del_pre_hook() returns @c EINA_TRUE, item free will be
4444  * deferred, or item will be freed here if it returns @c EINA_FALSE.
4445  *
4446  * @see elm_widget_item_del() convenience macro.
4447  * @ingroup Widget
4448  */
4449 EOLIAN static void
4450 _elm_widget_item_efl_object_invalidate(Eo *eo_item, Elm_Widget_Item_Data *item)
4451 {
4452    Evas_Object *view;
4453
4454    //Widget item delete callback
4455    elm_wdg_item_del_pre(item->eo_obj);
4456
4457    // TIZEN_ONLY(20200109): if item deletion process need to be intercepted for
4458    // provide animation on the view object, widget need to add efl_del_intercept_set()
4459    // and clear the view after all animation processed.
4460    if (!efl_del_intercept_get(eo_item))
4461      {
4462         view = item->view;
4463         if (item->view) efl_wref_del(item->view, &item->view);
4464         // FIXME: Is view an Efl.Ui or a legacy object ?
4465         evas_object_del(view);
4466         item->view = NULL;
4467      }
4468
4469    efl_invalidate(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
4470 }
4471
4472 EOLIAN static void
4473 _elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4474 {
4475 }
4476
4477 /**
4478  * @internal
4479  *
4480  * Notify object will be deleted without actually deleting it.
4481  *
4482  * This function will callback Elm_Widget_Item::del_cb if it is set
4483  * and then unset it so it is not called twice (ie: from
4484  * elm_widget_item_del()).
4485  *
4486  * @param item a valid #Elm_Widget_Item to be notified
4487  * @see elm_widget_item_pre_notify_del() convenience macro.
4488  * @ingroup Widget
4489  */
4490 EOLIAN static void
4491 _elm_widget_item_pre_notify_del(Eo *eo_item, Elm_Widget_Item_Data *item)
4492 {
4493    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4494    if (!item->del_func) return;
4495    item->del_func((void *)WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4496    item->del_func = NULL;
4497 }
4498
4499 /**
4500  * @internal
4501  *
4502  * Set the function to notify when item is being deleted.
4503  *
4504  * This function will complain if there was a callback set already,
4505  * however it will set the new one.
4506  *
4507  * The callback will be called from elm_widget_item_pre_notify_del()
4508  * or elm_widget_item_del() will be called with:
4509  *   - data: the Elm_Widget_Item::data value.
4510  *   - obj: the Elm_Widget_Item::widget evas object.
4511  *   - event_info: the item being deleted.
4512  *
4513  * @param item a valid #Elm_Widget_Item to be notified
4514  * @see elm_widget_item_del_cb_set() convenience macro.
4515  * @ingroup Widget
4516  */
4517 EOLIAN static void
4518 _elm_widget_item_del_cb_set(Eo *eo_item EINA_UNUSED,
4519                             Elm_Widget_Item_Data *item,
4520                             Evas_Smart_Cb func)
4521 {
4522    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4523    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4524
4525    if ((item->del_func) && (item->del_func != func))
4526      WRN("You're replacing a previously set del_cb %p of item %p with %p",
4527          item->del_func, item->eo_obj, func);
4528
4529    item->del_func = func;
4530 }
4531
4532 /**
4533  * @internal
4534  *
4535  * Get owner widget of this item.
4536  *
4537  * @param item a valid #Elm_Widget_Item to get data from.
4538  * @return owner widget of this item.
4539  * @ingroup Widget
4540  */
4541 EOLIAN static Evas_Object *
4542 _elm_widget_item_widget_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4543 {
4544    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4545    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4546
4547    return item->widget;
4548 }
4549
4550 EAPI Eina_Bool
4551 _elm_widget_onscreen_is(const Evas_Object *widget)
4552 {
4553    Evas_Object *parent = (Evas_Object *)widget;
4554    Eina_Rectangle r1, r2;
4555
4556    Evas *evas = evas_object_evas_get(widget);
4557    if (!evas) return EINA_FALSE;
4558
4559    evas_object_geometry_get(widget, &r1.x, &r1.y, &r1.w, &r1.h);
4560    if (eina_rectangle_is_empty(&r1))
4561      return EINA_FALSE;
4562
4563    // window does not have to check viewport and geometry
4564    if (efl_isa(widget, EFL_UI_WIN_CLASS))
4565       return EINA_TRUE;
4566
4567    // check if on canvas
4568    evas_output_viewport_get(evas, &r2.x, &r2.y, &r2.w, &r2.h);
4569    if (!eina_rectangles_intersect(&r1, &r2))
4570      return EINA_FALSE;
4571
4572    // check if inside scrollable parent viewport
4573    do {
4574       parent = elm_widget_parent_get(parent);
4575       if (parent && !evas_object_visible_get(parent))
4576         return EINA_FALSE;
4577       if (parent && efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4578         {
4579            evas_object_geometry_get(parent, &r2.x, &r2.y, &r2.w, &r2.h);
4580            if (!eina_rectangles_intersect(&r1, &r2))
4581              return EINA_FALSE;
4582         }
4583    } while (parent && (parent != elm_widget_top_get(widget)));
4584
4585    return EINA_TRUE;
4586 }
4587
4588 EAPI Eina_Bool
4589 _elm_widget_item_onscreen_is(const Elm_Object_Item *item)
4590 {
4591    Eina_Rectangle r1, r2;
4592    Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4593    if (!id || !id->view) return EINA_FALSE;
4594
4595    if (!evas_object_visible_get(id->view))
4596      return EINA_FALSE;
4597
4598    if (!_elm_widget_onscreen_is(id->widget))
4599      return EINA_FALSE;
4600
4601    evas_object_geometry_get(id->view, &r1.x, &r1.y, &r1.w, &r1.h);
4602    if (eina_rectangle_is_empty(&r1))
4603      return EINA_FALSE;
4604
4605    evas_object_geometry_get(id->widget, &r2.x, &r2.y, &r2.w, &r2.h);
4606    if (!eina_rectangles_intersect(&r1, &r2))
4607      return EINA_FALSE;
4608
4609    return EINA_TRUE;
4610 }
4611
4612 const char*
4613 _elm_widget_accessible_plain_name_get(const Evas_Object *obj, const char* name)
4614 {
4615    char *accessible_plain_name;
4616
4617    API_ENTRY return NULL;
4618
4619    accessible_plain_name = _elm_util_mkup_to_text(name);
4620    eina_stringshare_del(sd->accessible_name);
4621    sd->accessible_name =  eina_stringshare_add(accessible_plain_name);
4622    free(accessible_plain_name);
4623    return sd->accessible_name;
4624 }
4625
4626 const char*
4627 _elm_widget_item_accessible_plain_name_get(const Elm_Object_Item *item, const char* name)
4628 {
4629    char *accessible_plain_name;
4630
4631    Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4632    if (!id) return NULL;
4633
4634    accessible_plain_name = _elm_util_mkup_to_text(name);
4635    eina_stringshare_del(id->accessible_name);
4636    id->accessible_name =  eina_stringshare_add(accessible_plain_name);
4637    free(accessible_plain_name);
4638    return id->accessible_name;
4639 }
4640
4641 EOLIAN static Efl_Access_State_Set
4642 _elm_widget_item_efl_access_object_state_set_get(const Eo *eo_item, Elm_Widget_Item_Data *item)
4643 {
4644    Efl_Access_State_Set states = 0;
4645
4646    // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
4647    // //TIZEN_ONLY(20171108): bring HIGHLIGHT related changes
4648    // Evas_Object *win = elm_widget_top_get(item->widget);
4649    // if (win && efl_isa(win, EFL_UI_WIN_CLASS))
4650    //   {
4651    //      if (_elm_win_accessibility_highlight_get(win) == item->view)
4652    //        STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
4653    //   }
4654    // STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
4655    // //
4656    //
4657
4658    STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSABLE);
4659
4660    if (elm_object_item_focus_get(eo_item))
4661      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSED);
4662    if (!elm_object_item_disabled_get(eo_item))
4663      {
4664         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_ENABLED);
4665         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SENSITIVE);
4666         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
4667      }
4668    if (_elm_widget_item_onscreen_is(eo_item))
4669      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SHOWING);
4670
4671    //TIZEN_ONLY(20170207) : [ATSPI] enhance expose highlight information on atspi
4672    /* unrealized genlist item does not have item->view,
4673       and item cannot change its visibility, only widget can change the visibility */
4674    if (evas_object_visible_get(item->widget))
4675      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
4676    //
4677
4678    //TIZEN_ONLY(20170717) : expose highlight information on atspi
4679    if (_elm_widget_item_highlightable((Eo *)eo_item) && _accessible_object_on_scroll_is(item->view))
4680      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
4681    else
4682      STATE_TYPE_UNSET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
4683
4684    if (_elm_object_accessibility_currently_highlighted_get() == (void*)item->eo_obj)
4685      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED);
4686    //
4687    return states;
4688 }
4689
4690 EAPI void
4691 elm_object_item_data_set(Elm_Object_Item *it, void *data)
4692 {
4693    WIDGET_ITEM_DATA_SET(it, data);
4694 }
4695
4696 EAPI void *
4697 elm_object_item_data_get(const Elm_Object_Item *it)
4698 {
4699    return (void *) WIDGET_ITEM_DATA_GET(it);
4700 }
4701
4702 EOLIAN static void
4703 _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED,
4704                               Elm_Widget_Item_Data *item,
4705                               Eina_Bool disabled)
4706 {
4707    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4708    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4709
4710    if (item->disabled == disabled) return;
4711    item->disabled = !!disabled;
4712    elm_wdg_item_disable(item->eo_obj);
4713 }
4714
4715 EOLIAN static Eina_Bool
4716 _elm_widget_item_disabled_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4717 {
4718    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
4719    return item->disabled;
4720 }
4721
4722 EOLIAN static void
4723 _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style)
4724 {
4725    eina_stringshare_replace(&item->style, style);
4726 }
4727
4728 EOLIAN static const char *
4729 _elm_widget_item_style_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4730 {
4731    return item->style;
4732 }
4733
4734 EOLIAN static void
4735 _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4736 {
4737 }
4738
4739 EOLIAN static void
4740 _elm_widget_item_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED)
4741 {
4742    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set");
4743 }
4744
4745 EOLIAN static Eina_Bool
4746 _elm_widget_item_item_focus_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4747 {
4748    ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get");
4749    return EINA_FALSE;
4750 }
4751
4752 EOLIAN static void
4753 _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED,
4754                                                    Elm_Widget_Item_Data *item,
4755                                                    const char *part,
4756                                                    const char *domain,
4757                                                    const char *label)
4758 {
4759    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4760    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4761    Elm_Translate_String_Data *ts;
4762
4763    if (!label)
4764      {
4765         _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE,
4766                                     EINA_FALSE);
4767      }
4768    else
4769      {
4770         ts = _part_text_translatable_set(&item->translate_strings, part,
4771                                          EINA_TRUE, EINA_FALSE);
4772         if (!ts) return;
4773         if (!ts->string) ts->string = eina_stringshare_add(label);
4774         else eina_stringshare_replace(&ts->string, label);
4775         if (!ts->domain) ts->domain = eina_stringshare_add(domain);
4776         else eina_stringshare_replace(&ts->domain, domain);
4777 #ifdef HAVE_GETTEXT
4778         if (label[0]) label = dgettext(domain, label);
4779 #endif
4780      }
4781    item->on_translate = EINA_TRUE;
4782    elm_wdg_item_part_text_set(item->eo_obj, part, label);
4783    item->on_translate = EINA_FALSE;
4784 }
4785
4786 EOLIAN static const char *
4787 _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED,
4788                                             Elm_Widget_Item_Data *item,
4789                                             const char *part)
4790 {
4791    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4792    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4793
4794    Elm_Translate_String_Data *ts;
4795    ts = _translate_string_data_get(item->translate_strings, part);
4796    if (ts) return ts->string;
4797    return NULL;
4798 }
4799
4800 EOLIAN static void
4801 _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED,
4802                                                    Elm_Widget_Item_Data *item,
4803                                                    const char *part,
4804                                                    const char *domain,
4805                                                    Eina_Bool translatable)
4806 {
4807    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4808    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4809    Elm_Translate_String_Data *ts;
4810    const char *text;
4811
4812    ts = _part_text_translatable_set(&item->translate_strings, part,
4813                                     translatable, EINA_TRUE);
4814    if (!ts) return;
4815    if (!ts->domain) ts->domain = eina_stringshare_add(domain);
4816    else eina_stringshare_replace(&ts->domain, domain);
4817
4818    text = elm_wdg_item_part_text_get(item->eo_obj, part);
4819
4820    if (!text || !text[0]) return;
4821
4822    if (!ts->string) ts->string = eina_stringshare_add(text);
4823
4824 //Try to translate text since we don't know the text is already translated.
4825 #ifdef HAVE_GETTEXT
4826    text = dgettext(domain, text);
4827 #endif
4828    item->on_translate = EINA_TRUE;
4829    elm_wdg_item_part_text_set(item->eo_obj, part, text);
4830    item->on_translate = EINA_FALSE;
4831 }
4832
4833 EOLIAN static void
4834 _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4835 {
4836    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4837    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4838
4839    if (!item->track_obj) return;
4840
4841    while (evas_object_ref_get(item->track_obj) > 0)
4842      evas_object_unref(item->track_obj);
4843
4844    evas_object_del(item->track_obj);
4845 }
4846
4847 EOLIAN static Evas_Object *
4848 _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4849 {
4850    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4851    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4852
4853    if (item->track_obj)
4854      {
4855         evas_object_ref(item->track_obj);
4856         return item->track_obj;
4857      }
4858
4859    if (!item->view)
4860      {
4861         WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item);
4862         return NULL;
4863      }
4864
4865    Evas_Object *track =
4866       evas_object_rectangle_add(evas_object_evas_get(item->widget));
4867    evas_object_color_set(track, 0, 0, 0, 0);
4868    evas_object_pass_events_set(track, EINA_TRUE);
4869    _track_obj_update(track, item->view);
4870    evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del,
4871                                   item);
4872
4873    efl_event_callback_array_add(item->view, tracker_callbacks(), item);
4874
4875    evas_object_ref(track);
4876
4877    item->track_obj = track;
4878
4879    return track;
4880 }
4881
4882 EOLIAN static void
4883 _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4884 {
4885    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4886    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4887
4888    if (!item->track_obj) return;
4889    evas_object_unref(item->track_obj);
4890
4891    if (evas_object_ref_get(item->track_obj) == 0)
4892      evas_object_del(item->track_obj);
4893 }
4894
4895 EOLIAN static int
4896 _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4897 {
4898    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0);
4899    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0);
4900
4901    if (!item->track_obj) return 0;
4902    return evas_object_ref_get(item->track_obj);
4903 }
4904
4905 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
4906
4907 struct _Elm_Widget_Item_Tooltip
4908 {
4909    Elm_Widget_Item_Data       *item;
4910    Elm_Tooltip_Item_Content_Cb func;
4911    Evas_Smart_Cb               del_cb;
4912    const void                 *data;
4913 };
4914
4915 static Evas_Object *
4916 _elm_widget_item_tooltip_label_create(void *data,
4917                                       Evas_Object *obj EINA_UNUSED,
4918                                       Evas_Object *tooltip,
4919                                       void *item EINA_UNUSED)
4920 {
4921    Evas_Object *label = elm_label_add(tooltip);
4922    if (!label)
4923      return NULL;
4924    elm_object_style_set(label, "tooltip");
4925    elm_object_text_set(label, data);
4926    return label;
4927 }
4928
4929 static Evas_Object *
4930 _elm_widget_item_tooltip_trans_label_create(void *data,
4931                                             Evas_Object *obj EINA_UNUSED,
4932                                             Evas_Object *tooltip,
4933                                             void *item EINA_UNUSED)
4934 {
4935    Evas_Object *label = elm_label_add(tooltip);
4936    if (!label)
4937      return NULL;
4938    elm_object_style_set(label, "tooltip");
4939    elm_object_translatable_text_set(label, data);
4940    return label;
4941 }
4942
4943 static void
4944 _elm_widget_item_tooltip_label_del_cb(void *data,
4945                                       Evas_Object *obj EINA_UNUSED,
4946                                       void *event_info EINA_UNUSED)
4947 {
4948    eina_stringshare_del(data);
4949 }
4950
4951 /**
4952  * @internal
4953  *
4954  * Set the text to be shown in the widget item.
4955  *
4956  * @param item Target item
4957  * @param text The text to set in the content
4958  *
4959  * Setup the text as tooltip to object. The item can have only one tooltip,
4960  * so any previous tooltip data is removed.
4961  *
4962  * @ingroup Widget
4963  */
4964 EOLIAN static void
4965 _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED,
4966                                   Elm_Widget_Item_Data *item EINA_UNUSED,
4967                                   const char *text)
4968 {
4969    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4970    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4971    EINA_SAFETY_ON_NULL_RETURN(text);
4972
4973    text = eina_stringshare_add(text);
4974    elm_wdg_item_tooltip_content_cb_set(item->eo_obj, _elm_widget_item_tooltip_label_create, text, _elm_widget_item_tooltip_label_del_cb);
4975 }
4976
4977 EOLIAN static void
4978 _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED,
4979                                                Elm_Widget_Item_Data *item EINA_UNUSED,
4980                                                const char *text)
4981 {
4982    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4983    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4984    EINA_SAFETY_ON_NULL_RETURN(text);
4985
4986    text = eina_stringshare_add(text);
4987    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);
4988 }
4989
4990 static Evas_Object *
4991 _elm_widget_item_tooltip_create(void *data,
4992                                 Evas_Object *obj,
4993                                 Evas_Object *tooltip)
4994 {
4995    Elm_Widget_Item_Tooltip *wit = data;
4996    return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj);
4997 }
4998
4999 static void
5000 _elm_widget_item_tooltip_del_cb(void *data,
5001                                 Evas_Object *obj,
5002                                 void *event_info EINA_UNUSED)
5003 {
5004    Elm_Widget_Item_Tooltip *wit = data;
5005    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj);
5006    free(wit);
5007 }
5008
5009 /**
5010  * @internal
5011  *
5012  * Set the content to be shown in the tooltip item
5013  *
5014  * Setup the tooltip to item. The item can have only one tooltip,
5015  * so any previous tooltip data is removed. @p func(with @p data) will
5016  * be called every time that need show the tooltip and it should
5017  * return a valid Evas_Object. This object is then managed fully by
5018  * tooltip system and is deleted when the tooltip is gone.
5019  *
5020  * @param item the widget item being attached a tooltip.
5021  * @param func the function used to create the tooltip contents.
5022  * @param data what to provide to @a func as callback data/context.
5023  * @param del_cb called when data is not needed anymore, either when
5024  *        another callback replaces @func, the tooltip is unset with
5025  *        elm_widget_item_tooltip_unset() or the owner @a item
5026  *        dies. This callback receives as the first parameter the
5027  *        given @a data, and @c event_info is the item.
5028  *
5029  * @ingroup Widget
5030  */
5031 EOLIAN static void
5032 _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED,
5033                                         Elm_Widget_Item_Data *item,
5034                                         Elm_Tooltip_Item_Content_Cb func,
5035                                         const void *data,
5036                                         Evas_Smart_Cb del_cb)
5037 {
5038    Elm_Widget_Item_Tooltip *wit;
5039
5040    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
5041    //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem);
5042
5043    if (!func)
5044      {
5045         elm_wdg_item_tooltip_unset(item->eo_obj);
5046         return;
5047      }
5048
5049    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
5050    if (!wit) goto error;
5051    wit->item = item;
5052    wit->func = func;
5053    wit->data = data;
5054    wit->del_cb = del_cb;
5055
5056    elm_object_sub_tooltip_content_cb_set
5057      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
5058      _elm_widget_item_tooltip_del_cb);
5059
5060    return;
5061
5062 error_noitem:
5063    if (del_cb) del_cb((void *)data, NULL, item);
5064    return;
5065 error:
5066    if (del_cb) del_cb((void *)data, item->widget, item);
5067 }
5068
5069 /**
5070  * @internal
5071  *
5072  * Unset tooltip from item
5073  *
5074  * @param item widget item to remove previously set tooltip.
5075  *
5076  * Remove tooltip from item. The callback provided as del_cb to
5077  * elm_widget_item_tooltip_content_cb_set() will be called to notify
5078  * it is not used anymore.
5079  *
5080  * @see elm_widget_item_tooltip_content_cb_set()
5081  *
5082  * @ingroup Widget
5083  */
5084 EOLIAN static void
5085 _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5086 {
5087    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5088    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5089
5090    elm_object_tooltip_unset(item->view);
5091 }
5092
5093 /**
5094  * @internal
5095  *
5096  * Sets a different style for this item tooltip.
5097  *
5098  * @note before you set a style you should define a tooltip with
5099  *       elm_widget_item_tooltip_content_cb_set() or
5100  *       elm_widget_item_tooltip_text_set()
5101  *
5102  * @param item widget item with tooltip already set.
5103  * @param style the theme style to use (default, transparent, ...)
5104  *
5105  * @ingroup Widget
5106  */
5107 EOLIAN static void
5108 _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED,
5109                                    Elm_Widget_Item_Data *item,
5110                                    const char *style)
5111 {
5112    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5113    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5114
5115    elm_object_tooltip_style_set(item->view, style);
5116 }
5117
5118 EOLIAN static Eina_Bool
5119 _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED,
5120                                          Elm_Widget_Item_Data *item,
5121                                          Eina_Bool disable)
5122 {
5123    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5124    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5125
5126    return elm_object_tooltip_window_mode_set(item->view, disable);
5127 }
5128
5129 EOLIAN static Eina_Bool
5130 _elm_widget_item_tooltip_window_mode_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5131 {
5132    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5133    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5134
5135    return elm_object_tooltip_window_mode_get(item->view);
5136 }
5137
5138 /**
5139  * @internal
5140  *
5141  * Get the style for this item tooltip.
5142  *
5143  * @param item widget item with tooltip already set.
5144  * @return style the theme style in use, defaults to "default". If the
5145  *         object does not have a tooltip set, then NULL is returned.
5146  *
5147  * @ingroup Widget
5148  */
5149 EOLIAN static const char *
5150 _elm_widget_item_tooltip_style_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5151 {
5152    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5153
5154    return elm_object_tooltip_style_get(item->view);
5155 }
5156
5157 EOLIAN static void
5158 _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED,
5159                             Elm_Widget_Item_Data *item,
5160                             const char *cursor)
5161 {
5162    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5163    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5164
5165    elm_object_sub_cursor_set(item->view, item->widget, cursor);
5166 }
5167
5168 EOLIAN static const char *
5169 _elm_widget_item_cursor_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5170 {
5171    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5172    return elm_object_sub_cursor_get(item->view);
5173 }
5174
5175 EOLIAN static void
5176 _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5177 {
5178    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5179    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5180
5181    elm_object_cursor_unset(item->view);
5182 }
5183
5184 /**
5185  * @internal
5186  *
5187  * Sets a different style for this item cursor.
5188  *
5189  * @note before you set a style you should define a cursor with
5190  *       elm_widget_item_cursor_set()
5191  *
5192  * @param item widget item with cursor already set.
5193  * @param style the theme style to use (default, transparent, ...)
5194  *
5195  * @ingroup Widget
5196  */
5197 EOLIAN static void
5198 _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED,
5199                                   Elm_Widget_Item_Data *item,
5200                                   const char *style)
5201 {
5202    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5203    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5204
5205    elm_object_sub_cursor_style_set(item->view, style);
5206 }
5207
5208 /**
5209  * @internal
5210  *
5211  * Get the style for this item cursor.
5212  *
5213  * @param item widget item with cursor already set.
5214  * @return style the theme style in use, defaults to "default". If the
5215  *         object does not have a cursor set, then NULL is returned.
5216  *
5217  * @ingroup Widget
5218  */
5219 EOLIAN static const char *
5220 _elm_widget_item_cursor_style_get(const Eo *eo_item EINA_UNUSED,
5221                                   Elm_Widget_Item_Data *item)
5222 {
5223    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5224    return elm_object_sub_cursor_style_get(item->view);
5225 }
5226
5227 /**
5228  * @internal
5229  *
5230  * Set if the cursor set should be searched on the theme or should use
5231  * the provided by the engine, only.
5232  *
5233  * @note before you set if should look on theme you should define a cursor
5234  * with elm_object_cursor_set(). By default it will only look for cursors
5235  * provided by the engine.
5236  *
5237  * @param item widget item with cursor already set.
5238  * @param engine_only boolean to define it cursors should be looked only
5239  * between the provided by the engine or searched on widget's theme as well.
5240  *
5241  * @ingroup Widget
5242  */
5243 EOLIAN static void
5244 _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED,
5245                                         Elm_Widget_Item_Data *item,
5246                                         Eina_Bool engine_only)
5247 {
5248    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5249    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5250
5251    elm_object_sub_cursor_theme_search_enabled_set(item->view, !engine_only);
5252 }
5253
5254 /**
5255  * @internal
5256  *
5257  * Get the cursor engine only usage for this item cursor.
5258  *
5259  * @param item widget item with cursor already set.
5260  * @return engine_only boolean to define it cursors should be looked only
5261  * between the provided by the engine or searched on widget's theme as well. If
5262  *         the object does not have a cursor set, then EINA_FALSE is returned.
5263  *
5264  * @ingroup Widget
5265  */
5266 EOLIAN static Eina_Bool
5267 _elm_widget_item_cursor_engine_only_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5268 {
5269    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5270    return !elm_object_sub_cursor_theme_search_enabled_get(item->view);
5271 }
5272
5273 EOLIAN static void
5274 _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED,
5275                                   Elm_Widget_Item_Data *item,
5276                                   const char *part EINA_UNUSED,
5277                                   Evas_Object *content EINA_UNUSED)
5278 {
5279    ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()");
5280 }
5281
5282 EOLIAN static Evas_Object *
5283 _elm_widget_item_part_content_get(const Eo *eo_item EINA_UNUSED,
5284                                   Elm_Widget_Item_Data *item,
5285                                   const char *part EINA_UNUSED)
5286 {
5287    ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()");
5288    return NULL;
5289 }
5290
5291 EOLIAN static Evas_Object *
5292 _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED,
5293                                     Elm_Widget_Item_Data *item,
5294                                     const char *part EINA_UNUSED)
5295 {
5296    ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()");
5297    return NULL;
5298 }
5299
5300 EOLIAN static void
5301 _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
5302                                Elm_Widget_Item_Data *item,
5303                                const char *part EINA_UNUSED,
5304                                const char *label EINA_UNUSED)
5305 {
5306    ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()");
5307 }
5308
5309 EOLIAN static const char *
5310 _elm_widget_item_part_text_get(const Eo *eo_item EINA_UNUSED,
5311                                Elm_Widget_Item_Data *item,
5312                                const char *part EINA_UNUSED)
5313 {
5314    ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()");
5315    return NULL;
5316 }
5317
5318 static void
5319 _elm_widget_item_part_text_custom_free(void *data)
5320 {
5321    Elm_Label_Data *label;
5322    label = data;
5323    eina_stringshare_del(label->part);
5324    eina_stringshare_del(label->text);
5325    free(label);
5326 }
5327
5328 EOLIAN static void
5329 _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED,
5330                                       Elm_Widget_Item_Data *item,
5331                                       const char *part,
5332                                       const char *text)
5333 {
5334    Elm_Label_Data *label;
5335    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5336    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5337
5338    if (!item->labels)
5339      item->labels =
5340         eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free);
5341    label = eina_hash_find(item->labels, part);
5342    if (!label)
5343      {
5344         label = malloc(sizeof(Elm_Label_Data));
5345         if (!label)
5346           {
5347              ERR("Failed to allocate memory");
5348              return;
5349           }
5350         label->part = eina_stringshare_add(part);
5351         label->text = eina_stringshare_add(text);
5352         eina_hash_add(item->labels, part, label);
5353      }
5354    else
5355      eina_stringshare_replace(&label->text, text);
5356 }
5357
5358 EOLIAN static const char *
5359 _elm_widget_item_part_text_custom_get(const Eo *eo_item EINA_UNUSED,
5360                                       Elm_Widget_Item_Data *item,
5361                                       const char *part)
5362 {
5363    Elm_Label_Data *label;
5364    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5365    label = eina_hash_find(item->labels, part);
5366    return label ? label->text : NULL;
5367 }
5368
5369 static Eina_Bool
5370 _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED,
5371                                           const void *key EINA_UNUSED,
5372                                           void *data,
5373                                           void *func_data)
5374 {
5375    Elm_Label_Data *label;
5376    Elm_Widget_Item_Data *item;
5377    label = data;
5378    item = func_data;
5379
5380    elm_wdg_item_part_text_set(item->eo_obj, label->part, label->text);
5381
5382    return EINA_TRUE;
5383 }
5384
5385 EOLIAN static void
5386 _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5387 {
5388    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5389    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5390    if (item->labels)
5391      eina_hash_foreach(item->labels,
5392                        _elm_widget_item_part_text_custom_foreach, item);
5393 }
5394
5395 EOLIAN static void
5396 _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
5397                              Elm_Widget_Item_Data *item EINA_UNUSED,
5398                              const char *emission EINA_UNUSED,
5399                              const char *source EINA_UNUSED)
5400 {
5401
5402 }
5403
5404 EOLIAN static void
5405 _elm_widget_item_signal_callback_add(Eo *eo_item,
5406                                      Elm_Widget_Item_Data *item,
5407                                      const char *emission,
5408                                      const char *source,
5409                                      Elm_Object_Item_Signal_Cb func,
5410                                      void *data)
5411 {
5412    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5413    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5414    EINA_SAFETY_ON_NULL_RETURN(func);
5415
5416    Elm_Widget_Item_Signal_Data *wisd;
5417
5418    wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
5419    if (!wisd) return;
5420
5421    wisd->item = eo_item;
5422    wisd->func = (Elm_Widget_Item_Signal_Cb)func;
5423    wisd->data = data;
5424    wisd->emission = eina_stringshare_add(emission);
5425    wisd->source = eina_stringshare_add(source);
5426
5427    if (_elm_widget_is(item->view))
5428      elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5429    else if (efl_isa(item->view, EFL_CANVAS_LAYOUT_CLASS))
5430      edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5431    else
5432      {
5433         WRN("The %s widget item doesn't support signal callback add!",
5434             efl_class_name_get(efl_class_get(item->widget)));
5435         free(wisd);
5436         return;
5437      }
5438
5439    item->signals = eina_list_append(item->signals, wisd);
5440 }
5441
5442 EOLIAN static void *
5443 _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED,
5444                                      Elm_Widget_Item_Data *item,
5445                                      const char *emission,
5446                                      const char *source,
5447                                      Elm_Object_Item_Signal_Cb func)
5448 {
5449    Elm_Widget_Item_Signal_Data *wisd;
5450    Eina_List *l;
5451
5452    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5453    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5454    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
5455
5456    EINA_LIST_FOREACH(item->signals, l, wisd)
5457      {
5458         if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) &&
5459             !strcmp(wisd->emission, emission) &&
5460             !strcmp(wisd->source, source))
5461           return _elm_widget_item_signal_callback_list_get(item, l);
5462      }
5463
5464    return NULL;
5465 }
5466
5467
5468
5469 EOLIAN static void
5470 _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED,
5471                                  Elm_Widget_Item_Data *item,
5472                                  const char *txt)
5473 {
5474    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5475    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5476
5477    eina_stringshare_del(item->access_info);
5478    if (!txt) item->access_info = NULL;
5479    else item->access_info = eina_stringshare_add(txt);
5480 }
5481
5482 EOLIAN static void
5483 _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5484 {
5485    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5486    ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5487
5488 #ifdef HAVE_GETTEXT
5489    Elm_Translate_String_Data *ts;
5490    EINA_INLIST_FOREACH(item->translate_strings, ts)
5491      {
5492         if (!ts->string) continue;
5493         const char *s = dgettext(ts->domain, ts->string);
5494         item->on_translate = EINA_TRUE;
5495         elm_wdg_item_part_text_set(item->eo_obj, ts->id, s);
5496         item->on_translate = EINA_FALSE;
5497      }
5498 #endif
5499 }
5500
5501 EOLIAN static void
5502 _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED,
5503                                   Elm_Widget_Item_Data *item,
5504                                   Eina_List *objs)
5505 {
5506    _elm_access_widget_item_access_order_set(item, objs);
5507 }
5508
5509 EOLIAN static const Eina_List *
5510 _elm_widget_item_access_order_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5511 {
5512    return _elm_access_widget_item_access_order_get(item);
5513 }
5514
5515 EOLIAN static void
5516 _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5517 {
5518    _elm_access_widget_item_access_order_unset(item);
5519 }
5520
5521 EOLIAN static Evas_Object*
5522 _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5523 {
5524    _elm_access_widget_item_register(item);
5525    return item->access_obj;
5526 }
5527
5528 EOLIAN static void
5529 _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5530 {
5531    _elm_access_widget_item_unregister(item);
5532 }
5533
5534 EOLIAN static Evas_Object*
5535 _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5536 {
5537    return item->access_obj;
5538 }
5539
5540 EOLIAN static Evas_Object *
5541 _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5542 {
5543    Evas_Object *ret = NULL;
5544
5545    if (dir == ELM_FOCUS_PREVIOUS)
5546      ret = item->focus_previous;
5547    else if (dir == ELM_FOCUS_NEXT)
5548      ret = item->focus_next;
5549    else if (dir == ELM_FOCUS_UP)
5550      ret = item->focus_up;
5551    else if (dir == ELM_FOCUS_DOWN)
5552      ret = item->focus_down;
5553    else if (dir == ELM_FOCUS_RIGHT)
5554      ret = item->focus_right;
5555    else if (dir == ELM_FOCUS_LEFT)
5556      ret = item->focus_left;
5557
5558    return ret;
5559 }
5560
5561 EOLIAN static void
5562 _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir)
5563 {
5564    if (dir == ELM_FOCUS_PREVIOUS)
5565      item->focus_previous = next;
5566    else if (dir == ELM_FOCUS_NEXT)
5567      item->focus_next = next;
5568    else if (dir == ELM_FOCUS_UP)
5569      item->focus_up = next;
5570    else if (dir == ELM_FOCUS_DOWN)
5571      item->focus_down = next;
5572    else if (dir == ELM_FOCUS_RIGHT)
5573      item->focus_right = next;
5574    else if (dir == ELM_FOCUS_LEFT)
5575      item->focus_left = next;
5576 }
5577
5578 EOLIAN static Elm_Object_Item*
5579 _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5580 {
5581    Elm_Object_Item *ret = NULL;
5582
5583    if (dir == ELM_FOCUS_PREVIOUS)
5584      ret = item->item_focus_previous;
5585    else if (dir == ELM_FOCUS_NEXT)
5586      ret = item->item_focus_next;
5587    else if (dir == ELM_FOCUS_UP)
5588      ret = item->item_focus_up;
5589    else if (dir == ELM_FOCUS_DOWN)
5590      ret = item->item_focus_down;
5591    else if (dir == ELM_FOCUS_RIGHT)
5592      ret = item->item_focus_right;
5593    else if (dir == ELM_FOCUS_LEFT)
5594      ret = item->item_focus_left;
5595
5596    return ret;
5597 }
5598
5599 EOLIAN static void
5600 _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)
5601 {
5602    if (dir == ELM_FOCUS_PREVIOUS)
5603      item->item_focus_previous = next_item;
5604    else if (dir == ELM_FOCUS_NEXT)
5605      item->item_focus_next = next_item;
5606    else if (dir == ELM_FOCUS_UP)
5607      item->item_focus_up = next_item;
5608    else if (dir == ELM_FOCUS_DOWN)
5609      item->item_focus_down = next_item;
5610    else if (dir == ELM_FOCUS_RIGHT)
5611      item->item_focus_right = next_item;
5612    else if (dir == ELM_FOCUS_LEFT)
5613      item->item_focus_left = next_item;
5614 }
5615
5616 /* happy debug functions */
5617 #ifdef ELM_DEBUG
5618 static void
5619 _sub_obj_tree_dump(const Evas_Object *obj,
5620                    int lvl)
5621 {
5622    int i;
5623
5624    for (i = 0; i < lvl * 3; i++)
5625      putchar(' ');
5626
5627    if (_elm_widget_is(obj))
5628      {
5629         Eina_List *l;
5630         INTERNAL_ENTRY;
5631         DBG("+ %s(%p)\n",
5632             elm_widget_type_get(obj),
5633             obj);
5634        for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
5635          {
5636             obj = eina_array_data_get(sd->children, i);
5637           _sub_obj_tree_dump(obj, lvl + 1);
5638          }
5639      }
5640    else
5641      DBG("+ %s(%p)\n", evas_object_type_get(obj), obj);
5642 }
5643
5644 static void
5645 _sub_obj_tree_dot_dump(const Evas_Object *obj,
5646                        FILE *output)
5647 {
5648    if (!_elm_widget_is(obj))
5649      return;
5650    INTERNAL_ENTRY;
5651
5652    Eina_Bool visible = evas_object_visible_get(obj);
5653    Eina_Bool disabled = elm_widget_disabled_get(obj);
5654    Eina_Bool focused = efl_ui_focus_object_focus_get(obj);
5655    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
5656
5657    if (sd->parent_obj)
5658      {
5659         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
5660
5661         if (focused)
5662           fprintf(output, ", style=bold");
5663
5664         if (!visible)
5665           fprintf(output, ", color=gray28");
5666
5667         fprintf(output, " ];\n");
5668      }
5669
5670    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
5671                    "disabled: %d|focused: %d/%d|focus order:%d}\"",
5672            obj, obj, elm_widget_type_get(obj),
5673            evas_object_name_get(obj), visible, disabled, focused, can_focus,
5674            sd->focus_order);
5675
5676    if (focused)
5677      fprintf(output, ", style=bold");
5678
5679    if (!visible)
5680      fprintf(output, ", fontcolor=gray28");
5681
5682    if ((disabled) || (!visible))
5683      fprintf(output, ", color=gray");
5684
5685    fprintf(output, " ];\n");
5686
5687    Eina_List *l;
5688    Evas_Object *o;
5689
5690    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
5691      {
5692         o = eina_array_data_get(sd->children, i);
5693         _sub_obj_tree_dot_dump(o, output);
5694      }
5695 }
5696
5697 #endif
5698
5699 EAPI void
5700 elm_widget_tree_dump(const Evas_Object *top)
5701 {
5702 #ifdef ELM_DEBUG
5703    if (!_elm_widget_is(top))
5704      return;
5705    _sub_obj_tree_dump(top, 0);
5706 #else
5707    (void)top;
5708    return;
5709 #endif
5710 }
5711
5712 EAPI void
5713 elm_widget_tree_dot_dump(const Evas_Object *top,
5714                          FILE *output)
5715 {
5716 #ifdef ELM_DEBUG
5717    if (!_elm_widget_is(top))
5718      return;
5719    fprintf(output, "graph " " { node [shape=record];\n");
5720    _sub_obj_tree_dot_dump(top, output);
5721    fprintf(output, "}\n");
5722 #else
5723    (void)top;
5724    (void)output;
5725    return;
5726 #endif
5727 }
5728
5729 EINA_UNUSED static void
5730 _focus_event_changed(void *data EINA_UNUSED, const Efl_Event *event)
5731 {
5732    if (efl_ui_focus_object_focus_get(event->object))
5733      evas_object_smart_callback_call(event->object, "focused", NULL);
5734    else
5735      evas_object_smart_callback_call(event->object, "unfocused", NULL);
5736 }
5737
5738 EOLIAN static Eo *
5739 _efl_ui_widget_efl_object_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
5740 {
5741    Eo *parent = efl_parent_get(obj);
5742    sd->on_create = EINA_TRUE;
5743
5744    sd->window = efl_provider_find(efl_parent_get(obj), EFL_UI_WIN_CLASS);
5745    if (!efl_isa(obj, EFL_UI_WIN_CLASS))
5746      {
5747         if (!efl_isa(parent, EFL_UI_WIDGET_CLASS))
5748           {
5749              ERR("You passed a wrong parent parameter (%p %s). "
5750                  "Elementary widget's parent should be an elementary widget.",
5751                  parent, evas_object_type_get(parent));
5752           }
5753         else
5754           {
5755              ELM_WIDGET_DATA_GET(parent, parent_sd);
5756              if (parent_sd)
5757                sd->shared_win_data = parent_sd->shared_win_data;
5758           }
5759      }
5760    else
5761      {
5762         sd->shared_win_data = efl_ui_win_shared_data_get(obj);
5763      }
5764
5765    _efl_ui_focus_event_redirector(obj, obj);
5766    efl_canvas_group_clipped_set(obj, EINA_FALSE);
5767    obj = efl_constructor(efl_super(obj, MY_CLASS));
5768    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
5769    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
5770
5771    if (!efl_isa(obj, EFL_UI_WIN_CLASS) && efl_isa(parent, EFL_UI_WIDGET_CLASS))
5772      efl_ui_widget_sub_object_add(parent, obj);
5773
5774    sd->on_create = EINA_FALSE;
5775
5776    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_UNKNOWN);
5777    //TIZEN_ONLY(20170717) : expose highlight information on atspi
5778    sd->can_highlight = EINA_TRUE;
5779    //
5780    /***********************************************************
5781     * TIZEN_ONLY(20180117): Override Paragraph Direction APIs *
5782     ***********************************************************/
5783    sd->inherit_paragraph_direction = EINA_TRUE;
5784
5785    if (efl_isa(parent, EFL_CANVAS_OBJECT_CLASS))
5786      {
5787         if (sd->paragraph_direction != efl_canvas_object_paragraph_direction_get(parent))
5788           {
5789              sd->paragraph_direction = efl_canvas_object_paragraph_direction_get(parent);
5790              _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(obj, sd, sd->paragraph_direction);
5791              efl_canvas_object_paragraph_direction_set(efl_super(obj, MY_CLASS), sd->paragraph_direction);
5792           }
5793      }
5794    /*******
5795     * END *
5796     *******/
5797
5798    if (!elm_widget_is_legacy(obj))
5799      EINA_SAFETY_ON_NULL_RETURN_VAL(sd->shared_win_data, NULL);
5800
5801    return obj;
5802 }
5803
5804 EOLIAN static Efl_Object*
5805 _efl_ui_widget_efl_object_finalize(Eo *obj, Elm_Widget_Smart_Data *pd)
5806 {
5807   Eo *eo;
5808
5809   eo = efl_finalize(efl_super(obj, MY_CLASS));
5810
5811   _full_eval(obj, pd);
5812
5813   return eo;
5814 }
5815
5816
5817 EOLIAN static void
5818 _efl_ui_widget_efl_object_destructor(Eo *obj, Elm_Widget_Smart_Data *sd)
5819 {
5820    if (sd->manager.provider)
5821      {
5822         sd->manager.provider = NULL;
5823      }
5824
5825    //TIZEN_ONLY : elm_widget_item: add at-spi name setter
5826    efl_access_object_description_set(obj, NULL);
5827    efl_access_object_i18n_name_set(obj, NULL);
5828
5829    efl_access_object_description_cb_set(obj, NULL, NULL);
5830    efl_access_object_name_cb_set(obj, NULL, NULL);
5831    //
5832    //TIZEN_ONLY(20170405) Add gesture method to accessible interface
5833    efl_access_object_gesture_cb_set(obj, NULL, NULL);
5834    //
5835    //TIZEN_ONLY : elm_widget_item: add at-spi name setter
5836    efl_access_object_translation_domain_set(obj, NULL);
5837    efl_access_object_relationships_clear(obj);
5838    //
5839
5840    efl_access_object_attributes_clear(obj);
5841    if (sd->logical.parent)
5842      {
5843         efl_weak_unref(&sd->logical.parent);
5844         sd->logical.parent = NULL;
5845      }
5846
5847    // TIZEN_ONLY(20150709) : atspi relations api
5848    if (sd->atspi_custom_relations)
5849      efl_access_relation_set_free(&sd->atspi_custom_relations);
5850    //
5851
5852    //TIZEN_ONLY(20150717) add widget name setter
5853    if (sd->name)
5854      eina_stringshare_del(sd->name);
5855    //
5856
5857    //TIZEN_ONLY(20150731) : add i18n support for name and description
5858    if (sd->atspi_translation_domain)
5859      eina_stringshare_del(sd->atspi_translation_domain);
5860    ///
5861
5862    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
5863    if (sd->color_classes)
5864      ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
5865    //
5866
5867    if (sd->children)
5868      {
5869         eina_array_free(sd->children);
5870         sd->children = NULL;
5871      }
5872
5873    sd->on_destroy = EINA_TRUE;
5874    efl_destructor(efl_super(obj, EFL_UI_WIDGET_CLASS));
5875    sd->on_destroy = EINA_FALSE;
5876 }
5877
5878 /* internal eo */
5879
5880 EOLIAN static void
5881 _efl_ui_widget_efl_object_debug_name_override(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Strbuf *sb)
5882 {
5883    const char *focus = "";
5884
5885    if (efl_ui_focus_object_focus_get(obj)) focus = ":focused";
5886    efl_debug_name_override(efl_super(obj, MY_CLASS), sb);
5887    eina_strbuf_append_printf(sb, "%s", focus);
5888 }
5889
5890 EOLIAN static Eina_Bool
5891 _efl_ui_widget_efl_ui_focus_object_on_focus_update(Eo *obj, Elm_Widget_Smart_Data *sd)
5892 {
5893    Eina_Bool focused;
5894
5895    if (!elm_widget_can_focus_get(obj))
5896      return EINA_FALSE;
5897
5898    focused = efl_ui_focus_object_focus_get(obj);
5899
5900    if (!sd->resize_obj)
5901      evas_object_focus_set(obj, focused);
5902
5903    //TIZEN_ONLY(20180607): Restore legacy focus
5904    if (focused)
5905      evas_object_smart_callback_call(obj, "focused", NULL);
5906    else
5907      evas_object_smart_callback_call(obj, "unfocused", NULL);
5908    //
5909
5910    if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
5911      efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_FOCUSED, focused);
5912
5913    return EINA_TRUE;
5914 }
5915
5916 EOLIAN static Eina_Bool
5917 _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)
5918 {
5919    return EINA_FALSE;
5920 }
5921
5922 EOLIAN static Eina_Bool
5923 _efl_ui_widget_on_access_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Ui_Activate act EINA_UNUSED)
5924 {
5925    WRN("The %s widget does not implement the \"activate\" functions.",
5926        efl_class_name_get(efl_class_get(obj)));
5927    return EINA_TRUE;
5928 }
5929
5930 EOLIAN static void
5931 _efl_ui_widget_class_constructor(Efl_Class *klass)
5932 {
5933    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
5934 }
5935
5936 EOLIAN static Eina_Bool
5937 _efl_ui_widget_efl_access_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
5938 {
5939    if (elm_object_focus_allow_get(obj))
5940      {
5941        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
5942        if (!ee) return EINA_FALSE;
5943        ecore_evas_activate(ee);
5944        elm_object_focus_set(obj, EINA_TRUE);
5945        return EINA_TRUE;
5946      }
5947    return EINA_FALSE;
5948 }
5949
5950
5951 EOLIAN static const char*
5952 _efl_ui_widget_efl_access_object_i18n_name_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
5953 {
5954    const char *ret, *name;
5955    name = efl_access_object_i18n_name_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
5956
5957    if (name) return name;
5958
5959    //TIZEN_ONLY(20150717) add widget name setter
5960    if (_pd->name)
5961      {
5962 #ifdef HAVE_GETTEXT
5963         if (_pd->atspi_translation_domain)
5964           return dgettext(_pd->atspi_translation_domain, _pd->name);
5965 #endif
5966         return _pd->name;
5967      }
5968    //
5969
5970    //TIZEN_ONLY(20170110) : Ignore text from elm_object_text_set in accessible_name_get
5971    Efl_Access_Role role;
5972    role = efl_access_object_role_get(obj);
5973    if(role == EFL_ACCESS_ROLE_DIALOG || role == EFL_ACCESS_ROLE_PASSWORD_TEXT)
5974      return NULL;
5975    //
5976
5977    ret = elm_object_text_get(obj);
5978    if (!ret) return NULL;
5979
5980    return _elm_widget_accessible_plain_name_get(obj, ret);
5981 }
5982
5983 EOLIAN static Eina_List*
5984 _efl_ui_widget_efl_access_object_access_children_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
5985 {
5986    Eina_List *l, *accs = NULL;
5987    Evas_Object *widget;
5988    Eo *proxy = NULL;
5989
5990    /* this is for webapp which is using window only */
5991    if (efl_access_object_role_get(obj) == EFL_ACCESS_ROLE_WINDOW)
5992      {
5993         if (evas_object_data_get(obj, "__PlugID"))
5994           elm_atspi_ewk_wrapper_a11y_init((Eo *)obj, (Eo *)obj);
5995      }
5996
5997    for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
5998      {
5999         widget = eina_array_data_get(pd->children, i);
6000         const char *type = evas_object_type_get(widget);
6001         // TIZEN ONLY
6002         // Ugly Tizen hack to integrate AT-SPI2 accessibility provided by WebKit/Chromium with elementary one.
6003         // This wrapper class should be implemented in Webkit/Chromium EFL ports
6004         if (type && (!strcmp(type, "EWebView") || !strcmp(type, "WebView")))
6005           {
6006              elm_atspi_ewk_wrapper_a11y_init((Eo *)obj, widget);
6007           }
6008      }
6009    for (unsigned int i = 0; i < eina_array_count(pd->children); ++i)
6010      {
6011         widget = eina_array_data_get(pd->children, i);
6012
6013         // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6014         /* This assumes that only one proxy exists in obj */
6015         if (!proxy)
6016           {
6017              proxy = plug_type_proxy_get(obj, widget);
6018              if (proxy)
6019                {
6020                   accs = eina_list_append(accs, proxy);
6021                   continue;
6022                }
6023           }
6024         //
6025         // TIZEN ONLY - END
6026         if (!elm_object_widget_check(widget)) continue;
6027         if (!efl_isa(widget, EFL_ACCESS_OBJECT_MIXIN)) continue;
6028         accs = eina_list_append(accs, widget);
6029      }
6030    //TIZEN_ONLY(20150709) : spatially sort atspi children
6031    // sort children using its top-left coordinate
6032    accs = eina_list_sort(accs, -1, _sort_vertically);
6033    Eina_List *line, *lines = _lines_split(accs);
6034    accs = NULL;
6035    EINA_LIST_FREE(lines, line)
6036      accs = eina_list_merge(accs, eina_list_sort(line, -1, _sort_horizontally));
6037    //
6038
6039   if (proxy)
6040     {
6041        Eo *deputy = NULL;
6042        accs = eina_list_remove(accs, proxy);
6043        EINA_LIST_FOREACH(accs, l, widget)
6044          {
6045              if (efl_isa(widget, ELM_ACCESS_CLASS))
6046                {
6047                   Elm_Access_Info *info = _elm_access_info_get(widget);
6048                   if (!info) continue;
6049                   if (obj == info->part_object)
6050                     {
6051                        deputy = widget;
6052                        break;
6053                     }
6054                }
6055          }
6056
6057        if (deputy)
6058          {
6059             accs = eina_list_append_relative(accs, proxy, deputy);
6060          }
6061     }
6062
6063    return accs;
6064 }
6065
6066 /* Legacy APIs */
6067
6068 EOLIAN static Efl_Access_State_Set
6069 _efl_ui_widget_efl_access_object_state_set_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6070 {
6071    Efl_Access_State_Set states = 0;
6072
6073    states = efl_access_object_state_set_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
6074
6075    // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
6076    // //TIZEN_ONLY(20171108): bring HIGHLIGHT related changes
6077    // Evas_Object *win = elm_widget_top_get(obj);
6078    // if (win && efl_isa(win, EFL_UI_WIN_CLASS))
6079    //   {
6080    //      if (_elm_win_accessibility_highlight_get(win) == obj)
6081    //        STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
6082    //   }
6083    // STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6084    // //
6085    //
6086
6087    if (evas_object_visible_get(obj))
6088      {
6089         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_VISIBLE);
6090         if (_elm_widget_onscreen_is(obj))
6091           STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SHOWING);
6092      }
6093    if (!elm_widget_child_can_focus_get(obj))
6094      {
6095         if (elm_object_focus_allow_get(obj))
6096           STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSABLE);
6097         if (elm_object_focus_get(obj))
6098           STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_FOCUSED);
6099      }
6100    if (!elm_object_disabled_get(obj))
6101      {
6102         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_ENABLED);
6103         STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_SENSITIVE);
6104      }
6105
6106    //TIZEN_ONLY(20170717) : expose highlight information on atspi
6107    if (_elm_widget_highlightable(obj))
6108      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
6109    else
6110      STATE_TYPE_UNSET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTABLE);
6111
6112    if (_elm_object_accessibility_currently_highlighted_get() == (void*)obj)
6113      STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED);
6114    //
6115
6116    return states;
6117 }
6118
6119 EOLIAN static Eina_List*
6120 _efl_ui_widget_efl_access_object_attributes_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6121 {
6122    const char *type = NULL;
6123    const char *style = NULL;
6124    Eina_List *attr_list = NULL;
6125    Efl_Access_Attribute *attr = NULL;
6126
6127    attr_list = efl_access_object_attributes_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
6128
6129    //Add type and style information in addition.
6130    type = elm_widget_type_get(obj);
6131    if (type)
6132      {
6133         attr = calloc(1, sizeof(Efl_Access_Attribute));
6134         if (attr)
6135           {
6136              attr->key = eina_stringshare_add("type");
6137              attr->value = eina_stringshare_add(type);
6138              attr_list = eina_list_append(attr_list, attr);
6139            }
6140      }
6141
6142    style = elm_widget_style_get(obj);
6143    if (style)
6144      {
6145         attr = calloc(1, sizeof(Efl_Access_Attribute));
6146         if (attr)
6147           {
6148              attr->key = eina_stringshare_add("style");
6149              attr->value = eina_stringshare_add(style);
6150              attr_list = eina_list_append(attr_list, attr);
6151           }
6152      }
6153
6154    return attr_list;
6155 }
6156
6157 EOLIAN static Eina_List *
6158 _elm_widget_item_efl_access_object_attributes_get(const Eo *eo_item, Elm_Widget_Item_Data *pd  EINA_UNUSED)
6159 {
6160    const char *style = NULL;
6161    Eina_List *attr_list = NULL;
6162    Efl_Access_Attribute *attr = NULL;
6163
6164    attr_list = efl_access_object_attributes_get(efl_super(eo_item, ELM_WIDGET_ITEM_CLASS));
6165
6166    style = elm_object_item_style_get(eo_item);
6167    if (style)
6168      {
6169         attr = calloc(1, sizeof(Efl_Access_Attribute));
6170         if (attr)
6171           {
6172              attr->key = eina_stringshare_add("style");
6173              attr->value = eina_stringshare_add(style);
6174              attr_list = eina_list_append(attr_list, attr);
6175           }
6176      }
6177    return attr_list;
6178 }
6179
6180 EOLIAN static Eina_Rect
6181 _elm_widget_item_efl_access_component_extents_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords)
6182 {
6183    Eina_Rect r = EINA_RECT(-1, -1, -1, -1);
6184
6185    if (!sd->view) return r;
6186
6187    r = efl_gfx_entity_geometry_get(sd->view);
6188    if (screen_coords)
6189      {
6190         r = _efl_access_component_screen_coords_extents_get(obj, r);
6191      }
6192    return r;
6193 }
6194
6195 EOLIAN static Eina_Bool
6196 _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)
6197 {
6198    return EINA_FALSE;
6199 }
6200
6201 EOLIAN static Eina_Bool
6202 _elm_widget_item_efl_access_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6203 {
6204    elm_object_item_focus_set(obj, EINA_TRUE);
6205    return elm_object_item_focus_get(obj);
6206 }
6207
6208 EOLIAN static Efl_Object *
6209 _efl_ui_widget_efl_object_provider_find(const Eo *obj, Elm_Widget_Smart_Data *pd, const Efl_Object *klass)
6210 {
6211    Efl_Object *lookup = NULL;
6212
6213    if ((klass == EFL_CONFIG_INTERFACE) || (klass == EFL_CONFIG_GLOBAL_CLASS))
6214      return _efl_config_obj;
6215
6216    if (klass == EFL_UI_WIN_CLASS)
6217      {
6218         if (pd->window)
6219           return pd->window;
6220         //let the parent_obj lookup handle this
6221      }
6222
6223    if (klass == EFL_ACCESS_OBJECT_MIXIN)
6224      return (Eo*)obj;
6225
6226    if (pd->provider_lookup) return NULL;
6227    pd->provider_lookup = EINA_TRUE;
6228
6229    lookup = efl_provider_find(efl_super(obj, MY_CLASS), klass);
6230    if (!lookup && pd->parent_obj) lookup = efl_provider_find(pd->parent_obj, klass);
6231
6232    pd->provider_lookup = EINA_FALSE;
6233
6234    return lookup;
6235 }
6236
6237 //TIZEN_ONLY(20191205): fix build warnings of focus_manager functions
6238 #pragma GCC diagnostic push
6239 #pragma GCC diagnostic ignored "-Wunused-function"
6240 //
6241
6242 EOLIAN static Efl_Ui_Focus_Manager*
6243 _efl_ui_widget_efl_ui_focus_object_focus_parent_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6244 {
6245    return pd->focus.parent;
6246 }
6247
6248 EOLIAN static Efl_Ui_Focus_Manager*
6249 _efl_ui_widget_efl_ui_focus_object_focus_manager_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6250 {
6251    return pd->focus.manager;
6252 }
6253
6254 EOLIAN static Eina_Rect
6255 _efl_ui_widget_efl_ui_focus_object_focus_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6256 {
6257    return efl_gfx_entity_geometry_get(obj);
6258 }
6259
6260 EOLIAN static void
6261 _efl_ui_widget_efl_ui_focus_object_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool focus)
6262 {
6263    pd->focused = focus;
6264
6265    efl_ui_focus_object_focus_set(efl_super(obj, MY_CLASS), focus);
6266
6267    efl_ui_focus_object_on_focus_update(obj);
6268 }
6269
6270 EOLIAN static Efl_Ui_Focus_Manager*
6271 _efl_ui_widget_focus_manager_create(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root EINA_UNUSED)
6272 {
6273    ERR("No manager presented");
6274    return NULL;
6275 }
6276
6277 //TIZEN_ONLY(20191205): fix build warnings of focus_manager functions
6278 #pragma GCC diagnostic pop
6279 //
6280
6281 //TIZEN_ONLY(20160726): add API elm_object_part_access_object_get
6282 EOLIAN static Evas_Object*
6283 _efl_ui_widget_part_access_object_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part EINA_UNUSED)
6284 {
6285    WRN("The %s widget does not implement the \"part_access_object_get\" functions.",
6286        efl_class_name_get(efl_class_get(obj)));
6287    return NULL;
6288 }
6289 //
6290
6291 /* Legacy APIs */
6292
6293 EAPI void
6294 elm_widget_on_show_region_hook_set(Eo *obj, void *data, Elm_Widget_On_Show_Region_Cb func, Eina_Free_Cb func_free_cb)
6295 {
6296    ELM_WIDGET_DATA_GET(obj, sd);
6297
6298    if (!sd) return;
6299    if ((sd->on_show_region_data == data) && (sd->on_show_region == func))
6300      return;
6301
6302    if (sd->on_show_region_data && sd->on_show_region_data_free)
6303      sd->on_show_region_data_free(sd->on_show_region_data);
6304
6305    sd->on_show_region = func;
6306    sd->on_show_region_data = data;
6307    sd->on_show_region_data_free = func_free_cb;
6308 }
6309
6310 EAPI void
6311 elm_widget_show_region_set(Eo *obj, Eina_Rect sr, Eina_Bool forceshow)
6312 {
6313    Evas_Object *parent_obj, *child_obj;
6314    Evas_Coord px, py, cx, cy, nx = 0, ny = 0;
6315
6316    ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd);
6317
6318    /*****************************************************************************
6319     * TIZEN_ONLY_FEATURE: Fix entry size/cursor/region calculation for Tizen UX *
6320     *****************************************************************************
6321     * Move this code to the below to update show region geometry properly.
6322    evas_smart_objects_calculate(evas_object_evas_get(obj));
6323     */
6324    /*******
6325     * END *
6326     *******/
6327
6328    if (!forceshow && eina_rectangle_equal(&sr.rect, &sd->show_region.rect)) return;
6329
6330    sd->show_region = sr;
6331
6332    /*****************************************************************************
6333     * TIZEN_ONLY_FEATURE: Fix entry size/cursor/region calculation for Tizen UX *
6334     *****************************************************************************/
6335    /* Block nested call for evas_smart_objects_calculate() and region showing works */
6336    if (sd->on_show_region_set) return;
6337
6338    sd->on_show_region_set = EINA_TRUE;
6339
6340    evas_smart_objects_calculate(evas_object_evas_get(obj));
6341
6342    sd->on_show_region_set = EINA_FALSE;
6343
6344    /* show_region geometry could be changed during processing elm_widget_show_region_set().
6345       evas_smart_objects_calculate() can trigger nested show_region_set calls */
6346    sr = sd->show_region;
6347    /*******
6348     * END *
6349     *******/
6350
6351    if (sd->on_show_region)
6352      {
6353         sd->on_show_region(sd->on_show_region_data, obj, sr);
6354
6355         if (_elm_scrollable_is(obj))
6356           {
6357              if (elm_widget_is_legacy(obj))
6358                {
6359                   elm_interface_scrollable_content_pos_get(obj, &nx, &ny);
6360                   sr.x -= nx;
6361                   sr.y -= ny;
6362                }
6363              else
6364                {
6365                   Eina_Position2D pos;
6366                   pos = efl_ui_scrollable_content_pos_get(obj);
6367                   sr.x -= pos.x;
6368                   sr.y -= pos.y;
6369                }
6370           }
6371      }
6372    child_obj = obj;
6373    do
6374      {
6375         parent_obj = sd->parent_obj;
6376         if ((!parent_obj)) break;
6377         sd = efl_data_scope_get(parent_obj, MY_CLASS);
6378         if (!sd) break;
6379
6380         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
6381         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
6382
6383         sr.x += (cx - px);
6384         sr.y += (cy - py);
6385         sd->show_region = sr;
6386
6387         if (sd->on_show_region)
6388           sd->on_show_region(sd->on_show_region_data, parent_obj, sr);
6389         child_obj = parent_obj;
6390      }
6391    while (parent_obj);
6392 }
6393
6394 EAPI Eina_Rect
6395 elm_widget_show_region_get(const Eo *obj)
6396 {
6397    ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd, EINA_RECT_EMPTY());
6398    return (Eina_Rect) sd->show_region;
6399 }
6400 /* elm_object_content_xxx APIs are supposed to work on all objects for which
6401  * elm_object_widget_check() returns true. The below checks avoid printing out
6402  * undesired ERR messages. */
6403 EAPI void
6404 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
6405 {
6406    ELM_WIDGET_CHECK(obj);
6407    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6408      {
6409         elm_layout_content_set(obj, part, content);
6410         return;
6411      }
6412    if (!efl_isa(obj, EFL_PART_INTERFACE)) return;
6413    if (!part)
6414      {
6415         part = efl_ui_widget_default_content_part_get(obj);
6416         if (!part) return;
6417      }
6418    efl_content_set(efl_part(obj, part), content);
6419 }
6420
6421 EAPI Evas_Object *
6422 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
6423 {
6424    ELM_WIDGET_CHECK(obj) NULL;
6425    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6426      return elm_layout_content_get(obj, part);
6427    if (!efl_isa(obj, EFL_PART_INTERFACE)) return NULL;
6428    if (!part)
6429      {
6430         part = efl_ui_widget_default_content_part_get(obj);
6431         if (!part) return NULL;
6432      }
6433    return efl_content_get(efl_part(obj, part));
6434 }
6435
6436 EAPI Evas_Object *
6437 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
6438 {
6439    ELM_WIDGET_CHECK(obj) NULL;
6440    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6441      return elm_layout_content_unset(obj, part);
6442    if (!efl_isa(obj, EFL_PART_INTERFACE)) return NULL;
6443    if (!part)
6444      {
6445         part = efl_ui_widget_default_content_part_get(obj);
6446         if (!part) return NULL;
6447      }
6448    return efl_content_unset(efl_part(obj, part));
6449 }
6450
6451 EAPI void
6452 elm_widget_signal_emit(Eo *obj, const char *emission, const char *source)
6453 {
6454    ELM_WIDGET_CHECK(obj);
6455
6456    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
6457      elm_layout_signal_emit(obj, emission, source);
6458    else if (evas_object_smart_type_check(obj, "elm_icon"))
6459      {
6460         WRN("Deprecated function. This functionality on icon objects"
6461             " will be dropped on a next release.");
6462         _elm_icon_signal_emit(obj, emission, source);
6463      }
6464 }
6465
6466 EAPI void
6467 elm_widget_signal_callback_add(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
6468 {
6469    ELM_WIDGET_CHECK(obj);
6470    EINA_SAFETY_ON_NULL_RETURN(func);
6471    if (evas_object_smart_type_check(obj, "elm_layout"))
6472      elm_layout_signal_callback_add(obj, emission, source, func, data);
6473    else if (evas_object_smart_type_check(obj, "elm_icon"))
6474      {
6475         WRN("Deprecated function. This functionality on icon objects"
6476             " will be dropped on a next release.");
6477
6478         _elm_icon_signal_callback_add(obj, emission, source, func, data);
6479      }
6480 }
6481
6482 EAPI void *
6483 elm_widget_signal_callback_del(Eo *obj, const char *emission, const char *source, Edje_Signal_Cb func)
6484 {
6485    void *data = NULL;
6486
6487    ELM_WIDGET_CHECK(obj) NULL;
6488    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
6489    if (evas_object_smart_type_check(obj, "elm_layout"))
6490      data = elm_layout_signal_callback_del(obj, emission, source, func);
6491    else if (evas_object_smart_type_check(obj, "elm_icon"))
6492      {
6493         WRN("Deprecated function. This functionality on icon objects"
6494             " will be dropped on a next release.");
6495
6496         data = _elm_icon_signal_callback_del(obj, emission, source, func);
6497      }
6498
6499    return data;
6500 }
6501
6502
6503 /* Widget Shadow Begin */
6504
6505 typedef struct _Widget_Shadow
6506 {
6507    Eo *widget;
6508    Eo *surface;
6509    struct {
6510       double rx, ry, ox, oy, grow;
6511       int r, g, b, a;
6512    } props;
6513    Eina_Stringshare *code, *name;
6514 } Widget_Shadow;
6515
6516 static void _widget_shadow_update(Widget_Shadow *shadow);
6517
6518 static void
6519 _widget_shadow_del_cb(void *data, const Efl_Event *ev EINA_UNUSED)
6520 {
6521    Widget_Shadow *shadow = data;
6522
6523    efl_del(shadow->surface);
6524    free(shadow);
6525 }
6526
6527 static void
6528 _widget_shadow_event_cb(void *data, const Efl_Event *ev EINA_UNUSED)
6529 {
6530    Widget_Shadow *shadow = data;
6531    _widget_shadow_update(shadow);
6532 }
6533
6534 EFL_CALLBACKS_ARRAY_DEFINE(widget_shadow_cb,
6535 { EFL_EVENT_DEL, _widget_shadow_del_cb },
6536 { EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _widget_shadow_event_cb },
6537 { EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _widget_shadow_event_cb },
6538 { EFL_GFX_ENTITY_EVENT_STACKING_CHANGED, _widget_shadow_event_cb },
6539 { EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, _widget_shadow_event_cb });
6540
6541 static Widget_Shadow *
6542 _widget_shadow_part_get(const Eo *part_obj)
6543 {
6544    Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS);
6545    Widget_Shadow *shadow;
6546    Eo *widget = pd->obj;
6547
6548    shadow = efl_key_data_get(widget, "__elm_shadow");
6549    if (!shadow)
6550      {
6551         shadow = calloc(1, sizeof(*shadow));
6552         if (!shadow) return NULL;
6553         shadow->widget = pd->obj;
6554         efl_key_data_set(widget, "__elm_shadow", shadow);
6555         efl_event_callback_array_add(widget, widget_shadow_cb(), shadow);
6556      }
6557    return shadow;
6558 }
6559
6560 static void
6561 _widget_shadow_update(Widget_Shadow *ws)
6562 {
6563    int l = 0, r = 0, t = 0, b = 0;
6564    Eina_Rect srect, wrect;
6565    char filter[1024];
6566
6567 #define FILTER_FMT \
6568    "a = buffer { 'alpha' }" \
6569    "grow { %f, dst = a, alphaonly = true }" \
6570    "blur { src = a, rx = %f, ry = %f, color = color(%d,%d,%d,%d) }"
6571
6572    if (!ws->surface)
6573      {
6574         ws->surface = efl_add(EFL_CANVAS_PROXY_CLASS, ws->widget);
6575         efl_gfx_fill_auto_set(ws->surface, 1);
6576         efl_canvas_proxy_source_clip_set(ws->surface, EINA_FALSE);
6577         efl_canvas_proxy_source_events_set(ws->surface, EINA_FALSE);
6578         efl_canvas_proxy_source_set(ws->surface, ws->widget);
6579      }
6580
6581    if (!ws->code)
6582      {
6583         snprintf(filter, sizeof(filter), FILTER_FMT,
6584                  ws->props.grow, ws->props.rx, ws->props.ry,
6585                  ws->props.r, ws->props.g, ws->props.b, ws->props.a);
6586      }
6587
6588    efl_gfx_filter_program_set(ws->surface,
6589                               ws->code ? ws->code : filter,
6590                               ws->name ? ws->name : "shadow");
6591    efl_gfx_filter_padding_get(ws->surface, &l, &r, &t, &b);
6592
6593    wrect = efl_gfx_entity_geometry_get(ws->widget);
6594    srect.x = wrect.x + (int) (-l + ws->props.ox);
6595    srect.y = wrect.y + (int) (-t + ws->props.oy);
6596    srect.w = wrect.w + (int) (l + r);
6597    srect.h = wrect.h + (int) (t + b);
6598
6599    if ((!ws->props.a && !ws->code) ||
6600        !efl_gfx_entity_visible_get(ws->widget))
6601      {
6602         efl_gfx_entity_visible_set(ws->surface, EINA_FALSE);
6603         return;
6604      }
6605
6606    efl_canvas_object_clipper_set(ws->surface, efl_canvas_object_clipper_get(ws->widget));
6607    efl_canvas_group_member_add(efl_canvas_object_render_parent_get(ws->widget), ws->surface);
6608    efl_gfx_entity_geometry_set(ws->surface, srect);
6609    efl_gfx_stack_below(ws->surface, ws->widget);
6610    efl_gfx_entity_visible_set(ws->surface, EINA_TRUE);
6611 }
6612
6613 static void
6614 _elm_widget_shadow_update(Efl_Ui_Widget *obj)
6615 {
6616    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6617    _widget_shadow_update(shadow);
6618 }
6619
6620 EOLIAN static void
6621 _efl_ui_widget_part_shadow_efl_gfx_blur_offset_set(Eo *obj, void *_pd EINA_UNUSED, double ox, double oy)
6622 {
6623    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6624    shadow->props.ox = ox;
6625    shadow->props.oy = oy;
6626    _widget_shadow_update(shadow);
6627 }
6628
6629 EOLIAN static void
6630 _efl_ui_widget_part_shadow_efl_gfx_blur_offset_get(const Eo *obj, void *_pd EINA_UNUSED, double *ox, double *oy)
6631 {
6632    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6633    if (ox) *ox = shadow->props.ox;
6634    if (oy) *oy = shadow->props.oy;
6635 }
6636
6637 EOLIAN static void
6638 _efl_ui_widget_part_shadow_efl_gfx_blur_radius_set(Eo *obj, void *_pd EINA_UNUSED, double rx, double ry)
6639 {
6640    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6641    shadow->props.rx = rx;
6642    shadow->props.ry = ry;
6643    _widget_shadow_update(shadow);
6644 }
6645
6646 EOLIAN static void
6647 _efl_ui_widget_part_shadow_efl_gfx_blur_radius_get(const Eo *obj, void *_pd EINA_UNUSED, double *rx, double *ry)
6648 {
6649    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6650    if (rx) *rx = shadow->props.rx;
6651    if (ry) *ry = shadow->props.ry;
6652 }
6653
6654 EOLIAN static void
6655 _efl_ui_widget_part_shadow_efl_gfx_color_color_set(Eo *obj, void *_pd EINA_UNUSED, int r, int g, int b, int a)
6656 {
6657    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6658    shadow->props.r = r;
6659    shadow->props.g = g;
6660    shadow->props.b = b;
6661    shadow->props.a = a;
6662    _widget_shadow_update(shadow);
6663 }
6664
6665 EOLIAN static void
6666 _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)
6667 {
6668    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6669    if (r) *r = shadow->props.r;
6670    if (g) *g = shadow->props.g;
6671    if (b) *b = shadow->props.b;
6672    if (a) *a = shadow->props.a;
6673 }
6674
6675 EOLIAN static void
6676 _efl_ui_widget_part_shadow_efl_gfx_blur_grow_set(Eo *obj, void *_pd EINA_UNUSED, double radius)
6677 {
6678    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6679    shadow->props.grow = radius;
6680    _widget_shadow_update(shadow);
6681 }
6682
6683 EOLIAN static double
6684 _efl_ui_widget_part_shadow_efl_gfx_blur_grow_get(const Eo *obj, void *_pd EINA_UNUSED)
6685 {
6686    Widget_Shadow *shadow = _widget_shadow_part_get(obj);
6687    return shadow->props.grow;
6688 }
6689
6690 EOLIAN static void
6691 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_set(Eo *obj, void *_pd EINA_UNUSED, const char *code, const char *name)
6692 {
6693    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6694    eina_stringshare_replace(&ws->code, code);
6695    eina_stringshare_replace(&ws->name, name);
6696    _widget_shadow_update(ws);
6697 }
6698
6699 EOLIAN static void
6700 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_program_get(const Eo *obj, void *_pd EINA_UNUSED, const char **code, const char **name)
6701 {
6702    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6703    efl_gfx_filter_program_get(ws->surface, code, name);
6704 }
6705
6706 EOLIAN static void
6707 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_set(Eo *obj, void *_pd EINA_UNUSED, const char *name, Efl_Gfx_Entity *source)
6708 {
6709    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6710    _widget_shadow_update(ws);
6711    efl_gfx_filter_source_set(ws->surface, name, source);
6712 }
6713
6714 EOLIAN static Efl_Gfx_Entity *
6715 _efl_ui_widget_part_shadow_efl_gfx_filter_filter_source_get(const Eo *obj, void *_pd EINA_UNUSED, const char *name)
6716 {
6717    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6718    return efl_gfx_filter_source_get(ws->surface, name);
6719 }
6720
6721 EOLIAN static void
6722 _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)
6723 {
6724    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6725    _widget_shadow_update(ws);
6726    efl_gfx_filter_data_set(ws->surface, name, value, execute);
6727 }
6728
6729 EOLIAN static void
6730 _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)
6731 {
6732    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6733    efl_gfx_filter_data_get(ws->surface, name, value, execute);
6734 }
6735
6736 EOLIAN static void
6737 _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)
6738 {
6739    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6740    efl_gfx_filter_padding_get(ws->surface, l, r, t, b);
6741 }
6742
6743 EOLIAN static void
6744 _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)
6745 {
6746    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6747    efl_gfx_filter_state_set(ws->surface, cur_state, cur_val, next_state, next_val, pos);
6748 }
6749
6750 EOLIAN static void
6751 _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)
6752 {
6753    Widget_Shadow *ws = _widget_shadow_part_get(obj);
6754    efl_gfx_filter_state_get(ws->surface, cur_state, cur_val, next_state, next_val, pos);
6755 }
6756
6757 #include "efl_ui_widget_part_shadow.eo.c"
6758
6759 /* Widget Shadow End */
6760
6761
6762 /* Efl.Part implementation */
6763
6764 EOLIAN static Efl_Object *
6765 _efl_ui_widget_efl_part_part_get(const Eo *obj, Elm_Widget_Smart_Data *wd EINA_UNUSED, const char *part)
6766 {
6767    if (eina_streq(part, "background"))
6768      return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_BG_CLASS, obj, part);
6769    else if (eina_streq(part, "shadow"))
6770      return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_SHADOW_CLASS, obj, part);
6771    return ELM_PART_IMPLEMENT(EFL_UI_WIDGET_PART_CLASS, obj, part);
6772 }
6773
6774 EOLIAN static void \
6775 _efl_ui_widget_part_efl_object_destructor(Eo *obj, Elm_Part_Data *pd)
6776 {
6777    ELM_PART_HOOK;
6778    eina_tmpstr_del(pd->part);
6779    efl_destructor(efl_super(obj, EFL_UI_WIDGET_PART_CLASS));
6780 }
6781
6782 static Efl_Canvas_Layout_Part_Type
6783 _efl_ui_widget_part_efl_canvas_layout_part_type_provider_part_type_get(const Eo *obj EINA_UNUSED, Elm_Part_Data *pd)
6784 {
6785    Elm_Widget_Smart_Data *sd = efl_data_scope_safe_get(pd->obj, MY_CLASS);
6786    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EFL_CANVAS_LAYOUT_PART_TYPE_NONE);
6787    return efl_canvas_layout_part_type_get(efl_part(sd->resize_obj, pd->part));
6788 }
6789
6790 static Eina_Rect
6791 _efl_ui_widget_part_efl_gfx_entity_geometry_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, EINA_RECT_EMPTY());
6795    return efl_gfx_entity_geometry_get(efl_part(sd->resize_obj, pd->part));
6796 }
6797
6798 static Eina_Error
6799 _efl_ui_widget_part_efl_ui_property_bind_property_bind(Eo *obj, Elm_Part_Data *ppd,
6800                                                        const char *key, const char *property)
6801 {
6802    Efl_Ui_Widget_Data *pd;
6803    Eo *widget;
6804
6805    widget = efl_parent_get(obj);
6806    pd = efl_data_scope_get(widget, EFL_UI_WIDGET_CLASS);
6807
6808    return _efl_ui_property_bind(widget, obj, pd, ppd->part, key, property);
6809 }
6810
6811 #include "efl_ui_widget_part.eo.c"
6812
6813 /* Efl.Part end */
6814
6815 /* Efl.Part Bg implementation */
6816
6817 Efl_Canvas_Object *
6818 _efl_ui_widget_bg_get(const Efl_Ui_Widget *obj)
6819 {
6820    Elm_Widget_Smart_Data *sd = efl_data_scope_get(obj, MY_CLASS);
6821    Evas_Object *bg_obj = sd->bg;
6822
6823    if (!bg_obj)
6824      {
6825         bg_obj = efl_add(EFL_UI_BG_CLASS, (Eo *)obj);
6826         EINA_SAFETY_ON_NULL_RETURN_VAL(bg_obj, NULL);
6827         sd->bg = bg_obj;
6828         efl_canvas_group_member_add((Eo *)obj, sd->bg);
6829         evas_object_stack_below(sd->bg, sd->resize_obj);
6830         _smart_reconfigure((Eo*)obj, sd);
6831      }
6832
6833    return bg_obj;
6834 }
6835
6836 static inline Efl_Canvas_Object *
6837 efl_ui_widget_part_bg_get(const Eo *part_obj)
6838 {
6839    Elm_Part_Data *pd = efl_data_scope_get(part_obj, EFL_UI_WIDGET_PART_CLASS);
6840    return _efl_ui_widget_bg_get(pd->obj);
6841 }
6842
6843 EOLIAN static Eina_Error
6844 _efl_ui_widget_part_bg_efl_file_load(Eo *obj, void *pd EINA_UNUSED)
6845 {
6846    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6847
6848    return efl_file_load(bg_obj);
6849 }
6850
6851 EOLIAN static void
6852 _efl_ui_widget_part_bg_efl_file_unload(Eo *obj, void *pd EINA_UNUSED)
6853 {
6854    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6855
6856    efl_file_unload(bg_obj);
6857 }
6858
6859 EOLIAN static const char *
6860 _efl_ui_widget_part_bg_efl_file_file_get(const Eo *obj, void *pd EINA_UNUSED)
6861 {
6862    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6863
6864    return efl_file_get(bg_obj);
6865 }
6866
6867 EOLIAN static Eina_Error
6868 _efl_ui_widget_part_bg_efl_file_file_set(Eo *obj, void *pd EINA_UNUSED, const char *file)
6869 {
6870    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6871
6872    return efl_file_set(bg_obj, file);
6873 }
6874
6875 EOLIAN static const char *
6876 _efl_ui_widget_part_bg_efl_file_key_get(const Eo *obj, void *pd EINA_UNUSED)
6877 {
6878    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6879
6880    return efl_file_key_get(bg_obj);
6881 }
6882
6883 EOLIAN static void
6884 _efl_ui_widget_part_bg_efl_file_key_set(Eo *obj, void *pd EINA_UNUSED, const char *key)
6885 {
6886    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6887
6888    efl_file_key_set(bg_obj, key);
6889 }
6890
6891 EOLIAN static const Eina_File *
6892 _efl_ui_widget_part_bg_efl_file_mmap_get(const Eo *obj, void *pd EINA_UNUSED)
6893 {
6894    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6895
6896    return efl_file_mmap_get(bg_obj);
6897 }
6898
6899 EOLIAN static Eina_Error
6900 _efl_ui_widget_part_bg_efl_file_mmap_set(Eo *obj, void *pd EINA_UNUSED, const Eina_File *file)
6901 {
6902    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6903
6904    return efl_file_mmap_set(bg_obj, file);
6905 }
6906
6907 EOLIAN static void
6908 _efl_ui_widget_part_bg_efl_gfx_color_color_set(Eo *obj, void *pd EINA_UNUSED, int r, int g, int b, int a)
6909 {
6910    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6911
6912    efl_gfx_color_set(bg_obj, r, g, b, a);
6913 }
6914
6915 EOLIAN static void
6916 _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)
6917 {
6918    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6919
6920    efl_gfx_color_get(bg_obj, r, g, b, a);
6921 }
6922
6923 EOLIAN static Efl_Object*
6924 _efl_ui_widget_part_bg_efl_object_finalize(Eo *obj, void *pd EINA_UNUSED)
6925 {
6926    Evas_Object *bg_obj = efl_ui_widget_part_bg_get(obj);
6927
6928    efl_composite_attach(obj, bg_obj);
6929
6930    return efl_finalize(efl_super(obj, EFL_UI_WIDGET_PART_BG_CLASS));
6931 }
6932
6933
6934 typedef struct _Efl_Ui_Property_Bound Efl_Ui_Property_Bound;
6935 struct _Efl_Ui_Property_Bound
6936 {
6937    Eina_Stringshare *part; // Optional part to apply the property on
6938    Eina_Stringshare *key; // Local object property
6939    Eina_Stringshare *property; // Model property
6940    Eina_Future *f;
6941 };
6942
6943 static void
6944 _efl_ui_property_bind_free(void *data)
6945 {
6946    Efl_Ui_Property_Bound *prop = data;
6947
6948    eina_stringshare_del(prop->part);
6949    eina_stringshare_del(prop->key);
6950    eina_stringshare_del(prop->property);
6951    free(prop);
6952 }
6953
6954 static void
6955 _efl_ui_property_bind_clean(Eo *obj EINA_UNUSED,
6956                             void *data,
6957                             const Eina_Future *f EINA_UNUSED)
6958 {
6959    Efl_Ui_Property_Bound *prop = data;
6960
6961    prop->f = NULL;
6962 }
6963
6964 static void
6965 _efl_ui_property_bind_get(Eo *obj, Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
6966 {
6967    Eina_Value *value;
6968    Eina_Future *f;
6969    Eina_Error err;
6970    Eo *target;
6971
6972    // If there is no model set yet, no need to try anything
6973    if (!pd->properties.model) return ;
6974
6975    value = efl_model_property_get(pd->properties.model, prop->property);
6976    target = prop->part ? efl_part(obj, prop->part) : obj;
6977
6978    err = efl_property_reflection_set(target, prop->key, eina_value_reference_copy(value));
6979    eina_value_free(value);
6980
6981    if (!err) return ;
6982
6983    // Report back the error to the model
6984    if (prop->f) eina_future_cancel(prop->f);
6985    f = efl_model_property_set(pd->properties.model, prop->property,
6986                               eina_value_error_new(err));
6987    prop->f = efl_future_then(obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
6988 }
6989
6990 static void
6991 _efl_ui_property_bind_set(Eo *obj, Efl_Ui_Widget_Data *pd, Efl_Ui_Property_Bound *prop)
6992 {
6993    Eina_Value value;
6994    Eina_Future *f;
6995    Eo *target;
6996
6997    target = prop->part ? efl_part(obj, prop->part) : obj;
6998    value = efl_property_reflection_get(target, prop->key);
6999
7000    if (prop->f) eina_future_cancel(prop->f);
7001    f = efl_model_property_set(pd->properties.model, prop->property, eina_value_dup(&value));
7002    prop->f = efl_future_then(obj, f, .free = _efl_ui_property_bind_clean, .data = prop);
7003    eina_value_flush(&value);
7004 }
7005
7006 static void
7007 _efl_ui_model_property_bind_changed(void *data, const Efl_Event *event)
7008 {
7009    Efl_Model_Property_Event *evt = event->info;
7010    ELM_WIDGET_DATA_GET(data, pd);
7011    Eina_Array_Iterator it;
7012    const char *prop;
7013    unsigned int i;
7014
7015    if (!pd) return;
7016    EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
7017      {
7018         Efl_Ui_Property_Bound *lookup;
7019
7020         lookup = eina_hash_find(pd->properties.model_lookup, prop);
7021         if (lookup) _efl_ui_property_bind_get(data, pd, lookup);
7022      }
7023 }
7024
7025 static void
7026 _efl_ui_view_property_bind_changed(void *data, const Efl_Event *event)
7027 {
7028    Efl_Ui_Property_Event *evt = event->info;
7029    ELM_WIDGET_DATA_GET(data, pd);
7030    Eina_Array_Iterator it;
7031    Eina_Stringshare *prop;
7032    unsigned int i;
7033
7034    if (!pd) return;
7035    EINA_ARRAY_ITER_NEXT(evt->changed_properties, i, prop, it)
7036      {
7037         Efl_Ui_Property_Bound *lookup;
7038
7039         lookup = eina_hash_find(pd->properties.view_lookup, prop);
7040         if (lookup) _efl_ui_property_bind_set(data, pd, lookup);
7041      }
7042 }
7043
7044 static void
7045 _efl_ui_widget_model_update(Eo *obj, Efl_Ui_Widget_Data *pd)
7046 {
7047    Efl_Ui_Property_Bound *property;
7048    Eina_Iterator *it;
7049
7050    it = eina_hash_iterator_data_new(pd->properties.model_lookup);
7051    EINA_ITERATOR_FOREACH(it, property)
7052      _efl_ui_property_bind_get(obj, pd, property);
7053    eina_iterator_free(it);
7054 }
7055
7056 static void _efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event EINA_UNUSED);
7057 static void _efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED);
7058
7059 EFL_CALLBACKS_ARRAY_DEFINE(efl_ui_widget_model_provider_callbacks,
7060                            { EFL_EVENT_INVALIDATE, _efl_ui_widget_model_provider_invalidate },
7061                            { EFL_UI_VIEW_EVENT_MODEL_CHANGED, _efl_ui_widget_model_provider_model_change });
7062
7063 static void
7064 _efl_ui_widget_model_provider_model_change(void *data, const Efl_Event *event)
7065 {
7066    ELM_WIDGET_DATA_GET(data, pd);
7067
7068    if (!pd) return;
7069    efl_replace(&pd->properties.model,
7070                efl_ui_view_model_get(pd->properties.provider));
7071    _efl_ui_widget_model_update(data, pd);
7072
7073    efl_event_callback_call(data, EFL_UI_VIEW_EVENT_MODEL_CHANGED, event->info);
7074 }
7075
7076 static void
7077 _efl_ui_widget_model_provider_invalidate(void *data, const Efl_Event *event EINA_UNUSED)
7078 {
7079    ELM_WIDGET_DATA_GET(data, pd);
7080
7081    if (!pd) return;
7082    efl_event_callback_array_del(pd->properties.provider,
7083                                 efl_ui_widget_model_provider_callbacks(),
7084                                 data);
7085    efl_replace(&pd->properties.provider, NULL);
7086    efl_replace(&pd->properties.model, NULL);
7087    pd->properties.callback_to_provider = EINA_FALSE;
7088 }
7089
7090 static void
7091 _efl_ui_widget_model_register(Eo *obj, Efl_Ui_Widget_Data *pd)
7092 {
7093    if (pd->properties.registered) return ;
7094
7095    if (!pd->properties.model)
7096      {
7097         Efl_Model_Changed_Event ev;
7098
7099         efl_replace(&pd->properties.provider,
7100                     efl_provider_find(obj, EFL_MODEL_PROVIDER_CLASS));
7101         if (!pd->properties.provider) return ;
7102         if (!pd->properties.callback_to_provider)
7103           efl_event_callback_array_add(pd->properties.provider,
7104                                        efl_ui_widget_model_provider_callbacks(),
7105                                        obj);
7106         pd->properties.callback_to_provider = EINA_TRUE;
7107         efl_replace(&pd->properties.model,
7108                     efl_ui_view_model_get(pd->properties.provider));
7109
7110         if (!pd->properties.model) return ;
7111
7112         ev.current = pd->properties.model;
7113         ev.previous = NULL;
7114         efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
7115      }
7116
7117    if (!pd->properties.model) return ;
7118    if (!pd->properties.model_lookup) return ;
7119
7120    efl_event_callback_add(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
7121                           _efl_ui_model_property_bind_changed, obj);
7122    efl_event_callback_add(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
7123                           _efl_ui_view_property_bind_changed, obj);
7124    pd->properties.registered = EINA_TRUE;
7125 }
7126
7127 static void
7128 _efl_ui_widget_model_unregister(Eo *obj, Efl_Ui_Widget_Data *pd)
7129 {
7130    if (pd->properties.registered)
7131      {
7132         // Remove any existing handler that might exist for any reason
7133         efl_event_callback_del(pd->properties.model, EFL_MODEL_EVENT_PROPERTIES_CHANGED,
7134                                _efl_ui_model_property_bind_changed, obj);
7135         efl_event_callback_del(obj, EFL_UI_PROPERTY_BIND_EVENT_PROPERTIES_CHANGED,
7136                                _efl_ui_view_property_bind_changed, obj);
7137
7138         pd->properties.registered = EINA_FALSE;
7139      }
7140    // Invalidate must be called before setting a new model and even if no model is registered
7141    if (pd->properties.provider)
7142      _efl_ui_widget_model_provider_invalidate(obj, NULL);
7143 }
7144
7145 static Eina_Error
7146 _efl_ui_property_bind(Eo *widget, Eo *target, Efl_Ui_Widget_Data *pd,
7147                       const char *part, const char *key, const char *property)
7148 {
7149    Efl_Ui_Property_Bound *prop;
7150
7151    // Always check for a model and fetch a provider in case a bound property
7152    // is provided by a class down the hierarchy, but they still need to be notified
7153    // when a model change
7154    _efl_ui_widget_model_register(widget, pd);
7155
7156    // Check if the property is available from the reflection table of the object.
7157    if (!efl_property_reflection_exist(target, key)) return EFL_PROPERTY_ERROR_INVALID_KEY;
7158
7159    if (!pd->properties.model_lookup)
7160      {
7161         pd->properties.model_lookup = eina_hash_stringshared_new(_efl_ui_property_bind_free);
7162         pd->properties.view_lookup = eina_hash_stringshared_new(NULL);
7163      }
7164
7165    prop = calloc(1, sizeof (Efl_Ui_Property_Bound));
7166    if (!prop) return ENOMEM;
7167    prop->part = eina_stringshare_add(part);
7168    prop->key = eina_stringshare_add(key);
7169    prop->property = eina_stringshare_add(property);
7170
7171    eina_hash_direct_add(pd->properties.model_lookup, prop->property, prop);
7172    eina_hash_direct_add(pd->properties.view_lookup, prop->key, prop);
7173
7174    _efl_ui_property_bind_get(widget, pd, prop);
7175
7176    efl_event_callback_call(widget, EFL_UI_PROPERTY_BIND_EVENT_PROPERTY_BOUND, (void*) prop->key);
7177    // In case of part, we emit it also on the part so that the part too can act on it
7178    if (target)
7179      efl_event_callback_call(target, EFL_UI_PROPERTY_BIND_EVENT_PROPERTY_BOUND, (void*) prop->key);
7180
7181    return 0;
7182 }
7183
7184 static Eina_Error
7185 _efl_ui_widget_efl_ui_property_bind_property_bind(Eo *obj, Efl_Ui_Widget_Data *pd,
7186                                                   const char *key, const char *property)
7187 {
7188    return _efl_ui_property_bind(obj, obj, pd, NULL, key, property);
7189 }
7190
7191 static void
7192 _efl_ui_widget_efl_ui_view_model_set(Eo *obj,
7193                                      Efl_Ui_Widget_Data *pd,
7194                                      Efl_Model *model)
7195 {
7196    Efl_Model_Changed_Event ev;
7197
7198    ev.current = efl_ref(model);
7199    ev.previous = efl_ref(pd->properties.model);
7200
7201    _efl_ui_widget_model_unregister(obj, pd);
7202
7203    efl_replace(&pd->properties.model, model);
7204
7205    // Set the properties handler just in case
7206    _efl_ui_widget_model_register(obj, pd);
7207
7208    // In case the model set was NULL, but we did found a model provider
7209    // we shouldn't emit a second event. Otherwise we should.
7210    if (ev.current == pd->properties.model)
7211      efl_event_callback_call(obj, EFL_UI_VIEW_EVENT_MODEL_CHANGED, &ev);
7212
7213    if (pd->properties.model) _efl_ui_widget_model_update(obj, pd);
7214
7215    efl_unref(ev.current);
7216    efl_unref(ev.previous);
7217 }
7218
7219 static Efl_Model *
7220 _efl_ui_widget_efl_ui_view_model_get(const Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *pd)
7221 {
7222    return pd->properties.model;
7223 }
7224
7225 static void
7226 _efl_ui_widget_efl_object_invalidate(Eo *obj, Efl_Ui_Widget_Data *pd)
7227 {
7228    efl_invalidate(efl_super(obj, EFL_UI_WIDGET_CLASS));
7229
7230    _efl_ui_widget_model_unregister(obj, pd);
7231    efl_replace(&pd->properties.model, NULL);
7232
7233    if (pd->properties.view_lookup) eina_hash_free(pd->properties.view_lookup);
7234    pd->properties.view_lookup = NULL;
7235    if (pd->properties.model_lookup) eina_hash_free(pd->properties.model_lookup);
7236    pd->properties.model_lookup = NULL;
7237 }
7238
7239 #include "efl_ui_widget_part_bg.eo.c"
7240
7241 EAPI void
7242 efl_ui_widget_internal_set(Eo *obj, Eina_Bool b)
7243 {
7244    ELM_WIDGET_DATA_GET(obj, pd);
7245    EINA_SAFETY_ON_NULL_RETURN(pd);
7246
7247    pd->internal = b;
7248 }
7249
7250 EAPI Eina_Bool
7251 efl_ui_widget_internal_get(Eo *obj)
7252 {
7253    ELM_WIDGET_DATA_GET(obj, pd);
7254    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
7255
7256    return pd->internal;
7257 }
7258
7259 /* Efl.Part Bg end */
7260
7261
7262 /* Internal EO APIs and hidden overrides */
7263
7264 EFL_FUNC_BODY_CONST(efl_ui_widget_default_content_part_get, const char *, NULL)
7265 EFL_FUNC_BODY_CONST(efl_ui_widget_default_text_part_get, const char *, NULL)
7266
7267 ELM_PART_CONTENT_DEFAULT_GET(efl_ui_widget, NULL)
7268 ELM_PART_TEXT_DEFAULT_GET(efl_ui_widget, NULL)
7269
7270 /***********************************************************************************
7271  * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *
7272  ***********************************************************************************/
7273 /* Internal EO APIs and hidden overrides */
7274 EAPI EFL_FUNC_BODYV(elm_widget_class_color_set, Eina_Bool, EINA_FALSE,
7275                     EFL_FUNC_CALL(color_class, r, g, b, a),
7276                     const char *color_class, int r, int g, int b, int a)
7277 EAPI EFL_FUNC_BODYV(elm_widget_class_color_get, Eina_Bool, EINA_FALSE,
7278                     EFL_FUNC_CALL(color_class, r, g, b, a),
7279                     const char *color_class, int *r, int *g, int *b, int *a)
7280 EAPI EFL_FUNC_BODYV(elm_widget_class_color2_set, Eina_Bool, EINA_FALSE,
7281                     EFL_FUNC_CALL(color_class, r, g, b, a),
7282                     const char *color_class, int r, int g, int b, int a)
7283 EAPI EFL_FUNC_BODYV(elm_widget_class_color2_get, Eina_Bool, EINA_FALSE,
7284                     EFL_FUNC_CALL(color_class, r, g, b, a),
7285                     const char *color_class, int *r, int *g, int *b, int *a)
7286 EAPI EFL_FUNC_BODYV(elm_widget_class_color3_set, Eina_Bool, EINA_FALSE,
7287                     EFL_FUNC_CALL(color_class, r, g, b, a),
7288                     const char *color_class, int r, int g, int b, int a)
7289 EAPI EFL_FUNC_BODYV(elm_widget_class_color3_get, Eina_Bool, EINA_FALSE,
7290                     EFL_FUNC_CALL(color_class, r, g, b, a),
7291                     const char *color_class, int *r, int *g, int *b, int *a)
7292 EAPI EFL_VOID_FUNC_BODYV(elm_widget_class_color_del,
7293                          EFL_FUNC_CALL(color_class),
7294                          const char *color_class)
7295 EAPI EFL_VOID_FUNC_BODY(elm_widget_class_color_clear)
7296
7297 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);
7298 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);
7299 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);
7300 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);
7301 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);
7302 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);
7303 static void _elm_widget_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *color_class);
7304 static void _elm_widget_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd);
7305 /*******
7306  * END *
7307  *******/
7308
7309
7310 #define EFL_UI_WIDGET_EXTRA_OPS \
7311    EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_widget), \
7312    ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_widget), \
7313    ELM_PART_TEXT_DEFAULT_OPS(efl_ui_widget), \
7314    EFL_OBJECT_OP_FUNC(efl_canvas_object_is_frame_object_set, _efl_ui_widget_efl_canvas_object_is_frame_object_set), \
7315    EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_ui_widget_efl_object_dbg_info_get), \
7316 /***********************************************************************************  \
7317  * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *  \
7318  ***********************************************************************************/ \
7319    EFL_OBJECT_OP_FUNC(elm_widget_class_color_set, _elm_widget_class_color_set), \
7320    EFL_OBJECT_OP_FUNC(elm_widget_class_color_get, _elm_widget_class_color_get), \
7321    EFL_OBJECT_OP_FUNC(elm_widget_class_color2_set, _elm_widget_class_color2_set), \
7322    EFL_OBJECT_OP_FUNC(elm_widget_class_color2_get, _elm_widget_class_color2_get), \
7323    EFL_OBJECT_OP_FUNC(elm_widget_class_color3_set, _elm_widget_class_color3_set), \
7324    EFL_OBJECT_OP_FUNC(elm_widget_class_color3_get, _elm_widget_class_color3_get), \
7325    EFL_OBJECT_OP_FUNC(elm_widget_class_color_del, _elm_widget_class_color_del), \
7326    EFL_OBJECT_OP_FUNC(elm_widget_class_color_clear, _elm_widget_class_color_clear)
7327
7328 /*******
7329  * END *
7330  *******/
7331
7332 // TIZEN_ONLY(20150709) : atspi relations api
7333 EOLIAN static Efl_Access_Relation_Set
7334 _efl_ui_widget_efl_access_object_relation_set_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7335 {
7336    return efl_access_relation_set_clone(&sd->atspi_custom_relations);
7337 }
7338 EOLIAN static Eina_Bool
7339 _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)
7340 {
7341    return efl_access_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7342 }
7343
7344 EOLIAN static void
7345 _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)
7346 {
7347    efl_access_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7348 }
7349
7350 EOLIAN static void
7351 _efl_ui_widget_efl_access_object_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7352 {
7353    efl_access_relation_set_free(&sd->atspi_custom_relations);
7354    sd->atspi_custom_relations = NULL;
7355 }
7356
7357 EOLIAN static Elm_Atspi_Relation_Set
7358 _elm_widget_item_efl_access_object_relation_set_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
7359 {
7360    return efl_access_relation_set_clone(&sd->atspi_custom_relations);
7361 }
7362
7363 EOLIAN static Eina_Bool
7364 _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)
7365 {
7366    return efl_access_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7367 }
7368
7369 EOLIAN static void
7370 _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)
7371 {
7372    efl_access_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7373 }
7374
7375 EOLIAN static void
7376 _elm_widget_item_efl_access_object_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
7377 {
7378    efl_access_relation_set_free(&sd->atspi_custom_relations);
7379    sd->atspi_custom_relations = NULL;
7380 }
7381 //////////////////////////////
7382
7383 //TIZEN_ONLY(20160726): add API elm_atspi_accessible_can_highlight_set/get
7384 static Eina_Bool
7385 _children_highlight_check(Eo *obj)
7386 {
7387    Eina_List *children, *l;
7388    Eo *child;
7389
7390    if (_elm_object_accessibility_currently_highlighted_get() == (void *)obj)
7391      {
7392         efl_access_component_highlight_clear(obj);
7393         return EINA_TRUE;
7394      }
7395
7396    children = efl_access_object_access_children_get(obj);
7397    EINA_LIST_FOREACH(children, l, child)
7398      {
7399         if (_children_highlight_check(child)) return EINA_TRUE;
7400      }
7401
7402    return EINA_FALSE;
7403 }
7404
7405 EOLIAN static void
7406 _efl_ui_widget_efl_access_object_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Eina_Bool can_highlight)
7407 {
7408    if (!can_highlight) _children_highlight_check(obj);
7409    _pd->can_highlight = !!can_highlight;
7410 }
7411
7412 EOLIAN static Eina_Bool
7413 _efl_ui_widget_efl_access_object_can_highlight_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7414 {
7415    return _elm_widget_highlightable(obj);
7416 }
7417
7418 EOLIAN static void
7419 _elm_widget_item_efl_access_object_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, Eina_Bool can_highlight)
7420 {
7421    if (!can_highlight) _children_highlight_check(obj);
7422    _pd->can_highlight = !!can_highlight;
7423 }
7424
7425 EOLIAN static Eina_Bool
7426 _elm_widget_item_efl_access_object_can_highlight_get(const Eo *obj, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7427 {
7428    return _elm_widget_item_highlightable((Eo *)obj);
7429 }
7430 //
7431
7432 // TIZEN_ONLY(20150705): Genlist item align feature
7433 EAPI void
7434 elm_widget_scroll_item_align_enabled_set(Evas_Object *obj,
7435                                         Eina_Bool scroll_item_align_enable)
7436 {
7437    API_ENTRY return;
7438    if (sd->scroll_item_align_enable == scroll_item_align_enable) return;
7439    sd->scroll_item_align_enable = scroll_item_align_enable;
7440 }
7441
7442 EAPI Eina_Bool
7443 elm_widget_scroll_item_align_enabled_get(const Evas_Object *obj)
7444 {
7445    API_ENTRY return EINA_FALSE;
7446    return sd->scroll_item_align_enable;
7447 }
7448
7449
7450 //TIZEN_ONLY(20150717) add widget name setter
7451 EOLIAN void
7452 _efl_ui_widget_efl_access_object_i18n_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *name)
7453 {
7454    //TIZEN_ONLY(20220826): Remove markup from accessible name
7455    char *text;
7456
7457    text = _elm_util_mkup_to_text(name); // NULL is OK
7458    eina_stringshare_replace(&_pd->name, text);
7459    free(text);
7460    //
7461 }
7462 //
7463
7464 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
7465 EOLIAN void
7466 _efl_ui_widget_efl_access_object_description_set(Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data* _pd, const char *description)
7467 {
7468    if (_pd->description)
7469      eina_stringshare_del(_pd->description);
7470
7471    _pd->description = eina_stringshare_add(description);
7472 }
7473
7474 EOLIAN static const char*
7475 _efl_ui_widget_efl_access_object_description_get(const Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *_pd EINA_UNUSED)
7476 {
7477    const char *ret = NULL;
7478    ret = efl_access_object_description_get(efl_super(obj, EFL_UI_WIDGET_CLASS));
7479    if (ret) return ret;
7480
7481 #ifdef HAVE_GETTEXT
7482    if (_pd->atspi_translation_domain)
7483      return dgettext(_pd->atspi_translation_domain, _pd->description);
7484 #endif
7485    return _pd->description;
7486 }
7487 //
7488
7489 //TIZEN_ONLY(20171108): make atspi_proxy work
7490 static void
7491 _proxy_widget_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
7492 {
7493    Evas_Coord x, y;
7494    Eo *proxy = data;
7495
7496    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
7497    elm_atspi_bridge_utils_proxy_offset_set(proxy, x, y);
7498 }
7499
7500 static void
7501 _on_widget_del(void *data, const Efl_Event *event)
7502 {
7503    Eo *plug = data;
7504    evas_object_event_callback_del_full(event->object, EVAS_CALLBACK_MOVE,
7505                                        _proxy_widget_move_cb, plug);
7506    efl_access_object_attribute_del(event->object, "child_bus");
7507    efl_del(plug);
7508 }
7509
7510 static void
7511 _on_proxy_connected_cb(void *data, const Efl_Event *event)
7512 {
7513    Evas_Coord x, y;
7514    Evas_Object *widget = data;
7515
7516    evas_object_geometry_get(widget, &x, &y, NULL, NULL);
7517    elm_atspi_bridge_utils_proxy_offset_set(event->object, x, y);
7518
7519    evas_object_event_callback_add(widget, EVAS_CALLBACK_MOVE, _proxy_widget_move_cb, event->object);
7520 }
7521 //
7522
7523 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
7524 EOLIAN void
7525 _elm_widget_item_efl_access_object_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *description)
7526 {
7527    if (_pd->description)
7528      eina_stringshare_del(_pd->description);
7529
7530    _pd->description = eina_stringshare_add(description);
7531 }
7532
7533 EOLIAN const char*
7534 _elm_widget_item_efl_access_object_description_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7535 {
7536    const char *ret = NULL;
7537    ret = efl_access_object_description_get(efl_super(obj, ELM_WIDGET_ITEM_CLASS));
7538    if (ret) return ret;
7539
7540 #ifdef HAVE_GETTEXT
7541    if (_pd->atspi_translation_domain)
7542      return dgettext(_pd->atspi_translation_domain, _pd->description);
7543 #endif
7544    return _pd->description;
7545 }
7546 //
7547
7548 //TIZEN_ONLY(20150713) : add atspi name setter to widget_item
7549 EOLIAN void
7550 _elm_widget_item_efl_access_object_i18n_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *name)
7551 {
7552    //TIZEN_ONLY(20220826): Remove markup from accessible name
7553    char *text;
7554
7555    text = _elm_util_mkup_to_text(name); // NULL is OK
7556    eina_stringshare_replace(&_pd->name, text);
7557    free(text);
7558    //
7559 }
7560
7561 EOLIAN const char*
7562 _elm_widget_item_efl_access_object_i18n_name_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7563 {
7564    //TIZEN_ONLY(20190922): add name callback, description callback.
7565    const char *ret = NULL;
7566    ret = efl_access_object_i18n_name_get(efl_super(obj, ELM_WIDGET_ITEM_CLASS));
7567    if (ret) return ret;
7568    //
7569
7570    if (_pd->name)
7571      {
7572 #ifdef HAVE_GETTEXT
7573         if (_pd->atspi_translation_domain)
7574           return dgettext(_pd->atspi_translation_domain, _pd->name);
7575 #endif
7576         return _pd->name;
7577      }
7578
7579    return NULL;
7580 }
7581 ///
7582
7583 //TIZEN_ONLY(20150731) : add i18n support for name and description
7584 EOLIAN static void
7585 _efl_ui_widget_efl_access_object_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, const char *domain)
7586 {
7587    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7588 }
7589
7590 EOLIAN static const char*
7591 _efl_ui_widget_efl_access_object_translation_domain_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
7592 {
7593    return _pd->atspi_translation_domain;
7594 }
7595
7596 EOLIAN static void
7597 _elm_widget_item_efl_access_object_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, const char *domain)
7598 {
7599    eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7600 }
7601
7602 EOLIAN static const char*
7603 _elm_widget_item_efl_access_object_translation_domain_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd)
7604 {
7605    return _pd->atspi_translation_domain;
7606 }
7607 ///
7608
7609 static int _sort_vertically(const void *data1, const void *data2)
7610 {
7611    Evas_Coord y1, y2;
7612    evas_object_geometry_get(data1, NULL, &y1, NULL, NULL);
7613    evas_object_geometry_get(data2, NULL, &y2, NULL, NULL);
7614
7615    return y1 < y2 ? -1 : 1;
7616 }
7617
7618 static int _sort_horizontally(const void *data1, const void *data2)
7619 {
7620    Evas_Coord x1, x2;
7621    evas_object_geometry_get(data1, &x1, NULL, NULL, NULL);
7622    evas_object_geometry_get(data2, &x2, NULL, NULL, NULL);
7623
7624    return x1 < x2 ? -1 : 1;
7625 }
7626
7627 static Eina_List *_lines_split(Eina_List *children)
7628 {
7629    Eo *c;
7630    Eina_List *lines, *line, *l;
7631    Evas_Coord yl, y, hl, h;
7632    lines = line = NULL;
7633
7634    if (!children) return NULL;
7635
7636    EINA_LIST_FOREACH(children, l, c)
7637      {
7638         evas_object_geometry_get(c, NULL, &yl, NULL, &hl);
7639
7640         /* remove child if its height == 0 */
7641         if (hl != 0) break;
7642      }
7643
7644    EINA_LIST_FREE(children, c)
7645      {
7646         evas_object_geometry_get(c, NULL, &y, NULL, &h);
7647
7648         /* remove child if its height == 0 */
7649         if (h == 0) continue;
7650
7651         if ((yl + (int)(0.25 * hl)) >= y)
7652           {
7653              //same line
7654              line = eina_list_append(line,c);
7655           }
7656         else
7657           {
7658              // finish current line & start new
7659              lines = eina_list_append(lines, line);
7660              yl = y, hl = h;
7661              line = eina_list_append(NULL, c);
7662           }
7663      }
7664
7665    return eina_list_append(lines, line);
7666 }
7667 //
7668
7669 //TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
7670 Eo *
7671 plug_type_proxy_get(const Eo *obj, Evas_Object *widget)
7672 {
7673    Eo *proxy = NULL;
7674    const char *plug_id;
7675    char *svcname, *svcnum;
7676
7677    if ((plug_id = evas_object_data_get(widget, "___PLUGID")) != NULL)
7678      {
7679         // TIZEN_ONLY(20160930) : endless recursion fix
7680         efl_access_object_attribute_append(efl_super(obj, MY_CLASS), "___PlugID", plug_id);
7681         efl_access_object_role_set((Eo *)obj, EFL_ACCESS_ROLE_EMBEDDED);
7682
7683         proxy = evas_object_data_get(widget, "__widget_proxy");
7684         // TIZEN_ONLY(20171109) : fix for invalid proxy object, when at-spi has been restarted
7685         if (proxy)
7686           {
7687             if (!evas_object_data_get(proxy, "__proxy_invalid")) return proxy;
7688             evas_object_data_del(widget, "__widget_proxy");
7689           }
7690         //
7691
7692         if (_elm_atspi_bridge_plug_id_split(plug_id, &svcname, &svcnum))
7693           {
7694              proxy = _elm_atspi_bridge_utils_proxy_create((Eo *)obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
7695              evas_object_data_set(widget, "__widget_proxy", proxy);
7696              efl_event_callback_add(widget, EFL_EVENT_DEL, _on_widget_del, proxy);
7697              efl_event_callback_add(proxy, ELM_ATSPI_PROXY_EVENT_CONNECTED, _on_proxy_connected_cb, widget);
7698              elm_atspi_bridge_utils_proxy_connect(proxy);
7699              free(svcname);
7700              free(svcnum);
7701           }
7702      }
7703
7704    return proxy;
7705 }
7706
7707 EAPI Eo *
7708 elm_widget_atspi_plug_type_proxy_get(Evas_Object *obj)
7709 {
7710    Elm_Widget_Smart_Data *wd;
7711    Evas_Object *widget;
7712
7713    wd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
7714    if (!wd) return NULL;
7715
7716    Eo *proxy = NULL;
7717    for (unsigned int i = 0; i < eina_array_count(wd->children); ++i)
7718      {
7719         widget = eina_array_data_get(wd->children, i);
7720         proxy = plug_type_proxy_get(obj, widget);
7721         if (proxy) break;
7722      }
7723    return proxy;
7724 }
7725 //
7726
7727
7728 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
7729 EAPI Eina_Bool
7730 _elm_widget_highlightable(const Evas_Object *obj)
7731 {
7732    Eo *parent;
7733
7734    Elm_Widget_Smart_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
7735    if (!wd) return EINA_FALSE;
7736    if (!wd->can_highlight) return EINA_FALSE;
7737
7738    parent = efl_provider_find(efl_parent_get(obj), EFL_ACCESS_OBJECT_MIXIN);
7739    while (parent && !efl_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
7740      {
7741         //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
7742         if (!_elm_widget_can_highlight_get_by_class(parent)) return EINA_FALSE;
7743         //
7744         parent = efl_provider_find(efl_parent_get(parent), EFL_ACCESS_OBJECT_MIXIN);
7745      }
7746    return EINA_TRUE;
7747 }
7748 //
7749
7750 EAPI void
7751 elm_widget_scroll_item_valign_set(Evas_Object *obj,
7752                                   const char *scroll_item_valign)
7753 {
7754    API_ENTRY return;
7755    if (sd->scroll_item_valign) eina_stringshare_del(sd->scroll_item_valign);
7756    if (!scroll_item_valign) sd->scroll_item_valign = NULL;
7757    else sd->scroll_item_valign = eina_stringshare_add(scroll_item_valign);
7758 }
7759
7760 EAPI const char*
7761 elm_widget_scroll_item_valign_get(const Evas_Object *obj)
7762 {
7763    API_ENTRY return NULL;
7764    return sd->scroll_item_valign;
7765 }
7766 //
7767
7768 /* TIZEN_ONLY(20180504): add missing item class names and fix edje_class parse rule for legacy */
7769 const char *
7770 _elm_widget_item_legacy_type_get(const Evas_Object *obj)
7771 {
7772    const char *ret;
7773    int i;
7774
7775    ret = efl_class_name_get(efl_class_get(obj));
7776
7777    /* If the given widget is created for legacy,
7778     * convert type name to legacy. */
7779    for (i = 0; legacy_type_table[i][0] ; i++)
7780      {
7781         if (eina_streq(ret, legacy_type_table[i][0]))
7782           return legacy_type_table[i][1];
7783      }
7784
7785    return ret;
7786 }
7787 /* END */
7788
7789 EOLIAN static void
7790 _efl_ui_widget_focus_disabled_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7791 {
7792    efl_ui_widget_focus_tree_unfocusable_handle(obj);
7793 }
7794
7795 EOLIAN static unsigned int
7796 _efl_ui_widget_focus_order_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7797 {
7798    return sd->focus_order;
7799 }
7800
7801 EOLIAN static Evas_Object*
7802 _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)
7803 {
7804    Evas_Object *child, *cur, *best;
7805
7806    if (!evas_object_visible_get(obj)
7807        || (elm_widget_disabled_get(obj))
7808        || (elm_widget_tree_unfocusable_get(obj)))
7809      return NULL;
7810
7811    best = NULL;
7812    if (*newest_focus_order < sd->focus_order)
7813      {
7814         if (!can_focus_only || elm_widget_can_focus_get(obj))
7815           {
7816              *newest_focus_order = sd->focus_order;
7817              best = (Evas_Object *)obj;
7818           }
7819      }
7820    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
7821      {
7822         child = eina_array_data_get(sd->children, i);
7823         if (!_elm_widget_is(child)) continue;
7824
7825         cur = efl_ui_widget_newest_focus_order_get
7826            (child, newest_focus_order, can_focus_only);
7827         if (!cur) continue;
7828         best = cur;
7829      }
7830    return best;
7831 }
7832
7833 EOLIAN static Eina_Bool
7834 _efl_ui_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7835 {
7836    WRN("The %s widget does not implement the \"focus_next/focus_next_manager_is\" functions.",
7837        efl_class_name_get(efl_class_get(obj)));
7838    return EINA_FALSE;
7839 }
7840
7841 static Eina_Bool
7842 _efl_ui_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7843 {
7844    WRN("The %s widget does not implement the \"focus_direction/focus_direction_manager_is\" functions.",
7845        efl_class_name_get(efl_class_get(obj)));
7846    return EINA_FALSE;
7847 }
7848 //
7849 //TIZEN_ONLY(20180607): Restore legacy focus
7850 EOLIAN static void
7851 _efl_ui_widget_focus_mouse_up_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7852 {
7853    if (!obj) return;
7854    if (!_is_focusable(obj)) return;
7855
7856    efl_ui_widget_focus_steal(obj, NULL);
7857 }
7858
7859 //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
7860 static Eina_Bool
7861 _elm_widget_can_highlight_get_by_class(Eo *obj)
7862 {
7863    if (efl_isa(obj, ELM_WIDGET_ITEM_CLASS))
7864      {
7865         Elm_Widget_Item_Data *id = efl_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
7866         if (!id) return EINA_FALSE;
7867         if (!id->can_highlight) return EINA_FALSE;
7868      }
7869    else
7870      {
7871         Elm_Widget_Smart_Data *wd = efl_data_scope_get(obj, EFL_UI_WIDGET_CLASS);
7872         if (!wd) return EINA_FALSE;
7873         if (!wd->can_highlight) return EINA_FALSE;
7874      }
7875    return EINA_TRUE;
7876 }
7877 //
7878
7879 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
7880 EAPI Eina_Bool
7881 _elm_widget_item_highlightable(Elm_Object_Item *item)
7882 {
7883    Eo *parent;
7884
7885    Elm_Widget_Item_Data *id = efl_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
7886    if (!id) return EINA_FALSE;
7887    if (!id->can_highlight) return EINA_FALSE;
7888
7889    parent = efl_provider_find(efl_parent_get(item), EFL_ACCESS_OBJECT_MIXIN);
7890    while (parent && !efl_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
7891      {
7892         //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
7893         if (!_elm_widget_can_highlight_get_by_class(parent)) return EINA_FALSE;
7894         //
7895         parent = efl_provider_find(efl_parent_get(parent), EFL_ACCESS_OBJECT_MIXIN);
7896      }
7897    return EINA_TRUE;
7898 }
7899 //
7900
7901 //TIZEN_ONLY(20170206): Add check the object is in the scroller content size
7902 static Eina_Bool
7903 _accessible_object_on_scroll_is(Eo* obj)
7904 {
7905    /* in case of genlist item, the item->view is NULL if item is unrealized.
7906       this function is used to check if obj could have HIGHLIGHTABLE or not.
7907       the unrealized genlist item should have HIGHLIGHTABLE state.
7908       so if obj is NULL return EINA_TRUE */
7909    if(!obj) return EINA_TRUE;
7910
7911    Evas_Object *target = obj;
7912    Evas_Object *parent = NULL;
7913    Evas_Coord x, y, w, h, wx, wy, ww = 0, wh = 0, nx = 0, ny = 0;
7914
7915    evas_object_geometry_get(target, &x, &y ,&w, &h);
7916
7917    if (elm_widget_is(target))
7918      parent = elm_widget_parent_get(target);
7919    else
7920      parent = elm_widget_parent_widget_get(target);
7921
7922    while (parent)
7923      {
7924         if (efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
7925           {
7926              evas_object_geometry_get(parent, &wx, &wy, NULL, NULL);
7927              elm_interface_scrollable_content_size_get(parent, &ww, &wh);
7928              elm_interface_scrollable_content_pos_get(parent, &nx, &ny);
7929
7930              /* widget implements scrollable interface but does not use scoller
7931                 in this case, use widget geometry */
7932              if (ww == 0 || wh == 0)
7933                {
7934                   INF("%s is zero sized scrollable content", efl_class_name_get(efl_class_get(parent)));
7935                   evas_object_geometry_get(parent, NULL, NULL, &ww, &wh);
7936                }
7937
7938              wx -= nx;
7939              wy -= ny;
7940
7941              if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
7942                  ((wy < y) && (wy + wh < y)) || ((wy > y + h) && (wy + wh > y + h)))
7943                return EINA_FALSE;
7944
7945              break;
7946           }
7947         parent = elm_widget_parent_get(parent);
7948      }
7949
7950    return EINA_TRUE;
7951 }
7952 //
7953
7954 //TIZEN_ONLY(20180607): Restore legacy focus
7955 /**
7956  * @internal
7957  *
7958  * Resets the focus_move_policy mode from the system one
7959  * for widgets that are in automatic mode.
7960  *
7961  * @param obj The widget.
7962  *
7963  */
7964 static void
7965 _elm_widget_focus_move_policy_reload(Evas_Object *obj)
7966 {
7967    API_ENTRY return;
7968    Elm_Focus_Move_Policy focus_move_policy = elm_config_focus_move_policy_get();
7969
7970    if (efl_ui_widget_focus_move_policy_automatic_get(obj) &&
7971        (sd->focus_move_policy != focus_move_policy))
7972      {
7973         sd->focus_move_policy = focus_move_policy;
7974      }
7975 }
7976
7977 EOLIAN static void
7978 _efl_ui_widget_focus_reconfigure(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7979 {
7980    Evas_Object *child;
7981    API_ENTRY return;
7982
7983    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
7984      {
7985         child = eina_array_data_get(sd->children, i);
7986         if (elm_widget_is(child))
7987           efl_ui_widget_focus_reconfigure(child);
7988      }
7989
7990    if (sd->hover_obj) efl_ui_widget_focus_reconfigure(sd->hover_obj);
7991
7992    _elm_widget_focus_move_policy_reload(obj);
7993 }
7994 //
7995
7996 //TIZEN_ONLY(20160329): widget: improve accessible_at_point getter (a8aff0423202b9a55dbb3843205875226678fbd6)
7997 static void
7998 _coordinate_system_based_point_translate(const Eo *obj, Eina_Bool screen_coords, int *x, int *y)
7999 {
8000    Ecore_Evas *ee;
8001    int ee_x = 0;
8002    int ee_y = 0;
8003
8004    if (screen_coords)
8005      {
8006         ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
8007         if (!ee) return;
8008
8009         ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
8010         *x -= ee_x;
8011         *y -= ee_y;
8012      }
8013 }
8014
8015 static Evas_Object *
8016 _parent_get(Evas_Object *obj)
8017 {
8018    Evas_Object *parent;
8019
8020    parent = evas_object_smart_parent_get(obj);
8021    if (!parent)
8022      {
8023         if (strcmp("Efl_Ui_Win", efl_class_name_get(efl_class_get(obj))))
8024           parent = elm_widget_parent_get(obj);
8025      }
8026
8027    return parent;
8028 }
8029
8030 static Eina_Bool
8031 _is_inside(Evas_Object *obj, int x, int y)
8032 {
8033    Eina_Bool ret = EINA_TRUE;
8034    Evas_Coord cx = 0;
8035    Evas_Coord cy = 0;
8036    Evas_Coord cw = 0;
8037    Evas_Coord ch = 0;
8038    if (efl_isa(obj, ELM_WIDGET_ITEM_CLASS))
8039      {
8040         Elm_Widget_Item_Data *id = efl_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
8041         evas_object_geometry_get(id->view, &cx, &cy, &cw, &ch);
8042      }
8043    else
8044      evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
8045
8046    /* check the point is out of bound */
8047    if (x < cx || x > cx + cw || y < cy || y > cy + ch)
8048      {
8049         ret = EINA_FALSE;
8050      }
8051    return ret;
8052 }
8053
8054 static Eina_Bool
8055 _is_ancestor_of(Evas_Object *smart_parent, const Evas_Object *obj)
8056 {
8057    Eina_Bool ret = EINA_FALSE;
8058    Evas_Object *parent = elm_widget_parent_get(obj);
8059    while (parent)
8060      {
8061         /* No need to check more, the smart_parent is parent of obj */
8062         if (smart_parent == parent)
8063           {
8064              ret = EINA_TRUE;
8065              break;
8066           }
8067         parent = elm_widget_parent_get(parent);
8068      }
8069
8070    return ret;
8071 }
8072
8073 static Eina_Bool
8074 _acceptable_child_is(Eo *obj)
8075 {
8076    Efl_Access_Role role;
8077    Eina_List *children;
8078    Efl_Access_State_Set ss;
8079
8080    role = efl_access_object_role_get(obj);
8081    switch (role)
8082      {
8083        case EFL_ACCESS_ROLE_IMAGE:
8084        case EFL_ACCESS_ROLE_ICON:
8085        case EFL_ACCESS_ROLE_REDUNDANT_OBJECT:
8086        /* remove unacceptable leaf node */
8087          children = efl_access_object_access_children_get(obj);
8088          if (!children) return EINA_FALSE;
8089          break;
8090
8091        case EFL_ACCESS_ROLE_PANEL:
8092          /* remove closed panel fron children list */
8093          ss = efl_access_object_state_set_get(obj);
8094          if (!STATE_TYPE_GET(ss, EFL_ACCESS_STATE_TYPE_SHOWING)) return EINA_FALSE;
8095          break;
8096
8097        default:
8098          break;
8099      }
8100
8101    return EINA_TRUE;
8102 }
8103
8104 static int _sort_by_size(const void *data1, const void *data2)
8105 {
8106    Evas_Coord w, h;
8107    Evas_Coord w2, h2;
8108
8109    evas_object_geometry_get(data1, NULL, NULL, &w, &h);
8110    evas_object_geometry_get(data2, NULL, NULL, &w2, &h2);
8111
8112    if ((w * h) > (w2 * h2)) return 1;
8113    return -1;
8114 }
8115
8116 Eina_Bool
8117 _elm_widget_atspi_role_acceptable_check(Eo *obj)
8118 {
8119    Efl_Access_Role role;
8120    role = efl_access_object_role_get(obj);
8121
8122    switch (role)
8123      {
8124        case EFL_ACCESS_ROLE_APPLICATION:
8125        case EFL_ACCESS_ROLE_FILLER:
8126        case EFL_ACCESS_ROLE_SCROLL_PANE:
8127        case EFL_ACCESS_ROLE_SPLIT_PANE:
8128        case EFL_ACCESS_ROLE_WINDOW:
8129        case EFL_ACCESS_ROLE_IMAGE:
8130        case EFL_ACCESS_ROLE_LIST:
8131        case EFL_ACCESS_ROLE_ICON:
8132        case EFL_ACCESS_ROLE_TOOL_BAR:
8133        case EFL_ACCESS_ROLE_REDUNDANT_OBJECT:
8134        case EFL_ACCESS_ROLE_COLOR_CHOOSER:
8135        case EFL_ACCESS_ROLE_TREE_TABLE:
8136        case EFL_ACCESS_ROLE_PAGE_TAB_LIST:
8137        case EFL_ACCESS_ROLE_PAGE_TAB:
8138        case EFL_ACCESS_ROLE_SPIN_BUTTON:
8139        case EFL_ACCESS_ROLE_INPUT_METHOD_WINDOW:
8140        case EFL_ACCESS_ROLE_EMBEDDED:
8141        case EFL_ACCESS_ROLE_INVALID:
8142        case EFL_ACCESS_ROLE_NOTIFICATION:
8143          return EINA_FALSE;
8144        default:
8145          break;
8146      }
8147
8148    return EINA_TRUE;
8149 }
8150
8151 static Eo *
8152 _child_object_at_point_get(const Eo *obj, int x, int y)
8153 {
8154    Eina_List *l, *l_next, *children, *valid_children = NULL;
8155    Eo *child;
8156    Eo *target;
8157    int count;
8158
8159    children = efl_access_object_access_children_get(obj);
8160
8161    EINA_LIST_FOREACH(children, l, child)
8162      {
8163         if (_is_inside(child, x, y))
8164           valid_children = eina_list_append(valid_children, child);
8165      }
8166
8167    EINA_LIST_FOREACH_SAFE(valid_children, l, l_next, child)
8168      {
8169         children = efl_access_object_access_children_get(child);
8170
8171         /* do not use unacceptable leaf node */
8172         if (!_elm_widget_atspi_role_acceptable_check(child) &&
8173             eina_list_count(children) == 0)
8174           valid_children = eina_list_remove_list(valid_children, l);
8175      }
8176
8177    count = eina_list_count(valid_children);
8178    if (count > 0)
8179      {
8180         valid_children = eina_list_sort(valid_children, -1, _sort_by_size);
8181         target = eina_list_nth(valid_children, 0);
8182
8183         //TIZEN_ONLY(20191209):Do not accept children with unacceptable role
8184         //return _child_object_at_point_get(target, x, y);
8185         Eo *ret = (Eo *)_child_object_at_point_get(target, x, y);
8186         if (ret) return ret;
8187         //
8188      }
8189
8190    //TIZEN_ONLY(20191209):Do not accept children with unacceptable role
8191    //return obj;
8192    return _elm_widget_atspi_role_acceptable_check((Eo *)obj) ? (Eo *)obj : NULL;
8193    //
8194 }
8195
8196
8197 static Eo *
8198 _accessible_at_point_top_down_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
8199 {
8200    Eina_List *l, *l2, *children, *valid_children = NULL;
8201    Eo *child;
8202    Evas_Object *stack_item;
8203    Eo *compare_obj;
8204    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
8205    Eo *proxy;
8206    Evas_Coord px, py, pw, ph;
8207    //
8208
8209    _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
8210
8211    children = efl_access_object_access_children_get(obj);
8212
8213    EINA_LIST_FOREACH(children, l2, child)
8214      {
8215         if (_is_inside(child, x, y) && _acceptable_child_is(child))
8216           valid_children = eina_list_append(valid_children, child);
8217      }
8218
8219    /* If there is only one valid child at point, then return it.
8220       The evas_tree_objects_at_xy_get could not find proper object,
8221       if application does not have well aligned objects. */
8222    if (eina_list_count(valid_children) == 1)
8223      {
8224         eina_list_free(children);
8225         child = eina_list_nth(valid_children, 0);
8226         return child;
8227      }
8228
8229    /* Get evas_object stacked at given x,y coordinates starting from top */
8230    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
8231    /* Foreach stacked object starting from top */
8232    EINA_LIST_FOREACH(stack, l, stack_item)
8233      {
8234         /* Foreach at-spi valid children traverse stack_item evas_objects hierarchy */
8235         EINA_LIST_FOREACH(valid_children, l2, child)
8236           {
8237              Efl_Access_Role role;
8238              role = efl_access_object_role_get(child);
8239              if (role == EFL_ACCESS_ROLE_REDUNDANT_OBJECT)
8240                {
8241                   /* The redundant object ignores */
8242                   continue;
8243                }
8244              /* Compare object used to compare with stacked evas objects */
8245              compare_obj = child;
8246              /* In case of widget_items compare should be different then elm_widget_ item  object */
8247              if (efl_isa(child, ELM_WIDGET_ITEM_CLASS))
8248                {
8249                   Elm_Widget_Item_Data *id = efl_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
8250                   compare_obj = id->view;
8251                   if (TIZEN_PROFILE_WEARABLE)
8252                     {
8253                        Eo* it_view = evas_object_image_source_get(stack_item);
8254                        if (it_view && it_view == compare_obj)
8255                          {
8256                             eina_list_free(children);
8257                             eina_list_free(stack);
8258                             return child;
8259                          }
8260                     }
8261                }
8262              /* In case of access object compare should be 'wrapped' evas_object */
8263              if (efl_isa(child, ELM_ACCESS_CLASS))
8264                {
8265                    Elm_Access_Info *info = _elm_access_info_get(child);
8266                    if (!info) continue;
8267                    compare_obj = info->part_object;
8268                 }
8269              /* In case of widget is registerd by elm_access_object_register */
8270              Evas_Object *ao = elm_access_object_get(child);
8271              if (ao)
8272                {
8273                   eina_list_free(children);
8274                   eina_list_free(stack);
8275                   return ao;
8276                }
8277
8278              /* In case of ewk wrapper object compare with internal ewk_view evas_object */
8279              if (efl_isa(child, ELM_ATSPI_EWK_WRAPPER_CLASS))
8280                {
8281                   compare_obj = elm_atspi_ewk_wrapper_ewk_view_get(child);
8282                }
8283
8284              /* If spacial eo children do not have backing evas_object continue with search */
8285              if (!compare_obj)
8286                continue;
8287
8288              Evas_Object *smart_parent = stack_item;
8289              while (smart_parent)
8290                {
8291                    if (smart_parent == compare_obj)
8292                      {
8293                         eina_list_free(children);
8294                         eina_list_free(stack);
8295                         return child;
8296                      }
8297
8298                    // TIZEN_ONLY(20160705) - enable atspi_proxy to work
8299                    proxy = evas_object_data_get(smart_parent, "__widget_proxy");
8300                    if (proxy)
8301                      {
8302                         // TIZEN_ONLY(20171109) : fix for invalid proxy object, when at-spi has been restarted
8303                         Eo *parent;
8304                         parent = efl_provider_find(efl_parent_get(smart_parent), EFL_ACCESS_OBJECT_MIXIN);
8305                         proxy = plug_type_proxy_get(parent, smart_parent);
8306                         //
8307                         evas_object_geometry_get(smart_parent, &px, &py, &pw, &ph);
8308                         if (x >= px && x <= px + pw && y >= py && y <= py +ph)
8309                           {
8310                              eina_list_free(children);
8311                              eina_list_free(stack);
8312                              return proxy;
8313                           }
8314                      }
8315                    //
8316
8317                    smart_parent = _parent_get(smart_parent);
8318                    if (_is_ancestor_of(smart_parent, obj)) break;
8319                }
8320           }
8321      }
8322
8323    eina_list_free(children);
8324    eina_list_free(stack);
8325    return NULL;
8326 }
8327
8328 static int _sort_by_repeat_events(const void *data1, const void *data2)
8329 {
8330    Evas_Object *ao1, *ao2;
8331    Eina_Bool repeat1, repeat2;
8332
8333    ao1 = elm_access_object_get(data1);
8334    ao2 = elm_access_object_get(data2);
8335
8336    repeat1 = evas_object_repeat_events_get(data1);
8337    repeat2 = evas_object_repeat_events_get(data2);
8338
8339    if (repeat1 != repeat2)
8340      {
8341         if (repeat1 && !ao1) return 1;
8342      }
8343    else
8344      {
8345         if (repeat1 && !ao1 && ao2) return 1;
8346      }
8347
8348    return -1;
8349 }
8350
8351 static Eo *_item_at_point_get(Evas_Object *obj, int x, int y)
8352 {
8353    Eo *child;
8354    Eina_List *l, *children;
8355
8356    children = efl_access_object_access_children_get(obj);
8357
8358    EINA_LIST_FOREACH(children, l, child)
8359      {
8360         if (_is_inside(child, x, y)) return child;
8361      }
8362
8363    ERR("No child at point (%d, %d) on object %p", x, y, obj);
8364    return NULL;
8365 }
8366
8367 //TIZEN_ONLY(20171108): bring HIGHLIGHT related changes
8368 EOLIAN static Eo *
8369 _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)
8370 {
8371    Elm_Atspi_Role role;
8372    Eina_List *l;
8373    Evas_Object *stack_item;
8374
8375    role = efl_access_object_role_get(obj);
8376
8377    switch (role)
8378      {
8379       case ELM_ATSPI_ROLE_WINDOW:
8380         /* this is for webapp which is using window only */
8381         if (evas_object_data_get(obj, "__PlugID"))
8382           {
8383              Eina_List *children;
8384              Evas_Object *child;
8385              children = efl_access_object_access_children_get(obj);
8386              EINA_LIST_FOREACH(children, l, child)
8387                {
8388                   if (efl_access_object_role_get(child) == EFL_ACCESS_ROLE_EMBEDDED)
8389                     return child;
8390                }
8391           }
8392         DBG("Find accessible from bottom");
8393         break;
8394       case ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW:
8395       case ELM_ATSPI_ROLE_DIALOG:
8396       case ELM_ATSPI_ROLE_PAGE_TAB:
8397       //TIZEN_ONLY(20220915): Use top-down at-point search for POPUP_MENU
8398       //case ELM_ATSPI_ROLE_POPUP_MENU: // Bottom-up search would find buttons absent from the AT-SPI tree in case of CtxPopup
8399       //
8400       case ELM_ATSPI_ROLE_PANEL:
8401         DBG("Find accessible from bottom");
8402         break;
8403
8404       default:
8405         return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
8406      }
8407
8408    _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
8409
8410    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
8411    stack = eina_list_sort(stack, -1, _sort_by_repeat_events);
8412
8413    EINA_LIST_FOREACH(stack, l, stack_item)
8414      {
8415         Evas_Object *smart_parent = stack_item;
8416         while (smart_parent)
8417           {
8418              /* If parent equals to obj, it is not necessary to go upper.
8419                 So the top down logic would be better than NULL return. */
8420              if (smart_parent == obj)
8421                return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
8422
8423              Evas_Object *ao = elm_access_object_get(smart_parent);
8424              if (ao) return ao;
8425
8426              if (efl_isa(smart_parent, EFL_ACCESS_OBJECT_MIXIN))
8427                {
8428                   Eina_Bool acceptable = EINA_FALSE;
8429                   Eo *item_child;
8430                   role = efl_access_object_role_get(smart_parent);
8431                   switch (role)
8432                     {
8433                        case EFL_ACCESS_ROLE_FILLER: /* ex: View of colorselector item is layout */
8434                        case EFL_ACCESS_ROLE_ICON:
8435                        case EFL_ACCESS_ROLE_IMAGE:
8436                        case EFL_ACCESS_ROLE_REDUNDANT_OBJECT:
8437                        case EFL_ACCESS_ROLE_WINDOW:
8438                          DBG("Go for parent: %s (%p)\n", evas_object_type_get(smart_parent), smart_parent);
8439                          break;
8440                        case EFL_ACCESS_ROLE_LIST:
8441                            item_child = _item_at_point_get(smart_parent, x, y);
8442                            if (TIZEN_PROFILE_WEARABLE)
8443                              {
8444                                 item_child = _child_object_at_point_get(item_child, x, y);
8445                                 return item_child;
8446                              }
8447                            return item_child;
8448                          break;
8449                        default:
8450                          acceptable = EINA_TRUE;
8451                          break;
8452                     }
8453
8454                   if (acceptable) return smart_parent;
8455                }
8456
8457              smart_parent = _parent_get(smart_parent);
8458           }
8459      }
8460
8461    eina_list_free(stack);
8462    return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
8463 }
8464 // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
8465 // EOLIAN static Eina_Bool
8466 // _elm_widget_item_efl_access_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
8467 // {
8468 //    Evas_Object *win = elm_widget_top_get(sd->widget);
8469 //    if (win && efl_isa(win, EFL_UI_WIN_CLASS))
8470 //      {
8471 //         _elm_win_accessibility_highlight_set(win, sd->view);
8472 //         efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8473 //         return EINA_TRUE;
8474 //      }
8475 //    return EINA_FALSE;
8476 // }
8477 //
8478 //
8479 // EOLIAN static Eina_Bool
8480 // _elm_widget_item_efl_access_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
8481 // {
8482 //    Evas_Object *win = elm_widget_top_get(sd->widget);
8483 //    if (win && efl_isa(win, EFL_UI_WIN_CLASS))
8484 //      {
8485 //         if (_elm_win_accessibility_highlight_get(win) != sd->view)
8486 //           return EINA_TRUE;
8487 //
8488 //         _elm_win_accessibility_highlight_set(win, NULL);
8489 //         efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_FALSE);
8490 //         return EINA_TRUE;
8491 //      }
8492 //    return EINA_FALSE;
8493 // }
8494 //
8495
8496 //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
8497 void
8498 _elm_widget_showing_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
8499 {
8500    Evas_Object *parent;
8501    Evas_Coord px, py, sx, sy, sw, sh;
8502
8503    *x = 0;
8504    *y = 0;
8505    *w = 0;
8506    *h = 0;
8507    if (!obj) return;
8508
8509    evas_object_geometry_get(obj, x, y, w, h);
8510
8511    if (elm_widget_is(obj))
8512      parent = elm_widget_parent_get(obj);
8513    else
8514      parent = elm_widget_parent_widget_get(obj);
8515
8516    while (parent)
8517      {
8518         if (efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
8519           {
8520              evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
8521              px = *x;
8522              py = *y;
8523              *x = *x > sx ? *x : sx;
8524              *y = *y > sy ? *y : sy;
8525              *w = px + *w < sx + sw ? px + *w - *x : sx + sw - *x;
8526              *h = py + *h < sy + sh ? py + *h - *y : sy + sh - *y;
8527           }
8528         parent = elm_widget_parent_get(parent);
8529      }
8530 }
8531
8532 Eina_Bool
8533 _accessible_object_on_screen_is(Eo *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool is_complete)
8534 {
8535    if(!obj) return EINA_FALSE;
8536
8537    Evas_Object *target = obj;
8538    Evas_Object *parent = NULL;
8539    Evas_Coord px, py, sx, sy, sw, sh, ox, oy, ow, oh;
8540
8541    /* uninitialized data could be read */
8542    ow = 0;
8543    oh = 0;
8544
8545    if (elm_widget_is(target))
8546      parent = elm_widget_parent_get(target);
8547    else
8548      parent = elm_widget_parent_widget_get(target);
8549
8550    while (parent)
8551      {
8552         if (efl_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
8553           {
8554              evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
8555              px = ox = x;
8556              py = oy = y;
8557              ow = w;
8558              oh = h;
8559              ox = is_complete ? ox : ox + ow;
8560              oy = is_complete ? oy : oy + oh;
8561              ox = ox > sx ? ox : sx;
8562              oy = oy > sy ? oy : sy;
8563              ow = px + ow < sx + sw ? px + ow - ox : sx + sw - ox;
8564              oh = py + oh < sy + sh ? py + oh - oy : sy + sh - oy;
8565           }
8566         if (ow <= 0 || oh <= 0)
8567           return EINA_FALSE;
8568
8569         parent = elm_widget_parent_get(parent);
8570      }
8571    return EINA_TRUE;
8572 }
8573
8574 Eina_List *
8575 _accessible_scrollable_parent_list_get(const Eo *obj)
8576 {
8577    if(!obj) return NULL;
8578
8579    Evas_Object *parent = NULL;
8580    Eina_List *plist = NULL;
8581
8582    if (elm_widget_is(obj))
8583      parent = elm_widget_parent_get(obj);
8584    else
8585      parent = elm_widget_parent_widget_get(obj);
8586
8587    while (parent)
8588      {
8589         if (_elm_scrollable_is(parent))
8590           plist = eina_list_append(plist, parent);
8591
8592         parent = elm_widget_parent_get(parent);
8593    }
8594    return plist;
8595 }
8596
8597 void
8598 _accessible_highlight_region_show(Eo* obj)
8599 {
8600    if (!obj) return ;
8601
8602    Evas_Object *target = obj;
8603    Evas_Object *parent = NULL;
8604    Evas_Object *parent_sub = NULL;
8605    Eina_List *plist, *plist_sub;
8606    Eina_List *l, *l2;
8607
8608    Evas_Coord target_x, target_y, target_w, target_h;
8609
8610    evas_object_geometry_get(target, &target_x, &target_y, &target_w, &target_h);
8611
8612    plist = _accessible_scrollable_parent_list_get(target);
8613    if (!plist) return ;
8614    EINA_LIST_FOREACH(plist, l, parent)
8615      {
8616         if(!_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_TRUE))
8617           {
8618              plist_sub = _accessible_scrollable_parent_list_get(parent);
8619              plist_sub = eina_list_prepend(plist_sub, parent);
8620              EINA_LIST_FOREACH(plist_sub, l2, parent_sub)
8621                {
8622                   Evas_Coord scroll_x = 0, scroll_y = 0;
8623                   Evas_Coord scroll_x_back = 0, scroll_y_back = 0;
8624                   Evas_Coord x, y, w, h;
8625                   Evas_Coord px, py;
8626
8627                   elm_interface_scrollable_content_region_get(parent_sub, &scroll_x_back, &scroll_y_back, NULL, NULL);
8628                   evas_object_geometry_get(parent_sub, &px, &py, NULL, NULL);
8629                   x = target_x; y = target_y; w = target_w; h = target_h;
8630
8631                   x -= (px - scroll_x_back);
8632                   y -= (py - scroll_y_back);
8633                   switch (_elm_config->focus_autoscroll_mode)
8634                     {
8635                        case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
8636                           elm_interface_scrollable_content_region_show(parent_sub, x, y, w, h);
8637                           break;
8638                        case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
8639                           elm_interface_scrollable_region_bring_in(parent_sub, x, y, w, h);
8640                           break;
8641                        default:
8642                           break;
8643                     }
8644                   elm_interface_scrollable_content_region_get(parent_sub, &scroll_x, &scroll_y, NULL, NULL);
8645
8646                   target_x -= (scroll_x - scroll_x_back);
8647                   target_y -= (scroll_y - scroll_y_back);
8648
8649                   if(_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_FALSE))
8650                     break;
8651                }
8652              eina_list_free(plist_sub);
8653           }
8654      }
8655
8656    eina_list_free(plist);
8657 }
8658 //
8659
8660 //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8661 static Eo *_highlight_grabbing_object = NULL;
8662
8663 Eina_Bool
8664 _elm_widget_accessibility_highlight_grabbing_get(Eo *obj)
8665 {
8666   return _highlight_grabbing_object == obj;
8667 }
8668
8669 void
8670 _elm_widget_accessibility_highlight_grabbing_set(Eo *obj, Eina_Bool grabbing)
8671 {
8672    if (grabbing)
8673      {
8674        if (!_highlight_grabbing_object)
8675            _highlight_grabbing_object = obj;
8676        else if (_highlight_grabbing_object == obj)
8677            ERR("trying to set grabbing for %p, but it's already set to this object", obj);
8678        else
8679            ERR("trying to set grabbing for %p, but it's already set to %p", obj, _highlight_grabbing_object);
8680      }
8681    else
8682      {
8683        if (_highlight_grabbing_object != obj)
8684            ERR("trying to clear grabbing for %p, but it's set to %p", obj, _highlight_grabbing_object);
8685        else
8686            _highlight_grabbing_object = NULL;
8687      }
8688 }
8689 //
8690
8691 EOLIAN static Eina_Bool
8692 _efl_ui_widget_efl_access_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
8693 {
8694    if(!obj) return EINA_FALSE;
8695    if(!_elm_atspi_enabled())
8696       return EINA_FALSE;
8697
8698    // TIZEN_ONLY(20171020) : atspi : Do not send signal, if current object and highlight object are same
8699    if (_elm_object_accessibility_currently_highlighted_get() == obj)
8700       return EINA_FALSE;
8701    //
8702
8703    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8704    _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_TRUE);
8705    //
8706
8707    //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
8708    _accessible_highlight_region_show(obj);
8709    //
8710
8711    elm_object_accessibility_highlight_set(obj, EINA_TRUE);
8712    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8713
8714    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
8715    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_HIGHLIGHTED, NULL);
8716    //
8717
8718    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8719    _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_FALSE);
8720    //
8721    return EINA_TRUE;
8722 }
8723
8724 EOLIAN static Eina_Bool
8725 _efl_ui_widget_efl_access_component_highlight_clear(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
8726 {
8727    if (!obj) return EINA_FALSE;
8728    if (!_elm_atspi_enabled())
8729       return EINA_FALSE;
8730
8731    elm_object_accessibility_highlight_set(obj, EINA_FALSE);
8732    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_FALSE);
8733    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
8734    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, NULL);
8735    //
8736    return EINA_TRUE;
8737 }
8738 //
8739
8740 // TIZEN_ONLY(20171114) Accessibility Highlight Frame added
8741 EOLIAN static Eina_Bool
8742 _elm_widget_item_efl_access_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
8743 {
8744    // TIZEN_ONLY(20171117) Accessibility Highlight frame support for items
8745    // Evas_Object *win = elm_widget_top_get(sd->widget);
8746    // if (win && efl_isa(win, EFL_UI_WIN_CLASS))
8747    //   {
8748    //      elm_object_accessibility_highlight_set(sd->view, EINA_TRUE);
8749    //      efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8750    //      return EINA_TRUE;
8751    //   }
8752    // return EINA_FALSE;
8753
8754    if (!sd) return EINA_FALSE;
8755    if (!sd->view) return EINA_FALSE;
8756    if (!_elm_atspi_enabled())
8757       return EINA_FALSE;
8758
8759    // TIZEN_ONLY(20171020) : atspi : Do not send signal, if current object and highlight object are same
8760    if (_elm_object_accessibility_currently_highlighted_get() == obj)
8761       return EINA_FALSE;
8762    //
8763
8764    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8765    _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_TRUE);
8766    //
8767
8768    //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
8769    _accessible_highlight_region_show(sd->view);
8770    //
8771
8772    if (!sd->eo_obj) return EINA_FALSE;
8773    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_TRUE);
8774
8775    if (!obj) return EINA_FALSE;
8776    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_TRUE);
8777    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
8778    evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_HIGHLIGHTED, obj);
8779    //
8780
8781    //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
8782     _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_FALSE);
8783     //
8784
8785    return EINA_TRUE;
8786    //
8787 }
8788
8789 EOLIAN static Eina_Bool
8790 _elm_widget_item_efl_access_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
8791 {
8792    if (!obj) return EINA_FALSE;
8793    if (!_elm_atspi_enabled())
8794      return EINA_FALSE;
8795
8796    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_FALSE);
8797    efl_access_state_changed_signal_emit(obj, EFL_ACCESS_STATE_TYPE_HIGHLIGHTED, EINA_FALSE);
8798    //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
8799    evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, obj);
8800    //
8801    return EINA_TRUE;
8802 }
8803 //
8804
8805 //TIZEN_ONLY(20160527): widget: add AtspiAction interface to all widgets and widget_items, add handlers for reading stopped/cancelled
8806 EOLIAN const Efl_Access_Action_Data *
8807 _efl_ui_widget_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
8808 {
8809    return NULL;
8810 }
8811
8812 EOLIAN const Efl_Access_Action_Data *
8813 _elm_widget_item_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *pd EINA_UNUSED)
8814 {
8815    return NULL;
8816 }
8817
8818 /***********************************************************
8819  * TIZEN_ONLY(20180117): Override Paragraph Direction APIs *
8820  ***********************************************************/
8821 static void
8822 _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Efl_Ui_Widget_Data *sd, Efl_Text_Bidirectional_Type dir)
8823 {
8824    Evas_Object *child;
8825
8826    if (sd->on_destroy) return;
8827
8828    for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
8829      {
8830         child = eina_array_data_get(sd->children, i);
8831         if (_elm_widget_is(child))
8832           {
8833              Efl_Ui_Widget_Data *sdc = efl_data_scope_get(child, MY_CLASS);
8834
8835              if (sdc->inherit_paragraph_direction &&
8836                  (sdc->paragraph_direction != dir))
8837                {
8838                   sdc->paragraph_direction = dir;
8839                   _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(child, sdc, dir);
8840                   efl_canvas_object_paragraph_direction_set(efl_super(child, MY_CLASS), dir);
8841                }
8842           }
8843
8844         /* FIXME: There is no way to handle non-widget child object.
8845          * If a non-widget child object has smart parent, it will get the direction
8846          * from the smart parent. */
8847      }
8848 }
8849
8850 EOLIAN static void
8851 _efl_ui_widget_efl_canvas_object_paragraph_direction_set(Eo *obj, Efl_Ui_Widget_Data *sd, Efl_Text_Bidirectional_Type dir)
8852 {
8853    if ((!(sd->inherit_paragraph_direction) && (sd->paragraph_direction == dir)) ||
8854        (sd->inherit_paragraph_direction && (dir == EFL_TEXT_BIDIRECTIONAL_TYPE_INHERIT)))
8855      return;
8856
8857    if (dir == EFL_TEXT_BIDIRECTIONAL_TYPE_INHERIT)
8858      {
8859         sd->inherit_paragraph_direction = EINA_TRUE;
8860         Evas_BiDi_Direction parent_dir = EFL_TEXT_BIDIRECTIONAL_TYPE_NEUTRAL;
8861
8862         if (sd->parent_obj)
8863           parent_dir = efl_canvas_object_paragraph_direction_get(sd->parent_obj);
8864
8865         if (parent_dir != sd->paragraph_direction)
8866           {
8867              sd->paragraph_direction = parent_dir;
8868              _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(obj, sd, parent_dir);
8869           }
8870      }
8871    else
8872      {
8873         sd->inherit_paragraph_direction = EINA_FALSE;
8874         sd->paragraph_direction = dir;
8875         _efl_ui_widget_efl_canvas_object_paragraph_direction_set_internal(obj, sd, dir);
8876      }
8877
8878    efl_canvas_object_paragraph_direction_set(efl_super(obj, MY_CLASS), dir);
8879 }
8880 /*******
8881  * END *
8882  *******/
8883
8884 /***********************************************************************************
8885  * TIZEN_ONLY_FEATURE: apply Tizen's color_class features.                         *
8886  ***********************************************************************************/
8887 void
8888 _elm_widget_color_class_parent_set(Evas_Object *obj, Evas_Object *parent)
8889 {
8890    Evas_Object *edje = NULL, *parent_edje = NULL;
8891
8892    if (!obj || !parent) return;
8893
8894    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
8895      edje =  elm_layout_edje_get(obj);
8896    else if (efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))
8897      edje = obj;
8898
8899    if (efl_isa(parent, EFL_UI_LAYOUT_BASE_CLASS))
8900      parent_edje =  elm_layout_edje_get(parent);
8901    else if (efl_isa(parent, EFL_CANVAS_LAYOUT_CLASS))
8902      parent_edje = parent;
8903
8904    if (!edje || !parent_edje) return;
8905
8906    edje_object_color_class_parent_set(edje, parent_edje);
8907 }
8908
8909 void
8910 _elm_widget_color_class_parent_unset(Evas_Object *obj)
8911 {
8912    Evas_Object *edje = NULL;
8913
8914    if (!obj) return;
8915
8916    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))
8917      edje =  elm_layout_edje_get(obj);
8918    else if (efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))
8919      edje = obj;
8920
8921    if (!edje) return;
8922
8923    edje_object_color_class_parent_unset(edje);
8924 }
8925
8926 void
8927 _edje_color_class_free(void *data)
8928 {
8929    Edje_Color_Class *cc = data;
8930
8931    if (cc->name) eina_stringshare_del(cc->name);
8932    free(cc);
8933 }
8934
8935 Eina_Stringshare *
8936 _elm_widget_edje_class_get(const Evas_Object *obj, const char *style, const char *part)
8937 {
8938    Eina_Strbuf *buf;
8939    Eina_Stringshare *str;
8940    const char *klass_name = NULL;
8941    Eina_Bool is_legacy = EINA_FALSE;
8942    Eina_Bool is_item = efl_isa(obj, ELM_WIDGET_ITEM_CLASS);
8943
8944    if (is_item)
8945      is_legacy = elm_widget_is_legacy(elm_object_item_widget_get(obj));
8946    else
8947      is_legacy = elm_widget_is_legacy(obj);
8948
8949    buf = eina_strbuf_new();
8950
8951    if (is_legacy)
8952      {
8953         if (is_item)
8954           klass_name = _elm_widget_item_legacy_type_get(obj);
8955         else
8956           klass_name = elm_widget_type_get(obj);
8957      }
8958    else
8959      {
8960         klass_name = efl_class_name_get(efl_class_get(obj));
8961      }
8962
8963    if (klass_name)
8964      {
8965         if (is_legacy && strchr(klass_name, '_'))
8966           {
8967              eina_strbuf_append(buf, strchr(klass_name, '_') + 1);
8968              eina_strbuf_tolower(buf);
8969           }
8970         else
8971           {
8972              /* Get the last word from the given klass name */
8973              char *temp, *temp_orig, *temp_ret, *last_ret = NULL;
8974              const char *delim = NULL;
8975
8976              temp_orig = temp = strdup(klass_name);
8977
8978              /* If "." is not used for word serperator,
8979               * it assume the given klass name is legacy.
8980               * And legacy klass name was made with "_" as its word seperator. */
8981              if (strchr(klass_name, '.'))
8982                delim = ".";
8983              else
8984                delim = "_";
8985
8986              while ((temp_ret = strsep(&temp, delim)) != NULL)
8987                {
8988                   if (strcmp(temp_ret, ""))
8989                     last_ret = temp_ret;
8990                }
8991
8992              if (last_ret)
8993                {
8994                   eina_strbuf_append(buf, last_ret);
8995                   eina_strbuf_tolower(buf);
8996                }
8997
8998              free(temp_orig);
8999           }
9000      }
9001
9002    if (style)
9003      {
9004         eina_strbuf_append_printf(buf, "/%s/%s", style, part);
9005      }
9006    else
9007      {
9008         eina_strbuf_append_printf(buf, "/%s", part);
9009      }
9010
9011    str = eina_stringshare_add(eina_strbuf_string_get(buf));
9012
9013    eina_strbuf_free(buf);
9014    return str;
9015 }
9016
9017 Eina_Bool
9018 _elm_widget_color_class_set_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
9019                                      int r, int g, int b, int a,
9020                                      int r2, int g2, int b2, int a2,
9021                                      int r3, int g3, int b3, int a3)
9022 {
9023    Eina_Bool int_ret = EINA_TRUE;
9024    Eina_Stringshare *buf;
9025    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9026    Edje_Color_Class *cc = NULL;
9027    API_ENTRY return EINA_FALSE;
9028    //
9029    int temp_color[3][4] = { { r,  g,  b,  a },
9030                             { r2, g2, b2, a2 },
9031                             { r3, g3, b3, a3 } };
9032
9033    if (!color_class) return EINA_FALSE;
9034
9035    buf = _elm_widget_edje_class_get(obj, NULL, color_class);
9036
9037 #define TEMP_COLOR(x, y) \
9038    ((temp_color[x][y] == -1) ? &temp_color[x][y] : NULL)
9039
9040    edje_object_color_class_get(edje, buf,
9041                                TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
9042                                TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
9043                                TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
9044
9045 #undef TEMP_COLOR
9046
9047 #define TEMP_COLOR(x, y) \
9048    ((temp_color[x][y] == -1) ? 0 : temp_color[x][y])
9049
9050    int_ret &= edje_object_color_class_set(edje, buf,
9051                                           TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
9052                                           TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
9053                                           TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
9054
9055 #undef TEMP_COLOR
9056
9057    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9058    if (int_ret)
9059      {
9060         if (!sd->color_classes)
9061           sd->color_classes = eina_hash_string_small_new(_edje_color_class_free);
9062         else
9063           cc = eina_hash_find(sd->color_classes, buf);
9064         if (!cc)
9065           {
9066              cc = calloc(1, sizeof(Edje_Color_Class));
9067              if (!cc) goto on_error;
9068              cc->name = eina_stringshare_add(buf);
9069              eina_hash_direct_add(sd->color_classes, cc->name, cc);
9070           }
9071         cc->r = r; cc->g = g; cc->b = b; cc->a = a;
9072         cc->r2 = r2; cc->g2 = g2; cc->b2 = b2; cc->a2 = a2;
9073         cc->r3 = r3; cc->g3 = g3; cc->b3 = b3; cc->a3 = a3;
9074      }
9075    //
9076
9077 on_error:
9078    eina_stringshare_del(buf);
9079
9080    return int_ret;
9081 }
9082
9083 Eina_Bool
9084 _elm_widget_color_class_get_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
9085                                      int *r, int *g, int *b, int *a,
9086                                      int *r2, int *g2, int *b2, int *a2,
9087                                      int *r3, int *g3, int *b3, int *a3)
9088 {
9089    Eina_Bool int_ret = EINA_TRUE;
9090    Eina_Stringshare *buf;
9091
9092    if (!color_class) return EINA_FALSE;
9093
9094    buf = _elm_widget_edje_class_get(obj, elm_widget_style_get(obj), color_class);
9095
9096    int_ret &= edje_object_color_class_get(edje, buf,
9097                                           r,  g,  b,  a,
9098                                           r2, g2, b2, a2,
9099                                           r3, g3, b3, a3);
9100
9101    eina_stringshare_del(buf);
9102
9103    return int_ret;
9104 }
9105
9106 /* Internal EO API */
9107 static Eina_Bool
9108 _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)
9109 {
9110    Evas_Object *edje;
9111    Eina_Bool int_ret = EINA_TRUE;
9112
9113    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9114
9115    edje = elm_layout_edje_get(obj);
9116    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
9117                                                    r, g, b, a,
9118                                                    -1, -1, -1, -1,
9119                                                    -1, -1, -1, -1);
9120
9121    return int_ret;
9122 }
9123
9124 /* Internal EO API */
9125 static Eina_Bool
9126 _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)
9127 {
9128    Evas_Object *edje;
9129    Eina_Bool int_ret = EINA_TRUE;
9130
9131    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9132
9133    edje = elm_layout_edje_get(obj);
9134    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
9135                                                    r, g, b, a,
9136                                                    NULL, NULL, NULL, NULL,
9137                                                    NULL, NULL, NULL, NULL);
9138
9139    return int_ret;
9140 }
9141
9142 /* Internal EO API */
9143 static Eina_Bool
9144 _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)
9145 {
9146    Evas_Object *edje;
9147    Eina_Bool int_ret = EINA_TRUE;
9148
9149    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9150
9151    edje = elm_layout_edje_get(obj);
9152    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
9153                                                    -1, -1, -1, -1,
9154                                                    r, g, b, a,
9155                                                    -1, -1, -1, -1);
9156
9157    return int_ret;
9158 }
9159
9160 /* Internal EO API */
9161 static Eina_Bool
9162 _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)
9163 {
9164    Evas_Object *edje;
9165    Eina_Bool int_ret = EINA_TRUE;
9166
9167    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9168
9169    edje = elm_layout_edje_get(obj);
9170    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
9171                                                    NULL, NULL, NULL, NULL,
9172                                                    r, g, b, a,
9173                                                    NULL, NULL, NULL, NULL);
9174
9175    return int_ret;
9176 }
9177
9178 /* Internal EO API */
9179 static Eina_Bool
9180 _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)
9181 {
9182    Evas_Object *edje;
9183    Eina_Bool int_ret = EINA_TRUE;
9184
9185    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9186
9187    edje = elm_layout_edje_get(obj);
9188    int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
9189                                                    -1, -1, -1, -1,
9190                                                    -1, -1, -1, -1,
9191                                                    r, g, b, a);
9192
9193    return int_ret;
9194 }
9195
9196 /* Internal EO API */
9197 static Eina_Bool
9198 _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)
9199 {
9200    Evas_Object *edje;
9201    Eina_Bool int_ret = EINA_TRUE;
9202
9203    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return EINA_FALSE;
9204
9205    edje = elm_layout_edje_get(obj);
9206    int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
9207                                                    NULL, NULL, NULL, NULL,
9208                                                    NULL, NULL, NULL, NULL,
9209                                                    r, g, b, a);
9210
9211    return int_ret;
9212 }
9213
9214 /* Internal EO API */
9215 static void
9216 _elm_widget_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *color_class)
9217 {
9218    Eina_Stringshare *buf;
9219    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9220    Edje_Color_Class *cc = NULL;
9221    //
9222
9223    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return;
9224
9225    buf = _elm_widget_edje_class_get(obj, NULL, color_class);
9226    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9227    eina_hash_del(sd->color_classes, buf, cc);
9228    //
9229    edje_object_color_class_del(sd->resize_obj, buf);
9230    eina_stringshare_del(buf);
9231 }
9232
9233 /* Internal EO API */
9234 static void
9235 _elm_widget_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
9236 {
9237    if (!efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS)) return;
9238    // TIZEN_ONLY(20200623) : apply Tizen's color_class features
9239    ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
9240    //
9241    edje_object_color_class_clear(sd->resize_obj);
9242 }
9243
9244 #define ELM_COLOR_CLASS_UPDATE(obj, hash, cond)                                  \
9245    Evas_Object *edje = NULL;                                                     \
9246    Eina_Iterator *itr;                                                           \
9247    Edje_Color_Class *cc;                                                         \
9248    Eina_Bool int_ret = EINA_TRUE;                                                \
9249    if (cond) return EINA_FALSE;                                                  \
9250    if (efl_isa(obj, EFL_UI_LAYOUT_BASE_CLASS))                                            \
9251      edje =  elm_layout_edje_get(obj);                                           \
9252    else if (efl_isa(obj, EFL_CANVAS_LAYOUT_CLASS))                                      \
9253      edje = obj;                                                                 \
9254    if (!edje) return EINA_FALSE;                                                 \
9255    itr = eina_hash_iterator_data_new(hash);                                      \
9256    EINA_ITERATOR_FOREACH(itr, cc)                                                \
9257      {                                                                           \
9258         int_ret &= edje_object_color_class_set(edje, cc->name,                   \
9259                                                cc->r, cc->g, cc->b, cc->a,       \
9260                                                cc->r2, cc->g2, cc->b2, cc->a2,   \
9261                                                cc->r3, cc->g3, cc->b3, cc->a3);  \
9262      }                                                                           \
9263    eina_iterator_free(itr);                                                      \
9264    return int_ret
9265
9266 static Eina_Bool
9267 _elm_widget_color_class_update(Eo *obj, Elm_Widget_Smart_Data *sd)
9268 {
9269    ELM_COLOR_CLASS_UPDATE(obj, sd->color_classes, (!sd) || (!sd->color_classes) || (!obj));
9270 }
9271
9272 #define CHECK_BOUND(x)                                                           \
9273    if (x > 0xff) x = 0xff;                                                       \
9274    else if (x < 0) x = 0
9275
9276 #define ELM_COLOR_CLASS_SET_START(obj, cr, cg, cb, ca)                           \
9277    Eina_Bool int_ret = EINA_FALSE;                                               \
9278    Edje_Color_Class *cc = NULL;                                                  \
9279    Eina_Stringshare *buf;                                                        \
9280    buf = _elm_widget_edje_class_get(obj, NULL, color_class);       \
9281    CHECK_BOUND(r);                                                               \
9282    CHECK_BOUND(g);                                                               \
9283    CHECK_BOUND(b);                                                               \
9284    CHECK_BOUND(a);                                                               \
9285    _elm_color_unpremul(a, &r, &g, &b);                                           \
9286    if (!sd->color_classes)                                                       \
9287      sd->color_classes = eina_hash_string_small_new(_edje_color_class_free);     \
9288    else                                                                          \
9289      cc = eina_hash_find(sd->color_classes, buf);                                \
9290    if (!cc)                                                                      \
9291      {                                                                           \
9292         cc = calloc(1, sizeof(Edje_Color_Class));                                \
9293         cc->name = eina_stringshare_add(buf);                                    \
9294         if (!cc->name)                                                           \
9295           {                                                                      \
9296              free(cc);                                                           \
9297              eina_stringshare_del(buf);                                          \
9298              return EINA_FALSE;                                                  \
9299           }                                                                      \
9300         eina_hash_direct_add(sd->color_classes, cc->name, cc);                   \
9301      }                                                                           \
9302    else if ((cc->cr == r) && (cc->cg == g) &&                                    \
9303             (cc->cb == b) && (cc->ca == a))                                      \
9304      {                                                                           \
9305         eina_stringshare_del(buf);                                               \
9306         return EINA_TRUE;                                                        \
9307      }                                                                           \
9308    cc->cr = r;                                                                   \
9309    cc->cg = g;                                                                   \
9310    cc->cb = b;                                                                   \
9311    cc->ca = a;                                                                   \
9312    int_ret = EINA_TRUE
9313
9314 #define ELM_COLOR_CLASS_SET_END()                                                \
9315    eina_stringshare_del(buf);                                                    \
9316    return int_ret
9317
9318 #define ELM_COLOR_CLASS_GET(obj, cr, cg, cb, ca)                                 \
9319    Eina_Bool int_ret = EINA_FALSE;                                               \
9320    Edje_Color_Class *cc;                                                         \
9321    Eina_Stringshare *buf;                                                        \
9322    int alpha = 0;                                                                \
9323    buf = _elm_widget_edje_class_get(obj, NULL, color_class);       \
9324    if ((!sd->color_classes) || !(cc = eina_hash_find(sd->color_classes, buf)))   \
9325      {                                                                           \
9326         if (r) *r = 0;                                                           \
9327         if (g) *g = 0;                                                           \
9328         if (b) *b = 0;                                                           \
9329         if (a) *a = 0;                                                           \
9330         int_ret = EINA_FALSE;                                                    \
9331      }                                                                           \
9332    else                                                                          \
9333      {                                                                           \
9334         if (r) *r = cc->cr;                                                      \
9335         if (g) *g = cc->cg;                                                      \
9336         if (b) *b = cc->cb;                                                      \
9337         if (a) *a = cc->ca;                                                      \
9338         alpha = cc->ca;                                                          \
9339         int_ret = EINA_TRUE;                                                     \
9340      }                                                                           \
9341    _elm_color_premul(alpha, r, g, b);                                            \
9342    eina_stringshare_del(buf);                                                    \
9343    return int_ret
9344
9345 Eina_Bool
9346 _elm_widget_item_color_class_update(Elm_Widget_Item_Data *sd)
9347 {
9348    ELM_COLOR_CLASS_UPDATE(sd->view, sd->color_classes, (!sd) || (!sd->color_classes) || (!sd->view));
9349 }
9350
9351 /* Internal EO API */
9352 static Eina_Bool
9353 _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)
9354 {
9355    ELM_COLOR_CLASS_SET_START(obj, r, g, b, a);
9356
9357    int_ret &= _elm_widget_item_color_class_update(sd);
9358
9359    ELM_COLOR_CLASS_SET_END();
9360 }
9361
9362 /* Internal EO API */
9363 static Eina_Bool
9364 _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)
9365 {
9366    ELM_COLOR_CLASS_GET(obj, r, g, b, a);
9367 }
9368
9369 /* Internal EO API */
9370 static Eina_Bool
9371 _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)
9372 {
9373    ELM_COLOR_CLASS_SET_START(obj, r2, g2, b2, a2);
9374
9375    int_ret &= _elm_widget_item_color_class_update(sd);
9376
9377    ELM_COLOR_CLASS_SET_END();
9378 }
9379
9380 /* Internal EO API */
9381 static Eina_Bool
9382 _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)
9383 {
9384    ELM_COLOR_CLASS_GET(obj, r2, g2, b2, a2);
9385 }
9386
9387 /* Internal EO API */
9388 static Eina_Bool
9389 _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)
9390 {
9391    ELM_COLOR_CLASS_SET_START(obj, r3, g3, b3, a3);
9392
9393    int_ret &= _elm_widget_item_color_class_update(sd);
9394
9395    ELM_COLOR_CLASS_SET_END();
9396 }
9397
9398 /* Internal EO API */
9399 static Eina_Bool
9400 _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)
9401 {
9402    ELM_COLOR_CLASS_GET(obj, r3, g3, b3, a3);
9403 }
9404
9405 /* Internal EO API */
9406 static Evas_Object *
9407 _elm_widget_item_edje_get(const Eo *obj, Elm_Widget_Item_Data *sd)
9408 {
9409    if (!sd)
9410      sd = efl_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
9411
9412    if (efl_isa(sd->view, EFL_UI_LAYOUT_BASE_CLASS))
9413      return elm_layout_edje_get(sd->view);
9414    else if (efl_isa(sd->view, EFL_CANVAS_LAYOUT_CLASS))
9415      return sd->view;
9416
9417    return NULL;
9418 }
9419
9420 /* Internal EO API */
9421 static void
9422 _elm_widget_item_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, const char *color_class)
9423 {
9424    Eina_Stringshare *buf;
9425    Evas_Object *edje;
9426    Edje_Color_Class *cc = NULL;
9427
9428    if (!color_class) return;
9429
9430    buf = _elm_widget_edje_class_get(obj, NULL, color_class);
9431    eina_hash_del(sd->color_classes, buf, cc);
9432
9433    edje = _elm_widget_item_edje_get(obj, sd);
9434    if (edje)
9435      edje_object_color_class_del(edje, buf);
9436
9437    eina_stringshare_del(buf);
9438 }
9439
9440 /* Internal EO API */
9441 static void
9442 _elm_widget_item_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
9443 {
9444    Evas_Object *edje;
9445    ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
9446
9447    edje = _elm_widget_item_edje_get(obj, sd);
9448    if (!edje) return;
9449
9450    edje_object_color_class_clear(edje);
9451 }
9452
9453 /* Internal EO APIs and hidden overrides */
9454 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color_set, Eina_Bool, EINA_FALSE,
9455                     EFL_FUNC_CALL(color_class, r, g, b, a),
9456                     const char *color_class, int r, int g, int b, int a)
9457 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color_get, Eina_Bool, EINA_FALSE,
9458                     EFL_FUNC_CALL(color_class, r, g, b, a),
9459                     const char *color_class, int *r, int *g, int *b, int *a)
9460 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color2_set, Eina_Bool, EINA_FALSE,
9461                     EFL_FUNC_CALL(color_class, r, g, b, a),
9462                     const char *color_class, int r, int g, int b, int a)
9463 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color2_get, Eina_Bool, EINA_FALSE,
9464                     EFL_FUNC_CALL(color_class, r, g, b, a),
9465                     const char *color_class, int *r, int *g, int *b, int *a)
9466 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color3_set, Eina_Bool, EINA_FALSE,
9467                     EFL_FUNC_CALL(color_class, r, g, b, a),
9468                     const char *color_class, int r, int g, int b, int a)
9469 EAPI EFL_FUNC_BODYV(elm_widget_item_class_color3_get, Eina_Bool, EINA_FALSE,
9470                     EFL_FUNC_CALL(color_class, r, g, b, a),
9471                     const char *color_class, int *r, int *g, int *b, int *a)
9472 EAPI EFL_VOID_FUNC_BODYV(elm_widget_item_class_color_del,
9473                          EFL_FUNC_CALL(color_class),
9474                          const char *color_class)
9475 EAPI EFL_VOID_FUNC_BODY(elm_widget_item_class_color_clear)
9476
9477 #define ELM_WIDGET_ITEM_EXTRA_OPS \
9478    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_set, _elm_widget_item_class_color_set), \
9479    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_get, _elm_widget_item_class_color_get), \
9480    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color2_set, _elm_widget_item_class_color2_set), \
9481    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color2_get, _elm_widget_item_class_color2_get), \
9482    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color3_set, _elm_widget_item_class_color3_set), \
9483    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color3_get, _elm_widget_item_class_color3_get), \
9484    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_del, _elm_widget_item_class_color_del), \
9485    EFL_OBJECT_OP_FUNC(elm_widget_item_class_color_clear, _elm_widget_item_class_color_clear)
9486
9487 /*******
9488  * END *
9489  *******/
9490
9491 //TIZEN_ONLY(20180607): Restore legacy focus
9492 static void
9493 _if_focused_revert(Evas_Object *obj,
9494                    Eina_Bool can_focus_only)
9495 {
9496    Evas_Object *top;
9497    Evas_Object *newest = NULL;
9498    unsigned int newest_focus_order = 0;
9499
9500    INTERNAL_ENTRY;
9501
9502    if (!sd->focused) return;
9503    if (!sd->parent_obj) return;
9504
9505    top = elm_widget_top_get(sd->parent_obj);
9506    if (top)
9507      {
9508         newest = efl_ui_widget_newest_focus_order_get
9509            (top, &newest_focus_order, can_focus_only);
9510         if (newest)
9511           {
9512              if (newest == top)
9513                {
9514                   ELM_WIDGET_DATA_GET(newest, sd2);
9515                   if (!sd2) return;
9516
9517                   if (!_is_focused(newest))
9518                     efl_ui_widget_focus_steal(newest, NULL);
9519                   else
9520                     {
9521                        if (sd2->resize_obj && _is_focused(sd2->resize_obj))
9522                          efl_ui_widget_focused_object_clear(sd2->resize_obj);
9523                        else
9524                          {
9525                             Evas_Object *child;
9526                             for (unsigned int i = 0; i < eina_array_count(sd2->children); ++i)
9527                               {
9528                                  child = eina_array_data_get(sd2->children, i);
9529                                  if (!_elm_widget_is(child)) continue;
9530                                  if (_is_focused(child))
9531                                    {
9532                                       efl_ui_widget_focused_object_clear(child);
9533                                       break;
9534                                    }
9535                               }
9536                          }
9537                     }
9538                   evas_object_focus_set(newest, EINA_TRUE);
9539                }
9540              else
9541                {
9542                   if (_is_focused(newest))
9543                     efl_ui_widget_focused_object_clear(newest);
9544                   elm_object_focus_set(newest, EINA_TRUE);
9545                }
9546           }
9547      }
9548 }
9549
9550 /**
9551  * @internal
9552  *
9553  * Set custom focus chain.
9554  *
9555  * This function i set one new and overwrite any previous custom focus chain
9556  * with the list of objects. The previous list will be deleted and this list
9557  * will be managed. After setted, don't modity it.
9558  *
9559  * @note On focus cycle, only will be evaluated children of this container.
9560  *
9561  * @param obj The container widget
9562  * @param objs Chain of objects to pass focus
9563  * @ingroup Widget
9564  */
9565 EOLIAN static void
9566 _efl_ui_widget_focus_custom_chain_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_List *objs)
9567 {
9568    if (!_elm_widget_focus_chain_manager_is(obj)) return;
9569
9570    efl_ui_widget_focus_custom_chain_unset(obj);
9571
9572    Eina_List *l;
9573    Evas_Object *o;
9574
9575    EINA_LIST_FOREACH(objs, l, o)
9576      {
9577         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
9578                                        _elm_object_focus_chain_del_cb, obj);
9579      }
9580
9581    sd->focus_chain = objs;
9582 }
9583
9584 /**
9585  * @internal
9586  *
9587  * Get custom focus chain
9588  *
9589  * @param obj The container widget
9590  * @ingroup Widget
9591  */
9592 EOLIAN static const Eina_List*
9593 _efl_ui_widget_focus_custom_chain_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
9594 {
9595    return (const Eina_List *)sd->focus_chain;
9596 }
9597
9598 /**
9599  * @internal
9600  *
9601  * Unset custom focus chain
9602  *
9603  * @param obj The container widget
9604  * @ingroup Widget
9605  */
9606 EOLIAN static void
9607 _efl_ui_widget_focus_custom_chain_unset(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
9608 {
9609    Eina_List *l, *l_next;
9610    Evas_Object *o;
9611
9612    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
9613      {
9614         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
9615                                             _elm_object_focus_chain_del_cb, obj);
9616         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
9617      }
9618 }
9619
9620 /**
9621  * @internal
9622  *
9623  * Append object to custom focus chain.
9624  *
9625  * @note If relative_child equal to NULL or not in custom chain, the object
9626  * will be added in end.
9627  *
9628  * @note On focus cycle, only will be evaluated children of this container.
9629  *
9630  * @param obj The container widget
9631  * @param child The child to be added in custom chain
9632  * @param relative_child The relative object to position the child
9633  * @ingroup Widget
9634  */
9635 EOLIAN static void
9636 _efl_ui_widget_focus_custom_chain_append(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
9637 {
9638    EINA_SAFETY_ON_NULL_RETURN(child);
9639
9640    if (!_elm_widget_focus_chain_manager_is(obj)) return;
9641
9642    evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
9643                                   _elm_object_focus_chain_del_cb, obj);
9644
9645    if (!relative_child)
9646      sd->focus_chain = eina_list_append(sd->focus_chain, child);
9647    else
9648      sd->focus_chain = eina_list_append_relative(sd->focus_chain,
9649                                                  child, relative_child);
9650 }
9651
9652 /**
9653  * @internal
9654  *
9655  * Prepend object to custom focus chain.
9656  *
9657  * @note If relative_child equal to NULL or not in custom chain, the object
9658  * will be added in begin.
9659  *
9660  * @note On focus cycle, only will be evaluated children of this container.
9661  *
9662  * @param obj The container widget
9663  * @param child The child to be added in custom chain
9664  * @param relative_child The relative object to position the child
9665  * @ingroup Widget
9666  */
9667 EOLIAN static void
9668 _efl_ui_widget_focus_custom_chain_prepend(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
9669 {
9670    EINA_SAFETY_ON_NULL_RETURN(child);
9671
9672    if (!_elm_widget_focus_chain_manager_is(obj)) return;
9673
9674    evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
9675                                   _elm_object_focus_chain_del_cb, obj);
9676
9677    if (!relative_child)
9678      sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
9679    else
9680      sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
9681                                                   child, relative_child);
9682 }
9683
9684 /**
9685  * @internal
9686  *
9687  * Give focus to next object in object tree.
9688  *
9689  * Give focus to next object in focus chain of one object sub-tree.
9690  * If the last object of chain already have focus, the focus will go to the
9691  * first object of chain.
9692  *
9693  * @param obj The widget root of sub-tree
9694  * @param dir Direction to cycle the focus
9695  *
9696  * @ingroup Widget
9697  */
9698 EOLIAN static void
9699 _efl_ui_widget_focus_cycle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Efl_Ui_Focus_Direction dir)
9700 {
9701    Evas_Object *target = NULL;
9702    Elm_Object_Item *target_item = NULL;
9703    if (!_elm_widget_is(obj))
9704      return;
9705    efl_ui_widget_focus_next_get(obj, dir, &target, &target_item);
9706    if (target)
9707      {
9708         /* access */
9709         if (_elm_config->access_mode)
9710           {
9711              /* highlight cycle does not steal a focus, only after window gets
9712                 the ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE message,
9713                 target will steal focus, or focus its own job. */
9714              if (!_elm_access_auto_highlight_get())
9715                efl_ui_widget_focus_steal(target, target_item);
9716
9717              _elm_access_highlight_set(target);
9718              elm_widget_focus_region_show(target);
9719           }
9720         else efl_ui_widget_focus_steal(target, target_item);
9721      }
9722 }
9723
9724 /**
9725  * @internal
9726  *
9727  * Give focus to near object(in object tree) in one direction.
9728  *
9729  * Give focus to near object(in object tree) in direction of current
9730  * focused object.  If none focusable object in given direction or
9731  * none focused object in object tree, the focus will not change.
9732  *
9733  * @param obj The reference widget
9734  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
9735  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
9736  * @return EINA_TRUE if focus is moved.
9737  *
9738  * @ingroup Widget
9739  */
9740 EOLIAN static Eina_Bool
9741 _efl_ui_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, double degree)
9742 {
9743    Evas_Object *target = NULL;
9744    Elm_Object_Item *target_item = NULL;
9745    Evas_Object *current_focused = NULL;
9746    double weight = 0.0;
9747
9748    if (!_elm_widget_is(obj)) return EINA_FALSE;
9749    if (!_is_focused(obj)) return EINA_FALSE;
9750
9751    current_focused = efl_ui_widget_focused_object_get(obj);
9752
9753    if (efl_ui_widget_focus_direction_get
9754          (obj, current_focused, degree, &target, &target_item, &weight))
9755      {
9756         efl_ui_widget_focus_steal(target, NULL);
9757         return EINA_TRUE;
9758      }
9759
9760    return EINA_FALSE;
9761 }
9762
9763 /**
9764  * @internal
9765  *
9766  * Get near object in one direction of base object.
9767  *
9768  * Get near object(in the object sub-tree) in one direction of
9769  * base object. Return the near object by reference.
9770  * By initializing weight, you can filter objects locating far
9771  * from base object. If object is in the specific direction,
9772  * weight is (1/(distance^2)). If object is not exactly in one
9773  * direction, some penalty will be added.
9774  *
9775  * @param obj The widget root of sub-tree
9776  * @param base The base object of the direction
9777  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
9778  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
9779  * @param direction The near object in one direction
9780  * @param weight The weight is bigger when the object is located near
9781  * @return EINA_TRUE if near object is updated.
9782  *
9783  * @ingroup Widget
9784  */
9785
9786 EOLIAN static Eina_Bool
9787 _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)
9788 {
9789    double c_weight;
9790
9791    /* -1 means the best was already decided. Don't need any more searching. */
9792    if (!direction || !weight || !base || (obj == base))
9793      return EINA_FALSE;
9794
9795    /* Ignore if disabled */
9796    if ((!evas_object_visible_get(obj))
9797        || (elm_widget_disabled_get(obj))
9798        || (elm_widget_tree_unfocusable_get(obj)))
9799      return EINA_FALSE;
9800
9801    /* Try use hook */
9802    if (_internal_elm_widget_focus_direction_manager_is(obj))
9803      {
9804         Eina_Bool int_ret = EINA_FALSE;
9805         int_ret = efl_ui_widget_focus_direction((Eo *)obj, base, degree, direction, direction_item, weight);
9806         return int_ret;
9807      }
9808
9809    if (!elm_widget_can_focus_get(obj) || _is_focused((Eo *)obj))
9810      return EINA_FALSE;
9811
9812    c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree);
9813    if ((c_weight == -1.0) ||
9814        ((c_weight != 0.0) && (*weight != -1.0) &&
9815         ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
9816      {
9817         if (*direction &&
9818             ((int)(*weight * 1000000) == (int)(c_weight * 1000000)))
9819           {
9820              ELM_WIDGET_DATA_GET(*direction, sd1);
9821              if (sd1)
9822                {
9823                   if (sd->focus_order <= sd1->focus_order)
9824                     return EINA_FALSE;
9825                }
9826           }
9827         *direction = (Evas_Object *)obj;
9828         *weight = c_weight;
9829         return EINA_TRUE;
9830      }
9831
9832    return EINA_FALSE;
9833 }
9834
9835 /**
9836  * @internal
9837  *
9838  * Get near object in one direction of base object in list.
9839  *
9840  * Get near object in one direction of base object in the specific
9841  * object list. Return the near object by reference.
9842  * By initializing weight, you can filter objects locating far
9843  * from base object. If object is in the specific direction,
9844  * weight is (1/(distance^2)). If object is not exactly in one
9845  * direction, some penalty will be added.
9846  *
9847  * @param obj The widget root of sub-tree
9848  * @param base The base object of the direction
9849  * @param items list with ordered objects
9850  * @param list_data_get function to get the object from one item of list
9851  * @param degree Degree changes clockwise. i.e. 0-degree: Up,
9852  *               90-degree: Right, 180-degree: Down, and 270-degree: Left
9853  * @param direction The near object in one direction
9854  * @param weight The weight is bigger when the object is located near
9855  * @return EINA_TRUE if near object is updated.
9856  *
9857  * @ingroup Widget
9858  */
9859 EOLIAN static Eina_Bool
9860 _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)
9861 {
9862    if (!direction || !weight || !base || !items)
9863      return EINA_FALSE;
9864
9865    const Eina_List *l = items;
9866    Evas_Object *current_best = *direction;
9867
9868    for (; l; l = eina_list_next(l))
9869      {
9870         Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
9871         if (cur && _elm_widget_is(cur))
9872           efl_ui_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight);
9873      }
9874    if (current_best != *direction) return EINA_TRUE;
9875
9876    return EINA_FALSE;
9877 }
9878
9879 /**
9880  * @internal
9881  *
9882  * Get next object in focus chain of object tree.
9883  *
9884  * Get next object in focus chain of one object sub-tree.
9885  * Return the next object by reference. If don't have any candidate to receive
9886  * focus before chain end, the first candidate will be returned.
9887  *
9888  * @param obj The widget root of sub-tree
9889  * @param dir Direction of focus chain
9890  * @param next The next object in focus chain
9891  * @return EINA_TRUE if don't need focus chain restart/loop back
9892  *         to use 'next' obj.
9893  *
9894  * @ingroup Widget
9895  */
9896 EOLIAN static Eina_Bool
9897 _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)
9898 {
9899    Elm_Access_Info *ac;
9900
9901    if (!next)
9902      return EINA_FALSE;
9903    *next = NULL;
9904
9905    /* Ignore if disabled */
9906    if (_elm_config->access_mode && _elm_access_auto_highlight_get())
9907      {
9908         if (!evas_object_visible_get(obj)
9909             || (elm_widget_tree_unfocusable_get(obj)))
9910           return EINA_FALSE;
9911      }
9912    else
9913      {
9914         if ((!evas_object_visible_get(obj))
9915             || (elm_widget_disabled_get(obj))
9916             || (elm_widget_tree_unfocusable_get(obj)))
9917           return EINA_FALSE;
9918      }
9919
9920    /* Try use hook */
9921    if (_elm_widget_focus_chain_manager_is(obj))
9922      {
9923         Eina_Bool int_ret = EINA_FALSE;
9924         int_ret = efl_ui_widget_focus_next((Eo *)obj, dir, next, next_item);
9925         if (!int_ret && _is_focused((Eo *)obj))
9926           {
9927              Evas_Object *o = NULL;
9928              if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
9929                *next_item = sd->item_focus_previous;
9930              else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
9931                *next_item = sd->item_focus_next;
9932              else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
9933                *next_item = sd->item_focus_up;
9934              else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
9935                *next_item = sd->item_focus_down;
9936              else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
9937                *next_item = sd->item_focus_right;
9938              else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
9939                *next_item = sd->item_focus_left;
9940              if (*next_item)
9941                o = elm_object_item_widget_get(*next_item);
9942
9943              if (!o)
9944                {
9945                   if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
9946                     o = sd->focus_previous;
9947                   else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
9948                     o = sd->focus_next;
9949                   else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
9950                     o = sd->focus_up;
9951                   else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
9952                     o = sd->focus_down;
9953                   else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
9954                     o = sd->focus_right;
9955                   else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
9956                     o = sd->focus_left;
9957                }
9958
9959              if (o)
9960                {
9961                   *next = o;
9962                   return EINA_TRUE;
9963                }
9964           }
9965         return int_ret;
9966      }
9967
9968    /* access object does not check sd->can_focus, because an object could
9969       have highlight even though the object is not focusable. */
9970    if (_elm_config->access_mode && _elm_access_auto_highlight_get())
9971      {
9972         ac = _elm_access_info_get(obj);
9973         if (!ac) return EINA_FALSE;
9974
9975         /* check whether the hover object is visible or not */
9976         if (!evas_object_visible_get(ac->hoverobj))
9977           return EINA_FALSE;
9978      }
9979    else if (!elm_widget_can_focus_get(obj))
9980      return EINA_FALSE;
9981
9982    if (_is_focused((Eo *)obj))
9983      {
9984         if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
9985           *next_item = sd->item_focus_previous;
9986         else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
9987           *next_item = sd->item_focus_next;
9988         else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
9989           *next_item = sd->item_focus_up;
9990         else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
9991           *next_item = sd->item_focus_down;
9992         else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
9993           *next_item = sd->item_focus_right;
9994         else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
9995           *next_item = sd->item_focus_left;
9996         if (*next_item) *next = elm_object_item_widget_get(*next_item);
9997
9998         if (!(*next))
9999           {
10000              if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10001                *next = sd->focus_previous;
10002              else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10003                *next = sd->focus_next;
10004              else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10005                *next = sd->focus_up;
10006              else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10007                *next = sd->focus_down;
10008              else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10009                *next = sd->focus_right;
10010              else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10011                *next = sd->focus_left;
10012           }
10013
10014         if (*next) return EINA_TRUE;
10015      }
10016
10017    /* Return */
10018    *next = (Evas_Object *)obj;
10019    return !ELM_WIDGET_FOCUS_GET(obj);
10020 }
10021
10022 /**
10023  * @internal
10024  *
10025  * Get next object in focus chain of object tree in list.
10026  *
10027  * Get next object in focus chain of one object sub-tree ordered by one list.
10028  * Return the next object by reference. If don't have any candidate to receive
10029  * focus before list end, the first candidate will be returned.
10030  *
10031  * @param obj The widget root of sub-tree
10032  * @param items list with ordered objects
10033  * @param list_data_get function to get the object from one item of list
10034  * @param dir Direction of focus chain
10035  * @param next The next object in focus chain
10036  * @return EINA_TRUE if don't need focus chain restart/loop back
10037  *         to use 'next' obj.
10038  *
10039  * @ingroup Widget
10040  */
10041 EOLIAN static Eina_Bool
10042 _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)
10043 {
10044    Eina_List *(*list_next)(const Eina_List *list) = NULL;
10045    Evas_Object *focused_object = NULL;
10046
10047    if (!next)
10048      return EINA_FALSE;
10049    *next = NULL;
10050
10051    if (!_elm_widget_is(obj))
10052      return EINA_FALSE;
10053
10054    if (!items)
10055      return EINA_FALSE;
10056
10057    /* When Up, Down, Right, or Left, try direction_get first. */
10058    focused_object = efl_ui_widget_focused_object_get(obj);
10059    if (focused_object)
10060      {
10061         if ((dir == EFL_UI_FOCUS_DIRECTION_UP)
10062            || (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10063            || (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10064            || (dir == EFL_UI_FOCUS_DIRECTION_LEFT))
10065           {
10066              *next_item = efl_ui_widget_focus_next_item_get(focused_object, dir);
10067              if (*next_item)
10068                *next = elm_object_item_widget_get(*next_item);
10069              else
10070                *next = efl_ui_widget_focus_next_object_get(focused_object, dir);
10071              if (*next) return EINA_TRUE;
10072              else
10073                {
10074                   Evas_Object *n = NULL;
10075                   Elm_Object_Item *n_item = NULL;
10076                   double degree = 0;
10077                   double weight = 0.0;
10078
10079                   if (dir == EFL_UI_FOCUS_DIRECTION_UP) degree = 0.0;
10080                   else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN) degree = 180.0;
10081                   else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT) degree = 90.0;
10082                   else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT) degree = 270.0;
10083
10084                   if (efl_ui_widget_focus_list_direction_get(obj, focused_object,
10085                                                           items, list_data_get,
10086                                                           degree, &n, &n_item,
10087                                                           &weight))
10088                     {
10089                        *next_item = n_item;
10090                        *next = n;
10091                        return EINA_TRUE;
10092                     }
10093                }
10094           }
10095      }
10096
10097    /* Direction */
10098    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10099      {
10100         items = eina_list_last(items);
10101         list_next = eina_list_prev;
10102      }
10103    else if ((dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10104             || (dir == EFL_UI_FOCUS_DIRECTION_UP)
10105             || (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10106             || (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10107             || (dir == EFL_UI_FOCUS_DIRECTION_LEFT))
10108      list_next = eina_list_next;
10109    else
10110      return EINA_FALSE;
10111
10112    const Eina_List *l = items;
10113
10114    /* Recovery last focused sub item */
10115    if (ELM_WIDGET_FOCUS_GET(obj))
10116      {
10117         for (; l; l = list_next(l))
10118           {
10119              Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
10120              if (ELM_WIDGET_FOCUS_GET(cur)) break;
10121           }
10122
10123          /* Focused object, but no focused sub item */
10124          if (!l) l = items;
10125      }
10126
10127    const Eina_List *start = l;
10128    Evas_Object *to_focus = NULL;
10129    Elm_Object_Item *to_focus_item = NULL;
10130
10131    /* Iterate sub items */
10132    /* Go to the end of list */
10133    for (; l; l = list_next(l))
10134      {
10135         Evas_Object *tmp = NULL;
10136         Elm_Object_Item *tmp_item = NULL;
10137         Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
10138
10139         if (!cur) continue;
10140         if (!_elm_widget_is(cur)) continue;
10141         if (elm_widget_parent_get(cur) != obj)
10142           continue;
10143
10144         /* Try Focus cycle in subitem */
10145         if (efl_ui_widget_focus_next_get(cur, dir, &tmp, &tmp_item))
10146           {
10147              *next = tmp;
10148              *next_item = tmp_item;
10149              return EINA_TRUE;
10150           }
10151         else if ((dir == EFL_UI_FOCUS_DIRECTION_UP)
10152                  || (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10153                  || (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10154                  || (dir == EFL_UI_FOCUS_DIRECTION_LEFT))
10155           {
10156              if (tmp && _is_focused(cur))
10157                {
10158                   *next = tmp;
10159                   *next_item = tmp_item;
10160                   return EINA_FALSE;
10161                }
10162           }
10163         else if ((tmp) && (!to_focus))
10164           {
10165              to_focus = tmp;
10166              to_focus_item = tmp_item;
10167           }
10168      }
10169
10170    l = items;
10171
10172    /* Get First possible */
10173    for (; l != start; l = list_next(l))
10174      {
10175         Evas_Object *tmp = NULL;
10176         Elm_Object_Item *tmp_item = NULL;
10177         Evas_Object *cur = ((list_data_get_func_type)list_data_get)(l);
10178
10179         if (elm_widget_parent_get(cur) != obj)
10180           continue;
10181
10182         /* Try Focus cycle in subitem */
10183         efl_ui_widget_focus_next_get(cur, dir, &tmp, &tmp_item);
10184         if (tmp)
10185           {
10186              *next = tmp;
10187              *next_item = tmp_item;
10188              return EINA_FALSE;
10189           }
10190      }
10191
10192    *next = to_focus;
10193    *next_item = to_focus_item;
10194    return EINA_FALSE;
10195 }
10196
10197 /**
10198  * @internal
10199  *
10200  * Get next object which was set with specific focus direction.
10201  *
10202  * Get next object which was set by elm_widget_focus_next_object_set
10203  * with specific focus directioin.
10204  *
10205  * @param obj The widget
10206  * @param dir Direction of focus
10207  * @return Widget which was registered with sepecific focus direction.
10208  *
10209  * @ingroup Widget
10210  */
10211 EOLIAN static Evas_Object*
10212 _efl_ui_widget_focus_next_object_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Ui_Focus_Direction dir)
10213 {
10214    Evas_Object *ret = NULL;
10215
10216    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10217      ret = sd->focus_previous;
10218    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10219      ret = sd->focus_next;
10220    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10221      ret = sd->focus_up;
10222    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10223      ret = sd->focus_down;
10224    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10225      ret = sd->focus_right;
10226    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10227      ret = sd->focus_left;
10228
10229    return ret;
10230 }
10231
10232 /**
10233  * @internal
10234  *
10235  * Set next object with specific focus direction.
10236  *
10237  * When a widget is set with specific focus direction, this widget will be
10238  * the first candidate when finding the next focus object.
10239  * Focus next object can be registered with six directions that are previous,
10240  * next, up, down, right, and left.
10241  *
10242  * @param obj The widget
10243  * @param next Next focus object
10244  * @param dir Direction of focus
10245  *
10246  * @ingroup Widget
10247  */
10248 EOLIAN static void
10249 _efl_ui_widget_focus_next_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *next, Efl_Ui_Focus_Direction dir)
10250 {
10251
10252    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10253      sd->focus_previous = next;
10254    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10255      sd->focus_next = next;
10256    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10257      sd->focus_up = next;
10258    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10259      sd->focus_down = next;
10260    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10261      sd->focus_right = next;
10262    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10263      sd->focus_left = next;
10264
10265 }
10266
10267 EOLIAN static Elm_Object_Item*
10268 _efl_ui_widget_focus_next_item_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Efl_Ui_Focus_Direction dir)
10269 {
10270    Elm_Object_Item *ret = NULL;
10271
10272    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10273      ret = sd->item_focus_previous;
10274    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10275      ret = sd->item_focus_next;
10276    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10277      ret = sd->item_focus_up;
10278    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10279      ret = sd->item_focus_down;
10280    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10281      ret = sd->item_focus_right;
10282    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10283      ret = sd->item_focus_left;
10284
10285    return ret;
10286
10287 }
10288
10289 EOLIAN static void
10290 _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)
10291 {
10292    if (dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)
10293      sd->item_focus_previous = next_item;
10294    else if (dir == EFL_UI_FOCUS_DIRECTION_NEXT)
10295      sd->item_focus_next = next_item;
10296    else if (dir == EFL_UI_FOCUS_DIRECTION_UP)
10297      sd->item_focus_up = next_item;
10298    else if (dir == EFL_UI_FOCUS_DIRECTION_DOWN)
10299      sd->item_focus_down = next_item;
10300    else if (dir == EFL_UI_FOCUS_DIRECTION_RIGHT)
10301      sd->item_focus_right = next_item;
10302    else if (dir == EFL_UI_FOCUS_DIRECTION_LEFT)
10303      sd->item_focus_left = next_item;
10304 }
10305
10306 EAPI void
10307 elm_widget_focus_set(Eo *obj, Eina_Bool focus)
10308 {
10309    ELM_WIDGET_DATA_GET_OR_RETURN(obj, sd);
10310    if (!sd->focused)
10311      {
10312         focus_order++;
10313         sd->focus_order = focus_order;
10314         sd->focused = EINA_TRUE;
10315         efl_ui_focus_object_on_focus_update(obj);
10316      }
10317
10318    if (focus)
10319      {
10320         if ((_is_focusable(sd->resize_obj)) &&
10321             (!elm_widget_disabled_get(sd->resize_obj)))
10322           {
10323              elm_widget_focus_set(sd->resize_obj, focus);
10324           }
10325         else
10326           {
10327              Evas_Object *child;
10328
10329              for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
10330                {
10331                   child = eina_array_data_get(sd->children, i);
10332                   if (!_elm_widget_is(child)) continue;
10333                   if ((_is_focusable(child)) &&
10334                        (!elm_widget_disabled_get(child)))
10335                       {
10336                          elm_widget_focus_set(child, focus);
10337                          break;
10338                       }
10339                }
10340           }
10341      }
10342    else
10343      {
10344         Evas_Object *child;
10345         unsigned int i = eina_array_count(sd->children);
10346
10347         while (i >= 1)
10348           {
10349              i--;
10350              child = eina_array_data_get(sd->children, i);
10351              if (!_elm_widget_is(child)) continue;
10352              if ((_is_focusable(child)) &&
10353                  (!elm_widget_disabled_get(child)))
10354                {
10355                   elm_widget_focus_set(child, focus);
10356                   break;
10357                }
10358              if (i == 0) break;
10359           }
10360      }
10361 }
10362
10363 static void
10364 _focused_object_clear(Elm_Widget_Smart_Data *sd)
10365 {
10366    if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
10367        _is_focused(sd->resize_obj))
10368      {
10369         efl_ui_widget_focused_object_clear(sd->resize_obj);
10370      }
10371    else
10372      {
10373         Evas_Object *child;
10374         for (unsigned int i = 0; i < eina_array_count(sd->children); ++i)
10375           {
10376              child = eina_array_data_get(sd->children, i);
10377              if (_elm_widget_is(child) && _is_focused(child))
10378                {
10379                   efl_ui_widget_focused_object_clear(child);
10380                   break;
10381                }
10382           }
10383      }
10384 }
10385
10386 EOLIAN static void
10387 _efl_ui_widget_focused_object_clear(Eo *obj, Elm_Widget_Smart_Data *sd)
10388 {
10389    if (!sd->focused) return;
10390    _focused_object_clear(sd);
10391    sd->focused = EINA_FALSE;
10392    if (sd->top_win_focused)
10393      efl_ui_focus_object_on_focus_update(obj);
10394 }
10395
10396 EOLIAN static void
10397 _efl_ui_widget_focus_steal(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item)
10398 {
10399    Evas_Object *parent, *parent2, *o;
10400
10401    if (sd->focused) return;
10402    if (sd->disabled) return;
10403    if (!sd->can_focus) return;
10404    if (sd->tree_unfocusable) return;
10405    parent = obj;
10406    for (;; )
10407      {
10408         o = elm_widget_parent_get(parent);
10409         if (!o) break;
10410         sd = efl_data_scope_get(o, MY_CLASS);
10411         if (sd->disabled || sd->tree_unfocusable) return;
10412         if (sd->focused) break;
10413         parent = o;
10414      }
10415    if ((!elm_widget_parent_get(parent)))
10416      efl_ui_widget_focused_object_clear(parent);
10417    else
10418      {
10419         parent2 = elm_widget_parent_get(parent);
10420         parent = parent2;
10421         sd = efl_data_scope_get(parent, MY_CLASS);
10422         if (sd) _focused_object_clear(sd);
10423      }
10424    _parent_focus(obj, item);
10425    elm_widget_focus_region_show(obj);
10426    return;
10427 }
10428
10429 static void
10430 _parents_on_focus(Evas_Object *obj)
10431 {
10432    API_ENTRY return;
10433    if (!sd->focused || !sd->top_win_focused) return;
10434
10435    Evas_Object *o = elm_widget_parent_get(obj);
10436    if (o) _parents_on_focus(o);
10437    efl_ui_focus_object_on_focus_update(obj);
10438 }
10439
10440 EOLIAN static void
10441 _efl_ui_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
10442 {
10443    Evas_Object *newest = NULL;
10444    unsigned int newest_focus_order = 0;
10445
10446    newest = efl_ui_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
10447    if (newest)
10448      _parents_on_focus(newest);
10449 }
10450
10451 /**
10452  * @internal
10453  *
10454  * Check if the widget has its own focus next function.
10455  *
10456  * @param obj The widget.
10457  * @return focus next function is implemented/unimplemented.
10458  * (@c EINA_TRUE = implemented/@c EINA_FALSE = unimplemented.)
10459  */
10460 static inline Eina_Bool
10461 _elm_widget_focus_chain_manager_is(const Evas_Object *obj)
10462 {
10463    ELM_WIDGET_CHECK(obj) EINA_FALSE;
10464
10465    Eina_Bool manager_is = EINA_FALSE;
10466    manager_is = efl_ui_widget_focus_next_manager_is((Eo *)obj);
10467    return manager_is;
10468 }
10469
10470 static inline Eina_Bool
10471 _internal_elm_widget_focus_direction_manager_is(const Evas_Object *obj)
10472 {
10473    ELM_WIDGET_CHECK(obj) EINA_FALSE;
10474
10475    Eina_Bool manager_is = EINA_FALSE;
10476    manager_is = efl_ui_widget_focus_direction_manager_is((Eo *)obj);
10477    return manager_is;
10478 }
10479
10480 static void
10481 _parent_focus(Evas_Object *obj, Elm_Object_Item *item)
10482 {
10483    API_ENTRY return;
10484
10485    if (sd->focused) return;
10486
10487    Evas_Object *o = elm_widget_parent_get(obj);
10488    sd->focus_order_on_calc = EINA_TRUE;
10489
10490    if (o) _parent_focus(o, item);
10491
10492    if (!sd->focus_order_on_calc)
10493      return;  /* we don't want to override it if by means of any of the
10494                  callbacks below one gets to calculate our order
10495                  first. */
10496
10497    focus_order++;
10498    sd->focus_order = focus_order;
10499    sd->focused = EINA_TRUE;
10500
10501    if (sd->top_win_focused)
10502      efl_ui_focus_object_on_focus_update(obj);
10503    sd->focus_order_on_calc = EINA_FALSE;
10504
10505    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
10506      _elm_access_highlight_set(obj);
10507 }
10508
10509 static void
10510 _elm_object_focus_chain_del_cb(void *data,
10511                                Evas *e EINA_UNUSED,
10512                                Evas_Object *obj,
10513                                void *event_info EINA_UNUSED)
10514 {
10515    ELM_WIDGET_DATA_GET(data, sd);
10516
10517    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
10518 }
10519
10520 //TIZEN_ONLY(20200117): transition duration factor for widget transition customize
10521 EOLIAN static Eina_Bool
10522 _efl_ui_widget_transition_duration_factor_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd , double duration)
10523 {
10524    pd->transition_duration = duration;
10525    // the value need to be $true when widget have transition effect.
10526    return EINA_FALSE;
10527 }
10528
10529 EOLIAN static double
10530 _efl_ui_widget_transition_duration_factor_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
10531 {
10532    return pd->transition_duration;
10533 }
10534 //
10535
10536 //TIZEN_ONLT(20191218): efl_ui_widget: add widget_focus property to handle focus
10537 EOLIAN static Eina_Bool
10538 _efl_ui_widget_widget_focus_get(const Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
10539 {
10540    return elm_object_focus_get(obj);
10541 }
10542
10543 EOLIAN static void
10544 _efl_ui_widget_widget_focus_set(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED, Eina_Bool focus)
10545 {
10546    focus = !!focus;
10547    elm_object_focus_set(obj, focus);
10548 }
10549 //
10550
10551 #include "elm_widget_item_eo.c"
10552 #include "elm_widget_item_container_eo.c"
10553 #include "efl_ui_widget.eo.c"
10554 #include "efl_ui_widget_eo.legacy.c"
10555
10556 /* Others */
10557 #include "efl_ui_l10n.eo.c"