2 # include "elementary_config.h"
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8 #define ELM_WIDGET_ITEM_PROTECTED
9 #include <Elementary.h>
12 #include "elm_widget_container.h"
13 #include "elm_interface_scrollable.h"
15 #define MY_CLASS ELM_WIDGET_CLASS
17 #define MY_CLASS_NAME "Elm_Widget"
18 #define MY_CLASS_NAME_LEGACY "elm_widget"
20 #define ELM_WIDGET_DATA_GET(o, wd) \
21 Elm_Widget_Smart_Data *wd = eo_data_scope_get(o, MY_CLASS)
24 ELM_WIDGET_DATA_GET(obj, sd); \
25 if ((!sd) || (!_elm_widget_is(obj)))
26 #define INTERNAL_ENTRY \
27 ELM_WIDGET_DATA_GET(obj, sd); \
30 #define ELM_WIDGET_FOCUS_GET(obj) \
31 (eo_isa(obj, ELM_WIDGET_CLASS) && \
32 ((_elm_access_auto_highlight_get()) ? (elm_widget_highlight_get(obj)) : \
33 (elm_widget_focus_get(obj))))
35 const char SIG_WIDGET_FOCUSED[] = "focused";
36 const char SIG_WIDGET_UNFOCUSED[] = "unfocused";
37 const char SIG_WIDGET_LANG_CHANGED[] = "language,changed";
38 const char SIG_WIDGET_ACCESS_CHANGED[] = "access,changed";
40 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
41 const char SIG_WIDGET_ATSPI_HIGHLIGHTED[] = "atspi,highlighted";
42 const char SIG_WIDGET_ATSPI_UNHIGHLIGHTED[] = "atspi,unhighlighted";
45 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
46 typedef struct _Elm_Label_Data Elm_Label_Data;
47 typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
49 struct _Elm_Event_Cb_Data
55 struct _Elm_Label_Data
61 struct _Elm_Translate_String_Data
65 Eina_Stringshare *domain;
66 Eina_Stringshare *string;
70 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
72 _elm_widget_evas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir);
75 /* local subsystem globals */
76 static unsigned int focus_order = 0;
78 static inline Eina_Bool
79 _elm_widget_is(const Evas_Object *obj)
81 return eo_isa(obj, MY_CLASS);
84 static inline Eina_Bool
85 _is_focusable(Evas_Object *obj)
87 API_ENTRY return EINA_FALSE;
88 return sd->can_focus || (sd->child_can_focus);
91 static inline Eina_Bool
92 _is_focused(Evas_Object *obj)
94 API_ENTRY return EINA_FALSE;
98 static inline Eina_Bool
99 _elm_scrollable_is(const Evas_Object *obj)
101 INTERNAL_ENTRY EINA_FALSE;
103 eo_isa(obj, ELM_INTERFACE_SCROLLABLE_MIXIN);
107 elm_widget_disabled_internal(Eo *obj, Eina_Bool disabled);
109 _on_sub_obj_del(void *data,
111 const Eo_Event_Description *desc,
114 _on_sub_obj_hide(void *data,
116 const Eo_Event_Description *desc,
119 _propagate_event(void *data,
121 const Eo_Event_Description *desc,
124 EO_CALLBACKS_ARRAY_DEFINE(elm_widget_subitems_callbacks,
125 { EVAS_OBJECT_EVENT_DEL, _on_sub_obj_del },
126 { EVAS_OBJECT_EVENT_HIDE, _on_sub_obj_hide });
127 EO_CALLBACKS_ARRAY_DEFINE(efl_subitems_callbacks,
128 { EVAS_OBJECT_EVENT_DEL, _on_sub_obj_del });
129 EO_CALLBACKS_ARRAY_DEFINE(focus_callbacks,
130 { EVAS_OBJECT_EVENT_KEY_DOWN, _propagate_event },
131 { EVAS_OBJECT_EVENT_KEY_UP, _propagate_event },
132 { EVAS_OBJECT_EVENT_MOUSE_WHEEL, _propagate_event });
135 _callbacks_add(Eo *widget, void *data)
137 if (_elm_widget_is(widget))
140 eo_event_callback_array_add(elm_widget_subitems_callbacks(), data));
145 eo_event_callback_array_add(efl_subitems_callbacks(), data));
150 _callbacks_del(Eo *widget, void *data)
152 if (_elm_widget_is(widget))
155 eo_event_callback_array_del(elm_widget_subitems_callbacks(), data));
160 eo_event_callback_array_del(efl_subitems_callbacks(), data));
165 _elm_widget_item_highlight_in_theme(Evas_Object *obj, Elm_Object_Item *eo_it)
170 if (eo_isa(eo_it, ELM_WIDGET_ITEM_CLASS))
172 Elm_Widget_Item_Data *it = eo_data_scope_get(eo_it, ELM_WIDGET_ITEM_CLASS);
174 if (eo_isa(it->view, ELM_LAYOUT_CLASS))
175 str = edje_object_data_get(elm_layout_edje_get(it->view), "focus_highlight");
177 str = edje_object_data_get(it->view, "focus_highlight");
180 str = edje_object_data_get(((Elm_Widget_Item_Data *)eo_it)->view, "focus_highlight");
181 if ((str) && (!strcmp(str, "on")))
182 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
184 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
188 _elm_widget_focus_highlight_start(const Evas_Object *obj)
190 Evas_Object *top = elm_widget_top_get(obj);
192 if (top && eo_isa(top, ELM_WIN_CLASS))
193 _elm_win_focus_highlight_start(top);
197 _elm_widget_focus_highlight_object_get(const Evas_Object *obj)
199 Evas_Object *top = elm_widget_top_get(obj);
201 if (top && eo_isa(top, ELM_WIN_CLASS))
202 return _elm_win_focus_highlight_object_get(top);
207 elm_widget_focus_highlight_enabled_get(const Evas_Object *obj)
209 const Evas_Object *win = elm_widget_top_get(obj);
211 if (win && eo_isa(win, ELM_WIN_CLASS))
212 return elm_win_focus_highlight_enabled_get(win);
219 * Resets the mirrored mode from the system mirror mode for widgets that are in
220 * automatic mirroring mode. This function does not call elm_widget_theme.
222 * @param obj The widget.
223 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
226 _elm_widget_mirrored_reload(Evas_Object *obj)
229 Eina_Bool mirrored = elm_config_mirrored_get();
231 if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
233 sd->is_mirrored = mirrored;
237 EOLIAN static Eina_Bool
238 _elm_widget_on_focus_region(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Coord *x EINA_UNUSED, Evas_Coord *y EINA_UNUSED, Evas_Coord *w EINA_UNUSED, Evas_Coord *h EINA_UNUSED)
240 WRN("The %s widget does not implement the \"on_focus_region\" function.",
241 eo_class_name_get(eo_class_get(obj)));
247 _parents_focus(Evas_Object *obj)
249 for (; obj; obj = elm_widget_parent_get(obj))
252 if (sd->focused) return;
258 _parents_unfocus(Evas_Object *obj)
260 for (; obj; obj = elm_widget_parent_get(obj))
263 if (!sd->focused) return;
269 _on_sub_obj_hide(void *data EINA_UNUSED,
271 const Eo_Event_Description *desc EINA_UNUSED,
272 void *event_info EINA_UNUSED)
274 elm_widget_focus_hide_handle(obj);
275 return EO_CALLBACK_CONTINUE;
279 _on_sub_obj_del(void *data,
281 const Eo_Event_Description *desc EINA_UNUSED,
282 void *event_info EINA_UNUSED)
284 ELM_WIDGET_DATA_GET_OR_RETURN(data, sd, EINA_FALSE);
286 if (_elm_widget_is(obj))
288 if (_is_focused((Eo *)obj)) _parents_unfocus(sd->obj);
290 if (obj == sd->resize_obj)
292 /* already dels sub object */
293 elm_widget_resize_object_set(sd->obj, NULL, EINA_TRUE);
295 else if (obj == sd->hover_obj)
297 sd->hover_obj = NULL;
301 if (!elm_widget_sub_object_del(sd->obj, obj))
302 ERR("failed to remove sub object %p from %p\n", obj, sd->obj);
305 return EO_CALLBACK_CONTINUE;
308 static const Evas_Smart_Cb_Description _smart_callbacks[] =
310 {SIG_WIDGET_FOCUSED, ""},
311 {SIG_WIDGET_UNFOCUSED, ""},
312 {SIG_WIDGET_LANG_CHANGED, ""},
313 {SIG_WIDGET_ACCESS_CHANGED, ""},
314 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
315 {SIG_WIDGET_ATSPI_HIGHLIGHTED, ""},
316 {SIG_WIDGET_ATSPI_UNHIGHLIGHTED, ""},
322 _obj_mouse_down(void *data,
324 Evas_Object *obj EINA_UNUSED,
329 ELM_WIDGET_DATA_GET(data, sd);
330 Evas_Event_Mouse_Down *ev = event_info;
331 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
333 top = elm_widget_top_get(data);
334 if (top && eo_isa(top, ELM_WIN_CLASS)) _elm_win_focus_auto_hide(top);
335 sd->still_in = EINA_TRUE;
339 _obj_mouse_move(void *data,
344 ELM_WIDGET_DATA_GET(data, sd);
345 Evas_Event_Mouse_Move *ev = event_info;
346 if (!sd->still_in) return;
348 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
349 sd->still_in = EINA_FALSE;
352 Evas_Coord x, y, w, h;
353 evas_object_geometry_get(obj, &x, &y, &w, &h);
354 if (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y))
355 sd->still_in = EINA_FALSE;
360 _obj_mouse_up(void *data,
363 void *event_info EINA_UNUSED)
365 ELM_WIDGET_DATA_GET(data, sd);
367 (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_CLICK))
368 elm_widget_focus_mouse_up_handle(obj);
370 sd->still_in = EINA_FALSE;
374 _obj_mouse_in(void *data,
377 void *event_info EINA_UNUSED)
379 ELM_WIDGET_DATA_GET(data, sd);
380 if (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN)
381 elm_widget_focus_mouse_up_handle(obj);
385 _elm_widget_evas_object_smart_add(Eo *obj, Elm_Widget_Smart_Data *priv)
389 priv->mirrored_auto_mode = EINA_TRUE; /* will follow system locale
391 priv->focus_move_policy_auto_mode = EINA_TRUE;
392 priv->focus_region_show_mode = ELM_FOCUS_REGION_SHOW_WIDGET;
393 elm_widget_can_focus_set(obj, EINA_TRUE);
394 priv->is_mirrored = elm_config_mirrored_get();
395 priv->focus_move_policy = _elm_config->focus_move_policy;
397 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
398 _obj_mouse_down, obj);
399 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
400 _obj_mouse_move, obj);
401 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
403 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_IN,
405 /* just a helper for inheriting classes */
406 if (priv->resize_obj)
408 Evas_Object *r_obj = priv->resize_obj;
409 priv->resize_obj = NULL;
411 elm_widget_resize_object_set(obj, r_obj, EINA_TRUE);
416 _if_focused_revert(Evas_Object *obj,
417 Eina_Bool can_focus_only)
420 Evas_Object *newest = NULL;
421 unsigned int newest_focus_order = 0;
425 if (!sd->focused) return;
426 if (!sd->parent_obj) return;
428 top = elm_widget_top_get(sd->parent_obj);
431 newest = elm_widget_newest_focus_order_get
432 (top, &newest_focus_order, can_focus_only);
437 ELM_WIDGET_DATA_GET(newest, sd2);
440 if (!_is_focused(newest))
441 elm_widget_focus_steal(newest, NULL);
444 if (sd2->resize_obj && _is_focused(sd2->resize_obj))
445 elm_widget_focused_object_clear(sd2->resize_obj);
450 EINA_LIST_FOREACH(sd2->subobjs, l, child)
452 if (_is_focused(child))
454 elm_widget_focused_object_clear(child);
460 evas_object_focus_set(newest, EINA_TRUE);
464 elm_object_focus_set(newest, EINA_FALSE);
465 elm_object_focus_set(newest, EINA_TRUE);
472 _elm_widget_evas_object_smart_del(Eo *obj, Elm_Widget_Smart_Data *sd)
475 Elm_Translate_String_Data *ts;
476 Elm_Event_Cb_Data *ecb;
480 /* detach it from us */
481 _callbacks_del(sd->hover_obj, obj);
482 sd->hover_obj = NULL;
487 sobj = eina_list_data_get(sd->subobjs);
489 /* let the objects clean-up themselves and get rid of this list */
490 if (!elm_widget_sub_object_del(obj, sobj))
492 ERR("failed to remove sub object %p from %p\n", sobj, obj);
493 sd->subobjs = eina_list_remove_list
494 (sd->subobjs, sd->subobjs);
496 evas_object_del(sobj);
498 sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
499 sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
500 while (sd->translate_strings)
502 ts = EINA_INLIST_CONTAINER_GET(sd->translate_strings,
503 Elm_Translate_String_Data);
504 eina_stringshare_del(ts->id);
505 eina_stringshare_del(ts->domain);
506 eina_stringshare_del(ts->string);
507 sd->translate_strings = eina_inlist_remove(sd->translate_strings,
508 sd->translate_strings);
512 EINA_LIST_FREE(sd->event_cb, ecb)
515 eina_stringshare_del(sd->style);
516 if (sd->theme) elm_theme_free(sd->theme);
517 _if_focused_revert(obj, EINA_TRUE);
518 elm_widget_focus_custom_chain_unset(obj);
519 eina_stringshare_del(sd->access_info);
520 eina_stringshare_del(sd->accessible_name);
521 evas_object_smart_data_set(obj, NULL);
525 _smart_reconfigure(Elm_Widget_Smart_Data *sd)
529 evas_object_move(sd->resize_obj, sd->x, sd->y);
530 evas_object_resize(sd->resize_obj, sd->w, sd->h);
534 evas_object_move(sd->hover_obj, sd->x, sd->y);
535 evas_object_resize(sd->hover_obj, sd->w, sd->h);
540 _elm_widget_evas_object_smart_move(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord x, Evas_Coord y)
545 _smart_reconfigure(sd);
549 _elm_widget_evas_object_smart_resize(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord w, Evas_Coord h)
554 _smart_reconfigure(sd);
558 _elm_widget_evas_object_smart_show(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
563 if (_elm_atspi_enabled())
566 eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
567 if (parent) elm_interface_atspi_accessible_children_changed_added_signal_emit(parent, obj);
570 it = evas_object_smart_iterator_new(obj);
571 EINA_ITERATOR_FOREACH(it, o)
573 if (evas_object_data_get(o, "_elm_leaveme")) continue;
576 eina_iterator_free(it);
578 if (_elm_atspi_enabled())
580 elm_interface_atspi_accessible_added(obj);
581 if (_elm_widget_onscreen_is(obj))
582 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, EINA_TRUE);
587 _elm_widget_evas_object_smart_hide(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
592 it = evas_object_smart_iterator_new(obj);
593 EINA_ITERATOR_FOREACH(it, o)
595 if (evas_object_data_get(o, "_elm_leaveme")) continue;
598 eina_iterator_free(it);
600 if (_elm_atspi_enabled())
602 //TIZEN_ONLY(20161223) check if the parent of highlighted object is hide
604 highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
605 if (highlighted_obj && highlighted_obj != obj)
608 eo_do(highlighted_obj, parent = elm_interface_atspi_accessible_parent_get());
613 elm_interface_atspi_accessible_state_changed_signal_emit(highlighted_obj, ELM_ATSPI_STATE_SHOWING, EINA_FALSE);
614 eo_do(highlighted_obj, elm_interface_atspi_component_highlight_clear());
617 eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
622 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, EINA_FALSE);
627 _elm_widget_evas_object_smart_color_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, int r, int g, int b, int a)
632 it = evas_object_smart_iterator_new(obj);
633 EINA_ITERATOR_FOREACH(it, o)
635 if (evas_object_data_get(o, "_elm_leaveme")) continue;
636 evas_object_color_set(o, r, g, b, a);
638 eina_iterator_free(it);
642 _elm_widget_evas_object_smart_clip_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *clip)
647 it = evas_object_smart_iterator_new(obj);
648 EINA_ITERATOR_FOREACH(it, o)
650 if (evas_object_data_get(o, "_elm_leaveme")) continue;
651 evas_object_clip_set(o, clip);
653 eina_iterator_free(it);
657 _elm_widget_evas_object_smart_clip_unset(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
662 it = evas_object_smart_iterator_new(obj);
663 EINA_ITERATOR_FOREACH(it, o)
665 if (evas_object_data_get(o, "_elm_leaveme")) continue;
666 evas_object_clip_unset(o);
668 eina_iterator_free(it);
672 _elm_widget_evas_object_smart_calculate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
674 /* a NO-OP, on the base */
678 _elm_widget_evas_object_smart_member_add(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
681 eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(child));
683 if (evas_object_data_get(child, "_elm_leaveme")) return;
685 evas_object_color_get(obj, &r, &g, &b, &a);
686 evas_object_color_set(child, r, g, b, a);
688 evas_object_clip_set(child, evas_object_clip_get(obj));
690 if (evas_object_visible_get(obj))
691 evas_object_show(child);
693 evas_object_hide(child);
697 _elm_widget_evas_object_smart_member_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
699 if (!evas_object_data_get(child, "_elm_leaveme"))
700 evas_object_clip_unset(child);
701 eo_do_super(obj, MY_CLASS, evas_obj_smart_member_del(child));
708 * Check if the widget has its own focus next function.
710 * @param obj The widget.
711 * @return focus next function is implemented/unimplemented.
712 * (@c EINA_TRUE = implemented/@c EINA_FALSE = unimplemented.)
714 static inline Eina_Bool
715 _elm_widget_focus_chain_manager_is(const Evas_Object *obj)
717 ELM_WIDGET_CHECK(obj) EINA_FALSE;
719 Eina_Bool manager_is = EINA_FALSE;
720 eo_do((Eo *)obj, manager_is = elm_obj_widget_focus_next_manager_is());
724 static inline Eina_Bool
725 _internal_elm_widget_focus_direction_manager_is(const Evas_Object *obj)
727 ELM_WIDGET_CHECK(obj) EINA_FALSE;
729 Eina_Bool manager_is = EINA_FALSE;
730 eo_do((Eo *)obj, manager_is = elm_obj_widget_focus_direction_manager_is());
735 _propagate_x_drag_lock(Evas_Object *obj,
741 ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
744 sd2->child_drag_x_locked += dir;
745 _propagate_x_drag_lock(sd->parent_obj, dir);
751 _propagate_y_drag_lock(Evas_Object *obj,
757 ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
760 sd2->child_drag_y_locked += dir;
761 _propagate_y_drag_lock(sd->parent_obj, dir);
767 _propagate_event(void *data EINA_UNUSED,
769 const Eo_Event_Description *desc,
772 INTERNAL_ENTRY EO_CALLBACK_CONTINUE;
773 Evas_Callback_Type type;
774 Evas_Event_Flags *event_flags = NULL;
776 if (desc == EVAS_OBJECT_EVENT_KEY_DOWN)
778 Evas_Event_Key_Down *ev = event_info;
779 event_flags = &(ev->event_flags);
780 type = EVAS_CALLBACK_KEY_DOWN;
782 else if (desc == EVAS_OBJECT_EVENT_KEY_UP)
784 Evas_Event_Key_Up *ev = event_info;
785 event_flags = &(ev->event_flags);
786 type = EVAS_CALLBACK_KEY_UP;
788 else if (desc == EVAS_OBJECT_EVENT_MOUSE_WHEEL)
790 Evas_Event_Mouse_Wheel *ev = event_info;
791 event_flags = &(ev->event_flags);
792 type = EVAS_CALLBACK_MOUSE_WHEEL;
795 return EO_CALLBACK_CONTINUE;
797 elm_widget_event_propagate(obj, type, event_info, event_flags);
799 return EO_CALLBACK_CONTINUE;
805 * If elm_widget_focus_region_get() returns EINA_FALSE, this function will
806 * ignore region show action.
809 _elm_widget_focus_region_show(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
811 Evas_Coord x, y, w, h, ox, oy;
814 o = elm_widget_parent_get(obj);
817 if (!elm_widget_focus_region_get(obj, &x, &y, &w, &h))
820 evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
825 evas_object_geometry_get(o, &px, &py, NULL, NULL);
827 if (_elm_scrollable_is(o) && !elm_widget_disabled_get(o))
830 eo_do(o, elm_interface_scrollable_content_region_get(&sx, &sy, NULL, NULL));
832 // Get the object's on_focus_region position relative to the scroller.
834 rx = ox + x - px + sx;
835 ry = oy + y - py + sy;
837 switch (_elm_config->focus_autoscroll_mode)
839 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
840 eo_do(o, elm_interface_scrollable_content_region_show(rx, ry, w, h));
842 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
843 eo_do(o, elm_interface_scrollable_region_bring_in(rx, ry, w, h));
849 elm_widget_focus_region_get(o, &x, &y, &w, &h);
850 evas_object_geometry_get(o, &ox, &oy, NULL, NULL);
859 o = elm_widget_parent_get(o);
863 EOLIAN static Eina_Bool
864 _elm_widget_focus_highlight_style_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *style)
866 if (eina_stringshare_replace(&sd->focus_highlight_style, style)) return EINA_TRUE;
870 EOLIAN static const char*
871 _elm_widget_focus_highlight_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
873 return sd->focus_highlight_style;
877 _parent_focus(Evas_Object *obj, Elm_Object_Item *item)
881 if (sd->focused) return;
883 Evas_Object *o = elm_widget_parent_get(obj);
884 sd->focus_order_on_calc = EINA_TRUE;
886 if (o) _parent_focus(o, item);
888 if (!sd->focus_order_on_calc)
889 return; /* we don't want to override it if by means of any of the
890 callbacks below one gets to calculate our order
894 sd->focus_order = focus_order;
895 sd->focused = EINA_TRUE;
897 if (sd->top_win_focused)
898 eo_do(obj, elm_obj_widget_on_focus(item));
899 sd->focus_order_on_calc = EINA_FALSE;
901 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
902 _elm_access_highlight_set(obj);
906 _elm_object_focus_chain_del_cb(void *data,
909 void *event_info EINA_UNUSED)
911 ELM_WIDGET_DATA_GET(data, sd);
913 sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
917 _elm_widget_parent_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *parent EINA_UNUSED)
922 elm_widget_api_check(int ver)
924 if (ver != ELM_INTERNAL_API_VERSION)
926 CRI("Elementary widget api versions do not match");
933 elm_widget_access(Evas_Object *obj,
938 Eina_Bool ret = EINA_TRUE;
940 API_ENTRY return EINA_FALSE;
941 EINA_LIST_FOREACH(sd->subobjs, l, child)
943 if (elm_widget_is(child))
944 ret &= elm_widget_access(child, is_access);
947 eo_do(obj, elm_obj_widget_access(is_access));
948 eo_do(obj, eo_event_callback_call(ELM_WIDGET_EVENT_ACCESS_CHANGED, NULL));
953 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
954 //register/unregister access objects accordingly.
956 elm_widget_atspi(Evas_Object *obj,
961 Eina_Bool ret = EINA_TRUE;
963 API_ENTRY return EINA_FALSE;
964 EINA_LIST_FOREACH(sd->subobjs, l, child)
966 if (elm_widget_is(child))
967 ret &= elm_widget_atspi(child, is_atspi);
969 eo_do(obj, elm_obj_widget_atspi(is_atspi));
975 _elm_widget_atspi(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_atspi EINA_UNUSED)
981 _elm_widget_access(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_access EINA_UNUSED)
986 elm_widget_theme(Evas_Object *obj)
992 Elm_Theme_Apply ret = ELM_THEME_APPLY_SUCCESS;
994 API_ENTRY return ELM_THEME_APPLY_FAILED;
996 EINA_LIST_FOREACH(sd->subobjs, l, child)
997 if (_elm_widget_is(child))
998 ret &= elm_widget_theme(child);
1000 if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
1002 EINA_LIST_FOREACH(sd->tooltips, l, tt)
1003 elm_tooltip_theme(tt);
1004 EINA_LIST_FOREACH(sd->cursors, l, cur)
1005 elm_cursor_theme(cur);
1007 Elm_Theme_Apply ret2 = ELM_THEME_APPLY_FAILED;
1008 eo_do(obj, ret2 = elm_obj_widget_theme_apply());
1015 elm_widget_theme_specific(Evas_Object *obj,
1023 Elm_Theme *th2, *thdef;
1027 thdef = elm_theme_default_get();
1028 if (!th) th = thdef;
1032 if (!th2) th2 = thdef;
1040 if (th2 == thdef) break;
1041 th2 = th2->ref_theme;
1042 if (!th2) th2 = thdef;
1046 EINA_LIST_FOREACH(sd->subobjs, l, child)
1048 if (elm_widget_is(child))
1049 elm_widget_theme_specific(child, th, force);
1051 if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
1052 EINA_LIST_FOREACH(sd->tooltips, l, tt)
1053 elm_tooltip_theme(tt);
1054 EINA_LIST_FOREACH(sd->cursors, l, cur)
1055 elm_cursor_theme(cur);
1056 eo_do(obj, elm_obj_widget_theme_apply());
1059 EOLIAN static Elm_Theme_Apply
1060 _elm_widget_theme_apply(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
1062 _elm_widget_mirrored_reload(obj);
1063 if (elm_widget_disabled_get(obj))
1064 elm_widget_disabled_internal(obj, elm_widget_disabled_get(obj));
1066 return ELM_THEME_APPLY_SUCCESS;
1072 * Returns the widget's mirrored mode.
1074 * @param obj The widget.
1075 * @return mirrored mode of the object.
1078 EOLIAN static Eina_Bool
1079 _elm_widget_mirrored_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1081 return sd->is_mirrored;
1087 * Sets the widget's mirrored mode.
1089 * @param obj The widget.
1090 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
1093 _elm_widget_mirrored_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool mirrored)
1095 mirrored = !!mirrored;
1097 if (sd->is_mirrored == mirrored) return;
1099 sd->is_mirrored = mirrored;
1100 elm_widget_theme(obj);
1104 * Returns the widget's mirrored mode setting.
1106 * @param obj The widget.
1107 * @return mirrored mode setting of the object.
1110 EOLIAN static Eina_Bool
1111 _elm_widget_mirrored_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1113 return sd->mirrored_auto_mode;
1119 * Sets the widget's mirrored mode setting.
1120 * When widget in automatic mode, it follows the system mirrored mode set by
1121 * elm_mirrored_set().
1122 * @param obj The widget.
1123 * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
1126 _elm_widget_mirrored_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
1128 if (sd->mirrored_auto_mode != automatic)
1130 sd->mirrored_auto_mode = automatic;
1134 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
1140 _elm_widget_on_show_region_hook_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, region_hook_func_type func, void *data)
1142 sd->on_show_region = func;
1143 sd->on_show_region_data = data;
1149 * Add myself as a sub object of parent object
1151 * @see elm_widget_sub_object_add()
1154 elm_widget_sub_object_parent_add(Evas_Object *sobj)
1156 Eina_Bool ret = EINA_FALSE;
1159 eo_do(sobj, parent = eo_parent_get());
1160 if (!eo_isa(parent, ELM_WIDGET_CLASS))
1162 ERR("You passed a wrong parent parameter (%p %s). "
1163 "Elementary widget's parent should be an elementary widget.", parent, evas_object_type_get(parent));
1167 eo_do(parent, ret = elm_obj_widget_sub_object_add(sobj));
1175 * Add sobj to obj's sub object.
1177 * What does elementary sub object mean? This is unique in elementary, it
1178 * handles overall elementary policies between parent and sub objects.
1179 * focus, access, deletion, theme, scale, mirror, scrollable child get,
1180 * translate, name find, display mode set, orientation set, tree dump
1183 * @see elm_widget_sub_object_parent_add()
1185 EOLIAN static Eina_Bool
1186 _elm_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1188 Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
1190 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1192 if (sobj == sd->parent_obj)
1194 /* in this case, sobj must be an elm widget, or something
1195 * very wrong is happening */
1196 if (!_elm_widget_is(sobj)) return EINA_FALSE;
1198 if (!elm_widget_sub_object_del(sobj, obj)) return EINA_FALSE;
1199 WRN("You passed a parent object of obj = %p as the sub object = %p!",
1203 if (_elm_widget_is(sobj))
1205 ELM_WIDGET_DATA_GET(sobj, sdc);
1207 if (sdc->parent_obj == obj) goto end;
1208 if (sdc->parent_obj)
1210 if (!elm_widget_sub_object_del(sdc->parent_obj, sobj))
1213 sdc->parent_obj = obj;
1215 if (!sdc->on_create)
1216 eo_do(sobj, elm_obj_widget_orientation_set(sd->orient_mode));
1218 sdc->orient_mode = sd->orient_mode;
1220 if (!sdc->on_create)
1222 if (!sdc->disabled && (elm_widget_disabled_get(obj)))
1224 elm_widget_focus_disabled_handle(sobj);
1225 eo_do(sobj, elm_obj_widget_disable());
1229 _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
1231 /* update child focusable-ness on self and parents, now that a
1232 * focusable child got in */
1233 if (!sd->child_can_focus && (_is_focusable(sobj)))
1235 Elm_Widget_Smart_Data *sdp = sd;
1237 sdp->child_can_focus = EINA_TRUE;
1238 while (sdp->parent_obj)
1240 sdp = eo_data_scope_get(sdp->parent_obj, MY_CLASS);
1242 if (sdp->child_can_focus) break;
1244 sdp->child_can_focus = EINA_TRUE;
1250 void *data = evas_object_data_get(sobj, "elm-parent");
1254 if (data == obj) goto end;
1255 if (!elm_widget_sub_object_del(data, sobj)) return EINA_FALSE;
1258 sd->subobjs = eina_list_append(sd->subobjs, sobj);
1259 evas_object_data_set(sobj, "elm-parent", obj);
1261 _callbacks_add(sobj, obj);
1262 if (_elm_widget_is(sobj))
1264 ELM_WIDGET_DATA_GET(sobj, sdc);
1266 /* NOTE: In the following two lines, 'sobj' is correct. Do not change it.
1267 * Due to elementary's scale policy, scale and pscale can be different in
1268 * some cases. This happens when sobj's previous parent and new parent have
1269 * different scale value.
1270 * For example, if sobj's previous parent's scale is 5 and new parent's scale
1271 * is 2 while sobj's scale is 0. Then 'pscale' is 5 and 'scale' is 2. So we
1272 * need to reset sobj's scale to 5.
1273 * Note that each widget's scale is 0 by default.
1275 double scale, pscale = elm_widget_scale_get(sobj);
1276 Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
1278 scale = elm_widget_scale_get(sobj);
1279 th = elm_widget_theme_get(sobj);
1280 mirrored = elm_widget_mirrored_get(sobj);
1282 if (!sdc->on_create)
1284 if ((scale != pscale) || (th != pth) || (pmirrored != mirrored))
1285 elm_widget_theme(sobj);
1288 if (_is_focused(sobj)) _parents_focus(obj);
1290 elm_widget_display_mode_set(sobj,
1291 evas_object_size_hint_display_mode_get(obj));
1292 if (_elm_atspi_enabled() && !sdc->on_create)
1294 Elm_Interface_Atspi_Accessible *aparent;
1295 eo_do(sobj, aparent = elm_interface_atspi_accessible_parent_get());
1297 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, sobj);
1300 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
1301 if (sdc->inherit_paragraph_direction &&
1302 (sdc->paragraph_direction != evas_object_paragraph_direction_get(obj)))
1304 sdc->paragraph_direction = evas_object_paragraph_direction_get(obj);
1305 _elm_widget_evas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1306 eo_do_super(sobj, MY_CLASS, evas_obj_paragraph_direction_set(sdc->paragraph_direction));
1315 EOLIAN static Eina_Bool
1316 _elm_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1318 Evas_Object *sobj_parent;
1320 if (!sobj) return EINA_FALSE;
1322 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1324 sobj_parent = evas_object_data_del(sobj, "elm-parent");
1325 if (sobj_parent && sobj_parent != obj)
1327 static int abort_on_warn = -1;
1329 ERR("removing sub object %p (%s) from parent %p (%s), "
1330 "but elm-parent is different %p (%s)!",
1331 sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
1332 sobj_parent, elm_widget_type_get(sobj_parent));
1334 if (EINA_UNLIKELY(abort_on_warn == -1))
1336 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1337 else abort_on_warn = 0;
1339 if (abort_on_warn == 1) abort();
1344 if (_elm_widget_is(sobj))
1346 if (_is_focused(sobj))
1348 elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1349 elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1351 if ((sd->child_can_focus) && (_is_focusable(sobj)))
1353 Evas_Object *parent = obj;
1355 /* update child focusable-ness on self and parents, now that a
1356 * focusable child is gone */
1360 Evas_Object *subobj;
1362 ELM_WIDGET_DATA_GET(parent, sdp);
1364 sdp->child_can_focus = EINA_FALSE;
1365 EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
1367 if ((subobj != sobj) && (_is_focusable(subobj)))
1369 sdp->child_can_focus = EINA_TRUE;
1374 /* break again, child_can_focus went back to
1376 if (sdp->child_can_focus) break;
1377 parent = sdp->parent_obj;
1380 if (_elm_atspi_enabled() && !sd->on_destroy)
1382 Elm_Interface_Atspi_Accessible *aparent;
1383 eo_do(sobj, aparent = elm_interface_atspi_accessible_parent_get());
1385 elm_interface_atspi_accessible_children_changed_del_signal_emit(obj, sobj);
1388 ELM_WIDGET_DATA_GET(sobj, sdc);
1389 sdc->parent_obj = NULL;
1391 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
1392 if (sdc->inherit_paragraph_direction &&
1393 (sdc->paragraph_direction != EVAS_BIDI_DIRECTION_NEUTRAL))
1395 sdc->paragraph_direction = EVAS_BIDI_DIRECTION_NEUTRAL;
1396 _elm_widget_evas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1397 eo_do_super(sobj, MY_CLASS, evas_obj_paragraph_direction_set(EVAS_BIDI_DIRECTION_NEUTRAL));
1402 if (sd->resize_obj == sobj) sd->resize_obj = NULL;
1404 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1406 _callbacks_del(sobj, obj);
1414 * a resize object is added to and deleted from the smart member and the sub object
1415 * of the parent if the third argument, Eina_Bool sub_obj, is set as EINA_TRUE.
1418 _elm_widget_resize_object_set(Eo *obj, Elm_Widget_Smart_Data *sd,
1422 Evas_Object *parent;
1424 if (sd->resize_obj == sobj) return;
1426 // orphan previous resize obj
1427 if (sd->resize_obj && sub_obj)
1429 evas_object_clip_unset(sd->resize_obj);
1430 evas_object_smart_member_del(sd->resize_obj);
1432 if (_elm_widget_is(sd->resize_obj))
1434 if (_is_focused(sd->resize_obj)) _parents_unfocus(obj);
1436 elm_widget_sub_object_del(obj, sd->resize_obj);
1439 sd->resize_obj = sobj;
1442 // orphan new resize obj
1443 parent = evas_object_data_get(sobj, "elm-parent");
1444 if (parent && parent != obj)
1446 ELM_WIDGET_DATA_GET(parent, sdp);
1448 /* should be there, just being paranoid */
1451 if (sdp->resize_obj == sobj)
1452 elm_widget_resize_object_set(parent, NULL, sub_obj);
1454 elm_widget_sub_object_del(parent, sobj);
1459 elm_widget_sub_object_add(obj, sobj);
1460 evas_object_smart_member_add(sobj, obj);
1463 _smart_reconfigure(sd);
1469 * WARNING: the programmer is responsible, in the scenario of
1470 * exchanging a hover object, of cleaning the old hover "target"
1474 _elm_widget_hover_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1478 _callbacks_del(sd->hover_obj, obj);
1480 sd->hover_obj = sobj;
1483 _callbacks_add(sobj, obj);
1484 _smart_reconfigure(sd);
1489 _elm_widget_can_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool can_focus)
1491 can_focus = !!can_focus;
1493 if (sd->can_focus == can_focus) return;
1494 sd->can_focus = can_focus;
1497 /* update child_can_focus of parents */
1498 Evas_Object *o = obj;
1502 o = elm_widget_parent_get(o);
1504 sd = eo_data_scope_get(o, MY_CLASS);
1505 if (!sd || sd->child_can_focus) break;
1506 sd->child_can_focus = EINA_TRUE;
1509 eo_do(obj, eo_event_callback_array_add(focus_callbacks(), NULL));
1513 // update child_can_focus of parents */
1514 Evas_Object *parent = elm_widget_parent_get(obj);
1518 Evas_Object *subobj;
1520 ELM_WIDGET_DATA_GET(parent, sdp);
1522 sdp->child_can_focus = EINA_FALSE;
1523 EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
1525 if (_is_focusable(subobj))
1527 sdp->child_can_focus = EINA_TRUE;
1531 /* break again, child_can_focus went back to
1533 if (sdp->child_can_focus) break;
1534 parent = sdp->parent_obj;
1536 eo_do(obj, eo_event_callback_array_del(focus_callbacks(), NULL));
1540 EOLIAN static Eina_Bool
1541 _elm_widget_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1543 return sd->can_focus;
1546 EOLIAN static Eina_Bool
1547 _elm_widget_child_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1549 return sd->child_can_focus;
1555 * This API makes the widget object and its children to be unfocusable.
1557 * This API can be helpful for an object to be deleted.
1558 * When an object will be deleted soon, it and its children may not
1559 * want to get focus (by focus reverting or by other focus controls).
1560 * Then, just use this API before deleting.
1562 * @param obj The widget root of sub-tree
1563 * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1568 _elm_widget_tree_unfocusable_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool tree_unfocusable)
1570 tree_unfocusable = !!tree_unfocusable;
1571 if (sd->tree_unfocusable == tree_unfocusable) return;
1572 sd->tree_unfocusable = tree_unfocusable;
1573 elm_widget_focus_tree_unfocusable_handle(obj);
1579 * This returns true, if the object sub-tree is unfocusable.
1581 * @param obj The widget root of sub-tree
1582 * @return EINA_TRUE if the object sub-tree is unfocusable
1586 EOLIAN static Eina_Bool
1587 _elm_widget_tree_unfocusable_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1589 return sd->tree_unfocusable;
1595 * Get the list of focusable child objects.
1597 * This function retruns list of child objects which can get focus.
1599 * @param obj The parent widget
1600 * @retrun list of focusable child objects.
1604 EOLIAN static Eina_List*
1605 _elm_widget_can_focus_child_list_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1608 Eina_List *child_list = NULL;
1611 EINA_LIST_FOREACH(sd->subobjs, l, child)
1613 if (!_elm_widget_is(child)) continue;
1614 if ((elm_widget_can_focus_get(child)) &&
1615 (evas_object_visible_get(child)) &&
1616 (!elm_widget_disabled_get(child)))
1617 child_list = eina_list_append(child_list, child);
1620 Eina_List *can_focus_list;
1621 can_focus_list = elm_widget_can_focus_child_list_get(child);
1623 child_list = eina_list_merge(child_list, can_focus_list);
1631 _elm_widget_highlight_ignore_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool ignore)
1633 sd->highlight_ignore = !!ignore;
1636 EOLIAN static Eina_Bool
1637 _elm_widget_highlight_ignore_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1639 return sd->highlight_ignore;
1643 _elm_widget_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight)
1645 sd->highlight_in_theme = !!highlight;
1646 /* FIXME: if focused, it should switch from one mode to the other */
1650 _elm_widget_highlight_in_theme_update(Eo *obj)
1652 Evas_Object *top = elm_widget_top_get(obj);
1654 if (top && eo_isa(top, ELM_WIN_CLASS))
1656 _elm_win_focus_highlight_in_theme_update(
1657 top, elm_widget_highlight_in_theme_get(obj));
1661 EOLIAN static Eina_Bool
1662 _elm_widget_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1664 return sd->highlight_in_theme;
1668 _elm_widget_access_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight)
1670 sd->access_highlight_in_theme = !!highlight;
1673 EOLIAN static Eina_Bool
1674 _elm_widget_access_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1676 return sd->access_highlight_in_theme;
1679 EOLIAN static Eina_Bool
1680 _elm_widget_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1682 return (sd->focused && sd->top_win_focused);
1685 EOLIAN static Eina_Bool
1686 _elm_widget_highlight_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1688 return sd->highlighted;
1691 EOLIAN static Evas_Object*
1692 _elm_widget_focused_object_get(Eo *obj, Elm_Widget_Smart_Data *sd)
1694 const Evas_Object *subobj;
1697 if (!sd->focused || !sd->top_win_focused) return NULL;
1698 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1701 if (!_elm_widget_is(subobj)) continue;
1702 fobj = elm_widget_focused_object_get(subobj);
1703 if (fobj) return fobj;
1705 return (Evas_Object *)obj;
1708 EOLIAN static Evas_Object*
1709 _elm_widget_top_get(Eo *obj, Elm_Widget_Smart_Data *sd)
1713 Evas_Object *ret = NULL;
1714 if (!eo_isa(sd->parent_obj, ELM_WIDGET_CLASS)) return NULL;
1715 eo_do((Eo *) sd->parent_obj, ret = elm_obj_widget_top_get());
1718 return (Evas_Object *)obj;
1722 elm_widget_is(const Evas_Object *obj)
1724 return _elm_widget_is(obj);
1728 elm_widget_parent_widget_get(const Evas_Object *obj)
1730 Evas_Object *parent;
1732 if (_elm_widget_is(obj))
1734 ELM_WIDGET_DATA_GET(obj, sd);
1735 if (!sd) return NULL;
1736 parent = sd->parent_obj;
1740 parent = evas_object_data_get(obj, "elm-parent");
1741 if (!parent) parent = evas_object_smart_parent_get(obj);
1746 Evas_Object *elm_parent;
1747 if (_elm_widget_is(parent)) break;
1748 elm_parent = evas_object_data_get(parent, "elm-parent");
1749 if (elm_parent) parent = elm_parent;
1750 else parent = evas_object_smart_parent_get(parent);
1755 EOLIAN static Evas_Object *
1756 _elm_widget_parent2_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1762 _elm_widget_parent2_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *parent)
1764 sd->parent2 = parent;
1768 _elm_widget_event_callback_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Event_Cb func, const void *data)
1770 EINA_SAFETY_ON_NULL_RETURN(func);
1772 Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1775 ERR("Failed to allocate memory");
1780 sd->event_cb = eina_list_append(sd->event_cb, ecb);
1784 _elm_widget_event_callback_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Event_Cb func, const void *data)
1786 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1788 Elm_Event_Cb_Data *ecd;
1789 EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1790 if ((ecd->func == func) && (ecd->data == data))
1793 sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1794 return (void *)data;
1800 EOLIAN static Eina_Bool
1801 _elm_widget_event_propagate(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags)
1803 Evas_Object *parent = obj;
1804 Elm_Event_Cb_Data *ecd;
1805 Eina_List *l, *l_prev;
1808 (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1810 ELM_WIDGET_CHECK(parent) EINA_FALSE;
1811 Elm_Widget_Smart_Data *sd = eo_data_scope_get(parent, MY_CLASS);
1813 Eina_Bool int_ret = EINA_FALSE;
1815 if (elm_widget_disabled_get(obj))
1817 parent = sd->parent_obj;
1821 eo_do(parent, int_ret = elm_obj_widget_event(obj, type, event_info));
1822 if (int_ret) return EINA_TRUE;
1824 EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1826 if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1827 (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1830 parent = sd->parent_obj;
1839 * Set custom focus chain.
1841 * This function i set one new and overwrite any previous custom focus chain
1842 * with the list of objects. The previous list will be deleted and this list
1843 * will be managed. After setted, don't modity it.
1845 * @note On focus cycle, only will be evaluated children of this container.
1847 * @param obj The container widget
1848 * @param objs Chain of objects to pass focus
1852 _elm_widget_focus_custom_chain_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_List *objs)
1854 if (!_elm_widget_focus_chain_manager_is(obj)) return;
1856 elm_widget_focus_custom_chain_unset(obj);
1861 EINA_LIST_FOREACH(objs, l, o)
1863 evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1864 _elm_object_focus_chain_del_cb, obj);
1867 sd->focus_chain = objs;
1873 * Get custom focus chain
1875 * @param obj The container widget
1878 EOLIAN static const Eina_List*
1879 _elm_widget_focus_custom_chain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1881 return (const Eina_List *)sd->focus_chain;
1887 * Unset custom focus chain
1889 * @param obj The container widget
1893 _elm_widget_focus_custom_chain_unset(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1895 Eina_List *l, *l_next;
1898 EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1900 evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1901 _elm_object_focus_chain_del_cb, obj);
1902 sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1909 * Append object to custom focus chain.
1911 * @note If relative_child equal to NULL or not in custom chain, the object
1912 * will be added in end.
1914 * @note On focus cycle, only will be evaluated children of this container.
1916 * @param obj The container widget
1917 * @param child The child to be added in custom chain
1918 * @param relative_child The relative object to position the child
1922 _elm_widget_focus_custom_chain_append(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
1924 EINA_SAFETY_ON_NULL_RETURN(child);
1926 if (!_elm_widget_focus_chain_manager_is(obj)) return;
1928 evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
1929 _elm_object_focus_chain_del_cb, obj);
1931 if (!relative_child)
1932 sd->focus_chain = eina_list_append(sd->focus_chain, child);
1934 sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1935 child, relative_child);
1941 * Prepend object to custom focus chain.
1943 * @note If relative_child equal to NULL or not in custom chain, the object
1944 * will be added in begin.
1946 * @note On focus cycle, only will be evaluated children of this container.
1948 * @param obj The container widget
1949 * @param child The child to be added in custom chain
1950 * @param relative_child The relative object to position the child
1954 _elm_widget_focus_custom_chain_prepend(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
1956 EINA_SAFETY_ON_NULL_RETURN(child);
1958 if (!_elm_widget_focus_chain_manager_is(obj)) return;
1960 evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
1961 _elm_object_focus_chain_del_cb, obj);
1963 if (!relative_child)
1964 sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1966 sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1967 child, relative_child);
1973 * Give focus to next object in object tree.
1975 * Give focus to next object in focus chain of one object sub-tree.
1976 * If the last object of chain already have focus, the focus will go to the
1977 * first object of chain.
1979 * @param obj The widget root of sub-tree
1980 * @param dir Direction to cycle the focus
1985 _elm_widget_focus_cycle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Focus_Direction dir)
1987 Evas_Object *target = NULL;
1988 Elm_Object_Item *target_item = NULL;
1989 if (!_elm_widget_is(obj))
1991 elm_widget_focus_next_get(obj, dir, &target, &target_item);
1995 if (_elm_config->access_mode)
1997 /* highlight cycle does not steal a focus, only after window gets
1998 the ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE message,
1999 target will steal focus, or focus its own job. */
2000 if (!_elm_access_auto_highlight_get())
2001 elm_widget_focus_steal(target, target_item);
2003 _elm_access_highlight_set(target);
2004 elm_widget_focus_region_show(target);
2006 else elm_widget_focus_steal(target, target_item);
2013 * Give focus to near object(in object tree) in one direction.
2015 * Give focus to near object(in object tree) in direction of current
2016 * focused object. If none focusable object in given direction or
2017 * none focused object in object tree, the focus will not change.
2019 * @param obj The reference widget
2020 * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2021 * 90-degree: Right, 180-degree: Down, and 270-degree: Left
2022 * @return EINA_TRUE if focus is moved.
2026 EOLIAN static Eina_Bool
2027 _elm_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, double degree)
2029 Evas_Object *target = NULL;
2030 Elm_Object_Item *target_item = NULL;
2031 Evas_Object *current_focused = NULL;
2032 double weight = 0.0;
2034 if (!_elm_widget_is(obj)) return EINA_FALSE;
2035 if (!_is_focused(obj)) return EINA_FALSE;
2037 current_focused = elm_widget_focused_object_get(obj);
2039 if (elm_widget_focus_direction_get
2040 (obj, current_focused, degree, &target, &target_item, &weight))
2042 elm_widget_focus_steal(target, NULL);
2050 _elm_widget_focus_direction_weight_get(const Evas_Object *obj1,
2051 const Evas_Object *obj2,
2054 Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
2055 double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
2056 double ax, ay, cx, cy;
2057 double weight = -1.0, g = 0.0;
2059 if (obj1 == obj2) return 0.0;
2062 while (degree >= 360.0)
2064 while (degree < 0.0)
2067 evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
2068 cx = obj_x1 + (w1 / 2.0);
2069 cy = obj_y1 + (h1 / 2.0);
2070 evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
2072 /* For overlapping cases. */
2073 if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2))
2076 /* Change all points to relative one. */
2086 /* Get crossing points (ax, ay) between obj1 and a line extending
2087 * to the direction of current degree. */
2093 else if (degree == 90.0)
2098 else if (degree == 180.0)
2103 else if (degree == 270.0)
2110 g = tan(degree * (M_PI / 180.0));
2111 if ((degree > 0.0) && (degree < 90.0))
2114 if (ay <= yyy1) ax = xx1;
2121 else if ((degree > 90.0) && (degree < 180.0))
2124 if (ay <= yyy1) ax = x1;
2131 else if ((degree > 180.0) && (degree < 270.0))
2134 if (ay >= yy1) ax = x1;
2144 if (ay >= yy1) ax = xx1;
2153 /* Filter obj2, if it is not in the specific derection. */
2155 double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
2156 double t1, t2, u1, v1, u2, v2;
2158 if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) ||
2168 double g2 = tan((degree + 45.0) * (M_PI / 180.0));
2173 t1 = (u1 * ax) + (v1 * ay);
2174 t2 = (u2 * ax) + (v2 * ay);
2176 #define _R(x) (int)((x + 0.05) * 10.0)
2178 if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) +
2184 if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) +
2190 if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) +
2196 if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) &&
2197 (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
2206 if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2208 else if (degree == 90.0)
2210 if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2212 else if (degree == 180.0)
2214 if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2216 else if (degree == 270.0)
2218 if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2222 if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
2224 if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0)))
2227 else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
2229 if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0)))
2232 else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2)
2235 if (!((_R(ax * ((1.0 / g) * yy2)) > 0)
2236 && (_R(ay * yy2) > 0)))
2239 else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) &&
2240 (_R((1.0 / g) * yyy2) <= _R(xx2)))
2242 if (!((_R(ax * ((1.0 / g) * yyy2)) > 0)
2243 && (_R(ay * yyy2) > 0))) return 0.0;
2249 /* Calculate the weight for obj2. */
2252 if (_R(xx1) > _R(x2)) weight = -1.0;
2253 else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2254 weight = (x2 - xx1) * (x2 - xx1);
2255 else if (_R(yy2) > 0)
2256 weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
2257 else if (_R(yyy2) < 0)
2258 weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
2259 else weight = (x2 - xx1) * (x2 - xx1);
2261 else if (degree == 90.0)
2263 if (_R(yyy1) > _R(yy2)) weight = -1.0;
2264 else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2265 weight = (yy2 - yyy1) * (yy2 - yyy1);
2266 else if (_R(x2) > 0)
2267 weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
2268 else if (_R(xx2) < 0)
2269 weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
2270 else weight = (yy2 - yyy1) * (yy2 - yyy1);
2272 else if (degree == 180.0)
2274 if (_R(x1) < _R(xx2)) weight = -1.0;
2275 else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2276 weight = (x1 - xx2) * (x1 - xx2);
2277 else if (_R(yy2) > 0)
2278 weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
2279 else if (_R(yyy2) < 0)
2280 weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
2281 else weight = (x1 - xx2) * (x1 - xx2);
2283 else if (degree == 270.0)
2285 if (_R(yy1) < _R(yyy2)) weight = -1.0;
2286 else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2287 weight = (yy1 - yyy2) * (yy1 - yyy2);
2288 else if (_R(x2) > 0)
2289 weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
2290 else if (_R(xx2) < 0)
2291 weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
2292 else weight = (yy1 - yyy2) * (yy1 - yyy2);
2297 double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
2298 double t_weight[4] = {-1.0, -1.0, -1.0, -1.0};
2299 if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
2303 t_weight[j++] = ((ax - x2) * (ax - x2)) +
2304 ((ay - (g * x2)) * (ay - (g * x2)));
2306 if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
2310 t_weight[j++] = ((ax - xx2) * (ax - xx2)) +
2311 ((ay - (g * xx2)) * (ay - (g * xx2)));
2313 if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
2315 sx[j] = (1.0 / g) * yy2;
2318 ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) +
2319 ((ay - yy2) * (ay - yy2));
2321 if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2)
2324 sx[j] = (1.0 / g) * yyy2;
2327 ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) +
2328 ((ay - yyy2) * (ay - yyy2));
2331 if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) ||
2332 (_R(sy[0]) != _R(sy[1])))))
2336 if (_R(t_weight[k]) == 0) return -1.0;
2337 if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
2344 double ccx, ccy, t1_weight, x_diff, y_diff;
2345 ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
2347 x_diff = rx[k] - ccx;
2348 if (x_diff < 0) x_diff *= -1.0;
2349 y_diff = ry[k] - ccy;
2350 if (y_diff < 0) y_diff *= -1.0;
2352 (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
2353 ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
2354 if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
2359 /* Return the current object's weight. */
2360 if (weight == -1.0) return 0.0;
2361 if (_R(weight) == 0) return -1.0;
2365 return 1.0 / weight;
2371 * Get near object in one direction of base object.
2373 * Get near object(in the object sub-tree) in one direction of
2374 * base object. Return the near object by reference.
2375 * By initializing weight, you can filter objects locating far
2376 * from base object. If object is in the specific direction,
2377 * weight is (1/(distance^2)). If object is not exactly in one
2378 * direction, some penalty will be added.
2380 * @param obj The widget root of sub-tree
2381 * @param base The base object of the direction
2382 * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2383 * 90-degree: Right, 180-degree: Down, and 270-degree: Left
2384 * @param direction The near object in one direction
2385 * @param weight The weight is bigger when the object is located near
2386 * @return EINA_TRUE if near object is updated.
2391 EOLIAN static Eina_Bool
2392 _elm_widget_focus_direction_get(const Eo *obj, Elm_Widget_Smart_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight)
2396 /* -1 means the best was already decided. Don't need any more searching. */
2397 if (!direction || !weight || !base || (obj == base))
2400 /* Ignore if disabled */
2401 if ((!evas_object_visible_get(obj))
2402 || (elm_widget_disabled_get(obj))
2403 || (elm_widget_tree_unfocusable_get(obj)))
2407 if (_internal_elm_widget_focus_direction_manager_is(obj))
2409 Eina_Bool int_ret = EINA_FALSE;
2410 eo_do((Eo *)obj, int_ret = elm_obj_widget_focus_direction(base, degree, direction, direction_item, weight));
2414 if (!elm_widget_can_focus_get(obj) || _is_focused((Eo *)obj))
2417 c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree);
2418 if ((c_weight == -1.0) ||
2419 ((c_weight != 0.0) && (*weight != -1.0) &&
2420 ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
2423 ((int)(*weight * 1000000) == (int)(c_weight * 1000000)))
2425 ELM_WIDGET_DATA_GET(*direction, sd1);
2428 if (sd->focus_order <= sd1->focus_order)
2432 *direction = (Evas_Object *)obj;
2443 * Get near object in one direction of base object in list.
2445 * Get near object in one direction of base object in the specific
2446 * object list. Return the near object by reference.
2447 * By initializing weight, you can filter objects locating far
2448 * from base object. If object is in the specific direction,
2449 * weight is (1/(distance^2)). If object is not exactly in one
2450 * direction, some penalty will be added.
2452 * @param obj The widget root of sub-tree
2453 * @param base The base object of the direction
2454 * @param items list with ordered objects
2455 * @param list_data_get function to get the object from one item of list
2456 * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2457 * 90-degree: Right, 180-degree: Down, and 270-degree: Left
2458 * @param direction The near object in one direction
2459 * @param weight The weight is bigger when the object is located near
2460 * @return EINA_TRUE if near object is updated.
2464 EOLIAN static Eina_Bool
2465 _elm_widget_focus_list_direction_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Evas_Object *base, const Eina_List *items, list_data_get_func_type list_data_get, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight)
2467 if (!direction || !weight || !base || !items)
2470 const Eina_List *l = items;
2471 Evas_Object *current_best = *direction;
2473 for (; l; l = eina_list_next(l))
2475 Evas_Object *cur = list_data_get(l);
2476 if (cur && _elm_widget_is(cur))
2477 elm_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight);
2479 if (current_best != *direction) return EINA_TRUE;
2487 * Get next object in focus chain of object tree.
2489 * Get next object in focus chain of one object sub-tree.
2490 * Return the next object by reference. If don't have any candidate to receive
2491 * focus before chain end, the first candidate will be returned.
2493 * @param obj The widget root of sub-tree
2494 * @param dir Direction of focus chain
2495 * @param next The next object in focus chain
2496 * @return EINA_TRUE if don't need focus chain restart/loop back
2497 * to use 'next' obj.
2501 EOLIAN static Eina_Bool
2502 _elm_widget_focus_next_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
2504 Elm_Access_Info *ac;
2510 /* Ignore if disabled */
2511 if (_elm_config->access_mode && _elm_access_auto_highlight_get())
2513 if (!evas_object_visible_get(obj)
2514 || (elm_widget_tree_unfocusable_get(obj)))
2519 if ((!evas_object_visible_get(obj))
2520 || (elm_widget_disabled_get(obj))
2521 || (elm_widget_tree_unfocusable_get(obj)))
2526 if (_elm_widget_focus_chain_manager_is(obj))
2528 Eina_Bool int_ret = EINA_FALSE;
2529 eo_do((Eo *)obj, int_ret = elm_obj_widget_focus_next(dir, next, next_item));
2530 if (!int_ret && _is_focused((Eo *)obj))
2532 Evas_Object *o = NULL;
2533 if (dir == ELM_FOCUS_PREVIOUS)
2534 *next_item = sd->item_focus_previous;
2535 else if (dir == ELM_FOCUS_NEXT)
2536 *next_item = sd->item_focus_next;
2537 else if (dir == ELM_FOCUS_UP)
2538 *next_item = sd->item_focus_up;
2539 else if (dir == ELM_FOCUS_DOWN)
2540 *next_item = sd->item_focus_down;
2541 else if (dir == ELM_FOCUS_RIGHT)
2542 *next_item = sd->item_focus_right;
2543 else if (dir == ELM_FOCUS_LEFT)
2544 *next_item = sd->item_focus_left;
2545 o = elm_object_item_widget_get(*next_item);
2549 if (dir == ELM_FOCUS_PREVIOUS)
2550 o = sd->focus_previous;
2551 else if (dir == ELM_FOCUS_NEXT)
2553 else if (dir == ELM_FOCUS_UP)
2555 else if (dir == ELM_FOCUS_DOWN)
2557 else if (dir == ELM_FOCUS_RIGHT)
2558 o = sd->focus_right;
2559 else if (dir == ELM_FOCUS_LEFT)
2572 /* access object does not check sd->can_focus, because an object could
2573 have highlight even though the object is not focusable. */
2574 if (_elm_config->access_mode && _elm_access_auto_highlight_get())
2576 ac = _elm_access_info_get(obj);
2577 if (!ac) return EINA_FALSE;
2579 /* check whether the hover object is visible or not */
2580 if (!evas_object_visible_get(ac->hoverobj))
2583 else if (!elm_widget_can_focus_get(obj))
2586 if (_is_focused((Eo *)obj))
2588 if (dir == ELM_FOCUS_PREVIOUS)
2589 *next_item = sd->item_focus_previous;
2590 else if (dir == ELM_FOCUS_NEXT)
2591 *next_item = sd->item_focus_next;
2592 else if (dir == ELM_FOCUS_UP)
2593 *next_item = sd->item_focus_up;
2594 else if (dir == ELM_FOCUS_DOWN)
2595 *next_item = sd->item_focus_down;
2596 else if (dir == ELM_FOCUS_RIGHT)
2597 *next_item = sd->item_focus_right;
2598 else if (dir == ELM_FOCUS_LEFT)
2599 *next_item = sd->item_focus_left;
2600 *next = elm_object_item_widget_get(*next_item);
2604 if (dir == ELM_FOCUS_PREVIOUS)
2605 *next = sd->focus_previous;
2606 else if (dir == ELM_FOCUS_NEXT)
2607 *next = sd->focus_next;
2608 else if (dir == ELM_FOCUS_UP)
2609 *next = sd->focus_up;
2610 else if (dir == ELM_FOCUS_DOWN)
2611 *next = sd->focus_down;
2612 else if (dir == ELM_FOCUS_RIGHT)
2613 *next = sd->focus_right;
2614 else if (dir == ELM_FOCUS_LEFT)
2615 *next = sd->focus_left;
2618 if (*next) return EINA_TRUE;
2622 *next = (Evas_Object *)obj;
2623 return !ELM_WIDGET_FOCUS_GET(obj);
2629 * Get next object in focus chain of object tree in list.
2631 * Get next object in focus chain of one object sub-tree ordered by one list.
2632 * Return the next object by reference. If don't have any candidate to receive
2633 * focus before list end, the first candidate will be returned.
2635 * @param obj The widget root of sub-tree
2636 * @param items list with ordered objects
2637 * @param list_data_get function to get the object from one item of list
2638 * @param dir Direction of focus chain
2639 * @param next The next object in focus chain
2640 * @return EINA_TRUE if don't need focus chain restart/loop back
2641 * to use 'next' obj.
2645 EOLIAN static Eina_Bool
2646 _elm_widget_focus_list_next_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const Eina_List *items, list_data_get_func_type list_data_get, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
2648 Eina_List *(*list_next)(const Eina_List *list) = NULL;
2649 Evas_Object *focused_object = NULL;
2655 if (!_elm_widget_is(obj))
2661 /* When Up, Down, Right, or Left, try direction_get first. */
2662 focused_object = elm_widget_focused_object_get(obj);
2665 if ((dir == ELM_FOCUS_UP)
2666 || (dir == ELM_FOCUS_DOWN)
2667 || (dir == ELM_FOCUS_RIGHT)
2668 || (dir == ELM_FOCUS_LEFT))
2670 *next_item = elm_widget_focus_next_item_get(focused_object, dir);
2672 *next = elm_object_item_widget_get(*next_item);
2674 *next = elm_widget_focus_next_object_get(focused_object, dir);
2675 if (*next) return EINA_TRUE;
2678 Evas_Object *n = NULL;
2679 Elm_Object_Item *n_item = NULL;
2681 double weight = 0.0;
2683 if (dir == ELM_FOCUS_UP) degree = 0.0;
2684 else if (dir == ELM_FOCUS_DOWN) degree = 180.0;
2685 else if (dir == ELM_FOCUS_RIGHT) degree = 90.0;
2686 else if (dir == ELM_FOCUS_LEFT) degree = 270.0;
2688 if (elm_widget_focus_list_direction_get(obj, focused_object,
2689 items, list_data_get,
2690 degree, &n, &n_item,
2693 *next_item = n_item;
2702 if (dir == ELM_FOCUS_PREVIOUS)
2704 items = eina_list_last(items);
2705 list_next = eina_list_prev;
2707 else if ((dir == ELM_FOCUS_NEXT)
2708 || (dir == ELM_FOCUS_UP)
2709 || (dir == ELM_FOCUS_DOWN)
2710 || (dir == ELM_FOCUS_RIGHT)
2711 || (dir == ELM_FOCUS_LEFT))
2712 list_next = eina_list_next;
2716 const Eina_List *l = items;
2718 /* Recovery last focused sub item */
2719 if (ELM_WIDGET_FOCUS_GET(obj))
2721 for (; l; l = list_next(l))
2723 Evas_Object *cur = list_data_get(l);
2724 if (ELM_WIDGET_FOCUS_GET(cur)) break;
2727 /* Focused object, but no focused sub item */
2731 const Eina_List *start = l;
2732 Evas_Object *to_focus = NULL;
2733 Elm_Object_Item *to_focus_item = NULL;
2735 /* Iterate sub items */
2736 /* Go to the end of list */
2737 for (; l; l = list_next(l))
2739 Evas_Object *tmp = NULL;
2740 Elm_Object_Item *tmp_item = NULL;
2741 Evas_Object *cur = list_data_get(l);
2744 if (!_elm_widget_is(cur)) continue;
2745 if (elm_widget_parent_get(cur) != obj)
2748 /* Try Focus cycle in subitem */
2749 if (elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item))
2752 *next_item = tmp_item;
2755 else if ((dir == ELM_FOCUS_UP)
2756 || (dir == ELM_FOCUS_DOWN)
2757 || (dir == ELM_FOCUS_RIGHT)
2758 || (dir == ELM_FOCUS_LEFT))
2760 if (tmp && _is_focused(cur))
2763 *next_item = tmp_item;
2767 else if ((tmp) && (!to_focus))
2770 to_focus_item = tmp_item;
2776 /* Get First possible */
2777 for (; l != start; l = list_next(l))
2779 Evas_Object *tmp = NULL;
2780 Elm_Object_Item *tmp_item = NULL;
2781 Evas_Object *cur = list_data_get(l);
2783 if (elm_widget_parent_get(cur) != obj)
2786 /* Try Focus cycle in subitem */
2787 elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item);
2791 *next_item = tmp_item;
2797 *next_item = to_focus_item;
2804 * Get next object which was set with specific focus direction.
2806 * Get next object which was set by elm_widget_focus_next_object_set
2807 * with specific focus directioin.
2809 * @param obj The widget
2810 * @param dir Direction of focus
2811 * @return Widget which was registered with sepecific focus direction.
2815 EOLIAN static Evas_Object*
2816 _elm_widget_focus_next_object_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir)
2818 Evas_Object *ret = NULL;
2820 if (dir == ELM_FOCUS_PREVIOUS)
2821 ret = sd->focus_previous;
2822 else if (dir == ELM_FOCUS_NEXT)
2823 ret = sd->focus_next;
2824 else if (dir == ELM_FOCUS_UP)
2826 else if (dir == ELM_FOCUS_DOWN)
2827 ret = sd->focus_down;
2828 else if (dir == ELM_FOCUS_RIGHT)
2829 ret = sd->focus_right;
2830 else if (dir == ELM_FOCUS_LEFT)
2831 ret = sd->focus_left;
2839 * Set next object with specific focus direction.
2841 * When a widget is set with specific focus direction, this widget will be
2842 * the first candidate when finding the next focus object.
2843 * Focus next object can be registered with six directions that are previous,
2844 * next, up, down, right, and left.
2846 * @param obj The widget
2847 * @param next Next focus object
2848 * @param dir Direction of focus
2853 _elm_widget_focus_next_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *next, Elm_Focus_Direction dir)
2856 if (dir == ELM_FOCUS_PREVIOUS)
2857 sd->focus_previous = next;
2858 else if (dir == ELM_FOCUS_NEXT)
2859 sd->focus_next = next;
2860 else if (dir == ELM_FOCUS_UP)
2861 sd->focus_up = next;
2862 else if (dir == ELM_FOCUS_DOWN)
2863 sd->focus_down = next;
2864 else if (dir == ELM_FOCUS_RIGHT)
2865 sd->focus_right = next;
2866 else if (dir == ELM_FOCUS_LEFT)
2867 sd->focus_left = next;
2870 EOLIAN static Elm_Object_Item*
2871 _elm_widget_focus_next_item_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir)
2873 Elm_Object_Item *ret = NULL;
2875 if (dir == ELM_FOCUS_PREVIOUS)
2876 ret = sd->item_focus_previous;
2877 else if (dir == ELM_FOCUS_NEXT)
2878 ret = sd->item_focus_next;
2879 else if (dir == ELM_FOCUS_UP)
2880 ret = sd->item_focus_up;
2881 else if (dir == ELM_FOCUS_DOWN)
2882 ret = sd->item_focus_down;
2883 else if (dir == ELM_FOCUS_RIGHT)
2884 ret = sd->item_focus_right;
2885 else if (dir == ELM_FOCUS_LEFT)
2886 ret = sd->item_focus_left;
2892 _elm_widget_focus_next_item_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Object_Item *next_item, Elm_Focus_Direction dir)
2894 if (dir == ELM_FOCUS_PREVIOUS)
2895 sd->item_focus_previous = next_item;
2896 else if (dir == ELM_FOCUS_NEXT)
2897 sd->item_focus_next = next_item;
2898 else if (dir == ELM_FOCUS_UP)
2899 sd->item_focus_up = next_item;
2900 else if (dir == ELM_FOCUS_DOWN)
2901 sd->item_focus_down = next_item;
2902 else if (dir == ELM_FOCUS_RIGHT)
2903 sd->item_focus_right = next_item;
2904 else if (dir == ELM_FOCUS_LEFT)
2905 sd->item_focus_left = next_item;
2909 _elm_widget_parent_highlight_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool highlighted)
2911 highlighted = !!highlighted;
2913 Evas_Object *o = elm_widget_parent_get(obj);
2915 if (o) elm_widget_parent_highlight_set(o, highlighted);
2917 sd->highlighted = highlighted;
2921 _elm_widget_signal_emit(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source)
2923 if (evas_object_smart_type_check(obj, "elm_layout"))
2924 elm_layout_signal_emit(obj, emission, source);
2925 else if (evas_object_smart_type_check(obj, "elm_icon"))
2927 WRN("Deprecated function. This functionality on icon objects"
2928 " will be dropped on a next release.");
2929 _elm_icon_signal_emit(obj, emission, source);
2934 _elm_widget_signal_callback_add(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
2936 EINA_SAFETY_ON_NULL_RETURN(func);
2938 if (evas_object_smart_type_check(obj, "elm_layout"))
2939 elm_layout_signal_callback_add(obj, emission, source, func, data);
2940 else if (evas_object_smart_type_check(obj, "elm_icon"))
2942 WRN("Deprecated function. This functionality on icon objects"
2943 " will be dropped on a next release.");
2945 _elm_icon_signal_callback_add(obj, emission, source, func, data);
2950 _elm_widget_signal_callback_del(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source, Edje_Signal_Cb func)
2954 if (evas_object_smart_type_check(obj, "elm_layout"))
2955 data = elm_layout_signal_callback_del(obj, emission, source, func);
2956 else if (evas_object_smart_type_check(obj, "elm_icon"))
2958 WRN("Deprecated function. This functionality on icon objects"
2959 " will be dropped on a next release.");
2961 data = _elm_icon_signal_callback_del(obj, emission, source, func);
2968 _elm_widget_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool focus)
2973 sd->focus_order = focus_order;
2974 sd->focused = EINA_TRUE;
2975 eo_do(obj, elm_obj_widget_on_focus(NULL));
2980 if ((_is_focusable(sd->resize_obj)) &&
2981 (!elm_widget_disabled_get(sd->resize_obj)))
2983 elm_widget_focus_set(sd->resize_obj, focus);
2990 EINA_LIST_FOREACH(sd->subobjs, l, child)
2992 if (!_elm_widget_is(child)) continue;
2993 if ((_is_focusable(child)) &&
2994 (!elm_widget_disabled_get(child)))
2996 elm_widget_focus_set(child, focus);
3007 EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
3009 if (!_elm_widget_is(child)) continue;
3010 if ((_is_focusable(child)) &&
3011 (!elm_widget_disabled_get(child)))
3013 elm_widget_focus_set(child, focus);
3020 EOLIAN static Evas_Object*
3021 _elm_widget_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3023 return sd->parent_obj;
3027 _elm_widget_focused_object_clear(Eo *obj, Elm_Widget_Smart_Data *sd)
3029 if (!sd->focused) return;
3030 if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
3031 _is_focused(sd->resize_obj))
3033 eo_do(sd->resize_obj, elm_obj_widget_focused_object_clear());
3039 EINA_LIST_FOREACH(sd->subobjs, l, child)
3041 if (_elm_widget_is(child) && _is_focused(child))
3043 eo_do(child, elm_obj_widget_focused_object_clear());
3048 sd->focused = EINA_FALSE;
3049 if (sd->top_win_focused)
3050 eo_do(obj, elm_obj_widget_on_focus(NULL));
3054 _elm_widget_focus_steal(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item)
3056 Evas_Object *parent, *parent2, *o;
3058 if (sd->focused) return;
3059 if (sd->disabled) return;
3060 if (!sd->can_focus) return;
3061 if (sd->tree_unfocusable) return;
3065 o = elm_widget_parent_get(parent);
3067 sd = eo_data_scope_get(o, MY_CLASS);
3068 if (sd->disabled || sd->tree_unfocusable) return;
3069 if (sd->focused) break;
3072 if ((!elm_widget_parent_get(parent)) &&
3073 (!elm_widget_parent2_get(parent)))
3074 eo_do(parent, elm_obj_widget_focused_object_clear());
3077 parent2 = elm_widget_parent_get(parent);
3078 if (!parent2) parent2 = elm_widget_parent2_get(parent);
3080 sd = eo_data_scope_get(parent, MY_CLASS);
3083 if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
3084 _is_focused(sd->resize_obj))
3086 eo_do(sd->resize_obj, elm_obj_widget_focused_object_clear());
3092 EINA_LIST_FOREACH(sd->subobjs, l, child)
3094 if (_elm_widget_is(child) && _is_focused(child))
3096 eo_do(child, elm_obj_widget_focused_object_clear());
3103 /* TIZEN_ONLY(20161212): Some winsets should know whether it's focus target or not in _on_focus */
3104 sd = eo_data_scope_get(obj, MY_CLASS);
3105 sd->is_focus_target = EINA_TRUE;
3107 _parent_focus(obj, item);
3108 /* TIZEN_ONLY(20161212): Some winsets should know whether it's focus target or not in _on_focus */
3109 sd->is_focus_target = EINA_FALSE;
3111 elm_widget_focus_region_show(obj);
3116 _parents_on_focus(Evas_Object *obj)
3119 if (!sd->focused || !sd->top_win_focused) return;
3121 Evas_Object *o = elm_widget_parent_get(obj);
3122 if (o) _parents_on_focus(o);
3123 eo_do(obj, elm_obj_widget_on_focus(NULL));
3127 _elm_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3129 Evas_Object *newest = NULL;
3130 unsigned int newest_focus_order = 0;
3132 newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
3134 _parents_on_focus(newest);
3138 _elm_widget_focus_auto_show(Evas_Object *obj)
3140 Evas_Object *top = elm_widget_top_get(obj);
3141 if (top && eo_isa(top, ELM_WIN_CLASS)) _elm_win_focus_auto_show(top);
3145 _elm_widget_top_win_focused_set(Evas_Object *obj,
3146 Eina_Bool top_win_focused)
3152 if (sd->top_win_focused == top_win_focused) return;
3153 EINA_LIST_FOREACH(sd->subobjs, l, child)
3155 if (elm_widget_is(child))
3156 _elm_widget_top_win_focused_set(child, top_win_focused);
3158 sd->top_win_focused = top_win_focused;
3160 if (sd->focused && !sd->top_win_focused)
3161 eo_do(obj, elm_obj_widget_on_focus(NULL));
3165 _elm_widget_top_win_focused_get(const Evas_Object *obj)
3167 API_ENTRY return EINA_FALSE;
3168 return sd->top_win_focused;
3172 _elm_widget_disabled_eval(const Evas_Object *obj, Eina_Bool disabled)
3176 ELM_WIDGET_DATA_GET(obj, sd);
3180 EINA_LIST_FOREACH(sd->subobjs, l, child)
3182 if (elm_widget_is(child))
3184 elm_widget_focus_disabled_handle(child);
3185 eo_do(child, elm_obj_widget_disable());
3186 _elm_widget_disabled_eval(child, EINA_TRUE);
3192 EINA_LIST_FOREACH(sd->subobjs, l, child)
3194 ELM_WIDGET_DATA_GET(child, sdc);
3195 if (elm_widget_is(child) && !sdc->disabled)
3197 elm_widget_focus_disabled_handle(child);
3198 eo_do(child, elm_obj_widget_disable());
3199 _elm_widget_disabled_eval(child, EINA_FALSE);
3206 elm_widget_disabled_internal(Eo *obj, Eina_Bool disabled)
3208 Eina_Bool parent_state = EINA_FALSE;
3212 elm_widget_focus_disabled_handle(obj);
3213 eo_do(obj, elm_obj_widget_disable());
3214 _elm_widget_disabled_eval(obj, EINA_TRUE);
3218 parent_state = elm_widget_disabled_get(elm_widget_parent_get(obj));
3219 if (parent_state) return;
3220 elm_widget_focus_disabled_handle(obj);
3221 eo_do(obj, elm_obj_widget_disable());
3222 _elm_widget_disabled_eval(obj, EINA_FALSE);
3227 _elm_widget_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled)
3229 if (sd->disabled == disabled) return;
3230 sd->disabled = !!disabled;
3232 elm_widget_disabled_internal(obj, disabled);
3235 EOLIAN static Eina_Bool
3236 _elm_widget_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3238 Eina_Bool disabled = EINA_FALSE;
3240 if (sd->disabled) disabled = EINA_TRUE;
3241 else disabled = elm_widget_disabled_get(elm_widget_parent_get(obj));
3246 _elm_widget_show_region_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool forceshow)
3249 Evas_Object *parent_obj, *child_obj;
3250 Evas_Coord px, py, cx, cy, nx = 0, ny = 0;
3253 /* TIZEN_ONLY(20161222): Update show region geometry when entry is resized
3254 Move this code to the blow to update show region geometry properly.
3255 evas_smart_objects_calculate(evas_object_evas_get(obj));
3258 if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
3259 (w == sd->rw) && (h == sd->rh)) return;
3266 /* TIZEN_ONLY(20161222): Update show region geometry when entry is resized */
3267 /* Block nested call for evas_smart_objects_calculate() and region showing works */
3268 if (sd->on_show_region_set) return;
3270 sd->on_show_region_set = EINA_TRUE;
3272 evas_smart_objects_calculate(evas_object_evas_get(obj));
3274 sd->on_show_region_set = EINA_FALSE;
3276 /* show_region geometry could be changed during processing elm_widget_show_region_set().
3277 evas_smart_objects_calculate() can trigger nested show_region_set calls */
3284 if (sd->on_show_region)
3287 (sd->on_show_region_data, obj);
3289 if (_elm_scrollable_is(obj))
3291 eo_do(obj, elm_interface_scrollable_content_pos_get(&nx, &ny));
3299 parent_obj = sd->parent_obj;
3300 child_obj = sd->obj;
3301 if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
3302 sd = eo_data_scope_get(parent_obj, MY_CLASS);
3305 evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
3306 evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
3315 if (sd->on_show_region)
3318 (sd->on_show_region_data, parent_obj);
3325 _elm_widget_show_region_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3336 * Get the focus region of the given widget.
3338 * @return show region or not
3339 * (@c EINA_TRUE = show region/@c EINA_FALSE = do not show region). Default is @c EINA_FALSE.
3341 * The focus region is the area of a widget that should brought into the
3342 * visible area when the widget is focused. Mostly used to show the part of
3343 * an entry where the cursor is, for example. The area returned is relative
3344 * to the object @p obj.
3346 * @param obj The widget object
3347 * @param x Where to store the x coordinate of the area
3348 * @param y Where to store the y coordinate of the area
3349 * @param w Where to store the width of the area
3350 * @param h Where to store the height of the area
3354 EOLIAN static Eina_Bool
3355 _elm_widget_focus_region_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3357 Eina_Bool int_ret = EINA_FALSE;
3358 eo_do((Eo *)obj, int_ret = elm_obj_widget_on_focus_region(x, y, w, h));
3361 evas_object_geometry_get(obj, NULL, NULL, w, h);
3365 if ((*w <= 0) || (*h <= 0)) return EINA_FALSE;
3370 _elm_widget_parents_bounce_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool *horiz, Eina_Bool *vert)
3372 Evas_Object *parent_obj = obj;
3373 Eina_Bool h = EINA_FALSE, v = EINA_FALSE;
3375 *horiz = EINA_FALSE;
3380 parent_obj = elm_widget_parent_get(parent_obj);
3381 if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
3383 if (_elm_scrollable_is(parent_obj))
3385 eo_do(parent_obj, elm_interface_scrollable_bounce_allow_get(&h, &v));
3386 if (h) *horiz = EINA_TRUE;
3387 if (v) *vert = EINA_TRUE;
3393 EOLIAN static Eina_List*
3394 _elm_widget_scrollable_children_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3403 EINA_LIST_FOREACH(sd->subobjs, l, child)
3405 if (elm_widget_is(child) && _elm_scrollable_is(child))
3406 ret = eina_list_append(ret, child);
3413 _elm_widget_scroll_hold_push(Eo *obj, Elm_Widget_Smart_Data *sd)
3416 if (sd->scroll_hold == 1)
3418 if (_elm_scrollable_is(obj))
3419 eo_do(obj, elm_interface_scrollable_hold_set(EINA_TRUE));
3422 Eina_List *scr_children, *l;
3425 scr_children = elm_widget_scrollable_children_get(obj);
3426 EINA_LIST_FOREACH(scr_children, l, child)
3428 eo_do(child, elm_interface_scrollable_hold_set(EINA_TRUE));
3430 eina_list_free(scr_children);
3433 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_hold_push());
3434 // FIXME: on delete/reparent hold pop
3438 _elm_widget_scroll_hold_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
3441 if (!sd->scroll_hold)
3443 if (_elm_scrollable_is(obj))
3444 eo_do(obj, elm_interface_scrollable_hold_set(EINA_FALSE));
3447 Eina_List *scr_children, *l;
3450 scr_children = elm_widget_scrollable_children_get(obj);
3451 EINA_LIST_FOREACH(scr_children, l, child)
3453 eo_do(child, elm_interface_scrollable_hold_set(EINA_FALSE));
3455 eina_list_free(scr_children);
3458 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_hold_pop());
3459 if (sd->scroll_hold < 0) sd->scroll_hold = 0;
3463 _elm_widget_scroll_hold_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3465 return sd->scroll_hold;
3469 _elm_widget_scroll_freeze_push(Eo *obj, Elm_Widget_Smart_Data *sd)
3471 sd->scroll_freeze++;
3472 if (sd->scroll_freeze == 1)
3474 if (_elm_scrollable_is(obj))
3475 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_TRUE));
3478 Eina_List *scr_children, *l;
3481 scr_children = elm_widget_scrollable_children_get(obj);
3482 EINA_LIST_FOREACH(scr_children, l, child)
3484 eo_do(child, elm_interface_scrollable_freeze_set(EINA_TRUE));
3486 eina_list_free(scr_children);
3489 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_freeze_push());
3490 // FIXME: on delete/reparent freeze pop
3494 _elm_widget_scroll_freeze_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
3496 sd->scroll_freeze--;
3497 if (!sd->scroll_freeze)
3499 if (_elm_scrollable_is(obj))
3500 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_FALSE));
3503 Eina_List *scr_children, *l;
3506 scr_children = elm_widget_scrollable_children_get(obj);
3507 EINA_LIST_FOREACH(scr_children, l, child)
3509 eo_do(child, elm_interface_scrollable_freeze_set(EINA_FALSE));
3511 eina_list_free(scr_children);
3514 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_freeze_pop());
3515 if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
3519 _elm_widget_scroll_freeze_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3521 return sd->scroll_freeze;
3524 // TIZEN_ONLY(20150705): Genlist item align feature
3526 elm_widget_scroll_item_align_enabled_set(Evas_Object *obj,
3527 Eina_Bool scroll_item_align_enable)
3530 if (sd->scroll_item_align_enable == scroll_item_align_enable) return;
3531 sd->scroll_item_align_enable = scroll_item_align_enable;
3535 elm_widget_scroll_item_align_enabled_get(const Evas_Object *obj)
3537 API_ENTRY return EINA_FALSE;
3538 return sd->scroll_item_align_enable;
3542 elm_widget_scroll_item_valign_set(Evas_Object *obj,
3543 const char *scroll_item_valign)
3546 if (sd->scroll_item_valign) eina_stringshare_del(sd->scroll_item_valign);
3547 if (!scroll_item_valign) sd->scroll_item_valign = NULL;
3548 else sd->scroll_item_valign = eina_stringshare_add(scroll_item_valign);
3552 elm_widget_scroll_item_valign_get(const Evas_Object *obj)
3554 API_ENTRY return NULL;
3555 return sd->scroll_item_valign;
3560 _elm_widget_scale_set(Eo *obj, Elm_Widget_Smart_Data *sd, double scale)
3562 if (scale < 0.0) scale = 0.0;
3563 if (sd->scale != scale)
3566 elm_widget_theme(obj);
3570 EOLIAN static double
3571 _elm_widget_scale_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3573 // FIXME: save walking up the tree by storing/caching parent scale
3574 if (sd->scale == 0.0)
3576 if (sd->parent_obj && elm_widget_is(sd->parent_obj))
3578 return elm_widget_scale_get(sd->parent_obj);
3589 _elm_widget_theme_set(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Theme *th)
3591 Eina_Bool apply = EINA_FALSE;
3592 if (sd->theme != th)
3594 if (elm_widget_theme_get(obj) != th) apply = EINA_TRUE;
3595 if (sd->theme) elm_theme_free(sd->theme);
3598 if (apply) elm_widget_theme(obj);
3603 _elm_widget_part_text_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part, const char *label)
3605 if (evas_object_smart_type_check(obj, "elm_layout"))
3606 elm_layout_text_set(obj, part, label);
3609 EOLIAN static const char*
3610 _elm_widget_part_text_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part)
3612 if (evas_object_smart_type_check(obj, "elm_layout"))
3613 return elm_layout_text_get(obj, part);
3618 static Elm_Translate_String_Data *
3619 _translate_string_data_get(Eina_Inlist *translate_strings, const char *part)
3621 Elm_Translate_String_Data *ts;
3622 Eina_Stringshare *str;
3624 if (!translate_strings) return NULL;
3626 str = eina_stringshare_add(part);
3627 EINA_INLIST_FOREACH(translate_strings, ts)
3629 if (ts->id == str) break;
3632 eina_stringshare_del(str);
3637 static Elm_Translate_String_Data *
3638 _part_text_translatable_set(Eina_Inlist **translate_strings, const char *part, Eina_Bool translatable, Eina_Bool preset)
3641 Elm_Translate_String_Data *ts;
3642 t = *translate_strings;
3643 ts = _translate_string_data_get(t, part);
3649 ts = ELM_NEW(Elm_Translate_String_Data);
3650 if (!ts) return NULL;
3652 ts->id = eina_stringshare_add(part);
3653 t = eina_inlist_append(t, (Eina_Inlist*) ts);
3655 if (preset) ts->preset = EINA_TRUE;
3657 //Delete this exist one if this part has been not preset.
3658 //see elm_widget_part_text_translatable_set()
3659 else if (ts && ((preset) || (!ts->preset)))
3661 t = eina_inlist_remove(t, EINA_INLIST_GET(ts));
3662 eina_stringshare_del(ts->id);
3663 eina_stringshare_del(ts->domain);
3664 eina_stringshare_del(ts->string);
3665 ELM_SAFE_FREE(ts, free);
3668 *translate_strings = t;
3674 _elm_widget_domain_translatable_part_text_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, const char *label)
3677 Elm_Translate_String_Data *ts;
3681 _part_text_translatable_set(&sd->translate_strings, part, EINA_FALSE,
3686 ts = _part_text_translatable_set(&sd->translate_strings, part,
3687 EINA_TRUE, EINA_FALSE);
3689 if (!ts->string) ts->string = eina_stringshare_add(label);
3690 else eina_stringshare_replace(&ts->string, label);
3691 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3692 else eina_stringshare_replace(&ts->domain, domain);
3694 if (label[0]) label = dgettext(domain, label);
3698 sd->on_translate = EINA_TRUE;
3699 eo_do(obj, elm_obj_widget_part_text_set(part, label));
3700 sd->on_translate = EINA_FALSE;
3703 EOLIAN static const char*
3704 _elm_widget_translatable_part_text_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part)
3706 Elm_Translate_String_Data *ts;
3708 ts = _translate_string_data_get(sd->translate_strings, part);
3709 if (ts) return ts->string;
3714 _elm_widget_domain_part_text_translatable_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, Eina_Bool translatable)
3716 Elm_Translate_String_Data *ts;
3717 const char *text = NULL;
3719 ts = _part_text_translatable_set(&sd->translate_strings, part,
3720 translatable, EINA_TRUE);
3722 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3723 else eina_stringshare_replace(&ts->domain, domain);
3725 eo_do(obj, text = elm_obj_widget_part_text_get(part));
3726 if (!text || !text[0]) return;
3728 if (!ts->string) ts->string = eina_stringshare_add(text);
3730 //Try to translate text since we don't know the text is already translated.
3732 text = dgettext(domain, text);
3734 sd->on_translate = EINA_TRUE;
3735 eo_do(obj, elm_obj_widget_part_text_set(part, text));
3736 sd->on_translate = EINA_FALSE;
3740 elm_widget_translate(Evas_Object *obj)
3742 ELM_WIDGET_CHECK(obj);
3743 eo_do(obj, elm_obj_widget_translate());
3747 _part_text_translate(Eina_Inlist *translate_strings,
3751 Elm_Translate_String_Data *ts;
3752 ts = _translate_string_data_get(translate_strings, part);
3753 if (!ts) return text;
3755 if (!ts->string) ts->string = eina_stringshare_add(text);
3756 else eina_stringshare_replace(&ts->string, text);
3758 if (text && text[0])
3759 text = dgettext(ts->domain, text);
3764 EOLIAN static const char*
3765 _elm_widget_part_text_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part, const char *text)
3769 if (!sd->translate_strings || sd->on_translate) return text;
3770 return _part_text_translate(sd->translate_strings, part, text);
3773 EOLIAN static Eina_Bool
3774 _elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3778 API_ENTRY return EINA_FALSE;
3780 EINA_LIST_FOREACH(sd->subobjs, l, child)
3782 if (elm_widget_is(child))
3783 elm_widget_translate(child);
3786 if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
3789 Elm_Translate_String_Data *ts;
3790 EINA_INLIST_FOREACH(sd->translate_strings, ts)
3792 if (!ts->string) continue;
3793 const char *s = dgettext(ts->domain, ts->string);
3794 sd->on_translate = EINA_TRUE;
3795 eo_do(obj, elm_obj_widget_part_text_set(ts->id, s));
3796 sd->on_translate = EINA_FALSE;
3799 eo_do(obj, eo_event_callback_call(ELM_WIDGET_EVENT_LANGUAGE_CHANGED, NULL));
3806 * Resets the focus_move_policy mode from the system one
3807 * for widgets that are in automatic mode.
3809 * @param obj The widget.
3813 _elm_widget_focus_move_policy_reload(Evas_Object *obj)
3816 Elm_Focus_Move_Policy focus_move_policy = elm_config_focus_move_policy_get();
3818 if (elm_widget_focus_move_policy_automatic_get(obj) &&
3819 (sd->focus_move_policy != focus_move_policy))
3821 sd->focus_move_policy = focus_move_policy;
3826 _elm_widget_focus_reconfigure(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3832 EINA_LIST_FOREACH(sd->subobjs, l, child)
3834 if (elm_widget_is(child))
3835 elm_widget_focus_reconfigure(child);
3838 if (sd->hover_obj) elm_widget_focus_reconfigure(sd->hover_obj);
3840 _elm_widget_focus_move_policy_reload(obj);
3843 //TIZEN_ONLY(20160726): add API elm_object_part_access_object_get
3844 EOLIAN static Evas_Object*
3845 _elm_widget_part_access_object_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part EINA_UNUSED)
3847 WRN("The %s widget does not implement the \"part_access_object_get\" functions.",
3848 eo_class_name_get(eo_class_get(obj)));
3854 elm_widget_content_part_set(Evas_Object *obj,
3856 Evas_Object *content)
3858 ELM_WIDGET_CHECK(obj);
3859 eo_do(obj, elm_obj_container_content_set(part, content));
3863 * Returns the widget's focus_move_policy mode setting.
3865 * @param obj The widget.
3866 * @return focus_move_policy mode setting of the object.
3869 EOLIAN static Eina_Bool
3870 _elm_widget_focus_move_policy_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3872 return sd->focus_move_policy_auto_mode;
3878 * Sets the widget's focus_move_policy mode setting.
3879 * When widget in automatic mode, it follows the system focus_move_policy mode set by
3880 * elm_config_focus_move_policy_set().
3881 * @param obj The widget.
3882 * @param automatic EINA_TRUE for auto focus_move_policy mode. EINA_FALSE for manual.
3885 _elm_widget_focus_move_policy_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
3887 if (sd->focus_move_policy_auto_mode != automatic)
3889 sd->focus_move_policy_auto_mode = automatic;
3893 elm_widget_focus_move_policy_set(obj, elm_config_focus_move_policy_get());
3899 elm_widget_content_part_get(const Evas_Object *obj,
3902 ELM_WIDGET_CHECK(obj) NULL;
3903 Evas_Object *ret = NULL;
3904 eo_do((Eo *) obj, ret = elm_obj_container_content_get(part));
3909 elm_widget_content_part_unset(Evas_Object *obj,
3912 ELM_WIDGET_CHECK(obj) NULL;
3913 Evas_Object *ret = NULL;
3914 eo_do(obj, ret = elm_obj_container_content_unset(part));
3919 _elm_widget_access_info_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *txt)
3921 eina_stringshare_del(sd->access_info);
3922 if (!txt) sd->access_info = NULL;
3923 else sd->access_info = eina_stringshare_add(txt);
3926 EOLIAN static const char*
3927 _elm_widget_access_info_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3929 return sd->access_info;
3932 EOLIAN static Elm_Theme*
3933 _elm_widget_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3937 if (sd->parent_obj && elm_widget_is(sd->parent_obj))
3938 return elm_widget_theme_get(sd->parent_obj);
3944 EOLIAN static Elm_Theme_Apply
3945 _elm_widget_style_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *style)
3947 if (eina_stringshare_replace(&sd->style, style))
3948 return elm_widget_theme(obj);
3950 return ELM_THEME_APPLY_SUCCESS;
3953 /* TIZEN_ONLY(20161223): add widget style set furnction for internal usage
3954 this function is same with elm_widget_style_set
3955 but it doesn't apply sub object's theme */
3957 _elm_widget_style_set_internal(Evas_Object *obj, const char *style)
3959 Elm_Theme_Apply ret = ELM_THEME_APPLY_SUCCESS;
3961 API_ENTRY return ELM_THEME_APPLY_FAILED;
3963 if (eina_stringshare_replace(&sd->style, style))
3969 if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
3971 EINA_LIST_FOREACH(sd->tooltips, l, tt)
3972 elm_tooltip_theme(tt);
3973 EINA_LIST_FOREACH(sd->cursors, l, cur)
3974 elm_cursor_theme(cur);
3976 Elm_Theme_Apply ret2 = ELM_THEME_APPLY_FAILED;
3977 eo_do(obj, ret2 = elm_obj_widget_theme_apply());
3985 EOLIAN static const char*
3986 _elm_widget_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3990 if (sd->style) ret = sd->style;
3996 _elm_widget_tooltip_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt)
3998 sd->tooltips = eina_list_append(sd->tooltips, tt);
4002 _elm_widget_tooltip_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt)
4004 sd->tooltips = eina_list_remove(sd->tooltips, tt);
4008 _elm_widget_cursor_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Cursor *cur)
4010 sd->cursors = eina_list_append(sd->cursors, cur);
4014 _elm_widget_cursor_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Cursor *cur)
4016 sd->cursors = eina_list_remove(sd->cursors, cur);
4020 _elm_widget_drag_lock_x_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock)
4022 if (sd->drag_x_locked == lock) return;
4023 sd->drag_x_locked = lock;
4024 if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
4025 else _propagate_x_drag_lock(obj, -1);
4029 _elm_widget_drag_lock_y_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock)
4031 if (sd->drag_y_locked == lock) return;
4032 sd->drag_y_locked = lock;
4033 if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
4034 else _propagate_y_drag_lock(obj, -1);
4037 EOLIAN static Eina_Bool
4038 _elm_widget_drag_lock_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4040 return sd->drag_x_locked;
4043 EOLIAN static Eina_Bool
4044 _elm_widget_drag_lock_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4046 return sd->drag_y_locked;
4050 _elm_widget_drag_child_locked_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4052 return sd->child_drag_x_locked;
4056 _elm_widget_drag_child_locked_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4058 return sd->child_drag_y_locked;
4062 _elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Bool enable EINA_UNUSED)
4067 EOLIAN static Eina_Bool
4068 _elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED)
4073 EOLIAN static Elm_Theme_Apply
4074 _elm_widget_theme_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle)
4076 Elm_Theme_Apply ret = _elm_theme_object_set(obj, edj, wname, welement, wstyle);
4079 return ELM_THEME_APPLY_FAILED;
4082 if (sd->orient_mode != -1)
4085 snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
4086 eo_do(obj, elm_obj_widget_signal_emit(buf, "elm"));
4093 _elm_widget_eo_base_dbg_info_get(Eo *eo_obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eo_Dbg_Info *root)
4095 eo_do_super(eo_obj, MY_CLASS, eo_dbg_info_get(root));
4096 Eo_Dbg_Info *group = EO_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
4098 EO_DBG_INFO_APPEND(group, "Wid-Type", EINA_VALUE_TYPE_STRING, elm_widget_type_get(eo_obj));
4099 EO_DBG_INFO_APPEND(group, "Style", EINA_VALUE_TYPE_STRING, elm_widget_style_get(eo_obj));
4100 EO_DBG_INFO_APPEND(group, "Layer", EINA_VALUE_TYPE_INT,
4101 (int) evas_object_layer_get(eo_obj));
4102 EO_DBG_INFO_APPEND(group, "Scale", EINA_VALUE_TYPE_DOUBLE,
4103 evas_object_scale_get(eo_obj));
4104 EO_DBG_INFO_APPEND(group, "Has focus", EINA_VALUE_TYPE_CHAR,
4105 elm_object_focus_get(eo_obj));
4106 EO_DBG_INFO_APPEND(group, "Disabled", EINA_VALUE_TYPE_CHAR,
4107 elm_widget_disabled_get(eo_obj));
4108 EO_DBG_INFO_APPEND(group, "Mirrored", EINA_VALUE_TYPE_CHAR,
4109 elm_widget_mirrored_get(eo_obj));
4110 EO_DBG_INFO_APPEND(group, "Automatic mirroring", EINA_VALUE_TYPE_CHAR,
4111 elm_widget_mirrored_automatic_get(eo_obj));
4115 elm_widget_is_check(const Evas_Object *obj)
4117 static int abort_on_warn = -1;
4118 if (elm_widget_is(obj))
4121 ERR("Passing Object: %p.", obj);
4122 if (abort_on_warn == -1)
4124 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
4125 else abort_on_warn = 0;
4127 if (abort_on_warn == 1) abort();
4132 elm_widget_type_get(const Evas_Object *obj)
4134 API_ENTRY return NULL;
4136 return eo_class_name_get(eo_class_get(obj));
4140 elm_widget_type_check(const Evas_Object *obj,
4144 const char *provided, *expected = "(unknown)";
4145 static int abort_on_warn = -1;
4147 provided = elm_widget_type_get(obj);
4148 /* TODO: eventually migrate to check_ptr version */
4149 if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
4150 if (type) expected = type;
4151 if ((!provided) || (!provided[0]))
4153 provided = evas_object_type_get(obj);
4154 if ((!provided) || (!provided[0]))
4155 provided = "(unknown)";
4157 ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
4158 " type: '%s'", obj, func, provided, expected);
4159 if (abort_on_warn == -1)
4161 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
4162 else abort_on_warn = 0;
4164 if (abort_on_warn == 1) abort();
4168 static Evas_Object *
4169 _widget_name_find(const Evas_Object *obj,
4176 INTERNAL_ENTRY NULL;
4178 if (!_elm_widget_is(obj)) return NULL;
4179 EINA_LIST_FOREACH(sd->subobjs, l, child)
4181 s = evas_object_name_get(child);
4182 if ((s) && (!strcmp(s, name))) return child;
4183 if ((recurse != 0) &&
4184 ((child = _widget_name_find(child, name, recurse - 1))))
4189 s = evas_object_name_get(sd->hover_obj);
4190 if ((s) && (!strcmp(s, name))) return sd->hover_obj;
4191 if ((recurse != 0) &&
4192 ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
4198 EOLIAN static Evas_Object*
4199 _elm_widget_name_find(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *name, int recurse)
4201 if (!name) return NULL;
4202 return _widget_name_find(obj, name, recurse);
4208 * Split string in words
4210 * @param str Source string
4211 * @return List of const words
4213 * @see elm_widget_stringlist_free()
4217 elm_widget_stringlist_get(const char *str)
4219 Eina_List *list = NULL;
4221 if (!str) return NULL;
4222 for (b = s = str; 1; s++)
4224 if ((*s == ' ') || (!*s))
4226 char *t = malloc(s - b + 1);
4229 strncpy(t, b, s - b);
4231 list = eina_list_append(list, eina_stringshare_add(t));
4242 elm_widget_stringlist_free(Eina_List *list)
4245 EINA_LIST_FREE(list, s)
4246 eina_stringshare_del(s);
4250 _elm_widget_focus_hide_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4252 if (!_elm_widget_is(obj))
4254 _if_focused_revert(obj, EINA_TRUE);
4258 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
4260 Evas_Object *o = obj;
4263 if (_elm_widget_is(o)) break;
4264 o = evas_object_smart_parent_get(o);
4268 eo_do(o, elm_obj_widget_focus_mouse_up_handle());
4272 _elm_widget_focus_mouse_up_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4275 if (!_is_focusable(obj)) return;
4277 elm_widget_focus_steal(obj, NULL);
4281 _elm_widget_focus_tree_unfocusable_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4283 if (!elm_widget_parent_get(obj))
4284 elm_widget_focused_object_clear(obj);
4286 _if_focused_revert(obj, EINA_TRUE);
4290 _elm_widget_focus_disabled_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4292 elm_widget_focus_tree_unfocusable_handle(obj);
4295 EOLIAN static unsigned int
4296 _elm_widget_focus_order_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4298 return sd->focus_order;
4301 EOLIAN static Evas_Object*
4302 _elm_widget_newest_focus_order_get(const Eo *obj, Elm_Widget_Smart_Data *sd, unsigned int *newest_focus_order, Eina_Bool can_focus_only)
4305 Evas_Object *child, *cur, *best;
4307 if (!evas_object_visible_get(obj)
4308 || (elm_widget_disabled_get(obj))
4309 || (elm_widget_tree_unfocusable_get(obj)))
4313 if (*newest_focus_order < sd->focus_order)
4315 if (!can_focus_only || elm_widget_can_focus_get(obj))
4317 *newest_focus_order = sd->focus_order;
4318 best = (Evas_Object *)obj;
4321 EINA_LIST_FOREACH(sd->subobjs, l, child)
4323 if (!_elm_widget_is(child)) continue;
4325 cur = elm_widget_newest_focus_order_get
4326 (child, newest_focus_order, can_focus_only);
4336 * Get the focus highlight geometry of an widget.
4338 * @param obj Widget object for the focus highlight
4339 * @param x Focus highlight x coordinate
4340 * @param y Focus highlight y coordinate
4341 * @param w Focus highlight object width
4342 * @param h Focus highlight object height
4343 * @param is_next @c EINA_TRUE if this request is for the new focused object,
4344 * @c EINA_FALSE if this request is for the previously focused object. This
4345 * information becomes important when the focus highlight is changed inside one
4353 * Get the 'focus_part' geometry if there is any
4355 * This queries if there is a 'focus_part' request from the edc style. If edc
4356 * style offers 'focus_part' edje data item, this function requests for the
4357 * geometry of a specific part which is described in 'focus_part' edje data.
4359 * @param obj Widget object for the focus highlight
4360 * @param x Focus highlight x coordinate
4361 * @param y Focus highlight y coordinate
4362 * @param w Focus highlight object width
4363 * @param h Focus highlight object height
4365 * x, y, w, h already contain the object's geometry. If there is a 'focus_part'
4366 * support, these values will be updated accordingly or the values will be
4367 * remained as they were.
4372 elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj,
4378 Evas_Coord tx = 0, ty = 0, tw = 0, th = 0;
4379 const char *target_hl_part = NULL;
4380 const Evas_Object *edje_obj = NULL;
4382 if (obj && eo_isa(obj, EDJE_OBJECT_CLASS))
4385 if (!(target_hl_part = edje_object_data_get(edje_obj, "focus_part")))
4388 else if (obj && eo_isa(obj, ELM_LAYOUT_CLASS))
4390 edje_obj = elm_layout_edje_get(obj);
4391 if (!(target_hl_part = elm_layout_data_get(obj, "focus_part")))
4397 edje_object_part_geometry_get(edje_obj, target_hl_part,
4398 &tx, &ty, &tw, &th);
4401 if (tw != *w) *w = tw;
4402 if (th != *h) *h = th;
4406 _elm_widget_focus_highlight_geometry_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
4408 Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
4409 Evas_Object *scroller = (Evas_Object *)obj;
4411 evas_object_geometry_get(obj, x, y, w, h);
4412 elm_widget_focus_highlight_focus_part_geometry_get(sd->resize_obj, x, y, w, h);
4414 if (_elm_config->focus_autoscroll_mode != ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN)
4419 if (_elm_scrollable_is(scroller))
4422 elm_interface_scrollable_content_viewport_geometry_get(&ox, &oy, &ow, &oh));
4426 else if ((oy + oh) < (*y + *h))
4427 *y = (oy + oh - *h);
4430 else if ((ox + ow) < (*x + *w))
4431 *x = (ox + ow - *w);
4435 scroller = elm_widget_parent_get(scroller);
4439 EOLIAN static Elm_Object_Item*
4440 _elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4446 _elm_widget_focus_region_show_mode_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Elm_Focus_Region_Show_Mode mode)
4448 _pd->focus_region_show_mode = mode;
4451 EOLIAN static Elm_Focus_Region_Show_Mode
4452 _elm_widget_focus_region_show_mode_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
4454 return _pd->focus_region_show_mode;
4458 elm_widget_activate(Evas_Object *obj, Elm_Activate act)
4460 Evas_Object *parent;
4463 ELM_WIDGET_CHECK(obj);
4467 eo_do(obj, ret = elm_obj_widget_activate(act));
4471 parent = elm_widget_parent_get(obj);
4473 elm_widget_activate(parent, act);
4481 * Sets the widget and child widget's Evas_Display_Mode.
4483 * @param obj The widget.
4484 * @param dispmode Evas_Display_Mode to set widget's mode.
4486 * Widgets are resized by several reasons.
4487 * Evas_Display_Mode can help for widgets to get one more reason of resize.
4488 * For example, elm conform widget resizes it's contents when keypad state changed.
4489 * After keypad showing, conform widget can change child's Evas_Display_Mode.
4493 _elm_widget_display_mode_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Display_Mode dispmode)
4495 Evas_Display_Mode prev_dispmode;
4499 prev_dispmode = evas_object_size_hint_display_mode_get(obj);
4501 if ((prev_dispmode == dispmode) ||
4502 (prev_dispmode == EVAS_DISPLAY_MODE_DONT_CHANGE)) return;
4504 evas_object_size_hint_display_mode_set(obj, dispmode);
4506 EINA_LIST_FOREACH (sd->subobjs, l, child)
4508 if (elm_widget_is(child))
4509 elm_widget_display_mode_set(child, dispmode);
4514 _elm_widget_orientation_mode_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled)
4516 int orient_mode = -1;
4520 //Get current orient mode from it's parent otherwise, 0.
4521 sd->orient_mode = 0;
4522 ELM_WIDGET_DATA_GET(sd->parent_obj, sd_parent);
4523 if (!sd_parent) orient_mode = 0;
4524 else orient_mode = sd_parent->orient_mode;
4526 eo_do(obj, elm_obj_widget_orientation_set(orient_mode));
4529 EOLIAN static Eina_Bool
4530 _elm_widget_orientation_mode_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4532 if (sd->orient_mode == -1) return EINA_TRUE;
4533 else return EINA_FALSE;
4537 _elm_widget_orientation_set(Eo *obj, Elm_Widget_Smart_Data *sd, int orient_mode)
4542 sd->orient_mode = orient_mode;
4544 EINA_LIST_FOREACH (sd->subobjs, l, child)
4546 if (elm_widget_is(child))
4547 eo_do(child, elm_obj_widget_orientation_set(orient_mode));
4550 if (orient_mode != -1)
4553 snprintf(buf, sizeof(buf), "elm,state,orient,%d", orient_mode);
4554 eo_do(obj, elm_obj_widget_signal_emit(buf, "elm"));
4561 * Returns the widget's focus move policy.
4563 * @param obj The widget.
4564 * @return focus move policy of the object.
4567 EOLIAN static Elm_Focus_Move_Policy
4568 _elm_widget_focus_move_policy_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4570 return sd->focus_move_policy;
4576 * Sets the widget's focus move policy.
4578 * @param obj The widget.
4579 * @param policy Elm_Focus_Move_Policy to set object's focus move policy.
4583 _elm_widget_focus_move_policy_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Move_Policy policy)
4585 if (sd->focus_move_policy == policy) return;
4586 sd->focus_move_policy = policy;
4589 _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
4592 _track_obj_update(Evas_Object *track, Evas_Object *obj)
4595 Evas_Coord x, y, w, h;
4596 evas_object_geometry_get(obj, &x, &y, &w, &h);
4597 evas_object_move(track, x, y);
4598 evas_object_resize(track, w, h);
4601 if (evas_object_visible_get(obj)) evas_object_show(track);
4602 else evas_object_hide(track);
4606 _track_obj_view_update(void *data, Eo *obj,
4607 const Eo_Event_Description *desc EINA_UNUSED,
4608 void *event_info EINA_UNUSED)
4610 Elm_Widget_Item_Data *item = data;
4611 _track_obj_update(item->track_obj, obj);
4612 return EO_CALLBACK_CONTINUE;
4616 _track_obj_view_del(void *data, Eo *obj EINA_UNUSED,
4617 const Eo_Event_Description *desc EINA_UNUSED,
4618 void *event_info EINA_UNUSED);
4620 EO_CALLBACKS_ARRAY_DEFINE(tracker_callbacks,
4621 { EVAS_OBJECT_EVENT_RESIZE, _track_obj_view_update },
4622 { EVAS_OBJECT_EVENT_MOVE, _track_obj_view_update },
4623 { EVAS_OBJECT_EVENT_SHOW, _track_obj_view_update },
4624 { EVAS_OBJECT_EVENT_HIDE, _track_obj_view_update },
4625 { EVAS_OBJECT_EVENT_DEL, _track_obj_view_del });
4628 _track_obj_view_del(void *data, Eo *obj EINA_UNUSED,
4629 const Eo_Event_Description *desc EINA_UNUSED,
4630 void *event_info EINA_UNUSED)
4632 Elm_Widget_Item_Data *item = data;
4634 while (evas_object_ref_get(item->track_obj) > 0)
4635 evas_object_unref(item->track_obj);
4637 evas_object_event_callback_del(item->track_obj, EVAS_CALLBACK_DEL,
4639 evas_object_del(item->track_obj);
4640 item->track_obj = NULL;
4642 return EO_CALLBACK_CONTINUE;
4646 _track_obj_del(void *data, Evas *e EINA_UNUSED,
4647 Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
4649 Elm_Widget_Item_Data *item = data;
4650 item->track_obj = NULL;
4652 if (!item->view) return;
4654 eo_do(item->view, eo_event_callback_array_del(tracker_callbacks(), item));
4658 _elm_widget_item_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission,
4661 Elm_Widget_Item_Signal_Data *wisd = data;
4662 wisd->func(wisd->data, wisd->item, emission, source);
4666 _elm_widget_item_signal_callback_list_get(Elm_Widget_Item_Data *item, Eina_List *position)
4668 Elm_Widget_Item_Signal_Data *wisd = eina_list_data_get(position);
4671 item->signals = eina_list_remove_list(item->signals, position);
4674 if (_elm_widget_is(item->view))
4675 elm_object_signal_callback_del(item->view,
4676 wisd->emission, wisd->source,
4677 _elm_widget_item_signal_cb);
4678 else if (eo_isa(item->view, EDJE_OBJECT_CLASS))
4679 edje_object_signal_callback_del_full(item->view,
4680 wisd->emission, wisd->source,
4681 _elm_widget_item_signal_cb, wisd);
4683 eina_stringshare_del(wisd->emission);
4684 eina_stringshare_del(wisd->source);
4690 #define ERR_NOT_SUPPORTED(item, method) ERR("%s does not support %s API.", elm_widget_type_get(item->widget), method);
4693 _eo_del_cb(void *data EINA_UNUSED, Eo *eo_item, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
4695 Elm_Widget_Item_Data *item = eo_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS);
4696 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_TRUE);
4698 item->del_func((void *) WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4705 * Allocate a new Elm_Widget_Item-derived structure.
4707 * The goal of this structure is to provide common ground for actions
4708 * that a widget item have, such as the owner widget, callback to
4709 * notify deletion, data pointer and maybe more.
4711 * @param widget the owner widget that holds this item, must be an elm_widget!
4712 * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
4713 * be used to allocate memory.
4715 * @return allocated memory that is already zeroed out, or NULL on errors.
4717 * @see elm_widget_item_new() convenience macro.
4718 * @see elm_widget_item_del() to release memory.
4722 _elm_widget_item_eo_base_constructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4724 Evas_Object *widget;
4725 eo_do (eo_item, widget = eo_parent_get());
4727 if (!_elm_widget_is(widget))
4733 eo_item = eo_do_super_ret(eo_item, ELM_WIDGET_ITEM_CLASS, eo_item, eo_constructor());
4735 EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
4737 item->widget = widget;
4738 item->eo_obj = eo_item;
4739 //TIZEN_ONLY(20170717) : expose highlight information on atspi
4740 item->can_highlight = EINA_TRUE;
4743 eo_do(eo_item, eo_event_callback_add(EO_BASE_EVENT_DEL, _eo_del_cb, NULL));
4749 _elm_widget_item_eo_base_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4751 Elm_Translate_String_Data *ts;
4753 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4755 evas_object_del(item->view);
4757 eina_stringshare_del(item->access_info);
4758 eina_stringshare_del(item->accessible_name);
4760 while (item->signals)
4761 _elm_widget_item_signal_callback_list_get(item, item->signals);
4763 while (item->translate_strings)
4765 ts = EINA_INLIST_CONTAINER_GET(item->translate_strings,
4766 Elm_Translate_String_Data);
4767 eina_stringshare_del(ts->id);
4768 eina_stringshare_del(ts->domain);
4769 eina_stringshare_del(ts->string);
4770 item->translate_strings = eina_inlist_remove(item->translate_strings,
4771 item->translate_strings);
4774 eina_hash_free(item->labels);
4777 elm_interface_atspi_accessible_description_set(NULL),
4778 elm_interface_atspi_accessible_name_set(NULL),
4779 //TIZEN_ONLY(20190922): add name callback, description callback.
4780 elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
4781 elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
4783 elm_interface_atspi_accessible_translation_domain_set(NULL),
4784 elm_interface_atspi_accessible_relationships_clear(),
4785 // TIZEN_ONLY(20160930) : endless recursion fix
4786 elm_interface_atspi_accessible_attributes_clear()
4791 eina_stringshare_del(item->name);
4793 if (item->atspi_custom_relations)
4794 elm_atspi_relation_set_free(&item->atspi_custom_relations);
4796 //TIZEN_ONLY(20150731) : add i18n support for name and description
4797 if (item->atspi_translation_domain)
4798 eina_stringshare_del(item->atspi_translation_domain);
4800 //Tizen Only(20160728) free attribute list
4801 if (item->attr_list)
4803 Elm_Atspi_Attribute *attr;
4804 EINA_LIST_FREE(item->attr_list, attr)
4806 eina_stringshare_del(attr->key);
4807 eina_stringshare_del(attr->value);
4813 //TIZEN_ONLY(20161013): clean up elm color class feature
4814 if (item->color_classes)
4815 ELM_SAFE_FREE(item->color_classes, eina_hash_free);
4818 EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
4820 eo_do_super(eo_item, ELM_WIDGET_ITEM_CLASS, eo_destructor());
4826 * Releases widget item memory, calling back item_del_pre_hook() and
4827 * item_del_cb() if they exist.
4829 * @param item a valid #Elm_Widget_Item to be deleted.
4831 * If there is an Elm_Widget_Item::del_cb, then it will be called prior
4832 * to memory release. Note that elm_widget_item_pre_notify_del() calls
4833 * this function and then unset it, thus being useful for 2 step
4834 * cleanup whenever the del_cb may use any of the data that must be
4835 * deleted from item.
4837 * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
4840 * Note that if item_del_pre_hook() returns @c EINA_TRUE, item free will be
4841 * deferred, or item will be freed here if it returns @c EINA_FALSE.
4843 * @see elm_widget_item_del() convenience macro.
4847 _elm_widget_item_del(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4849 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4850 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4851 item->on_deletion = EINA_TRUE;
4853 //Widget item delete callback
4855 eo_do(item->eo_obj, del_ok = elm_wdg_item_del_pre());
4857 eo_del(item->eo_obj);
4861 EOLIAN static Eina_Bool
4862 _elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4870 * Notify object will be deleted without actually deleting it.
4872 * This function will callback Elm_Widget_Item::del_cb if it is set
4873 * and then unset it so it is not called twice (ie: from
4874 * elm_widget_item_del()).
4876 * @param item a valid #Elm_Widget_Item to be notified
4877 * @see elm_widget_item_pre_notify_del() convenience macro.
4881 _elm_widget_item_pre_notify_del(Eo *eo_item, Elm_Widget_Item_Data *item)
4883 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4884 if (!item->del_func) return;
4885 item->del_func((void *)WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4886 item->del_func = NULL;
4892 * Set the function to notify when item is being deleted.
4894 * This function will complain if there was a callback set already,
4895 * however it will set the new one.
4897 * The callback will be called from elm_widget_item_pre_notify_del()
4898 * or elm_widget_item_del() will be called with:
4899 * - data: the Elm_Widget_Item::data value.
4900 * - obj: the Elm_Widget_Item::widget evas object.
4901 * - event_info: the item being deleted.
4903 * @param item a valid #Elm_Widget_Item to be notified
4904 * @see elm_widget_item_del_cb_set() convenience macro.
4908 _elm_widget_item_del_cb_set(Eo *eo_item EINA_UNUSED,
4909 Elm_Widget_Item_Data *item,
4912 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4913 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4915 if ((item->del_func) && (item->del_func != func))
4916 WRN("You're replacing a previously set del_cb %p of item %p with %p",
4917 item->del_func, item->eo_obj, func);
4919 item->del_func = func;
4925 * Get owner widget of this item.
4927 * @param item a valid #Elm_Widget_Item to get data from.
4928 * @return owner widget of this item.
4931 EOLIAN static Evas_Object *
4932 _elm_widget_item_widget_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4934 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4935 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4937 return item->widget;
4941 _elm_widget_onscreen_is(Evas_Object *widget)
4943 Evas_Object *parent = widget;
4944 Evas_Coord x, y, w, h, wx, wy, ww, wh;
4946 Evas *evas = evas_object_evas_get(widget);
4947 if (!evas) return EINA_FALSE;
4949 // check if on canvas
4950 evas_output_viewport_get(evas, &x, &y, &w, &h);
4951 evas_object_geometry_get(widget, &wx, &wy, &ww, &wh);
4952 if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4953 ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4956 // check if inside scrollable parent viewport
4958 parent = elm_widget_parent_get(parent);
4959 if (parent && !evas_object_visible_get(parent))
4961 if (parent && eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4963 evas_object_geometry_get(parent, &x, &y, &w, &h);
4964 if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4965 ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4968 } while (parent && (parent != elm_widget_top_get(widget)));
4974 _elm_widget_item_onscreen_is(Elm_Object_Item *item)
4976 Evas_Coord x, y, w, h, wx, wy, ww, wh;
4977 Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4978 if (!id || !id->view) return EINA_FALSE;
4980 if (!evas_object_visible_get(id->view))
4983 if (!_elm_widget_onscreen_is(id->widget))
4986 evas_object_geometry_get(id->view, &x, &y, &w, &h);
4987 evas_object_geometry_get(id->widget, &wx, &wy, &ww, &wh);
4988 if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4989 ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4995 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
4997 _elm_widget_item_highlightable(Elm_Object_Item *item)
4999 Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
5000 if (!id) return EINA_FALSE;
5001 if (!id->can_highlight) return EINA_FALSE;
5002 Evas_Object *widget = id->widget;
5003 Evas_Object *parent = widget;
5004 Elm_Widget_Smart_Data *wd;
5005 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
5007 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
5008 if (!wd->can_highlight) return EINA_FALSE;
5012 parent = elm_widget_parent_get(parent);
5013 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
5015 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
5016 if (!wd->can_highlight) return EINA_FALSE;
5019 while (parent && (parent != elm_widget_top_get(widget)));
5024 EOLIAN static Elm_Atspi_State_Set
5025 _elm_widget_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_item,
5026 Elm_Widget_Item_Data *item)
5028 Elm_Atspi_State_Set states = 0;
5030 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
5032 if (elm_object_item_focus_get(eo_item))
5033 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
5034 if (!elm_object_item_disabled_get(eo_item))
5036 STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
5037 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
5038 STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
5040 if (_elm_widget_item_onscreen_is(eo_item))
5041 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
5043 //TIZEN_ONLY(20170717) : expose highlight information on atspi
5044 if (_elm_widget_item_highlightable(eo_item))
5045 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
5047 STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
5049 if (_elm_object_accessibility_currently_highlighted_get() == (void*)item->eo_obj)
5050 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
5056 _elm_widget_item_elm_interface_atspi_accessible_parent_get(Eo *eo_item, Elm_Widget_Item_Data *item EINA_UNUSED)
5059 eo_do(eo_item, parent = eo_parent_get());
5064 elm_object_item_data_set(Elm_Object_Item *it, void *data)
5066 WIDGET_ITEM_DATA_SET(it, data);
5070 elm_object_item_data_get(const Elm_Object_Item *it)
5072 return (void *) WIDGET_ITEM_DATA_GET(it);
5076 _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED,
5077 Elm_Widget_Item_Data *item,
5080 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5081 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5083 if (item->disabled == disabled) return;
5084 item->disabled = !!disabled;
5085 eo_do(item->eo_obj, elm_wdg_item_disable());
5088 EOLIAN static Eina_Bool
5089 _elm_widget_item_disabled_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5091 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5092 return item->disabled;
5096 _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style EINA_UNUSED)
5098 ERR_NOT_SUPPORTED(item, "elm_object_style_set()");
5101 EOLIAN static const char *
5102 _elm_widget_item_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5104 ERR_NOT_SUPPORTED(item, "elm_object_style_get()");
5109 _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
5114 _elm_widget_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED)
5116 ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set");
5119 EOLIAN static Eina_Bool
5120 _elm_widget_item_focus_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5122 ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get");
5127 _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED,
5128 Elm_Widget_Item_Data *item,
5133 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5134 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5135 Elm_Translate_String_Data *ts;
5139 _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE,
5144 ts = _part_text_translatable_set(&item->translate_strings, part,
5145 EINA_TRUE, EINA_FALSE);
5147 if (!ts->string) ts->string = eina_stringshare_add(label);
5148 else eina_stringshare_replace(&ts->string, label);
5149 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5150 else eina_stringshare_replace(&ts->domain, domain);
5152 if (label[0]) label = dgettext(domain, label);
5155 item->on_translate = EINA_TRUE;
5156 eo_do(item->eo_obj, elm_wdg_item_part_text_set(part, label));
5157 item->on_translate = EINA_FALSE;
5160 EOLIAN static const char *
5161 _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED,
5162 Elm_Widget_Item_Data *item,
5165 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5166 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5168 Elm_Translate_String_Data *ts;
5169 ts = _translate_string_data_get(item->translate_strings, part);
5170 if (ts) return ts->string;
5175 _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED,
5176 Elm_Widget_Item_Data *item,
5179 Eina_Bool translatable)
5181 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5182 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5183 Elm_Translate_String_Data *ts;
5186 ts = _part_text_translatable_set(&item->translate_strings, part,
5187 translatable, EINA_TRUE);
5189 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5190 else eina_stringshare_replace(&ts->domain, domain);
5192 eo_do(item->eo_obj, text = elm_wdg_item_part_text_get(part));
5194 if (!text || !text[0]) return;
5196 if (!ts->string) ts->string = eina_stringshare_add(text);
5198 //Try to translate text since we don't know the text is already translated.
5200 text = dgettext(domain, text);
5202 item->on_translate = EINA_TRUE;
5203 eo_do (item->eo_obj, elm_wdg_item_part_text_set(part, text));
5204 item->on_translate = EINA_FALSE;
5208 _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5210 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5211 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5213 if (!item->track_obj) return;
5215 while (evas_object_ref_get(item->track_obj) > 0)
5216 evas_object_unref(item->track_obj);
5218 evas_object_del(item->track_obj);
5221 EOLIAN static Evas_Object *
5222 _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5224 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5225 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5227 if (item->track_obj)
5229 evas_object_ref(item->track_obj);
5230 return item->track_obj;
5235 WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item);
5239 Evas_Object *track =
5240 evas_object_rectangle_add(evas_object_evas_get(item->widget));
5241 evas_object_color_set(track, 0, 0, 0, 0);
5242 evas_object_pass_events_set(track, EINA_TRUE);
5243 _track_obj_update(track, item->view);
5244 evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del,
5248 eo_event_callback_array_add(tracker_callbacks(), item));
5250 evas_object_ref(track);
5252 item->track_obj = track;
5258 _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5260 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5261 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5263 if (!item->track_obj) return;
5264 evas_object_unref(item->track_obj);
5266 if (evas_object_ref_get(item->track_obj) == 0)
5267 evas_object_del(item->track_obj);
5271 _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5273 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0);
5274 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0);
5276 if (!item->track_obj) return 0;
5277 return evas_object_ref_get(item->track_obj);
5280 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
5282 struct _Elm_Widget_Item_Tooltip
5284 Elm_Widget_Item_Data *item;
5285 Elm_Tooltip_Item_Content_Cb func;
5286 Evas_Smart_Cb del_cb;
5290 static Evas_Object *
5291 _elm_widget_item_tooltip_label_create(void *data,
5292 Evas_Object *obj EINA_UNUSED,
5293 Evas_Object *tooltip,
5294 void *item EINA_UNUSED)
5296 Evas_Object *label = elm_label_add(tooltip);
5299 elm_object_style_set(label, "tooltip");
5300 elm_object_text_set(label, data);
5304 static Evas_Object *
5305 _elm_widget_item_tooltip_trans_label_create(void *data,
5306 Evas_Object *obj EINA_UNUSED,
5307 Evas_Object *tooltip,
5308 void *item EINA_UNUSED)
5310 Evas_Object *label = elm_label_add(tooltip);
5313 elm_object_style_set(label, "tooltip");
5314 elm_object_translatable_text_set(label, data);
5319 _elm_widget_item_tooltip_label_del_cb(void *data,
5320 Evas_Object *obj EINA_UNUSED,
5321 void *event_info EINA_UNUSED)
5323 eina_stringshare_del(data);
5329 * Set the text to be shown in the widget item.
5331 * @param item Target item
5332 * @param text The text to set in the content
5334 * Setup the text as tooltip to object. The item can have only one tooltip,
5335 * so any previous tooltip data is removed.
5340 _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED,
5341 Elm_Widget_Item_Data *item EINA_UNUSED,
5344 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5345 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5346 EINA_SAFETY_ON_NULL_RETURN(text);
5348 text = eina_stringshare_add(text);
5349 eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5350 _elm_widget_item_tooltip_label_create,
5352 _elm_widget_item_tooltip_label_del_cb));
5356 _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED,
5357 Elm_Widget_Item_Data *item EINA_UNUSED,
5360 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5361 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5362 EINA_SAFETY_ON_NULL_RETURN(text);
5364 text = eina_stringshare_add(text);
5365 eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5366 _elm_widget_item_tooltip_trans_label_create,
5368 _elm_widget_item_tooltip_label_del_cb));
5371 static Evas_Object *
5372 _elm_widget_item_tooltip_create(void *data,
5374 Evas_Object *tooltip)
5376 Elm_Widget_Item_Tooltip *wit = data;
5377 return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj);
5381 _elm_widget_item_tooltip_del_cb(void *data,
5383 void *event_info EINA_UNUSED)
5385 Elm_Widget_Item_Tooltip *wit = data;
5386 if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj);
5393 * Set the content to be shown in the tooltip item
5395 * Setup the tooltip to item. The item can have only one tooltip,
5396 * so any previous tooltip data is removed. @p func(with @p data) will
5397 * be called every time that need show the tooltip and it should
5398 * return a valid Evas_Object. This object is then managed fully by
5399 * tooltip system and is deleted when the tooltip is gone.
5401 * @param item the widget item being attached a tooltip.
5402 * @param func the function used to create the tooltip contents.
5403 * @param data what to provide to @a func as callback data/context.
5404 * @param del_cb called when data is not needed anymore, either when
5405 * another callback replaces @func, the tooltip is unset with
5406 * elm_widget_item_tooltip_unset() or the owner @a item
5407 * dies. This callback receives as the first parameter the
5408 * given @a data, and @c event_info is the item.
5413 _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED,
5414 Elm_Widget_Item_Data *item,
5415 Elm_Tooltip_Item_Content_Cb func,
5417 Evas_Smart_Cb del_cb)
5419 Elm_Widget_Item_Tooltip *wit;
5421 ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
5422 //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem);
5426 eo_do(item->eo_obj, elm_wdg_item_tooltip_unset());
5430 wit = ELM_NEW(Elm_Widget_Item_Tooltip);
5431 if (!wit) goto error;
5435 wit->del_cb = del_cb;
5437 elm_object_sub_tooltip_content_cb_set
5438 (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
5439 _elm_widget_item_tooltip_del_cb);
5444 if (del_cb) del_cb((void *)data, NULL, item);
5447 if (del_cb) del_cb((void *)data, item->widget, item);
5453 * Unset tooltip from item
5455 * @param item widget item to remove previously set tooltip.
5457 * Remove tooltip from item. The callback provided as del_cb to
5458 * elm_widget_item_tooltip_content_cb_set() will be called to notify
5459 * it is not used anymore.
5461 * @see elm_widget_item_tooltip_content_cb_set()
5466 _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5468 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5469 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5471 elm_object_tooltip_unset(item->view);
5477 * Sets a different style for this item tooltip.
5479 * @note before you set a style you should define a tooltip with
5480 * elm_widget_item_tooltip_content_cb_set() or
5481 * elm_widget_item_tooltip_text_set()
5483 * @param item widget item with tooltip already set.
5484 * @param style the theme style to use (default, transparent, ...)
5489 _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED,
5490 Elm_Widget_Item_Data *item,
5493 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5494 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5496 elm_object_tooltip_style_set(item->view, style);
5499 EOLIAN static Eina_Bool
5500 _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED,
5501 Elm_Widget_Item_Data *item,
5504 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5505 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5507 return elm_object_tooltip_window_mode_set(item->view, disable);
5510 EOLIAN static Eina_Bool
5511 _elm_widget_item_tooltip_window_mode_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5513 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5514 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5516 return elm_object_tooltip_window_mode_get(item->view);
5522 * Get the style for this item tooltip.
5524 * @param item widget item with tooltip already set.
5525 * @return style the theme style in use, defaults to "default". If the
5526 * object does not have a tooltip set, then NULL is returned.
5530 EOLIAN static const char *
5531 _elm_widget_item_tooltip_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5533 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5535 return elm_object_tooltip_style_get(item->view);
5539 _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED,
5540 Elm_Widget_Item_Data *item,
5543 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5544 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5546 elm_object_sub_cursor_set(item->view, item->widget, cursor);
5549 EOLIAN static const char *
5550 _elm_widget_item_cursor_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5552 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5553 return elm_object_cursor_get(item->view);
5557 _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5559 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5560 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5562 elm_object_cursor_unset(item->view);
5568 * Sets a different style for this item cursor.
5570 * @note before you set a style you should define a cursor with
5571 * elm_widget_item_cursor_set()
5573 * @param item widget item with cursor already set.
5574 * @param style the theme style to use (default, transparent, ...)
5579 _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED,
5580 Elm_Widget_Item_Data *item,
5583 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5584 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5586 elm_object_cursor_style_set(item->view, style);
5592 * Get the style for this item cursor.
5594 * @param item widget item with cursor already set.
5595 * @return style the theme style in use, defaults to "default". If the
5596 * object does not have a cursor set, then NULL is returned.
5600 EOLIAN static const char *
5601 _elm_widget_item_cursor_style_get(Eo *eo_item EINA_UNUSED,
5602 Elm_Widget_Item_Data *item)
5604 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5605 return elm_object_cursor_style_get(item->view);
5611 * Set if the cursor set should be searched on the theme or should use
5612 * the provided by the engine, only.
5614 * @note before you set if should look on theme you should define a cursor
5615 * with elm_object_cursor_set(). By default it will only look for cursors
5616 * provided by the engine.
5618 * @param item widget item with cursor already set.
5619 * @param engine_only boolean to define it cursors should be looked only
5620 * between the provided by the engine or searched on widget's theme as well.
5625 _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED,
5626 Elm_Widget_Item_Data *item,
5627 Eina_Bool engine_only)
5629 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5630 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5632 elm_object_cursor_theme_search_enabled_set(item->view, !engine_only);
5638 * Get the cursor engine only usage for this item cursor.
5640 * @param item widget item with cursor already set.
5641 * @return engine_only boolean to define it cursors should be looked only
5642 * between the provided by the engine or searched on widget's theme as well. If
5643 * the object does not have a cursor set, then EINA_FALSE is returned.
5647 EOLIAN static Eina_Bool
5648 _elm_widget_item_cursor_engine_only_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5650 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5651 return !elm_object_cursor_theme_search_enabled_get(item->view);
5655 _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED,
5656 Elm_Widget_Item_Data *item,
5657 const char *part EINA_UNUSED,
5658 Evas_Object *content EINA_UNUSED)
5660 ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()");
5663 EOLIAN static Evas_Object *
5664 _elm_widget_item_part_content_get(Eo *eo_item EINA_UNUSED,
5665 Elm_Widget_Item_Data *item,
5666 const char *part EINA_UNUSED)
5668 ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()");
5672 EOLIAN static Evas_Object *
5673 _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED,
5674 Elm_Widget_Item_Data *item,
5675 const char *part EINA_UNUSED)
5677 ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()");
5682 _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
5683 Elm_Widget_Item_Data *item,
5684 const char *part EINA_UNUSED,
5685 const char *label EINA_UNUSED)
5687 ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()");
5690 EOLIAN static const char *
5691 _elm_widget_item_part_text_get(Eo *eo_item EINA_UNUSED,
5692 Elm_Widget_Item_Data *item,
5693 const char *part EINA_UNUSED)
5695 ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()");
5700 _elm_widget_item_part_text_custom_free(void *data)
5702 Elm_Label_Data *label;
5704 eina_stringshare_del(label->part);
5705 eina_stringshare_del(label->text);
5710 _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED,
5711 Elm_Widget_Item_Data *item,
5715 Elm_Label_Data *label;
5716 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5717 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5721 eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free);
5722 label = eina_hash_find(item->labels, part);
5725 label = malloc(sizeof(Elm_Label_Data));
5728 ERR("Failed to allocate memory");
5731 label->part = eina_stringshare_add(part);
5732 label->text = eina_stringshare_add(text);
5733 eina_hash_add(item->labels, part, label);
5736 eina_stringshare_replace(&label->text, text);
5739 EOLIAN static const char *
5740 _elm_widget_item_part_text_custom_get(Eo *eo_item EINA_UNUSED,
5741 Elm_Widget_Item_Data *item,
5744 Elm_Label_Data *label;
5745 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5746 label = eina_hash_find(item->labels, part);
5747 return label ? label->text : NULL;
5751 _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED,
5752 const void *key EINA_UNUSED,
5756 Elm_Label_Data *label;
5757 Elm_Widget_Item_Data *item;
5761 eo_do(item->eo_obj, elm_wdg_item_part_text_set(label->part, label->text));
5767 _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5769 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5770 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5772 eina_hash_foreach(item->labels,
5773 _elm_widget_item_part_text_custom_foreach, item);
5777 _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
5778 Elm_Widget_Item_Data *item EINA_UNUSED,
5779 const char *emission EINA_UNUSED,
5780 const char *source EINA_UNUSED)
5786 _elm_widget_item_signal_callback_add(Eo *eo_item,
5787 Elm_Widget_Item_Data *item,
5788 const char *emission,
5790 Elm_Object_Item_Signal_Cb func,
5793 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5794 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5795 EINA_SAFETY_ON_NULL_RETURN(func);
5797 Elm_Widget_Item_Signal_Data *wisd;
5799 wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
5802 wisd->item = eo_item;
5803 wisd->func = (Elm_Widget_Item_Signal_Cb)func;
5805 wisd->emission = eina_stringshare_add(emission);
5806 wisd->source = eina_stringshare_add(source);
5808 if (_elm_widget_is(item->view))
5809 elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5810 else if (eo_isa(item->view, EDJE_OBJECT_CLASS))
5811 edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5814 WRN("The %s widget item doesn't support signal callback add!",
5815 eo_class_name_get(eo_class_get(item->widget)));
5820 item->signals = eina_list_append(item->signals, wisd);
5823 EOLIAN static void *
5824 _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED,
5825 Elm_Widget_Item_Data *item,
5826 const char *emission,
5828 Elm_Object_Item_Signal_Cb func)
5830 Elm_Widget_Item_Signal_Data *wisd;
5833 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5834 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5835 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
5837 EINA_LIST_FOREACH(item->signals, l, wisd)
5839 if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) &&
5840 !strcmp(wisd->emission, emission) &&
5841 !strcmp(wisd->source, source))
5842 return _elm_widget_item_signal_callback_list_get(item, l);
5849 _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED,
5850 Elm_Widget_Item_Data *item,
5853 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5854 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5856 eina_stringshare_del(item->access_info);
5857 if (!txt) item->access_info = NULL;
5858 else item->access_info = eina_stringshare_add(txt);
5862 _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5864 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5865 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5868 Elm_Translate_String_Data *ts;
5869 EINA_INLIST_FOREACH(item->translate_strings, ts)
5871 if (!ts->string) continue;
5872 const char *s = dgettext(ts->domain, ts->string);
5873 item->on_translate = EINA_TRUE;
5874 eo_do(item->eo_obj, elm_wdg_item_part_text_set(ts->id, s));
5875 item->on_translate = EINA_FALSE;
5881 _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED,
5882 Elm_Widget_Item_Data *item,
5885 _elm_access_widget_item_access_order_set(item, objs);
5888 EOLIAN static const Eina_List *
5889 _elm_widget_item_access_order_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5891 return _elm_access_widget_item_access_order_get(item);
5895 _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5897 _elm_access_widget_item_access_order_unset(item);
5900 EOLIAN static Evas_Object*
5901 _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5903 _elm_access_widget_item_register(item);
5904 return item->access_obj;
5908 _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5910 _elm_access_widget_item_unregister(item);
5913 EOLIAN static Evas_Object*
5914 _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5916 return item->access_obj;
5919 EOLIAN static Evas_Object *
5920 _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5922 Evas_Object *ret = NULL;
5924 if (dir == ELM_FOCUS_PREVIOUS)
5925 ret = item->focus_previous;
5926 else if (dir == ELM_FOCUS_NEXT)
5927 ret = item->focus_next;
5928 else if (dir == ELM_FOCUS_UP)
5929 ret = item->focus_up;
5930 else if (dir == ELM_FOCUS_DOWN)
5931 ret = item->focus_down;
5932 else if (dir == ELM_FOCUS_RIGHT)
5933 ret = item->focus_right;
5934 else if (dir == ELM_FOCUS_LEFT)
5935 ret = item->focus_left;
5941 _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir)
5943 if (dir == ELM_FOCUS_PREVIOUS)
5944 item->focus_previous = next;
5945 else if (dir == ELM_FOCUS_NEXT)
5946 item->focus_next = next;
5947 else if (dir == ELM_FOCUS_UP)
5948 item->focus_up = next;
5949 else if (dir == ELM_FOCUS_DOWN)
5950 item->focus_down = next;
5951 else if (dir == ELM_FOCUS_RIGHT)
5952 item->focus_right = next;
5953 else if (dir == ELM_FOCUS_LEFT)
5954 item->focus_left = next;
5957 EOLIAN static Elm_Object_Item*
5958 _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5960 Elm_Object_Item *ret = NULL;
5962 if (dir == ELM_FOCUS_PREVIOUS)
5963 ret = item->item_focus_previous;
5964 else if (dir == ELM_FOCUS_NEXT)
5965 ret = item->item_focus_next;
5966 else if (dir == ELM_FOCUS_UP)
5967 ret = item->item_focus_up;
5968 else if (dir == ELM_FOCUS_DOWN)
5969 ret = item->item_focus_down;
5970 else if (dir == ELM_FOCUS_RIGHT)
5971 ret = item->item_focus_right;
5972 else if (dir == ELM_FOCUS_LEFT)
5973 ret = item->item_focus_left;
5979 _elm_widget_item_focus_next_item_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Object_Item *next_item, Elm_Focus_Direction dir)
5981 if (dir == ELM_FOCUS_PREVIOUS)
5982 item->item_focus_previous = next_item;
5983 else if (dir == ELM_FOCUS_NEXT)
5984 item->item_focus_next = next_item;
5985 else if (dir == ELM_FOCUS_UP)
5986 item->item_focus_up = next_item;
5987 else if (dir == ELM_FOCUS_DOWN)
5988 item->item_focus_down = next_item;
5989 else if (dir == ELM_FOCUS_RIGHT)
5990 item->item_focus_right = next_item;
5991 else if (dir == ELM_FOCUS_LEFT)
5992 item->item_focus_left = next_item;
5995 /* happy debug functions */
5998 _sub_obj_tree_dump(const Evas_Object *obj,
6003 for (i = 0; i < lvl * 3; i++)
6006 if (_elm_widget_is(obj))
6011 elm_widget_type_get(obj),
6013 EINA_LIST_FOREACH(sd->subobjs, l, obj)
6014 _sub_obj_tree_dump(obj, lvl + 1);
6017 DBG("+ %s(%p)\n", evas_object_type_get(obj), obj);
6021 _sub_obj_tree_dot_dump(const Evas_Object *obj,
6024 if (!_elm_widget_is(obj))
6028 Eina_Bool visible = evas_object_visible_get(obj);
6029 Eina_Bool disabled = elm_widget_disabled_get(obj);
6030 Eina_Bool focused = elm_widget_focus_get(obj);
6031 Eina_Bool can_focus = elm_widget_can_focus_get(obj);
6035 fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
6038 fprintf(output, ", style=bold");
6041 fprintf(output, ", color=gray28");
6043 fprintf(output, " ];\n");
6046 fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
6047 "disabled: %d|focused: %d/%d|focus order:%d}\"",
6048 obj, obj, elm_widget_type_get(obj),
6049 evas_object_name_get(obj), visible, disabled, focused, can_focus,
6053 fprintf(output, ", style=bold");
6056 fprintf(output, ", fontcolor=gray28");
6058 if ((disabled) || (!visible))
6059 fprintf(output, ", color=gray");
6061 fprintf(output, " ];\n");
6065 EINA_LIST_FOREACH(sd->subobjs, l, o)
6066 _sub_obj_tree_dot_dump(o, output);
6072 elm_widget_tree_dump(const Evas_Object *top)
6075 if (!_elm_widget_is(top))
6077 _sub_obj_tree_dump(top, 0);
6085 elm_widget_tree_dot_dump(const Evas_Object *top,
6089 if (!_elm_widget_is(top))
6091 fprintf(output, "graph " " { node [shape=record];\n");
6092 _sub_obj_tree_dot_dump(top, output);
6093 fprintf(output, "}\n");
6102 _elm_widget_eo_base_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
6106 sd->on_create = EINA_TRUE;
6107 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
6109 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
6110 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
6111 parent = eo_parent_get());
6112 eo_do(obj, elm_obj_widget_parent_set(parent));
6113 sd->on_create = EINA_FALSE;
6114 //TIZEN_ONLY(20170717) : expose highlight information on atspi
6115 sd->can_highlight = EINA_TRUE;
6117 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
6118 sd->inherit_paragraph_direction = EINA_TRUE;
6121 eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_UNKNOWN));
6123 /* TIZEN_ONLY(20161117): Inherit paragraph direction from widget parent */
6124 if (sd->paragraph_direction != evas_object_paragraph_direction_get(parent))
6126 sd->paragraph_direction = evas_object_paragraph_direction_get(parent);
6127 _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, sd->paragraph_direction);
6128 eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(sd->paragraph_direction));
6136 _elm_widget_eo_base_destructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
6138 sd->on_destroy = EINA_TRUE;
6140 elm_interface_atspi_accessible_description_set(NULL),
6141 elm_interface_atspi_accessible_name_set(NULL),
6142 //TIZEN_ONLY(20190922): add name callback, description callback.
6143 elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
6144 elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
6146 elm_interface_atspi_accessible_translation_domain_set(NULL),
6147 elm_interface_atspi_accessible_relationships_clear(),
6148 // TIZEN_ONLY(20160930) : endless recursion fix
6149 elm_interface_atspi_accessible_attributes_clear()
6152 // TIZEN_ONLY(20150709) : atspi relations api
6153 if (sd->atspi_custom_relations)
6154 elm_atspi_relation_set_free(&sd->atspi_custom_relations);
6156 //TIZEN_ONLY(20150717) add widget name setter
6158 eina_stringshare_del(sd->name);
6161 //TIZEN_ONLY(20150731) : add i18n support for name and description
6162 if (sd->atspi_translation_domain)
6163 eina_stringshare_del(sd->atspi_translation_domain);
6165 //Tizen Only(20160728) free attribute list
6168 Elm_Atspi_Attribute *attr;
6169 EINA_LIST_FREE(sd->attr_list, attr)
6171 eina_stringshare_del(attr->key);
6172 eina_stringshare_del(attr->value);
6178 eo_do_super(obj, ELM_WIDGET_CLASS, eo_destructor());
6179 sd->on_destroy = EINA_FALSE;
6181 elm_interface_atspi_accessible_removed(obj);
6184 EOLIAN static Eina_Bool
6185 _elm_widget_on_focus(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item EINA_UNUSED)
6187 if (elm_widget_can_focus_get(obj))
6189 if (elm_widget_focus_get(obj))
6191 if (!sd->resize_obj)
6192 evas_object_focus_set(obj, EINA_TRUE);
6193 eo_do(obj, eo_event_callback_call
6194 (ELM_WIDGET_EVENT_FOCUSED, NULL));
6195 if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6196 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_TRUE);
6200 if (!sd->resize_obj)
6201 evas_object_focus_set(obj, EINA_FALSE);
6202 eo_do(obj, eo_event_callback_call
6203 (ELM_WIDGET_EVENT_UNFOCUSED, NULL));
6204 if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6205 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_FALSE);
6214 EOLIAN static Eina_Bool
6215 _elm_widget_disable(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6220 EOLIAN static Eina_Bool
6221 _elm_widget_event(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *source EINA_UNUSED, Evas_Callback_Type type EINA_UNUSED, void *event_info EINA_UNUSED)
6226 EOLIAN static Eina_Bool
6227 _elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6229 WRN("The %s widget does not implement the \"focus_next/focus_next_manager_is\" functions.",
6230 eo_class_name_get(eo_class_get(obj)));
6235 _elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6237 WRN("The %s widget does not implement the \"focus_direction/focus_direction_manager_is\" functions.",
6238 eo_class_name_get(eo_class_get(obj)));
6242 EOLIAN static Eina_Bool
6243 _elm_widget_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Activate act EINA_UNUSED)
6245 WRN("The %s widget does not implement the \"activate\" functions.",
6246 eo_class_name_get(eo_class_get(obj)));
6251 _elm_widget_class_constructor(Eo_Class *klass)
6253 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
6256 EOLIAN static Eina_Bool
6257 _elm_widget_elm_interface_atspi_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6259 if (elm_object_focus_allow_get(obj))
6261 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
6262 if (!ee) return EINA_FALSE;
6263 ecore_evas_activate(ee);
6264 elm_object_focus_set(obj, EINA_TRUE);
6270 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
6271 EOLIAN static Eina_Bool
6272 _elm_widget_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6274 if(!_elm_atspi_enabled())
6277 elm_widget_focus_region_show(obj);
6279 elm_object_accessibility_highlight_set(obj, EINA_TRUE);
6280 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
6282 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6283 evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_HIGHLIGHTED, NULL);
6288 EOLIAN static Eina_Bool
6289 _elm_widget_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6291 if(!_elm_atspi_enabled())
6293 elm_object_accessibility_highlight_set(obj, EINA_FALSE);
6294 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
6296 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6297 evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, NULL);
6303 EOLIAN static const char*
6304 _elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
6306 char *accessible_name;
6307 //TIZEN_ONLY(20190922): add name callback, description callback.
6308 const char *ret = NULL;
6309 eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_name_get());
6310 if (ret) return ret;
6313 //TIZEN_ONLY(20150717) add widget name setter
6317 if (_pd->atspi_translation_domain)
6318 return dgettext(_pd->atspi_translation_domain, _pd->name);
6324 //TIZEN_ONLY(20170110) : Ignore text from elm_object_text_set in accessible_name_get
6325 Elm_Atspi_Role role;
6326 eo_do(obj, role = elm_interface_atspi_accessible_role_get());
6327 if(role == ELM_ATSPI_ROLE_DIALOG)
6331 ret = elm_object_text_get(obj);
6332 if (!ret) return NULL;
6334 accessible_name = _elm_util_mkup_to_text(ret);
6335 eina_stringshare_del(_pd->accessible_name);
6336 _pd->accessible_name = eina_stringshare_add(accessible_name);
6337 free(accessible_name);
6338 return _pd->accessible_name;
6340 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
6342 _elm_widget_elm_interface_atspi_accessible_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *description)
6344 if (_pd->description)
6345 eina_stringshare_del(_pd->description);
6347 _pd->description = eina_stringshare_add(description);
6350 EOLIAN static const char*
6351 _elm_widget_elm_interface_atspi_accessible_description_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6353 const char *ret = NULL;
6354 eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_description_get());
6355 if (ret) return ret;
6358 if (_pd->atspi_translation_domain)
6359 return dgettext(_pd->atspi_translation_domain, _pd->description);
6361 return _pd->description;
6365 //TIZEN_ONLY(20150713) : add atspi name setter to widget_item
6367 _elm_widget_item_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *name)
6370 eina_stringshare_del(_pd->name);
6372 _pd->name = eina_stringshare_add(name);
6376 _elm_widget_item_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6378 //TIZEN_ONLY(20190922): add name callback, description callback.
6379 const char *ret = NULL;
6380 eo_do_super(obj, ELM_WIDGET_ITEM_CLASS, ret = elm_interface_atspi_accessible_name_get());
6381 if (ret) return ret;
6387 if (_pd->atspi_translation_domain)
6388 return dgettext(_pd->atspi_translation_domain, _pd->name);
6396 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
6398 _elm_widget_item_elm_interface_atspi_accessible_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *description)
6400 if (_pd->description)
6401 eina_stringshare_del(_pd->description);
6403 _pd->description = eina_stringshare_add(description);
6407 _elm_widget_item_elm_interface_atspi_accessible_description_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6409 const char *ret = NULL;
6410 eo_do_super(obj, ELM_WIDGET_ITEM_CLASS, ret = elm_interface_atspi_accessible_description_get());
6411 if (ret) return ret;
6414 if (_pd->atspi_translation_domain)
6415 return dgettext(_pd->atspi_translation_domain, _pd->description);
6417 return _pd->description;
6420 //TIZEN_ONLY(20150709) : spatially sort atspi children
6421 static int _sort_vertically(const void *data1, const void *data2)
6424 evas_object_geometry_get(data1, NULL, &y1, NULL, NULL);
6425 evas_object_geometry_get(data2, NULL, &y2, NULL, NULL);
6427 return y1 < y2 ? -1 : 1;
6430 static int _sort_horizontally(const void *data1, const void *data2)
6433 evas_object_geometry_get(data1, &x1, NULL, NULL, NULL);
6434 evas_object_geometry_get(data2, &x2, NULL, NULL, NULL);
6436 return x1 < x2 ? -1 : 1;
6439 static Eina_List *_lines_split(Eina_List *children)
6442 Eina_List *lines, *line, *l;
6443 Evas_Coord yl, y, hl, h;
6444 lines = line = NULL;
6446 if (!children) return NULL;
6448 EINA_LIST_FOREACH(children, l, c)
6450 evas_object_geometry_get(c, NULL, &yl, NULL, &hl);
6452 /* remove child if its height == 0 */
6456 EINA_LIST_FREE(children, c)
6458 evas_object_geometry_get(c, NULL, &y, NULL, &h);
6460 /* remove child if its height == 0 */
6461 if (h == 0) continue;
6463 if ((yl + (int)(0.25 * hl)) >= y)
6466 line = eina_list_append(line,c);
6470 // finish current line & start new
6471 lines = eina_list_append(lines, line);
6473 line = eina_list_append(NULL, c);
6477 return eina_list_append(lines, line);
6481 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6483 _proxy_widget_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6488 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
6489 elm_atspi_bridge_utils_proxy_offset_set(proxy, x, y);
6494 _on_widget_del(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6497 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6498 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
6499 _proxy_widget_move_cb, plug);
6505 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6507 _on_proxy_connected_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6510 Evas_Object *widget = data;
6512 evas_object_geometry_get(widget, &x, &y, NULL, NULL);
6513 elm_atspi_bridge_utils_proxy_offset_set(obj, x, y);
6515 evas_object_event_callback_add(widget, EVAS_CALLBACK_MOVE, _proxy_widget_move_cb, obj);
6521 EOLIAN static Eina_List*
6522 _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6524 Eina_List *l, *accs = NULL;
6525 Elm_Widget_Smart_Data *wd;
6526 Evas_Object *widget;
6527 // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6531 wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6532 if (!wd) return NULL;
6534 EINA_LIST_FOREACH(wd->subobjs, l, widget)
6536 const char *type = evas_object_type_get(widget);
6538 // Ugly Tizen hack to integrate AT-SPI2 accessibility provided by WebKit/Chromium with elementary one.
6539 // This wrapper class should be implemented in Webkit/Chromium EFL ports
6540 if (type && (!strcmp(type, "EWebView") || !strcmp(type, "WebView"))) {
6541 elm_atspi_ewk_wrapper_a11y_init(obj, widget);
6545 EINA_LIST_FOREACH(wd->subobjs, l, widget)
6547 // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6548 if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) {
6549 eo_do(widget, parent = elm_interface_atspi_accessible_parent_get());
6550 if (parent && (parent != obj)) continue;
6553 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6554 const char *plug_id_2;
6555 if ((plug_id_2 = evas_object_data_get(widget, "___PLUGID")) != NULL)
6557 // TIZEN_ONLY(20160930) : endless recursion fix
6558 eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id_2));
6561 char *svcname, *svcnum;
6563 proxy = evas_object_data_get(widget, "__widget_proxy");
6566 accs = eina_list_append(accs, proxy);
6570 if (_elm_atspi_bridge_plug_id_split(plug_id_2, &svcname, &svcnum))
6572 proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
6573 evas_object_data_set(widget, "__widget_proxy", proxy);
6574 eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
6575 eo_do(proxy, eo_event_callback_add(ELM_ATSPI_PROXY_EVENT_CONNECTED, _on_proxy_connected_cb, widget));
6576 elm_atspi_bridge_utils_proxy_connect(proxy);
6577 accs = eina_list_append(accs, proxy);
6585 if (!elm_object_widget_check(widget)) continue;
6586 if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6587 accs = eina_list_append(accs, widget);
6589 //TIZEN_ONLY(20150709) : spatially sort atspi children
6590 // sort children using its top-left coordinate
6591 accs = eina_list_sort(accs, -1, _sort_vertically);
6592 Eina_List *line, *lines = _lines_split(accs);
6594 EINA_LIST_FREE(lines, line)
6595 accs = eina_list_merge(accs, eina_list_sort(line, -1, _sort_horizontally));
6601 _elm_widget_elm_interface_atspi_accessible_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
6604 eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_parent_get());
6606 return ret ? ret : pd->parent_obj;
6609 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
6611 _elm_widget_highlightable(Evas_Object *obj)
6613 Elm_Widget_Smart_Data *wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6614 if (!wd) return EINA_FALSE;
6615 if (!wd->can_highlight) return EINA_FALSE;
6616 Evas_Object *parent = elm_widget_parent_get(obj);
6617 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6619 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
6620 if (!wd->can_highlight) return EINA_FALSE;
6624 parent = elm_widget_parent_get(parent);
6625 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6627 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
6628 if (!wd->can_highlight) return EINA_FALSE;
6631 while (parent && (parent != elm_widget_top_get(obj)));
6636 EOLIAN static Elm_Atspi_State_Set
6637 _elm_widget_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Widget_Smart_Data *pd)
6639 Elm_Atspi_State_Set states = 0;
6641 eo_do_super(obj, ELM_WIDGET_CLASS, states = elm_interface_atspi_accessible_state_set_get());
6643 if (evas_object_visible_get(obj))
6645 STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
6646 if (_elm_widget_onscreen_is(obj))
6647 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
6649 if (!elm_widget_child_can_focus_get(obj))
6651 if (elm_object_focus_allow_get(obj))
6652 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
6653 if (elm_object_focus_get(obj))
6654 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
6656 if (!elm_object_disabled_get(obj))
6658 STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
6659 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
6662 //TIZEN_ONLY(20170717) : expose highlight information on atspi
6663 if (_elm_widget_highlightable(obj))
6664 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6666 STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6668 if (_elm_object_accessibility_currently_highlighted_get() == (void*)pd->obj)
6669 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
6675 //TIZEN_ONLY(20160729): attributes_get, append APIs added/updated.
6676 EOLIAN static Eina_List*
6677 _elm_widget_elm_interface_atspi_accessible_attributes_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6679 Eina_List *attr_list = NULL;
6680 // TIZEN_ONLY(20160930) : endless recursion fix
6681 eo_do_super(obj, MY_CLASS, attr_list = elm_interface_atspi_accessible_attributes_get());
6683 //Add type and style information in addition.
6684 Elm_Atspi_Attribute *attr = NULL;
6685 attr = calloc(1, sizeof(Elm_Atspi_Attribute));
6688 attr->key = eina_stringshare_add("type");
6689 attr->value = eina_stringshare_add(elm_widget_type_get(obj));
6690 attr_list = eina_list_append(attr_list, attr);
6693 attr = calloc(1, sizeof(Elm_Atspi_Attribute));
6696 attr->key = eina_stringshare_add("style");
6697 attr->value = eina_stringshare_add(elm_widget_style_get(obj));
6698 attr_list = eina_list_append(attr_list, attr);
6704 //TIZEN_ONLY(20150709) : atspi relations api
6705 EOLIAN static Elm_Atspi_Relation_Set
6706 _elm_widget_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
6708 return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
6711 EOLIAN static Elm_Atspi_Relation_Set
6712 _elm_widget_item_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
6714 return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
6719 _elm_widget_item_elm_interface_atspi_component_extents_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords, int *x, int *y, int *w, int *h)
6732 evas_object_geometry_get(sd->view, x, y, w, h);
6735 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->view));
6737 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
6743 EOLIAN static Eina_Bool
6744 _elm_widget_item_elm_interface_atspi_component_extents_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED, Eina_Bool screen_coords EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
6750 _elm_widget_item_elm_interface_atspi_component_layer_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
6754 return evas_object_layer_get(sd->view);
6757 EOLIAN static Eina_Bool
6758 _elm_widget_item_elm_interface_atspi_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6760 elm_object_item_focus_set(obj, EINA_TRUE);
6761 return elm_object_item_focus_get(obj);
6764 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods
6765 EOLIAN static Eina_Bool
6766 _elm_widget_item_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
6769 if (!obj) return EINA_FALSE;
6771 Evas_Object *o = elm_object_parent_widget_get(sd->view);
6772 if (_elm_scrollable_is(o))
6774 Evas_Coord bx, by, bw, bh;
6775 Evas_Coord x, y, w, h;
6776 Evas_Object *w1 = elm_object_parent_widget_get(o);
6777 evas_object_geometry_get(sd->view, &x, &y, &w, &h);
6778 evas_object_geometry_get(o, &bx, &by, &bw, &bh);
6781 switch (_elm_config->focus_autoscroll_mode)
6783 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
6784 eo_do(w1, elm_interface_scrollable_content_region_show(x, y, w, h));
6786 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
6787 eo_do(w1, elm_interface_scrollable_region_bring_in(x, y, w, h));
6794 elm_object_accessibility_highlight_set(sd->eo_obj, EINA_TRUE);
6795 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
6801 EOLIAN static Eina_Bool
6802 _elm_widget_item_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
6804 if (!obj) return EINA_FALSE;
6805 elm_object_accessibility_highlight_set(sd->eo_obj, EINA_FALSE);
6806 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
6811 EOLIAN static double
6812 _elm_widget_item_elm_interface_atspi_component_alpha_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
6816 if (!sd->view) return -1.0;
6817 evas_object_color_get(sd->view, NULL, NULL, NULL, &alpha);
6818 return (double)alpha / 255.0;
6821 //TIZEN_ONLY(20150717) add widget name setter
6823 _elm_widget_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *name)
6826 eina_stringshare_del(_pd->name);
6828 _pd->name = eina_stringshare_add(name);
6832 //TIZEN_ONLY(20160329): widget: improve accessibile_at_point getter (a8aff0423202b9a55dbb3843205875226678fbd6)
6834 _coordinate_system_based_point_translate(Eo *obj, Eina_Bool screen_coords, int *x, int *y)
6842 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
6845 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
6851 static Evas_Object *
6852 _parent_get(Evas_Object *obj)
6854 Evas_Object *parent;
6856 parent = evas_object_smart_parent_get(obj);
6859 if (strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))))
6860 parent = elm_widget_parent_get(obj);
6867 _is_inside(Evas_Object *obj, int x, int y)
6869 Eina_Bool ret = EINA_TRUE;
6874 if (eo_isa(obj, ELM_WIDGET_ITEM_CLASS))
6876 Elm_Widget_Item_Data *id = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
6877 evas_object_geometry_get(id->view, &cx, &cy, &cw, &ch);
6880 evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
6882 /* check the point is out of bound */
6883 if (x < cx || x > cx + cw || y < cy || y > cy + ch)
6891 _is_ancestor_of(Evas_Object *smart_parent, Evas_Object *obj)
6893 Eina_Bool ret = EINA_FALSE;
6894 Evas_Object *parent = elm_widget_parent_get(obj);
6897 /* No need to check more, the smart_parent is parent of obj */
6898 if (smart_parent == parent)
6903 parent = elm_widget_parent_get(parent);
6910 _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
6912 Eina_List *l, *l2, *children, *valid_children = NULL;
6914 Evas_Object *stack_item;
6916 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6918 Evas_Coord px, py, pw, ph;
6921 _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
6923 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
6925 EINA_LIST_FOREACH(children, l2, child)
6927 if (_is_inside(child, x, y))
6928 valid_children = eina_list_append(valid_children, child);
6930 /* Get evas_object stacked at given x,y coordinates starting from top */
6931 Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
6932 /* Foreach stacked object starting from top */
6933 EINA_LIST_FOREACH(stack, l, stack_item)
6935 /* Foreach at-spi valid children traverse stack_item evas_objects hierarchy */
6936 EINA_LIST_FOREACH(valid_children, l2, child)
6938 Elm_Atspi_Role role;
6939 eo_do(child, role = elm_interface_atspi_accessible_role_get());
6940 if (role == ELM_ATSPI_ROLE_REDUNDANT_OBJECT)
6942 /* The redundant object ignores */
6945 /* Compare object used to compare with stacked evas objects */
6946 compare_obj = child;
6947 /* In case of widget_items compare should be different then elm_widget_ item object */
6948 if (eo_isa(child, ELM_WIDGET_ITEM_CLASS))
6950 Elm_Widget_Item_Data *id = eo_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
6951 compare_obj = id->view;
6953 /* In case of access object compare should be 'wrapped' evas_object */
6954 if (eo_isa(child, ELM_ACCESS_CLASS))
6956 Elm_Access_Info *info = _elm_access_info_get(child);
6957 if (!info) continue;
6958 compare_obj = info->part_object;
6960 /* In case of widget is registerd by elm_access_object_register */
6961 Evas_Object *ao = elm_access_object_get(child);
6964 eina_list_free(children);
6965 eina_list_free(stack);
6969 /* In case of ewk wrapper object compare with internal ewk_view evas_object */
6970 if (eo_isa(child, ELM_ATSPI_EWK_WRAPPER_CLASS))
6972 compare_obj = elm_atspi_ewk_wrapper_ewk_view_get(child);
6975 /* If spacial eo children do not have backing evas_object continue with search */
6979 Evas_Object *smart_parent = stack_item;
6980 while (smart_parent)
6982 if (smart_parent == compare_obj)
6984 eina_list_free(children);
6985 eina_list_free(stack);
6989 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6990 proxy = evas_object_data_get(smart_parent, "__widget_proxy");
6993 evas_object_geometry_get(smart_parent, &px, &py, &pw, &ph);
6994 if (x >= px && x <= px + pw && y >= py && y <= py +ph)
6996 eina_list_free(children);
6997 eina_list_free(stack);
7003 smart_parent = _parent_get(smart_parent);
7004 if (_is_ancestor_of(smart_parent, obj)) break;
7009 eina_list_free(children);
7010 eina_list_free(stack);
7014 static int _sort_by_repeat_events(const void *data1, const void *data2)
7016 Eina_Bool repeat1, repeat2;
7018 repeat1 = evas_object_repeat_events_get(data1);
7019 repeat2 = evas_object_repeat_events_get(data2);
7021 if (repeat1 != repeat2 && repeat1 == EINA_TRUE) return 1;
7025 static Eo *_item_at_point_get(Evas_Object *obj, int x, int y)
7028 Eina_List *l, *children;
7030 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7032 EINA_LIST_FOREACH(children, l, child)
7034 if (_is_inside(child, x, y)) return child;
7037 ERR("No child at point (%d, %d) on object %p", x, y, obj);
7042 _elm_widget_elm_interface_atspi_component_accessible_at_point_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
7045 Evas_Object *stack_item;
7047 if(strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))))
7048 return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
7050 _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
7052 Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
7053 stack = eina_list_sort(stack, -1, _sort_by_repeat_events);
7055 EINA_LIST_FOREACH(stack, l, stack_item)
7057 Evas_Object *smart_parent = stack_item;
7058 while (smart_parent)
7060 Evas_Object *ao = elm_access_object_get(smart_parent);
7063 if (eo_isa(smart_parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
7065 Eina_Bool acceptable = EINA_FALSE;
7067 Elm_Atspi_Role role;
7068 eo_do(smart_parent, role = elm_interface_atspi_accessible_role_get());
7071 case ELM_ATSPI_ROLE_FILLER: /* ex: View of colorselector item is layout */
7072 case ELM_ATSPI_ROLE_ICON:
7073 case ELM_ATSPI_ROLE_IMAGE:
7074 case ELM_ATSPI_ROLE_REDUNDANT_OBJECT:
7075 case ELM_ATSPI_ROLE_WINDOW:
7076 DBG("Go for parent: %s (%p)\n", evas_object_type_get(smart_parent), smart_parent);
7079 case ELM_ATSPI_ROLE_LIST:
7080 return _item_at_point_get(smart_parent, x, y);
7084 acceptable = EINA_TRUE;
7088 if (acceptable) return smart_parent;
7091 smart_parent = _parent_get(smart_parent);
7094 return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
7098 //TIZEN_ONLY(20150709) add relations atpi
7099 EOLIAN static Eina_Bool
7100 _elm_widget_elm_interface_atspi_accessible_relationship_append(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
7102 return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7106 _elm_widget_elm_interface_atspi_accessible_relationship_remove(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
7108 elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7111 EOLIAN static Eina_Bool
7112 _elm_widget_item_elm_interface_atspi_accessible_relationship_append(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
7114 return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7118 _elm_widget_item_elm_interface_atspi_accessible_relationship_remove(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, Elm_Atspi_Relation_Type type, const Eo *relation_obj)
7120 elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7124 //TIZEN_ONLY(20150731) : add i18n support for name and description
7126 _elm_widget_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, const char *domain)
7128 eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7131 EOLIAN static const char*
7132 _elm_widget_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
7134 return _pd->atspi_translation_domain;
7138 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, const char *domain)
7140 eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7143 EOLIAN static const char*
7144 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd)
7146 return _pd->atspi_translation_domain;
7149 //TIZEN_ONLY(20160726): add API elm_atspi_accessible_can_highlight_set/get
7151 _children_highlight_check(Eo *obj)
7153 Eina_List *children, *l;
7156 if (_elm_object_accessibility_currently_highlighted_get() == (void *)obj)
7158 eo_do(obj, elm_interface_atspi_component_highlight_clear());
7162 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7163 EINA_LIST_FOREACH(children, l, child)
7165 if (_children_highlight_check(child)) return EINA_TRUE;
7172 _elm_widget_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Eina_Bool can_highlight)
7174 if (!can_highlight) _children_highlight_check(obj);
7175 _pd->can_highlight = !!can_highlight;
7178 EOLIAN static Eina_Bool
7179 _elm_widget_elm_interface_atspi_accessible_can_highlight_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7181 return _elm_widget_highlightable(obj);
7185 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, Eina_Bool can_highlight)
7187 if (!can_highlight) _children_highlight_check(obj);
7188 _pd->can_highlight = !!can_highlight;
7191 EOLIAN static Eina_Bool
7192 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_get(Eo *obj, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7194 return _elm_widget_item_highlightable(obj);
7198 //TIZEN_ONLY(20160622): Override Paragraph Direction APIs
7200 _elm_widget_evas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
7205 if (sd->on_destroy) return;
7207 EINA_LIST_FOREACH(sd->subobjs, l, child)
7209 if (_elm_widget_is(child))
7211 Elm_Widget_Smart_Data *sdc = eo_data_scope_get(child, MY_CLASS);
7213 if (sdc->inherit_paragraph_direction &&
7214 (sdc->paragraph_direction != dir))
7216 sdc->paragraph_direction = dir;
7217 _elm_widget_evas_object_paragraph_direction_set_internal(child, sdc, dir);
7218 eo_do_super(child, MY_CLASS, evas_obj_paragraph_direction_set(dir));
7222 /* FIXME: There is no way to handle non-widget child object.
7223 * If a non-widget child object has smart parent, it will get the direction
7224 * from the smart parent. */
7229 _elm_widget_evas_object_paragraph_direction_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
7231 if ((!(sd->inherit_paragraph_direction) && (sd->paragraph_direction == dir)) ||
7232 (sd->inherit_paragraph_direction && (dir == EVAS_BIDI_DIRECTION_INHERIT)))
7235 if (dir == EVAS_BIDI_DIRECTION_INHERIT)
7237 sd->inherit_paragraph_direction = EINA_TRUE;
7238 Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
7241 parent_dir = evas_object_paragraph_direction_get(sd->parent_obj);
7243 if (parent_dir != sd->paragraph_direction)
7245 sd->paragraph_direction = parent_dir;
7246 _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, parent_dir);
7251 sd->inherit_paragraph_direction = EINA_FALSE;
7252 sd->paragraph_direction = dir;
7253 _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, dir);
7256 eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(dir));
7261 //TIZEN_ONLY(20161013): clean up elm color class feature
7263 _edje_color_class_free(void *data)
7265 Edje_Color_Class *cc = data;
7267 if (cc->name) eina_stringshare_del(cc->name);
7272 _elm_widget_edje_class_get(const Eo_Class *klass, const char *style, const char *part)
7275 Eina_Stringshare *str;
7277 buf = eina_strbuf_new();
7279 eina_strbuf_append(buf, strchr(eo_class_name_get(klass), '_') + 1);
7280 eina_strbuf_tolower(buf);
7284 eina_strbuf_append_printf(buf, "/%s/%s", style, part);
7288 eina_strbuf_append_printf(buf, "/%s", part);
7291 str = eina_stringshare_add(eina_strbuf_string_get(buf));
7293 eina_strbuf_free(buf);
7297 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
7299 _elm_widget_color_class_set_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
7300 int r, int g, int b, int a,
7301 int r2, int g2, int b2, int a2,
7302 int r3, int g3, int b3, int a3)
7304 Eina_Bool int_ret = EINA_TRUE;
7305 Eina_Stringshare *buf;
7306 int temp_color[3][4] = { { r, g, b, a },
7308 { r3, g3, b3, a3 } };
7310 if (!color_class) return EINA_FALSE;
7312 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
7314 #define TEMP_COLOR(x, y) \
7315 ((temp_color[x][y] == -1) ? &temp_color[x][y] : NULL)
7317 edje_object_color_class_get(edje, buf,
7318 TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
7319 TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
7320 TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
7324 #define TEMP_COLOR(x, y) \
7325 ((temp_color[x][y] == -1) ? 0 : temp_color[x][y])
7327 int_ret &= edje_object_color_class_set(edje, buf,
7328 TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
7329 TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
7330 TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
7334 eina_stringshare_del(buf);
7340 _elm_widget_color_class_get_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
7341 int *r, int *g, int *b, int *a,
7342 int *r2, int *g2, int *b2, int *a2,
7343 int *r3, int *g3, int *b3, int *a3)
7345 Eina_Bool int_ret = EINA_TRUE;
7346 Eina_Stringshare *buf;
7348 if (!color_class) return EINA_FALSE;
7350 buf = _elm_widget_edje_class_get(eo_class_get(obj), elm_widget_style_get(obj), color_class);
7352 int_ret &= edje_object_color_class_get(edje, buf,
7357 eina_stringshare_del(buf);
7364 _elm_widget_class_color_set(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int r, int g, int b, int a)
7367 Eina_Bool int_ret = EINA_TRUE;
7369 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7371 edje = elm_layout_edje_get(obj);
7372 int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7381 _elm_widget_class_color_get(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int *r, int *g, int *b, int *a)
7384 Eina_Bool int_ret = EINA_TRUE;
7386 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7388 edje = elm_layout_edje_get(obj);
7389 int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7391 NULL, NULL, NULL, NULL,
7392 NULL, NULL, NULL, NULL);
7398 _elm_widget_class_color2_set(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int r, int g, int b, int a)
7401 Eina_Bool int_ret = EINA_TRUE;
7403 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7405 edje = elm_layout_edje_get(obj);
7406 int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7415 _elm_widget_class_color2_get(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int *r, int *g, int *b, int *a)
7418 Eina_Bool int_ret = EINA_TRUE;
7420 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7422 edje = elm_layout_edje_get(obj);
7423 int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7424 NULL, NULL, NULL, NULL,
7426 NULL, NULL, NULL, NULL);
7432 _elm_widget_class_color3_set(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int r, int g, int b, int a)
7435 Eina_Bool int_ret = EINA_TRUE;
7437 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7439 edje = elm_layout_edje_get(obj);
7440 int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7449 _elm_widget_class_color3_get(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED, const char *color_class, int *r, int *g, int *b, int *a)
7452 Eina_Bool int_ret = EINA_TRUE;
7454 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7456 edje = elm_layout_edje_get(obj);
7457 int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7458 NULL, NULL, NULL, NULL,
7459 NULL, NULL, NULL, NULL,
7466 _elm_widget_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *color_class)
7468 Eina_Stringshare *buf;
7470 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return;
7472 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
7473 edje_object_color_class_del(sd->resize_obj, buf);
7474 eina_stringshare_del(buf);
7478 _elm_widget_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
7480 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return;
7481 edje_object_color_class_clear(sd->resize_obj);
7484 #define ELM_COLOR_CLASS_UPDATE(obj, hash, cond) \
7485 Evas_Object *edje = NULL; \
7486 Eina_Iterator *itr; \
7487 Edje_Color_Class *cc; \
7488 Eina_Bool int_ret = EINA_TRUE; \
7489 if (cond) return EINA_FALSE; \
7490 if (eo_isa(obj, ELM_LAYOUT_CLASS)) \
7491 edje = elm_layout_edje_get(obj); \
7492 else if (eo_isa(obj, EDJE_OBJECT_CLASS)) \
7494 if (!edje) return EINA_FALSE; \
7495 itr = eina_hash_iterator_data_new(hash); \
7496 EINA_ITERATOR_FOREACH(itr, cc) \
7498 int_ret &= edje_object_color_class_set(edje, cc->name, \
7499 cc->r, cc->g, cc->b, cc->a, \
7500 cc->r2, cc->g2, cc->b2, cc->a2, \
7501 cc->r3, cc->g3, cc->b3, cc->a3); \
7503 eina_iterator_free(itr); \
7507 #define CHECK_BOUND(x) \
7508 if (x > 0xff) x = 0xff; \
7509 else if (x < 0) x = 0
7511 #define ELM_COLOR_CLASS_SET_START(obj, cr, cg, cb, ca) \
7512 Eina_Bool int_ret = EINA_FALSE; \
7513 Edje_Color_Class *cc = NULL; \
7514 Eina_Stringshare *buf; \
7515 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class); \
7520 _elm_color_unpremul(a, &r, &g, &b); \
7521 if (!sd->color_classes) \
7522 sd->color_classes = eina_hash_string_small_new(_edje_color_class_free); \
7524 cc = eina_hash_find(sd->color_classes, buf); \
7527 cc = calloc(1, sizeof(Edje_Color_Class)); \
7528 cc->name = eina_stringshare_add(buf); \
7532 eina_stringshare_del(buf); \
7533 return EINA_FALSE; \
7535 eina_hash_direct_add(sd->color_classes, cc->name, cc); \
7537 else if ((cc->cr == r) && (cc->cg == g) && \
7538 (cc->cb == b) && (cc->ca == a)) \
7540 eina_stringshare_del(buf); \
7549 #define ELM_COLOR_CLASS_SET_END() \
7550 eina_stringshare_del(buf); \
7553 #define ELM_COLOR_CLASS_GET(obj, cr, cg, cb, ca) \
7554 Eina_Bool int_ret = EINA_FALSE; \
7555 Edje_Color_Class *cc; \
7556 Eina_Stringshare *buf; \
7558 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class); \
7559 if ((!sd->color_classes) || !(cc = eina_hash_find(sd->color_classes, buf))) \
7565 int_ret = EINA_FALSE; \
7569 if (r) *r = cc->cr; \
7570 if (g) *g = cc->cg; \
7571 if (b) *b = cc->cb; \
7572 if (a) *a = cc->ca; \
7574 int_ret = EINA_TRUE; \
7576 _elm_color_premul(alpha, r, g, b); \
7577 eina_stringshare_del(buf); \
7581 _elm_widget_item_color_class_update(Elm_Widget_Item_Data *sd)
7583 ELM_COLOR_CLASS_UPDATE(sd->view, sd->color_classes, (!sd) || (!sd->color_classes) || (!sd->view));
7587 _elm_widget_item_class_color_set(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int r, int g, int b, int a)
7589 ELM_COLOR_CLASS_SET_START(obj, r, g, b, a);
7591 int_ret &= _elm_widget_item_color_class_update(sd);
7593 ELM_COLOR_CLASS_SET_END();
7597 _elm_widget_item_class_color_get(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
7599 ELM_COLOR_CLASS_GET(obj, r, g, b, a);
7603 _elm_widget_item_class_color2_set(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int r, int g, int b, int a)
7605 ELM_COLOR_CLASS_SET_START(obj, r2, g2, b2, a2);
7607 int_ret &= _elm_widget_item_color_class_update(sd);
7609 ELM_COLOR_CLASS_SET_END();
7613 _elm_widget_item_class_color2_get(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
7615 ELM_COLOR_CLASS_GET(obj, r2, g2, b2, a2);
7619 _elm_widget_item_class_color3_set(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int r, int g, int b, int a)
7621 ELM_COLOR_CLASS_SET_START(obj, r3, g3, b3, a3);
7623 int_ret &= _elm_widget_item_color_class_update(sd);
7625 ELM_COLOR_CLASS_SET_END();
7629 _elm_widget_item_class_color3_get(Eo *obj, Elm_Widget_Item_Data *sd, const char *color_class, int *r, int *g, int *b, int *a)
7631 ELM_COLOR_CLASS_GET(obj, r3, g3, b3, a3);
7634 static Evas_Object *
7635 _elm_widget_item_edje_get(Eo *obj, Elm_Widget_Item_Data *sd)
7638 sd = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
7640 if (eo_isa(sd->view, ELM_LAYOUT_CLASS))
7641 return elm_layout_edje_get(sd->view);
7642 else if (eo_isa(sd->view, EDJE_OBJECT_CLASS))
7649 _elm_widget_item_class_color_del(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd, const char *color_class)
7651 Eina_Stringshare *buf;
7653 Edje_Color_Class *cc = NULL;
7655 if (!color_class) return;
7657 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
7658 eina_hash_del(sd->color_classes, buf, cc);
7660 edje = _elm_widget_item_edje_get(obj, sd);
7662 edje_object_color_class_del(edje, buf);
7664 eina_stringshare_del(buf);
7668 _elm_widget_item_class_color_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
7671 ELM_SAFE_FREE(sd->color_classes, eina_hash_free);
7673 edje = _elm_widget_item_edje_get(obj, sd);
7676 edje_object_color_class_clear(edje);
7680 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
7682 _elm_widget_color_class_parent_set(Evas_Object *obj, Evas_Object *parent)
7684 Evas_Object *edje = NULL, *parent_edje = NULL;
7686 if (!obj || !parent) return;
7688 if (eo_isa(obj, ELM_LAYOUT_CLASS))
7689 edje = elm_layout_edje_get(obj);
7690 else if (eo_isa(obj, EDJE_OBJECT_CLASS))
7693 if (eo_isa(parent, ELM_LAYOUT_CLASS))
7694 parent_edje = elm_layout_edje_get(parent);
7695 else if (eo_isa(parent, EDJE_OBJECT_CLASS))
7696 parent_edje = parent;
7698 if (!edje || !parent_edje) return;
7700 edje_object_color_class_parent_set(edje, parent_edje);
7704 _elm_widget_color_class_parent_unset(Evas_Object *obj)
7706 Evas_Object *edje = NULL;
7710 if (eo_isa(obj, ELM_LAYOUT_CLASS))
7711 edje = elm_layout_edje_get(obj);
7712 else if (eo_isa(obj, EDJE_OBJECT_CLASS))
7717 edje_object_color_class_parent_unset(edje);
7721 //TIZEN_ONLY(20160527): widget: add AtspiAction interface to all widgets and widget_items, add handlers for reading stopped/cancelled
7722 EOLIAN const Elm_Atspi_Action *
7723 _elm_widget_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
7728 EOLIAN const Elm_Atspi_Action *
7729 _elm_widget_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *pd EINA_UNUSED)
7735 #include "elm_widget_item.eo.c"
7736 #include "elm_widget.eo.c"