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(data, sd);
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())
601 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, EINA_FALSE);
605 _elm_widget_evas_object_smart_color_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, int r, int g, int b, int a)
610 it = evas_object_smart_iterator_new(obj);
611 EINA_ITERATOR_FOREACH(it, o)
613 if (evas_object_data_get(o, "_elm_leaveme")) continue;
614 evas_object_color_set(o, r, g, b, a);
616 eina_iterator_free(it);
620 _elm_widget_evas_object_smart_clip_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *clip)
625 it = evas_object_smart_iterator_new(obj);
626 EINA_ITERATOR_FOREACH(it, o)
628 if (evas_object_data_get(o, "_elm_leaveme")) continue;
629 evas_object_clip_set(o, clip);
631 eina_iterator_free(it);
635 _elm_widget_evas_object_smart_clip_unset(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
640 it = evas_object_smart_iterator_new(obj);
641 EINA_ITERATOR_FOREACH(it, o)
643 if (evas_object_data_get(o, "_elm_leaveme")) continue;
644 evas_object_clip_unset(o);
646 eina_iterator_free(it);
650 _elm_widget_evas_object_smart_calculate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
652 /* a NO-OP, on the base */
656 _elm_widget_evas_object_smart_member_add(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
659 eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(child));
661 if (evas_object_data_get(child, "_elm_leaveme")) return;
663 evas_object_color_get(obj, &r, &g, &b, &a);
664 evas_object_color_set(child, r, g, b, a);
666 evas_object_clip_set(child, evas_object_clip_get(obj));
668 if (evas_object_visible_get(obj))
669 evas_object_show(child);
671 evas_object_hide(child);
675 _elm_widget_evas_object_smart_member_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *child)
677 if (!evas_object_data_get(child, "_elm_leaveme"))
678 evas_object_clip_unset(child);
679 eo_do_super(obj, MY_CLASS, evas_obj_smart_member_del(child));
686 * Check if the widget has its own focus next function.
688 * @param obj The widget.
689 * @return focus next function is implemented/unimplemented.
690 * (@c EINA_TRUE = implemented/@c EINA_FALSE = unimplemented.)
692 static inline Eina_Bool
693 _elm_widget_focus_chain_manager_is(const Evas_Object *obj)
695 ELM_WIDGET_CHECK(obj) EINA_FALSE;
697 Eina_Bool manager_is = EINA_FALSE;
698 eo_do((Eo *)obj, manager_is = elm_obj_widget_focus_next_manager_is());
702 static inline Eina_Bool
703 _internal_elm_widget_focus_direction_manager_is(const Evas_Object *obj)
705 ELM_WIDGET_CHECK(obj) EINA_FALSE;
707 Eina_Bool manager_is = EINA_FALSE;
708 eo_do((Eo *)obj, manager_is = elm_obj_widget_focus_direction_manager_is());
713 _propagate_x_drag_lock(Evas_Object *obj,
719 ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
722 sd2->child_drag_x_locked += dir;
723 _propagate_x_drag_lock(sd->parent_obj, dir);
729 _propagate_y_drag_lock(Evas_Object *obj,
735 ELM_WIDGET_DATA_GET(sd->parent_obj, sd2);
738 sd2->child_drag_y_locked += dir;
739 _propagate_y_drag_lock(sd->parent_obj, dir);
745 _propagate_event(void *data EINA_UNUSED,
747 const Eo_Event_Description *desc,
750 INTERNAL_ENTRY EO_CALLBACK_CONTINUE;
751 Evas_Callback_Type type;
752 Evas_Event_Flags *event_flags = NULL;
754 if (desc == EVAS_OBJECT_EVENT_KEY_DOWN)
756 Evas_Event_Key_Down *ev = event_info;
757 event_flags = &(ev->event_flags);
758 type = EVAS_CALLBACK_KEY_DOWN;
760 else if (desc == EVAS_OBJECT_EVENT_KEY_UP)
762 Evas_Event_Key_Up *ev = event_info;
763 event_flags = &(ev->event_flags);
764 type = EVAS_CALLBACK_KEY_UP;
766 else if (desc == EVAS_OBJECT_EVENT_MOUSE_WHEEL)
768 Evas_Event_Mouse_Wheel *ev = event_info;
769 event_flags = &(ev->event_flags);
770 type = EVAS_CALLBACK_MOUSE_WHEEL;
773 return EO_CALLBACK_CONTINUE;
775 elm_widget_event_propagate(obj, type, event_info, event_flags);
777 return EO_CALLBACK_CONTINUE;
783 * If elm_widget_focus_region_get() returns EINA_FALSE, this function will
784 * ignore region show action.
787 _elm_widget_focus_region_show(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
789 Evas_Coord x, y, w, h, ox, oy;
792 o = elm_widget_parent_get(obj);
795 if (!elm_widget_focus_region_get(obj, &x, &y, &w, &h))
798 evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
803 evas_object_geometry_get(o, &px, &py, NULL, NULL);
805 if (_elm_scrollable_is(o) && !elm_widget_disabled_get(o))
808 eo_do(o, elm_interface_scrollable_content_region_get(&sx, &sy, NULL, NULL));
810 // Get the object's on_focus_region position relative to the scroller.
812 rx = ox + x - px + sx;
813 ry = oy + y - py + sy;
815 switch (_elm_config->focus_autoscroll_mode)
817 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
818 eo_do(o, elm_interface_scrollable_content_region_show(rx, ry, w, h));
820 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
821 eo_do(o, elm_interface_scrollable_region_bring_in(rx, ry, w, h));
827 if (!elm_widget_focus_region_get(o, &x, &y, &w, &h))
829 o = elm_widget_parent_get(o);
840 o = elm_widget_parent_get(o);
844 EOLIAN static Eina_Bool
845 _elm_widget_focus_highlight_style_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *style)
847 if (eina_stringshare_replace(&sd->focus_highlight_style, style)) return EINA_TRUE;
851 EOLIAN static const char*
852 _elm_widget_focus_highlight_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
854 return sd->focus_highlight_style;
858 _parent_focus(Evas_Object *obj, Elm_Object_Item *item)
862 if (sd->focused) return;
864 Evas_Object *o = elm_widget_parent_get(obj);
865 sd->focus_order_on_calc = EINA_TRUE;
867 if (o) _parent_focus(o, item);
869 if (!sd->focus_order_on_calc)
870 return; /* we don't want to override it if by means of any of the
871 callbacks below one gets to calculate our order
875 sd->focus_order = focus_order;
876 sd->focused = EINA_TRUE;
878 if (sd->top_win_focused)
879 eo_do(obj, elm_obj_widget_on_focus(item));
880 sd->focus_order_on_calc = EINA_FALSE;
882 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
883 _elm_access_highlight_set(obj);
887 _elm_object_focus_chain_del_cb(void *data,
890 void *event_info EINA_UNUSED)
892 ELM_WIDGET_DATA_GET(data, sd);
894 sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
898 _elm_widget_parent_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Evas_Object *parent EINA_UNUSED)
903 elm_widget_api_check(int ver)
905 if (ver != ELM_INTERNAL_API_VERSION)
907 CRI("Elementary widget api versions do not match");
914 elm_widget_access(Evas_Object *obj,
919 Eina_Bool ret = EINA_TRUE;
921 API_ENTRY return EINA_FALSE;
922 EINA_LIST_FOREACH(sd->subobjs, l, child)
924 if (elm_widget_is(child))
925 ret &= elm_widget_access(child, is_access);
928 eo_do(obj, elm_obj_widget_access(is_access));
929 eo_do(obj, eo_event_callback_call(ELM_WIDGET_EVENT_ACCESS_CHANGED, NULL));
934 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
935 //register/unregister access objects accordingly.
937 elm_widget_atspi(Evas_Object *obj,
942 Eina_Bool ret = EINA_TRUE;
944 API_ENTRY return EINA_FALSE;
945 EINA_LIST_FOREACH(sd->subobjs, l, child)
947 if (elm_widget_is(child))
948 ret &= elm_widget_atspi(child, is_atspi);
950 eo_do(obj, elm_obj_widget_atspi(is_atspi));
956 _elm_widget_atspi(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_atspi EINA_UNUSED)
962 _elm_widget_access(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_access EINA_UNUSED)
967 elm_widget_theme(Evas_Object *obj)
973 Elm_Theme_Apply ret = ELM_THEME_APPLY_SUCCESS;
975 API_ENTRY return ELM_THEME_APPLY_FAILED;
977 EINA_LIST_FOREACH(sd->subobjs, l, child)
978 if (_elm_widget_is(child))
979 ret &= elm_widget_theme(child);
981 if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
983 EINA_LIST_FOREACH(sd->tooltips, l, tt)
984 elm_tooltip_theme(tt);
985 EINA_LIST_FOREACH(sd->cursors, l, cur)
986 elm_cursor_theme(cur);
988 Elm_Theme_Apply ret2 = ELM_THEME_APPLY_FAILED;
989 eo_do(obj, ret2 = elm_obj_widget_theme_apply());
996 elm_widget_theme_specific(Evas_Object *obj,
1004 Elm_Theme *th2, *thdef;
1008 thdef = elm_theme_default_get();
1009 if (!th) th = thdef;
1013 if (!th2) th2 = thdef;
1021 if (th2 == thdef) break;
1022 th2 = th2->ref_theme;
1023 if (!th2) th2 = thdef;
1027 EINA_LIST_FOREACH(sd->subobjs, l, child)
1029 if (elm_widget_is(child))
1030 elm_widget_theme_specific(child, th, force);
1032 if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
1033 EINA_LIST_FOREACH(sd->tooltips, l, tt)
1034 elm_tooltip_theme(tt);
1035 EINA_LIST_FOREACH(sd->cursors, l, cur)
1036 elm_cursor_theme(cur);
1037 eo_do(obj, elm_obj_widget_theme_apply());
1040 EOLIAN static Elm_Theme_Apply
1041 _elm_widget_theme_apply(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
1043 _elm_widget_mirrored_reload(obj);
1044 if (elm_widget_disabled_get(obj))
1045 elm_widget_disabled_internal(obj, elm_widget_disabled_get(obj));
1047 return ELM_THEME_APPLY_SUCCESS;
1053 * Returns the widget's mirrored mode.
1055 * @param obj The widget.
1056 * @return mirrored mode of the object.
1059 EOLIAN static Eina_Bool
1060 _elm_widget_mirrored_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1062 return sd->is_mirrored;
1068 * Sets the widget's mirrored mode.
1070 * @param obj The widget.
1071 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
1074 _elm_widget_mirrored_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool mirrored)
1076 mirrored = !!mirrored;
1078 if (sd->is_mirrored == mirrored) return;
1080 sd->is_mirrored = mirrored;
1081 elm_widget_theme(obj);
1085 * Returns the widget's mirrored mode setting.
1087 * @param obj The widget.
1088 * @return mirrored mode setting of the object.
1091 EOLIAN static Eina_Bool
1092 _elm_widget_mirrored_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1094 return sd->mirrored_auto_mode;
1100 * Sets the widget's mirrored mode setting.
1101 * When widget in automatic mode, it follows the system mirrored mode set by
1102 * elm_mirrored_set().
1103 * @param obj The widget.
1104 * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
1107 _elm_widget_mirrored_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
1109 if (sd->mirrored_auto_mode != automatic)
1111 sd->mirrored_auto_mode = automatic;
1115 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
1121 _elm_widget_on_show_region_hook_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, region_hook_func_type func, void *data)
1123 sd->on_show_region = func;
1124 sd->on_show_region_data = data;
1130 * Add myself as a sub object of parent object
1132 * @see elm_widget_sub_object_add()
1135 elm_widget_sub_object_parent_add(Evas_Object *sobj)
1137 Eina_Bool ret = EINA_FALSE;
1140 eo_do(sobj, parent = eo_parent_get());
1141 if (!eo_isa(parent, ELM_WIDGET_CLASS))
1143 ERR("You passed a wrong parent parameter (%p %s). "
1144 "Elementary widget's parent should be an elementary widget.", parent, evas_object_type_get(parent));
1148 eo_do(parent, ret = elm_obj_widget_sub_object_add(sobj));
1156 * Add sobj to obj's sub object.
1158 * What does elementary sub object mean? This is unique in elementary, it
1159 * handles overall elementary policies between parent and sub objects.
1160 * focus, access, deletion, theme, scale, mirror, scrollable child get,
1161 * translate, name find, display mode set, orientation set, tree dump
1164 * @see elm_widget_sub_object_parent_add()
1166 EOLIAN static Eina_Bool
1167 _elm_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1169 Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
1171 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1173 if (sobj == sd->parent_obj)
1175 /* in this case, sobj must be an elm widget, or something
1176 * very wrong is happening */
1177 if (!_elm_widget_is(sobj)) return EINA_FALSE;
1179 if (!elm_widget_sub_object_del(sobj, obj)) return EINA_FALSE;
1180 WRN("You passed a parent object of obj = %p as the sub object = %p!",
1184 if (_elm_widget_is(sobj))
1186 ELM_WIDGET_DATA_GET(sobj, sdc);
1188 if (sdc->parent_obj == obj) goto end;
1189 if (sdc->parent_obj)
1191 if (!elm_widget_sub_object_del(sdc->parent_obj, sobj))
1194 sdc->parent_obj = obj;
1196 if (!sdc->on_create)
1197 eo_do(sobj, elm_obj_widget_orientation_set(sd->orient_mode));
1199 sdc->orient_mode = sd->orient_mode;
1201 if (!sdc->on_create)
1203 if (!sdc->disabled && (elm_widget_disabled_get(obj)))
1205 elm_widget_focus_disabled_handle(sobj);
1206 eo_do(sobj, elm_obj_widget_disable());
1210 _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
1212 /* update child focusable-ness on self and parents, now that a
1213 * focusable child got in */
1214 if (!sd->child_can_focus && (_is_focusable(sobj)))
1216 Elm_Widget_Smart_Data *sdp = sd;
1218 sdp->child_can_focus = EINA_TRUE;
1219 while (sdp->parent_obj)
1221 sdp = eo_data_scope_get(sdp->parent_obj, MY_CLASS);
1223 if (sdp->child_can_focus) break;
1225 sdp->child_can_focus = EINA_TRUE;
1231 void *data = evas_object_data_get(sobj, "elm-parent");
1235 if (data == obj) goto end;
1236 if (!elm_widget_sub_object_del(data, sobj)) return EINA_FALSE;
1239 sd->subobjs = eina_list_append(sd->subobjs, sobj);
1240 evas_object_data_set(sobj, "elm-parent", obj);
1242 _callbacks_add(sobj, obj);
1243 if (_elm_widget_is(sobj))
1245 ELM_WIDGET_DATA_GET(sobj, sdc);
1247 /* NOTE: In the following two lines, 'sobj' is correct. Do not change it.
1248 * Due to elementary's scale policy, scale and pscale can be different in
1249 * some cases. This happens when sobj's previous parent and new parent have
1250 * different scale value.
1251 * For example, if sobj's previous parent's scale is 5 and new parent's scale
1252 * is 2 while sobj's scale is 0. Then 'pscale' is 5 and 'scale' is 2. So we
1253 * need to reset sobj's scale to 5.
1254 * Note that each widget's scale is 0 by default.
1256 double scale, pscale = elm_widget_scale_get(sobj);
1257 Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
1259 scale = elm_widget_scale_get(sobj);
1260 th = elm_widget_theme_get(sobj);
1261 mirrored = elm_widget_mirrored_get(sobj);
1263 if (!sdc->on_create)
1265 if ((scale != pscale) || (th != pth) || (pmirrored != mirrored))
1266 elm_widget_theme(sobj);
1269 if (_is_focused(sobj)) _parents_focus(obj);
1271 elm_widget_display_mode_set(sobj,
1272 evas_object_size_hint_display_mode_get(obj));
1273 if (_elm_atspi_enabled() && !sdc->on_create)
1275 Elm_Interface_Atspi_Accessible *aparent;
1276 eo_do(sobj, aparent = elm_interface_atspi_accessible_parent_get());
1278 elm_interface_atspi_accessible_children_changed_added_signal_emit(obj, sobj);
1281 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
1282 if (sdc->inherit_paragraph_direction &&
1283 (sdc->paragraph_direction != evas_object_paragraph_direction_get(obj)))
1285 sdc->paragraph_direction = evas_object_paragraph_direction_get(obj);
1286 _elm_widget_evas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1287 eo_do_super(sobj, MY_CLASS, evas_obj_paragraph_direction_set(sdc->paragraph_direction));
1296 EOLIAN static Eina_Bool
1297 _elm_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1299 Evas_Object *sobj_parent;
1301 if (!sobj) return EINA_FALSE;
1303 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj == sobj, EINA_FALSE);
1305 sobj_parent = evas_object_data_del(sobj, "elm-parent");
1306 if (sobj_parent && sobj_parent != obj)
1308 static int abort_on_warn = -1;
1310 ERR("removing sub object %p (%s) from parent %p (%s), "
1311 "but elm-parent is different %p (%s)!",
1312 sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
1313 sobj_parent, elm_widget_type_get(sobj_parent));
1315 if (EINA_UNLIKELY(abort_on_warn == -1))
1317 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
1318 else abort_on_warn = 0;
1320 if (abort_on_warn == 1) abort();
1325 if (_elm_widget_is(sobj))
1327 if (_is_focused(sobj))
1329 elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1330 elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1332 if ((sd->child_can_focus) && (_is_focusable(sobj)))
1334 Evas_Object *parent = obj;
1336 /* update child focusable-ness on self and parents, now that a
1337 * focusable child is gone */
1341 Evas_Object *subobj;
1343 ELM_WIDGET_DATA_GET(parent, sdp);
1345 sdp->child_can_focus = EINA_FALSE;
1346 EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
1348 if ((subobj != sobj) && (_is_focusable(subobj)))
1350 sdp->child_can_focus = EINA_TRUE;
1355 /* break again, child_can_focus went back to
1357 if (sdp->child_can_focus) break;
1358 parent = sdp->parent_obj;
1361 if (_elm_atspi_enabled() && !sd->on_destroy)
1363 Elm_Interface_Atspi_Accessible *aparent;
1364 eo_do(sobj, aparent = elm_interface_atspi_accessible_parent_get());
1366 elm_interface_atspi_accessible_children_changed_del_signal_emit(obj, sobj);
1369 ELM_WIDGET_DATA_GET(sobj, sdc);
1370 sdc->parent_obj = NULL;
1372 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
1373 if (sdc->inherit_paragraph_direction &&
1374 (sdc->paragraph_direction != EVAS_BIDI_DIRECTION_NEUTRAL))
1376 sdc->paragraph_direction = EVAS_BIDI_DIRECTION_NEUTRAL;
1377 _elm_widget_evas_object_paragraph_direction_set_internal(sobj, sdc, sdc->paragraph_direction);
1378 eo_do_super(sobj, MY_CLASS, evas_obj_paragraph_direction_set(EVAS_BIDI_DIRECTION_NEUTRAL));
1383 if (sd->resize_obj == sobj) sd->resize_obj = NULL;
1385 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1387 _callbacks_del(sobj, obj);
1395 * a resize object is added to and deleted from the smart member and the sub object
1396 * of the parent if the third argument, Eina_Bool sub_obj, is set as EINA_TRUE.
1399 _elm_widget_resize_object_set(Eo *obj, Elm_Widget_Smart_Data *sd,
1403 Evas_Object *parent;
1405 if (sd->resize_obj == sobj) return;
1407 // orphan previous resize obj
1408 if (sd->resize_obj && sub_obj)
1410 evas_object_clip_unset(sd->resize_obj);
1411 evas_object_smart_member_del(sd->resize_obj);
1413 if (_elm_widget_is(sd->resize_obj))
1415 if (_is_focused(sd->resize_obj)) _parents_unfocus(obj);
1417 elm_widget_sub_object_del(obj, sd->resize_obj);
1420 sd->resize_obj = sobj;
1423 // orphan new resize obj
1424 parent = evas_object_data_get(sobj, "elm-parent");
1425 if (parent && parent != obj)
1427 ELM_WIDGET_DATA_GET(parent, sdp);
1429 /* should be there, just being paranoid */
1432 if (sdp->resize_obj == sobj)
1433 elm_widget_resize_object_set(parent, NULL, sub_obj);
1435 elm_widget_sub_object_del(parent, sobj);
1440 elm_widget_sub_object_add(obj, sobj);
1441 evas_object_smart_member_add(sobj, obj);
1444 _smart_reconfigure(sd);
1450 * WARNING: the programmer is responsible, in the scenario of
1451 * exchanging a hover object, of cleaning the old hover "target"
1455 _elm_widget_hover_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *sobj)
1459 _callbacks_del(sd->hover_obj, obj);
1461 sd->hover_obj = sobj;
1464 _callbacks_add(sobj, obj);
1465 _smart_reconfigure(sd);
1470 _elm_widget_can_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool can_focus)
1472 can_focus = !!can_focus;
1474 if (sd->can_focus == can_focus) return;
1475 sd->can_focus = can_focus;
1478 /* update child_can_focus of parents */
1479 Evas_Object *o = obj;
1483 o = elm_widget_parent_get(o);
1485 sd = eo_data_scope_get(o, MY_CLASS);
1486 if (!sd || sd->child_can_focus) break;
1487 sd->child_can_focus = EINA_TRUE;
1490 eo_do(obj, eo_event_callback_array_add(focus_callbacks(), NULL));
1494 // update child_can_focus of parents */
1495 Evas_Object *parent = elm_widget_parent_get(obj);
1499 Evas_Object *subobj;
1501 ELM_WIDGET_DATA_GET(parent, sdp);
1503 sdp->child_can_focus = EINA_FALSE;
1504 EINA_LIST_FOREACH(sdp->subobjs, l, subobj)
1506 if (_is_focusable(subobj))
1508 sdp->child_can_focus = EINA_TRUE;
1512 /* break again, child_can_focus went back to
1514 if (sdp->child_can_focus) break;
1515 parent = sdp->parent_obj;
1517 eo_do(obj, eo_event_callback_array_del(focus_callbacks(), NULL));
1521 EOLIAN static Eina_Bool
1522 _elm_widget_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1524 return sd->can_focus;
1527 EOLIAN static Eina_Bool
1528 _elm_widget_child_can_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1530 return sd->child_can_focus;
1536 * This API makes the widget object and its children to be unfocusable.
1538 * This API can be helpful for an object to be deleted.
1539 * When an object will be deleted soon, it and its children may not
1540 * want to get focus (by focus reverting or by other focus controls).
1541 * Then, just use this API before deleting.
1543 * @param obj The widget root of sub-tree
1544 * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1549 _elm_widget_tree_unfocusable_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool tree_unfocusable)
1551 tree_unfocusable = !!tree_unfocusable;
1552 if (sd->tree_unfocusable == tree_unfocusable) return;
1553 sd->tree_unfocusable = tree_unfocusable;
1554 elm_widget_focus_tree_unfocusable_handle(obj);
1560 * This returns true, if the object sub-tree is unfocusable.
1562 * @param obj The widget root of sub-tree
1563 * @return EINA_TRUE if the object sub-tree is unfocusable
1567 EOLIAN static Eina_Bool
1568 _elm_widget_tree_unfocusable_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1570 return sd->tree_unfocusable;
1576 * Get the list of focusable child objects.
1578 * This function retruns list of child objects which can get focus.
1580 * @param obj The parent widget
1581 * @retrun list of focusable child objects.
1585 EOLIAN static Eina_List*
1586 _elm_widget_can_focus_child_list_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1589 Eina_List *child_list = NULL;
1592 EINA_LIST_FOREACH(sd->subobjs, l, child)
1594 if (!_elm_widget_is(child)) continue;
1595 if ((elm_widget_can_focus_get(child)) &&
1596 (evas_object_visible_get(child)) &&
1597 (!elm_widget_disabled_get(child)))
1598 child_list = eina_list_append(child_list, child);
1601 Eina_List *can_focus_list;
1602 can_focus_list = elm_widget_can_focus_child_list_get(child);
1604 child_list = eina_list_merge(child_list, can_focus_list);
1612 _elm_widget_highlight_ignore_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool ignore)
1614 sd->highlight_ignore = !!ignore;
1617 EOLIAN static Eina_Bool
1618 _elm_widget_highlight_ignore_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1620 return sd->highlight_ignore;
1624 _elm_widget_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight)
1626 sd->highlight_in_theme = !!highlight;
1627 /* FIXME: if focused, it should switch from one mode to the other */
1631 _elm_widget_highlight_in_theme_update(Eo *obj)
1633 Evas_Object *top = elm_widget_top_get(obj);
1635 if (top && eo_isa(top, ELM_WIN_CLASS))
1637 _elm_win_focus_highlight_in_theme_update(
1638 top, elm_widget_highlight_in_theme_get(obj));
1642 EOLIAN static Eina_Bool
1643 _elm_widget_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1645 return sd->highlight_in_theme;
1649 _elm_widget_access_highlight_in_theme_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Eina_Bool highlight)
1651 sd->access_highlight_in_theme = !!highlight;
1654 EOLIAN static Eina_Bool
1655 _elm_widget_access_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1657 return sd->access_highlight_in_theme;
1660 EOLIAN static Eina_Bool
1661 _elm_widget_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1663 return (sd->focused && sd->top_win_focused);
1666 EOLIAN static Eina_Bool
1667 _elm_widget_highlight_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1669 return sd->highlighted;
1672 EOLIAN static Evas_Object*
1673 _elm_widget_focused_object_get(Eo *obj, Elm_Widget_Smart_Data *sd)
1675 const Evas_Object *subobj;
1678 if (!sd->focused || !sd->top_win_focused) return NULL;
1679 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1682 if (!_elm_widget_is(subobj)) continue;
1683 fobj = elm_widget_focused_object_get(subobj);
1684 if (fobj) return fobj;
1686 return (Evas_Object *)obj;
1689 EOLIAN static Evas_Object*
1690 _elm_widget_top_get(Eo *obj, Elm_Widget_Smart_Data *sd)
1694 Evas_Object *ret = NULL;
1695 if (!eo_isa(sd->parent_obj, ELM_WIDGET_CLASS)) return NULL;
1696 eo_do((Eo *) sd->parent_obj, ret = elm_obj_widget_top_get());
1699 return (Evas_Object *)obj;
1703 elm_widget_is(const Evas_Object *obj)
1705 return _elm_widget_is(obj);
1709 elm_widget_parent_widget_get(const Evas_Object *obj)
1711 Evas_Object *parent;
1713 if (_elm_widget_is(obj))
1715 ELM_WIDGET_DATA_GET(obj, sd);
1716 if (!sd) return NULL;
1717 parent = sd->parent_obj;
1721 parent = evas_object_data_get(obj, "elm-parent");
1722 if (!parent) parent = evas_object_smart_parent_get(obj);
1727 Evas_Object *elm_parent;
1728 if (_elm_widget_is(parent)) break;
1729 elm_parent = evas_object_data_get(parent, "elm-parent");
1730 if (elm_parent) parent = elm_parent;
1731 else parent = evas_object_smart_parent_get(parent);
1736 EOLIAN static Evas_Object *
1737 _elm_widget_parent2_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1743 _elm_widget_parent2_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *parent)
1745 sd->parent2 = parent;
1749 _elm_widget_event_callback_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Event_Cb func, const void *data)
1751 EINA_SAFETY_ON_NULL_RETURN(func);
1753 Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1756 ERR("Failed to allocate memory");
1761 sd->event_cb = eina_list_append(sd->event_cb, ecb);
1765 _elm_widget_event_callback_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Event_Cb func, const void *data)
1767 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1769 Elm_Event_Cb_Data *ecd;
1770 EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1771 if ((ecd->func == func) && (ecd->data == data))
1774 sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1775 return (void *)data;
1781 EOLIAN static Eina_Bool
1782 _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)
1784 Evas_Object *parent = obj;
1785 Elm_Event_Cb_Data *ecd;
1786 Eina_List *l, *l_prev;
1789 (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1791 ELM_WIDGET_CHECK(parent) EINA_FALSE;
1792 Elm_Widget_Smart_Data *sd = eo_data_scope_get(parent, MY_CLASS);
1794 Eina_Bool int_ret = EINA_FALSE;
1796 if (elm_widget_disabled_get(obj))
1798 parent = sd->parent_obj;
1802 eo_do(parent, int_ret = elm_obj_widget_event(obj, type, event_info));
1803 if (int_ret) return EINA_TRUE;
1805 EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1807 if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1808 (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1811 parent = sd->parent_obj;
1820 * Set custom focus chain.
1822 * This function i set one new and overwrite any previous custom focus chain
1823 * with the list of objects. The previous list will be deleted and this list
1824 * will be managed. After setted, don't modity it.
1826 * @note On focus cycle, only will be evaluated children of this container.
1828 * @param obj The container widget
1829 * @param objs Chain of objects to pass focus
1833 _elm_widget_focus_custom_chain_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_List *objs)
1835 if (!_elm_widget_focus_chain_manager_is(obj)) return;
1837 elm_widget_focus_custom_chain_unset(obj);
1842 EINA_LIST_FOREACH(objs, l, o)
1844 evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1845 _elm_object_focus_chain_del_cb, obj);
1848 sd->focus_chain = objs;
1854 * Get custom focus chain
1856 * @param obj The container widget
1859 EOLIAN static const Eina_List*
1860 _elm_widget_focus_custom_chain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1862 return (const Eina_List *)sd->focus_chain;
1868 * Unset custom focus chain
1870 * @param obj The container widget
1874 _elm_widget_focus_custom_chain_unset(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
1876 Eina_List *l, *l_next;
1879 EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1881 evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1882 _elm_object_focus_chain_del_cb, obj);
1883 sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1890 * Append object to custom focus chain.
1892 * @note If relative_child equal to NULL or not in custom chain, the object
1893 * will be added in end.
1895 * @note On focus cycle, only will be evaluated children of this container.
1897 * @param obj The container widget
1898 * @param child The child to be added in custom chain
1899 * @param relative_child The relative object to position the child
1903 _elm_widget_focus_custom_chain_append(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
1905 EINA_SAFETY_ON_NULL_RETURN(child);
1907 if (!_elm_widget_focus_chain_manager_is(obj)) return;
1909 evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
1910 _elm_object_focus_chain_del_cb, obj);
1912 if (!relative_child)
1913 sd->focus_chain = eina_list_append(sd->focus_chain, child);
1915 sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1916 child, relative_child);
1922 * Prepend object to custom focus chain.
1924 * @note If relative_child equal to NULL or not in custom chain, the object
1925 * will be added in begin.
1927 * @note On focus cycle, only will be evaluated children of this container.
1929 * @param obj The container widget
1930 * @param child The child to be added in custom chain
1931 * @param relative_child The relative object to position the child
1935 _elm_widget_focus_custom_chain_prepend(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *child, Evas_Object *relative_child)
1937 EINA_SAFETY_ON_NULL_RETURN(child);
1939 if (!_elm_widget_focus_chain_manager_is(obj)) return;
1941 evas_object_event_callback_add(child, EVAS_CALLBACK_DEL,
1942 _elm_object_focus_chain_del_cb, obj);
1944 if (!relative_child)
1945 sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1947 sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1948 child, relative_child);
1954 * Give focus to next object in object tree.
1956 * Give focus to next object in focus chain of one object sub-tree.
1957 * If the last object of chain already have focus, the focus will go to the
1958 * first object of chain.
1960 * @param obj The widget root of sub-tree
1961 * @param dir Direction to cycle the focus
1966 _elm_widget_focus_cycle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Focus_Direction dir)
1968 Evas_Object *target = NULL;
1969 Elm_Object_Item *target_item = NULL;
1970 if (!_elm_widget_is(obj))
1972 elm_widget_focus_next_get(obj, dir, &target, &target_item);
1976 if (_elm_config->access_mode)
1978 /* highlight cycle does not steal a focus, only after window gets
1979 the ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE message,
1980 target will steal focus, or focus its own job. */
1981 if (!_elm_access_auto_highlight_get())
1982 elm_widget_focus_steal(target, target_item);
1984 _elm_access_highlight_set(target);
1985 elm_widget_focus_region_show(target);
1987 else elm_widget_focus_steal(target, target_item);
1994 * Give focus to near object(in object tree) in one direction.
1996 * Give focus to near object(in object tree) in direction of current
1997 * focused object. If none focusable object in given direction or
1998 * none focused object in object tree, the focus will not change.
2000 * @param obj The reference widget
2001 * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2002 * 90-degree: Right, 180-degree: Down, and 270-degree: Left
2003 * @return EINA_TRUE if focus is moved.
2007 EOLIAN static Eina_Bool
2008 _elm_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, double degree)
2010 Evas_Object *target = NULL;
2011 Elm_Object_Item *target_item = NULL;
2012 Evas_Object *current_focused = NULL;
2013 double weight = 0.0;
2015 if (!_elm_widget_is(obj)) return EINA_FALSE;
2016 if (!_is_focused(obj)) return EINA_FALSE;
2018 current_focused = elm_widget_focused_object_get(obj);
2020 if (elm_widget_focus_direction_get
2021 (obj, current_focused, degree, &target, &target_item, &weight))
2023 elm_widget_focus_steal(target, NULL);
2031 _elm_widget_focus_direction_weight_get(const Evas_Object *obj1,
2032 const Evas_Object *obj2,
2035 Evas_Coord obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2;
2036 double x1, yy1, x2, yy2, xx1, yyy1, xx2, yyy2;
2037 double ax, ay, cx, cy;
2038 double weight = -1.0, g = 0.0;
2040 if (obj1 == obj2) return 0.0;
2043 while (degree >= 360.0)
2045 while (degree < 0.0)
2048 evas_object_geometry_get(obj1, &obj_x1, &obj_y1, &w1, &h1);
2049 cx = obj_x1 + (w1 / 2.0);
2050 cy = obj_y1 + (h1 / 2.0);
2051 evas_object_geometry_get(obj2, &obj_x2, &obj_y2, &w2, &h2);
2053 /* For overlapping cases. */
2054 if (ELM_RECTS_INTERSECT(obj_x1, obj_y1, w1, h1, obj_x2, obj_y2, w2, h2))
2057 /* Change all points to relative one. */
2067 /* Get crossing points (ax, ay) between obj1 and a line extending
2068 * to the direction of current degree. */
2074 else if (degree == 90.0)
2079 else if (degree == 180.0)
2084 else if (degree == 270.0)
2091 g = tan(degree * (M_PI / 180.0));
2092 if ((degree > 0.0) && (degree < 90.0))
2095 if (ay <= yyy1) ax = xx1;
2102 else if ((degree > 90.0) && (degree < 180.0))
2105 if (ay <= yyy1) ax = x1;
2112 else if ((degree > 180.0) && (degree < 270.0))
2115 if (ay >= yy1) ax = x1;
2125 if (ay >= yy1) ax = xx1;
2134 /* Filter obj2, if it is not in the specific derection. */
2136 double rx[4] = {0.0, 0.0, 0.0, 0.0}, ry[4] = {0.0, 0.0, 0.0, 0.0};
2137 double t1, t2, u1, v1, u2, v2;
2139 if ((degree == 45.0) || (degree == 225.0) || (degree == 135.0) ||
2149 double g2 = tan((degree + 45.0) * (M_PI / 180.0));
2154 t1 = (u1 * ax) + (v1 * ay);
2155 t2 = (u2 * ax) + (v2 * ay);
2157 #define _R(x) (int)((x + 0.05) * 10.0)
2159 if ((_R(t1 * ((u1 * x2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * x2) +
2165 if ((_R(t1 * ((u1 * x2) + (v1 * yyy2))) > 0) && (_R(t2 * ((u2 * x2) +
2171 if ((_R(t1 * ((u1 * xx2) + (v1 * yy2))) > 0) && (_R(t2 * ((u2 * xx2) +
2177 if ((_R(t1 * ((u1 * xx2) + (v1 * yyy2))) > 0) &&
2178 (_R(t2 * ((u2 * xx2) + (v2 * yyy2))) > 0))
2187 if ((_R(xx2) < 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2189 else if (degree == 90.0)
2191 if ((_R(yyy2) < 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2193 else if (degree == 180.0)
2195 if ((_R(x2) > 0) || (_R(yy2) > 0) || (_R(yyy2) < 0)) return 0.0;
2197 else if (degree == 270.0)
2199 if ((_R(yy2) > 0) || (_R(x2) > 0) || (_R(xx2) < 0)) return 0.0;
2203 if ((_R(g * x2) >= _R(yy2)) && (_R((g * x2)) <= _R(yyy2)))
2205 if (!((_R(ax * x2) > 0) && (_R(ay * (g * x2)) > 0)))
2208 else if ((_R(g * xx2) >= _R(yy2)) && (_R((g * xx2)) <= _R(yyy2)))
2210 if (!((_R(ax * xx2) > 0) && (_R(ay * (g * xx2)) > 0)))
2213 else if ((_R((1.0 / g) * yy2) >= _R(xx2)) && (_R((1.0 / g) * yy2)
2216 if (!((_R(ax * ((1.0 / g) * yy2)) > 0)
2217 && (_R(ay * yy2) > 0)))
2220 else if ((_R((1.0 / g) * yyy2) >= _R(xx2)) &&
2221 (_R((1.0 / g) * yyy2) <= _R(xx2)))
2223 if (!((_R(ax * ((1.0 / g) * yyy2)) > 0)
2224 && (_R(ay * yyy2) > 0))) return 0.0;
2230 /* Calculate the weight for obj2. */
2233 if (_R(xx1) > _R(x2)) weight = -1.0;
2234 else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2235 weight = (x2 - xx1) * (x2 - xx1);
2236 else if (_R(yy2) > 0)
2237 weight = ((x2 - xx1) * (x2 - xx1)) + (yy2 * yy2);
2238 else if (_R(yyy2) < 0)
2239 weight = ((x2 - xx1) * (x2 - xx1)) + (yyy2 * yyy2);
2240 else weight = (x2 - xx1) * (x2 - xx1);
2242 else if (degree == 90.0)
2244 if (_R(yyy1) > _R(yy2)) weight = -1.0;
2245 else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2246 weight = (yy2 - yyy1) * (yy2 - yyy1);
2247 else if (_R(x2) > 0)
2248 weight = (x2 * x2) + ((yy2 - yyy1) * (yy2 - yyy1));
2249 else if (_R(xx2) < 0)
2250 weight = (xx2 * xx2) + ((yy2 - yyy1) * (yy2 - yyy1));
2251 else weight = (yy2 - yyy1) * (yy2 - yyy1);
2253 else if (degree == 180.0)
2255 if (_R(x1) < _R(xx2)) weight = -1.0;
2256 else if ((_R(yy2) >= _R(yy1)) && (_R(yyy2) <= _R(yyy1)))
2257 weight = (x1 - xx2) * (x1 - xx2);
2258 else if (_R(yy2) > 0)
2259 weight = ((x1 - xx2) * (x1 - xx2)) + (yy2 * yy2);
2260 else if (_R(yyy2) < 0)
2261 weight = ((x1 - xx2) * (x1 - xx2)) + (yyy2 * yyy2);
2262 else weight = (x1 - xx2) * (x1 - xx2);
2264 else if (degree == 270.0)
2266 if (_R(yy1) < _R(yyy2)) weight = -1.0;
2267 else if ((_R(x2) >= _R(x1)) && (_R(xx2) <= _R(xx1)))
2268 weight = (yy1 - yyy2) * (yy1 - yyy2);
2269 else if (_R(x2) > 0)
2270 weight = (x2 * x2) + ((yy1 - yyy2) * (yy1 - yyy2));
2271 else if (_R(xx2) < 0)
2272 weight = (xx2 * xx2) + ((yy1 - yyy2) * (yy1 - yyy2));
2273 else weight = (yy1 - yyy2) * (yy1 - yyy2);
2278 double sx[4] = {0.0, 0.0, 0.0, 0.0}, sy[4] = {0.0, 0.0, 0.0, 0.0};
2279 double t_weight[4] = {-1.0, -1.0, -1.0, -1.0};
2280 if ((_R(g * x2) >= _R(yy2)) && (_R(g * x2) <= _R(yyy2)))
2284 t_weight[j++] = ((ax - x2) * (ax - x2)) +
2285 ((ay - (g * x2)) * (ay - (g * x2)));
2287 if ((_R(g * xx2) >= _R(yy2)) && (_R(g * xx2) <= _R(yyy2)))
2291 t_weight[j++] = ((ax - xx2) * (ax - xx2)) +
2292 ((ay - (g * xx2)) * (ay - (g * xx2)));
2294 if ((_R((1.0 / g) * yy2) >= _R(x2)) && (_R((1.0 / g) * yy2) <= _R(xx2)))
2296 sx[j] = (1.0 / g) * yy2;
2299 ((ax - ((1.0 / g) * yy2)) * (ax - ((1.0 / g) * yy2))) +
2300 ((ay - yy2) * (ay - yy2));
2302 if ((_R((1.0 / g) * yyy2) >= _R(x2)) && (_R((1.0 / g) * yyy2)
2305 sx[j] = (1.0 / g) * yyy2;
2308 ((ax - ((1.0 / g) * yyy2)) * (ax - ((1.0 / g) * yyy2))) +
2309 ((ay - yyy2) * (ay - yyy2));
2312 if ((j > 2) || ((j == 2) && ((_R(sx[0]) != _R(sx[1])) ||
2313 (_R(sy[0]) != _R(sy[1])))))
2317 if (_R(t_weight[k]) == 0) return -1.0;
2318 if ((1 / weight) < (1 / t_weight[k])) weight = t_weight[k];
2325 double ccx, ccy, t1_weight, x_diff, y_diff;
2326 ccx = ((1.0 / g) * rx[k] + ry[k]) / (g + (1.0 / g));
2328 x_diff = rx[k] - ccx;
2329 if (x_diff < 0) x_diff *= -1.0;
2330 y_diff = ry[k] - ccy;
2331 if (y_diff < 0) y_diff *= -1.0;
2333 (((ax - ccx) * (ax - ccx)) + ((ay - ccy) * (ay - ccy))) +
2334 ((x_diff * x_diff * x_diff) + (y_diff * y_diff * y_diff));
2335 if ((_R(t1_weight) != 0) && ((1 / weight) < (1 / t1_weight)))
2340 /* Return the current object's weight. */
2341 if (weight == -1.0) return 0.0;
2342 if (_R(weight) == 0) return -1.0;
2346 return 1.0 / weight;
2352 * Get near object in one direction of base object.
2354 * Get near object(in the object sub-tree) in one direction of
2355 * base object. Return the near object by reference.
2356 * By initializing weight, you can filter objects locating far
2357 * from base object. If object is in the specific direction,
2358 * weight is (1/(distance^2)). If object is not exactly in one
2359 * direction, some penalty will be added.
2361 * @param obj The widget root of sub-tree
2362 * @param base The base object of the direction
2363 * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2364 * 90-degree: Right, 180-degree: Down, and 270-degree: Left
2365 * @param direction The near object in one direction
2366 * @param weight The weight is bigger when the object is located near
2367 * @return EINA_TRUE if near object is updated.
2372 EOLIAN static Eina_Bool
2373 _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)
2377 /* -1 means the best was already decided. Don't need any more searching. */
2378 if (!direction || !weight || !base || (obj == base))
2381 /* Ignore if disabled */
2382 if ((!evas_object_visible_get(obj))
2383 || (elm_widget_disabled_get(obj))
2384 || (elm_widget_tree_unfocusable_get(obj)))
2388 if (_internal_elm_widget_focus_direction_manager_is(obj))
2390 Eina_Bool int_ret = EINA_FALSE;
2391 eo_do((Eo *)obj, int_ret = elm_obj_widget_focus_direction(base, degree, direction, direction_item, weight));
2395 if (!elm_widget_can_focus_get(obj) || _is_focused((Eo *)obj))
2398 c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree);
2399 if ((c_weight == -1.0) ||
2400 ((c_weight != 0.0) && (*weight != -1.0) &&
2401 ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
2404 ((int)(*weight * 1000000) == (int)(c_weight * 1000000)))
2406 ELM_WIDGET_DATA_GET(*direction, sd1);
2409 if (sd->focus_order <= sd1->focus_order)
2413 *direction = (Evas_Object *)obj;
2424 * Get near object in one direction of base object in list.
2426 * Get near object in one direction of base object in the specific
2427 * object list. Return the near object by reference.
2428 * By initializing weight, you can filter objects locating far
2429 * from base object. If object is in the specific direction,
2430 * weight is (1/(distance^2)). If object is not exactly in one
2431 * direction, some penalty will be added.
2433 * @param obj The widget root of sub-tree
2434 * @param base The base object of the direction
2435 * @param items list with ordered objects
2436 * @param list_data_get function to get the object from one item of list
2437 * @param degree Degree changes clockwise. i.e. 0-degree: Up,
2438 * 90-degree: Right, 180-degree: Down, and 270-degree: Left
2439 * @param direction The near object in one direction
2440 * @param weight The weight is bigger when the object is located near
2441 * @return EINA_TRUE if near object is updated.
2445 EOLIAN static Eina_Bool
2446 _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)
2448 if (!direction || !weight || !base || !items)
2451 const Eina_List *l = items;
2452 Evas_Object *current_best = *direction;
2454 for (; l; l = eina_list_next(l))
2456 Evas_Object *cur = list_data_get(l);
2457 if (cur && _elm_widget_is(cur))
2458 elm_widget_focus_direction_get(cur, base, degree, direction, direction_item, weight);
2460 if (current_best != *direction) return EINA_TRUE;
2468 * Get next object in focus chain of object tree.
2470 * Get next object in focus chain of one object sub-tree.
2471 * Return the next object by reference. If don't have any candidate to receive
2472 * focus before chain end, the first candidate will be returned.
2474 * @param obj The widget root of sub-tree
2475 * @param dir Direction of focus chain
2476 * @param next The next object in focus chain
2477 * @return EINA_TRUE if don't need focus chain restart/loop back
2478 * to use 'next' obj.
2482 EOLIAN static Eina_Bool
2483 _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)
2485 Elm_Access_Info *ac;
2491 /* Ignore if disabled */
2492 if (_elm_config->access_mode && _elm_access_auto_highlight_get())
2494 if (!evas_object_visible_get(obj)
2495 || (elm_widget_tree_unfocusable_get(obj)))
2500 if ((!evas_object_visible_get(obj))
2501 || (elm_widget_disabled_get(obj))
2502 || (elm_widget_tree_unfocusable_get(obj)))
2507 if (_elm_widget_focus_chain_manager_is(obj))
2509 Eina_Bool int_ret = EINA_FALSE;
2510 eo_do((Eo *)obj, int_ret = elm_obj_widget_focus_next(dir, next, next_item));
2511 if (!int_ret && _is_focused((Eo *)obj))
2513 Evas_Object *o = NULL;
2514 if (dir == ELM_FOCUS_PREVIOUS)
2515 *next_item = sd->item_focus_previous;
2516 else if (dir == ELM_FOCUS_NEXT)
2517 *next_item = sd->item_focus_next;
2518 else if (dir == ELM_FOCUS_UP)
2519 *next_item = sd->item_focus_up;
2520 else if (dir == ELM_FOCUS_DOWN)
2521 *next_item = sd->item_focus_down;
2522 else if (dir == ELM_FOCUS_RIGHT)
2523 *next_item = sd->item_focus_right;
2524 else if (dir == ELM_FOCUS_LEFT)
2525 *next_item = sd->item_focus_left;
2526 o = elm_object_item_widget_get(*next_item);
2530 if (dir == ELM_FOCUS_PREVIOUS)
2531 o = sd->focus_previous;
2532 else if (dir == ELM_FOCUS_NEXT)
2534 else if (dir == ELM_FOCUS_UP)
2536 else if (dir == ELM_FOCUS_DOWN)
2538 else if (dir == ELM_FOCUS_RIGHT)
2539 o = sd->focus_right;
2540 else if (dir == ELM_FOCUS_LEFT)
2553 /* access object does not check sd->can_focus, because an object could
2554 have highlight even though the object is not focusable. */
2555 if (_elm_config->access_mode && _elm_access_auto_highlight_get())
2557 ac = _elm_access_info_get(obj);
2558 if (!ac) return EINA_FALSE;
2560 /* check whether the hover object is visible or not */
2561 if (!evas_object_visible_get(ac->hoverobj))
2564 else if (!elm_widget_can_focus_get(obj))
2567 if (_is_focused((Eo *)obj))
2569 if (dir == ELM_FOCUS_PREVIOUS)
2570 *next_item = sd->item_focus_previous;
2571 else if (dir == ELM_FOCUS_NEXT)
2572 *next_item = sd->item_focus_next;
2573 else if (dir == ELM_FOCUS_UP)
2574 *next_item = sd->item_focus_up;
2575 else if (dir == ELM_FOCUS_DOWN)
2576 *next_item = sd->item_focus_down;
2577 else if (dir == ELM_FOCUS_RIGHT)
2578 *next_item = sd->item_focus_right;
2579 else if (dir == ELM_FOCUS_LEFT)
2580 *next_item = sd->item_focus_left;
2581 *next = elm_object_item_widget_get(*next_item);
2585 if (dir == ELM_FOCUS_PREVIOUS)
2586 *next = sd->focus_previous;
2587 else if (dir == ELM_FOCUS_NEXT)
2588 *next = sd->focus_next;
2589 else if (dir == ELM_FOCUS_UP)
2590 *next = sd->focus_up;
2591 else if (dir == ELM_FOCUS_DOWN)
2592 *next = sd->focus_down;
2593 else if (dir == ELM_FOCUS_RIGHT)
2594 *next = sd->focus_right;
2595 else if (dir == ELM_FOCUS_LEFT)
2596 *next = sd->focus_left;
2599 if (*next) return EINA_TRUE;
2603 *next = (Evas_Object *)obj;
2604 return !ELM_WIDGET_FOCUS_GET(obj);
2610 * Get next object in focus chain of object tree in list.
2612 * Get next object in focus chain of one object sub-tree ordered by one list.
2613 * Return the next object by reference. If don't have any candidate to receive
2614 * focus before list end, the first candidate will be returned.
2616 * @param obj The widget root of sub-tree
2617 * @param items list with ordered objects
2618 * @param list_data_get function to get the object from one item of list
2619 * @param dir Direction of focus chain
2620 * @param next The next object in focus chain
2621 * @return EINA_TRUE if don't need focus chain restart/loop back
2622 * to use 'next' obj.
2626 EOLIAN static Eina_Bool
2627 _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)
2629 Eina_List *(*list_next)(const Eina_List *list) = NULL;
2630 Evas_Object *focused_object = NULL;
2636 if (!_elm_widget_is(obj))
2642 /* When Up, Down, Right, or Left, try direction_get first. */
2643 focused_object = elm_widget_focused_object_get(obj);
2646 if ((dir == ELM_FOCUS_UP)
2647 || (dir == ELM_FOCUS_DOWN)
2648 || (dir == ELM_FOCUS_RIGHT)
2649 || (dir == ELM_FOCUS_LEFT))
2651 *next_item = elm_widget_focus_next_item_get(focused_object, dir);
2653 *next = elm_object_item_widget_get(*next_item);
2655 *next = elm_widget_focus_next_object_get(focused_object, dir);
2656 if (*next) return EINA_TRUE;
2659 Evas_Object *n = NULL;
2660 Elm_Object_Item *n_item = NULL;
2662 double weight = 0.0;
2664 if (dir == ELM_FOCUS_UP) degree = 0.0;
2665 else if (dir == ELM_FOCUS_DOWN) degree = 180.0;
2666 else if (dir == ELM_FOCUS_RIGHT) degree = 90.0;
2667 else if (dir == ELM_FOCUS_LEFT) degree = 270.0;
2669 if (elm_widget_focus_list_direction_get(obj, focused_object,
2670 items, list_data_get,
2671 degree, &n, &n_item,
2674 *next_item = n_item;
2683 if (dir == ELM_FOCUS_PREVIOUS)
2685 items = eina_list_last(items);
2686 list_next = eina_list_prev;
2688 else if ((dir == ELM_FOCUS_NEXT)
2689 || (dir == ELM_FOCUS_UP)
2690 || (dir == ELM_FOCUS_DOWN)
2691 || (dir == ELM_FOCUS_RIGHT)
2692 || (dir == ELM_FOCUS_LEFT))
2693 list_next = eina_list_next;
2697 const Eina_List *l = items;
2699 /* Recovery last focused sub item */
2700 if (ELM_WIDGET_FOCUS_GET(obj))
2702 for (; l; l = list_next(l))
2704 Evas_Object *cur = list_data_get(l);
2705 if (ELM_WIDGET_FOCUS_GET(cur)) break;
2708 /* Focused object, but no focused sub item */
2712 const Eina_List *start = l;
2713 Evas_Object *to_focus = NULL;
2714 Elm_Object_Item *to_focus_item = NULL;
2716 /* Iterate sub items */
2717 /* Go to the end of list */
2718 for (; l; l = list_next(l))
2720 Evas_Object *tmp = NULL;
2721 Elm_Object_Item *tmp_item = NULL;
2722 Evas_Object *cur = list_data_get(l);
2725 if (!_elm_widget_is(cur)) continue;
2726 if (elm_widget_parent_get(cur) != obj)
2729 /* Try Focus cycle in subitem */
2730 if (elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item))
2733 *next_item = tmp_item;
2736 else if ((dir == ELM_FOCUS_UP)
2737 || (dir == ELM_FOCUS_DOWN)
2738 || (dir == ELM_FOCUS_RIGHT)
2739 || (dir == ELM_FOCUS_LEFT))
2741 if (tmp && _is_focused(cur))
2744 *next_item = tmp_item;
2748 else if ((tmp) && (!to_focus))
2751 to_focus_item = tmp_item;
2757 /* Get First possible */
2758 for (; l != start; l = list_next(l))
2760 Evas_Object *tmp = NULL;
2761 Elm_Object_Item *tmp_item = NULL;
2762 Evas_Object *cur = list_data_get(l);
2764 if (elm_widget_parent_get(cur) != obj)
2767 /* Try Focus cycle in subitem */
2768 elm_widget_focus_next_get(cur, dir, &tmp, &tmp_item);
2772 *next_item = tmp_item;
2778 *next_item = to_focus_item;
2785 * Get next object which was set with specific focus direction.
2787 * Get next object which was set by elm_widget_focus_next_object_set
2788 * with specific focus directioin.
2790 * @param obj The widget
2791 * @param dir Direction of focus
2792 * @return Widget which was registered with sepecific focus direction.
2796 EOLIAN static Evas_Object*
2797 _elm_widget_focus_next_object_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir)
2799 Evas_Object *ret = NULL;
2801 if (dir == ELM_FOCUS_PREVIOUS)
2802 ret = sd->focus_previous;
2803 else if (dir == ELM_FOCUS_NEXT)
2804 ret = sd->focus_next;
2805 else if (dir == ELM_FOCUS_UP)
2807 else if (dir == ELM_FOCUS_DOWN)
2808 ret = sd->focus_down;
2809 else if (dir == ELM_FOCUS_RIGHT)
2810 ret = sd->focus_right;
2811 else if (dir == ELM_FOCUS_LEFT)
2812 ret = sd->focus_left;
2820 * Set next object with specific focus direction.
2822 * When a widget is set with specific focus direction, this widget will be
2823 * the first candidate when finding the next focus object.
2824 * Focus next object can be registered with six directions that are previous,
2825 * next, up, down, right, and left.
2827 * @param obj The widget
2828 * @param next Next focus object
2829 * @param dir Direction of focus
2834 _elm_widget_focus_next_object_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_Object *next, Elm_Focus_Direction dir)
2837 if (dir == ELM_FOCUS_PREVIOUS)
2838 sd->focus_previous = next;
2839 else if (dir == ELM_FOCUS_NEXT)
2840 sd->focus_next = next;
2841 else if (dir == ELM_FOCUS_UP)
2842 sd->focus_up = next;
2843 else if (dir == ELM_FOCUS_DOWN)
2844 sd->focus_down = next;
2845 else if (dir == ELM_FOCUS_RIGHT)
2846 sd->focus_right = next;
2847 else if (dir == ELM_FOCUS_LEFT)
2848 sd->focus_left = next;
2851 EOLIAN static Elm_Object_Item*
2852 _elm_widget_focus_next_item_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Direction dir)
2854 Elm_Object_Item *ret = NULL;
2856 if (dir == ELM_FOCUS_PREVIOUS)
2857 ret = sd->item_focus_previous;
2858 else if (dir == ELM_FOCUS_NEXT)
2859 ret = sd->item_focus_next;
2860 else if (dir == ELM_FOCUS_UP)
2861 ret = sd->item_focus_up;
2862 else if (dir == ELM_FOCUS_DOWN)
2863 ret = sd->item_focus_down;
2864 else if (dir == ELM_FOCUS_RIGHT)
2865 ret = sd->item_focus_right;
2866 else if (dir == ELM_FOCUS_LEFT)
2867 ret = sd->item_focus_left;
2873 _elm_widget_focus_next_item_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Object_Item *next_item, Elm_Focus_Direction dir)
2875 if (dir == ELM_FOCUS_PREVIOUS)
2876 sd->item_focus_previous = next_item;
2877 else if (dir == ELM_FOCUS_NEXT)
2878 sd->item_focus_next = next_item;
2879 else if (dir == ELM_FOCUS_UP)
2880 sd->item_focus_up = next_item;
2881 else if (dir == ELM_FOCUS_DOWN)
2882 sd->item_focus_down = next_item;
2883 else if (dir == ELM_FOCUS_RIGHT)
2884 sd->item_focus_right = next_item;
2885 else if (dir == ELM_FOCUS_LEFT)
2886 sd->item_focus_left = next_item;
2890 _elm_widget_parent_highlight_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool highlighted)
2892 highlighted = !!highlighted;
2894 Evas_Object *o = elm_widget_parent_get(obj);
2896 if (o) elm_widget_parent_highlight_set(o, highlighted);
2898 sd->highlighted = highlighted;
2902 _elm_widget_signal_emit(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source)
2904 if (evas_object_smart_type_check(obj, "elm_layout"))
2905 elm_layout_signal_emit(obj, emission, source);
2906 else if (evas_object_smart_type_check(obj, "elm_icon"))
2908 WRN("Deprecated function. This functionality on icon objects"
2909 " will be dropped on a next release.");
2910 _elm_icon_signal_emit(obj, emission, source);
2915 _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)
2917 EINA_SAFETY_ON_NULL_RETURN(func);
2919 if (evas_object_smart_type_check(obj, "elm_layout"))
2920 elm_layout_signal_callback_add(obj, emission, source, func, data);
2921 else if (evas_object_smart_type_check(obj, "elm_icon"))
2923 WRN("Deprecated function. This functionality on icon objects"
2924 " will be dropped on a next release.");
2926 _elm_icon_signal_callback_add(obj, emission, source, func, data);
2931 _elm_widget_signal_callback_del(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *emission, const char *source, Edje_Signal_Cb func)
2935 if (evas_object_smart_type_check(obj, "elm_layout"))
2936 data = elm_layout_signal_callback_del(obj, emission, source, func);
2937 else if (evas_object_smart_type_check(obj, "elm_icon"))
2939 WRN("Deprecated function. This functionality on icon objects"
2940 " will be dropped on a next release.");
2942 data = _elm_icon_signal_callback_del(obj, emission, source, func);
2949 _elm_widget_focus_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool focus)
2954 sd->focus_order = focus_order;
2955 sd->focused = EINA_TRUE;
2956 eo_do(obj, elm_obj_widget_on_focus(NULL));
2961 if ((_is_focusable(sd->resize_obj)) &&
2962 (!elm_widget_disabled_get(sd->resize_obj)))
2964 elm_widget_focus_set(sd->resize_obj, focus);
2971 EINA_LIST_FOREACH(sd->subobjs, l, child)
2973 if (!_elm_widget_is(child)) continue;
2974 if ((_is_focusable(child)) &&
2975 (!elm_widget_disabled_get(child)))
2977 elm_widget_focus_set(child, focus);
2988 EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
2990 if (!_elm_widget_is(child)) continue;
2991 if ((_is_focusable(child)) &&
2992 (!elm_widget_disabled_get(child)))
2994 elm_widget_focus_set(child, focus);
3001 EOLIAN static Evas_Object*
3002 _elm_widget_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3004 return sd->parent_obj;
3008 _elm_widget_focused_object_clear(Eo *obj, Elm_Widget_Smart_Data *sd)
3010 if (!sd->focused) return;
3011 if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
3012 _is_focused(sd->resize_obj))
3014 eo_do(sd->resize_obj, elm_obj_widget_focused_object_clear());
3020 EINA_LIST_FOREACH(sd->subobjs, l, child)
3022 if (_elm_widget_is(child) && _is_focused(child))
3024 eo_do(child, elm_obj_widget_focused_object_clear());
3029 sd->focused = EINA_FALSE;
3030 if (sd->top_win_focused)
3031 eo_do(obj, elm_obj_widget_on_focus(NULL));
3035 _elm_widget_focus_steal(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item)
3037 Evas_Object *parent, *parent2, *o;
3039 if (sd->focused) return;
3040 if (sd->disabled) return;
3041 if (!sd->can_focus) return;
3042 if (sd->tree_unfocusable) return;
3046 o = elm_widget_parent_get(parent);
3048 sd = eo_data_scope_get(o, MY_CLASS);
3049 if (sd->disabled || sd->tree_unfocusable) return;
3050 if (sd->focused) break;
3053 if ((!elm_widget_parent_get(parent)) &&
3054 (!elm_widget_parent2_get(parent)))
3055 eo_do(parent, elm_obj_widget_focused_object_clear());
3058 parent2 = elm_widget_parent_get(parent);
3059 if (!parent2) parent2 = elm_widget_parent2_get(parent);
3061 sd = eo_data_scope_get(parent, MY_CLASS);
3064 if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
3065 _is_focused(sd->resize_obj))
3067 eo_do(sd->resize_obj, elm_obj_widget_focused_object_clear());
3073 EINA_LIST_FOREACH(sd->subobjs, l, child)
3075 if (_elm_widget_is(child) && _is_focused(child))
3077 eo_do(child, elm_obj_widget_focused_object_clear());
3084 _parent_focus(obj, item);
3085 elm_widget_focus_region_show(obj);
3090 _parents_on_focus(Evas_Object *obj)
3093 if (!sd->focused || !sd->top_win_focused) return;
3095 Evas_Object *o = elm_widget_parent_get(obj);
3096 if (o) _parents_on_focus(o);
3097 eo_do(obj, elm_obj_widget_on_focus(NULL));
3101 _elm_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3103 Evas_Object *newest = NULL;
3104 unsigned int newest_focus_order = 0;
3106 newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
3108 _parents_on_focus(newest);
3112 _elm_widget_focus_auto_show(Evas_Object *obj)
3114 Evas_Object *top = elm_widget_top_get(obj);
3115 if (top && eo_isa(top, ELM_WIN_CLASS)) _elm_win_focus_auto_show(top);
3119 _elm_widget_top_win_focused_set(Evas_Object *obj,
3120 Eina_Bool top_win_focused)
3126 if (sd->top_win_focused == top_win_focused) return;
3127 EINA_LIST_FOREACH(sd->subobjs, l, child)
3129 if (elm_widget_is(child))
3130 _elm_widget_top_win_focused_set(child, top_win_focused);
3132 sd->top_win_focused = top_win_focused;
3134 if (sd->focused && !sd->top_win_focused)
3135 eo_do(obj, elm_obj_widget_on_focus(NULL));
3139 _elm_widget_top_win_focused_get(const Evas_Object *obj)
3141 API_ENTRY return EINA_FALSE;
3142 return sd->top_win_focused;
3146 _elm_widget_disabled_eval(const Evas_Object *obj, Eina_Bool disabled)
3150 ELM_WIDGET_DATA_GET(obj, sd);
3154 EINA_LIST_FOREACH(sd->subobjs, l, child)
3156 if (elm_widget_is(child))
3158 elm_widget_focus_disabled_handle(child);
3159 eo_do(child, elm_obj_widget_disable());
3160 _elm_widget_disabled_eval(child, EINA_TRUE);
3166 EINA_LIST_FOREACH(sd->subobjs, l, child)
3168 ELM_WIDGET_DATA_GET(child, sdc);
3169 if (elm_widget_is(child) && !sdc->disabled)
3171 elm_widget_focus_disabled_handle(child);
3172 eo_do(child, elm_obj_widget_disable());
3173 _elm_widget_disabled_eval(child, EINA_FALSE);
3180 elm_widget_disabled_internal(Eo *obj, Eina_Bool disabled)
3182 Eina_Bool parent_state = EINA_FALSE;
3186 elm_widget_focus_disabled_handle(obj);
3187 eo_do(obj, elm_obj_widget_disable());
3188 _elm_widget_disabled_eval(obj, EINA_TRUE);
3192 parent_state = elm_widget_disabled_get(elm_widget_parent_get(obj));
3193 if (parent_state) return;
3194 elm_widget_focus_disabled_handle(obj);
3195 eo_do(obj, elm_obj_widget_disable());
3196 _elm_widget_disabled_eval(obj, EINA_FALSE);
3201 _elm_widget_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled)
3203 if (sd->disabled == disabled) return;
3204 sd->disabled = !!disabled;
3206 elm_widget_disabled_internal(obj, disabled);
3209 EOLIAN static Eina_Bool
3210 _elm_widget_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3212 Eina_Bool disabled = EINA_FALSE;
3214 if (sd->disabled) disabled = EINA_TRUE;
3215 else disabled = elm_widget_disabled_get(elm_widget_parent_get(obj));
3220 _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)
3223 Evas_Object *parent_obj, *child_obj;
3224 Evas_Coord px, py, cx, cy, nx = 0, ny = 0;
3227 evas_smart_objects_calculate(evas_object_evas_get(obj));
3229 if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
3230 (w == sd->rw) && (h == sd->rh)) return;
3236 if (sd->on_show_region)
3239 (sd->on_show_region_data, obj);
3241 if (_elm_scrollable_is(obj))
3243 eo_do(obj, elm_interface_scrollable_content_pos_get(&nx, &ny));
3251 parent_obj = sd->parent_obj;
3252 child_obj = sd->obj;
3253 if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
3254 sd = eo_data_scope_get(parent_obj, MY_CLASS);
3257 evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
3258 evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
3267 if (sd->on_show_region)
3270 (sd->on_show_region_data, parent_obj);
3277 _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)
3288 * Get the focus region of the given widget.
3290 * @return show region or not
3291 * (@c EINA_TRUE = show region/@c EINA_FALSE = do not show region). Default is @c EINA_FALSE.
3293 * The focus region is the area of a widget that should brought into the
3294 * visible area when the widget is focused. Mostly used to show the part of
3295 * an entry where the cursor is, for example. The area returned is relative
3296 * to the object @p obj.
3298 * @param obj The widget object
3299 * @param x Where to store the x coordinate of the area
3300 * @param y Where to store the y coordinate of the area
3301 * @param w Where to store the width of the area
3302 * @param h Where to store the height of the area
3306 EOLIAN static Eina_Bool
3307 _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)
3309 Eina_Bool int_ret = EINA_FALSE;
3310 eo_do((Eo *)obj, int_ret = elm_obj_widget_on_focus_region(x, y, w, h));
3313 evas_object_geometry_get(obj, NULL, NULL, w, h);
3317 if ((*w <= 0) || (*h <= 0)) return EINA_FALSE;
3322 _elm_widget_parents_bounce_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool *horiz, Eina_Bool *vert)
3324 Evas_Object *parent_obj = obj;
3325 Eina_Bool h = EINA_FALSE, v = EINA_FALSE;
3327 *horiz = EINA_FALSE;
3332 parent_obj = elm_widget_parent_get(parent_obj);
3333 if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
3335 if (_elm_scrollable_is(parent_obj))
3337 eo_do(parent_obj, elm_interface_scrollable_bounce_allow_get(&h, &v));
3338 if (h) *horiz = EINA_TRUE;
3339 if (v) *vert = EINA_TRUE;
3345 EOLIAN static Eina_List*
3346 _elm_widget_scrollable_children_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3355 EINA_LIST_FOREACH(sd->subobjs, l, child)
3357 if (elm_widget_is(child) && _elm_scrollable_is(child))
3358 ret = eina_list_append(ret, child);
3365 _elm_widget_scroll_hold_push(Eo *obj, Elm_Widget_Smart_Data *sd)
3368 if (sd->scroll_hold == 1)
3370 if (_elm_scrollable_is(obj))
3371 eo_do(obj, elm_interface_scrollable_hold_set(EINA_TRUE));
3374 Eina_List *scr_children, *l;
3377 scr_children = elm_widget_scrollable_children_get(obj);
3378 EINA_LIST_FOREACH(scr_children, l, child)
3380 eo_do(child, elm_interface_scrollable_hold_set(EINA_TRUE));
3382 eina_list_free(scr_children);
3385 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_hold_push());
3386 // FIXME: on delete/reparent hold pop
3390 _elm_widget_scroll_hold_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
3393 if (!sd->scroll_hold)
3395 if (_elm_scrollable_is(obj))
3396 eo_do(obj, elm_interface_scrollable_hold_set(EINA_FALSE));
3399 Eina_List *scr_children, *l;
3402 scr_children = elm_widget_scrollable_children_get(obj);
3403 EINA_LIST_FOREACH(scr_children, l, child)
3405 eo_do(child, elm_interface_scrollable_hold_set(EINA_FALSE));
3407 eina_list_free(scr_children);
3410 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_hold_pop());
3411 if (sd->scroll_hold < 0) sd->scroll_hold = 0;
3415 _elm_widget_scroll_hold_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3417 return sd->scroll_hold;
3421 _elm_widget_scroll_freeze_push(Eo *obj, Elm_Widget_Smart_Data *sd)
3423 sd->scroll_freeze++;
3424 if (sd->scroll_freeze == 1)
3426 if (_elm_scrollable_is(obj))
3427 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_TRUE));
3430 Eina_List *scr_children, *l;
3433 scr_children = elm_widget_scrollable_children_get(obj);
3434 EINA_LIST_FOREACH(scr_children, l, child)
3436 eo_do(child, elm_interface_scrollable_freeze_set(EINA_TRUE));
3438 eina_list_free(scr_children);
3441 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_freeze_push());
3442 // FIXME: on delete/reparent freeze pop
3446 _elm_widget_scroll_freeze_pop(Eo *obj, Elm_Widget_Smart_Data *sd)
3448 sd->scroll_freeze--;
3449 if (!sd->scroll_freeze)
3451 if (_elm_scrollable_is(obj))
3452 eo_do(obj, elm_interface_scrollable_freeze_set(EINA_FALSE));
3455 Eina_List *scr_children, *l;
3458 scr_children = elm_widget_scrollable_children_get(obj);
3459 EINA_LIST_FOREACH(scr_children, l, child)
3461 eo_do(child, elm_interface_scrollable_freeze_set(EINA_FALSE));
3463 eina_list_free(scr_children);
3466 if (sd->parent_obj) eo_do(sd->parent_obj, elm_obj_widget_scroll_freeze_pop());
3467 if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
3471 _elm_widget_scroll_freeze_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3473 return sd->scroll_freeze;
3476 // TIZEN_ONLY(20150705): Genlist item align feature
3478 elm_widget_scroll_item_align_enabled_set(Evas_Object *obj,
3479 Eina_Bool scroll_item_align_enable)
3482 if (sd->scroll_item_align_enable == scroll_item_align_enable) return;
3483 sd->scroll_item_align_enable = scroll_item_align_enable;
3487 elm_widget_scroll_item_align_enabled_get(const Evas_Object *obj)
3489 API_ENTRY return EINA_FALSE;
3490 return sd->scroll_item_align_enable;
3494 elm_widget_scroll_item_valign_set(Evas_Object *obj,
3495 const char *scroll_item_valign)
3498 if (sd->scroll_item_valign) eina_stringshare_del(sd->scroll_item_valign);
3499 if (!scroll_item_valign) sd->scroll_item_valign = NULL;
3500 else sd->scroll_item_valign = eina_stringshare_add(scroll_item_valign);
3504 elm_widget_scroll_item_valign_get(const Evas_Object *obj)
3506 API_ENTRY return NULL;
3507 return sd->scroll_item_valign;
3512 _elm_widget_scale_set(Eo *obj, Elm_Widget_Smart_Data *sd, double scale)
3514 if (scale < 0.0) scale = 0.0;
3515 if (sd->scale != scale)
3518 elm_widget_theme(obj);
3522 EOLIAN static double
3523 _elm_widget_scale_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3525 // FIXME: save walking up the tree by storing/caching parent scale
3526 if (sd->scale == 0.0)
3528 if (sd->parent_obj && elm_widget_is(sd->parent_obj))
3530 return elm_widget_scale_get(sd->parent_obj);
3541 _elm_widget_theme_set(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Theme *th)
3543 Eina_Bool apply = EINA_FALSE;
3544 if (sd->theme != th)
3546 if (elm_widget_theme_get(obj) != th) apply = EINA_TRUE;
3547 if (sd->theme) elm_theme_free(sd->theme);
3550 if (apply) elm_widget_theme(obj);
3555 _elm_widget_part_text_set(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part, const char *label)
3557 if (evas_object_smart_type_check(obj, "elm_layout"))
3558 elm_layout_text_set(obj, part, label);
3561 EOLIAN static const char*
3562 _elm_widget_part_text_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part)
3564 if (evas_object_smart_type_check(obj, "elm_layout"))
3565 return elm_layout_text_get(obj, part);
3570 static Elm_Translate_String_Data *
3571 _translate_string_data_get(Eina_Inlist *translate_strings, const char *part)
3573 Elm_Translate_String_Data *ts;
3574 Eina_Stringshare *str;
3576 if (!translate_strings) return NULL;
3578 str = eina_stringshare_add(part);
3579 EINA_INLIST_FOREACH(translate_strings, ts)
3581 if (ts->id == str) break;
3584 eina_stringshare_del(str);
3589 static Elm_Translate_String_Data *
3590 _part_text_translatable_set(Eina_Inlist **translate_strings, const char *part, Eina_Bool translatable, Eina_Bool preset)
3593 Elm_Translate_String_Data *ts;
3594 t = *translate_strings;
3595 ts = _translate_string_data_get(t, part);
3601 ts = ELM_NEW(Elm_Translate_String_Data);
3602 if (!ts) return NULL;
3604 ts->id = eina_stringshare_add(part);
3605 t = eina_inlist_append(t, (Eina_Inlist*) ts);
3607 if (preset) ts->preset = EINA_TRUE;
3609 //Delete this exist one if this part has been not preset.
3610 //see elm_widget_part_text_translatable_set()
3611 else if (ts && ((preset) || (!ts->preset)))
3613 t = eina_inlist_remove(t, EINA_INLIST_GET(ts));
3614 eina_stringshare_del(ts->id);
3615 eina_stringshare_del(ts->domain);
3616 eina_stringshare_del(ts->string);
3617 ELM_SAFE_FREE(ts, free);
3620 *translate_strings = t;
3626 _elm_widget_domain_translatable_part_text_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, const char *label)
3629 Elm_Translate_String_Data *ts;
3633 _part_text_translatable_set(&sd->translate_strings, part, EINA_FALSE,
3638 ts = _part_text_translatable_set(&sd->translate_strings, part,
3639 EINA_TRUE, EINA_FALSE);
3641 if (!ts->string) ts->string = eina_stringshare_add(label);
3642 else eina_stringshare_replace(&ts->string, label);
3643 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3644 else eina_stringshare_replace(&ts->domain, domain);
3646 if (label[0]) label = dgettext(domain, label);
3650 sd->on_translate = EINA_TRUE;
3651 eo_do(obj, elm_obj_widget_part_text_set(part, label));
3652 sd->on_translate = EINA_FALSE;
3655 EOLIAN static const char*
3656 _elm_widget_translatable_part_text_get(const Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part)
3658 Elm_Translate_String_Data *ts;
3660 ts = _translate_string_data_get(sd->translate_strings, part);
3661 if (ts) return ts->string;
3666 _elm_widget_domain_part_text_translatable_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *part, const char *domain, Eina_Bool translatable)
3668 Elm_Translate_String_Data *ts;
3669 const char *text = NULL;
3671 ts = _part_text_translatable_set(&sd->translate_strings, part,
3672 translatable, EINA_TRUE);
3674 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
3675 else eina_stringshare_replace(&ts->domain, domain);
3677 eo_do(obj, text = elm_obj_widget_part_text_get(part));
3678 if (!text || !text[0]) return;
3680 if (!ts->string) ts->string = eina_stringshare_add(text);
3682 //Try to translate text since we don't know the text is already translated.
3684 text = dgettext(domain, text);
3686 sd->on_translate = EINA_TRUE;
3687 eo_do(obj, elm_obj_widget_part_text_set(part, text));
3688 sd->on_translate = EINA_FALSE;
3692 elm_widget_translate(Evas_Object *obj)
3694 ELM_WIDGET_CHECK(obj);
3695 eo_do(obj, elm_obj_widget_translate());
3699 _part_text_translate(Eina_Inlist *translate_strings,
3703 Elm_Translate_String_Data *ts;
3704 ts = _translate_string_data_get(translate_strings, part);
3705 if (!ts) return text;
3707 if (!ts->string) ts->string = eina_stringshare_add(text);
3708 else eina_stringshare_replace(&ts->string, text);
3710 if (text && text[0])
3711 text = dgettext(ts->domain, text);
3716 EOLIAN static const char*
3717 _elm_widget_part_text_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *part, const char *text)
3721 if (!sd->translate_strings || sd->on_translate) return text;
3722 return _part_text_translate(sd->translate_strings, part, text);
3725 EOLIAN static Eina_Bool
3726 _elm_widget_translate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3730 API_ENTRY return EINA_FALSE;
3732 EINA_LIST_FOREACH(sd->subobjs, l, child)
3734 if (elm_widget_is(child))
3735 elm_widget_translate(child);
3738 if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
3741 Elm_Translate_String_Data *ts;
3742 EINA_INLIST_FOREACH(sd->translate_strings, ts)
3744 if (!ts->string) continue;
3745 const char *s = dgettext(ts->domain, ts->string);
3746 sd->on_translate = EINA_TRUE;
3747 eo_do(obj, elm_obj_widget_part_text_set(ts->id, s));
3748 sd->on_translate = EINA_FALSE;
3751 eo_do(obj, eo_event_callback_call(ELM_WIDGET_EVENT_LANGUAGE_CHANGED, NULL));
3758 * Resets the focus_move_policy mode from the system one
3759 * for widgets that are in automatic mode.
3761 * @param obj The widget.
3765 _elm_widget_focus_move_policy_reload(Evas_Object *obj)
3768 Elm_Focus_Move_Policy focus_move_policy = elm_config_focus_move_policy_get();
3770 if (elm_widget_focus_move_policy_automatic_get(obj) &&
3771 (sd->focus_move_policy != focus_move_policy))
3773 sd->focus_move_policy = focus_move_policy;
3778 _elm_widget_focus_reconfigure(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
3784 EINA_LIST_FOREACH(sd->subobjs, l, child)
3786 if (elm_widget_is(child))
3787 elm_widget_focus_reconfigure(child);
3790 if (sd->hover_obj) elm_widget_focus_reconfigure(sd->hover_obj);
3792 _elm_widget_focus_move_policy_reload(obj);
3795 //TIZEN_ONLY(20160726): add API elm_object_part_access_object_get
3796 EOLIAN static Evas_Object*
3797 _elm_widget_part_access_object_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *part EINA_UNUSED)
3799 WRN("The %s widget does not implement the \"part_access_object_get\" functions.",
3800 eo_class_name_get(eo_class_get(obj)));
3806 elm_widget_content_part_set(Evas_Object *obj,
3808 Evas_Object *content)
3810 ELM_WIDGET_CHECK(obj);
3811 eo_do(obj, elm_obj_container_content_set(part, content));
3815 * Returns the widget's focus_move_policy mode setting.
3817 * @param obj The widget.
3818 * @return focus_move_policy mode setting of the object.
3821 EOLIAN static Eina_Bool
3822 _elm_widget_focus_move_policy_automatic_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3824 return sd->focus_move_policy_auto_mode;
3830 * Sets the widget's focus_move_policy mode setting.
3831 * When widget in automatic mode, it follows the system focus_move_policy mode set by
3832 * elm_config_focus_move_policy_set().
3833 * @param obj The widget.
3834 * @param automatic EINA_TRUE for auto focus_move_policy mode. EINA_FALSE for manual.
3837 _elm_widget_focus_move_policy_automatic_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool automatic)
3839 if (sd->focus_move_policy_auto_mode != automatic)
3841 sd->focus_move_policy_auto_mode = automatic;
3845 elm_widget_focus_move_policy_set(obj, elm_config_focus_move_policy_get());
3851 elm_widget_content_part_get(const Evas_Object *obj,
3854 ELM_WIDGET_CHECK(obj) NULL;
3855 Evas_Object *ret = NULL;
3856 eo_do((Eo *) obj, ret = elm_obj_container_content_get(part));
3861 elm_widget_content_part_unset(Evas_Object *obj,
3864 ELM_WIDGET_CHECK(obj) NULL;
3865 Evas_Object *ret = NULL;
3866 eo_do(obj, ret = elm_obj_container_content_unset(part));
3871 _elm_widget_access_info_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, const char *txt)
3873 eina_stringshare_del(sd->access_info);
3874 if (!txt) sd->access_info = NULL;
3875 else sd->access_info = eina_stringshare_add(txt);
3878 EOLIAN static const char*
3879 _elm_widget_access_info_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3881 return sd->access_info;
3884 EOLIAN static Elm_Theme*
3885 _elm_widget_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3889 if (sd->parent_obj && elm_widget_is(sd->parent_obj))
3890 return elm_widget_theme_get(sd->parent_obj);
3896 EOLIAN static Elm_Theme_Apply
3897 _elm_widget_style_set(Eo *obj, Elm_Widget_Smart_Data *sd, const char *style)
3899 if (eina_stringshare_replace(&sd->style, style))
3900 return elm_widget_theme(obj);
3902 return ELM_THEME_APPLY_SUCCESS;
3905 EOLIAN static const char*
3906 _elm_widget_style_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3910 if (sd->style) ret = sd->style;
3916 _elm_widget_tooltip_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt)
3918 sd->tooltips = eina_list_append(sd->tooltips, tt);
3922 _elm_widget_tooltip_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Tooltip *tt)
3924 sd->tooltips = eina_list_remove(sd->tooltips, tt);
3928 _elm_widget_cursor_add(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Cursor *cur)
3930 sd->cursors = eina_list_append(sd->cursors, cur);
3934 _elm_widget_cursor_del(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Cursor *cur)
3936 sd->cursors = eina_list_remove(sd->cursors, cur);
3940 _elm_widget_drag_lock_x_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock)
3942 if (sd->drag_x_locked == lock) return;
3943 sd->drag_x_locked = lock;
3944 if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
3945 else _propagate_x_drag_lock(obj, -1);
3949 _elm_widget_drag_lock_y_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool lock)
3951 if (sd->drag_y_locked == lock) return;
3952 sd->drag_y_locked = lock;
3953 if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
3954 else _propagate_y_drag_lock(obj, -1);
3957 EOLIAN static Eina_Bool
3958 _elm_widget_drag_lock_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3960 return sd->drag_x_locked;
3963 EOLIAN static Eina_Bool
3964 _elm_widget_drag_lock_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3966 return sd->drag_y_locked;
3970 _elm_widget_drag_child_locked_x_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3972 return sd->child_drag_x_locked;
3976 _elm_widget_drag_child_locked_y_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
3978 return sd->child_drag_y_locked;
3982 _elm_widget_item_loop_enabled_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED, Eina_Bool enable EINA_UNUSED)
3987 EOLIAN static Eina_Bool
3988 _elm_widget_item_loop_enabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd EINA_UNUSED)
3993 EOLIAN static Elm_Theme_Apply
3994 _elm_widget_theme_object_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle)
3996 Elm_Theme_Apply ret = _elm_theme_object_set(obj, edj, wname, welement, wstyle);
3999 return ELM_THEME_APPLY_FAILED;
4002 if (sd->orient_mode != -1)
4005 snprintf(buf, sizeof(buf), "elm,state,orient,%d", sd->orient_mode);
4006 eo_do(obj, elm_obj_widget_signal_emit(buf, "elm"));
4013 _elm_widget_eo_base_dbg_info_get(Eo *eo_obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eo_Dbg_Info *root)
4015 eo_do_super(eo_obj, MY_CLASS, eo_dbg_info_get(root));
4016 Eo_Dbg_Info *group = EO_DBG_INFO_LIST_APPEND(root, MY_CLASS_NAME);
4018 EO_DBG_INFO_APPEND(group, "Wid-Type", EINA_VALUE_TYPE_STRING, elm_widget_type_get(eo_obj));
4019 EO_DBG_INFO_APPEND(group, "Style", EINA_VALUE_TYPE_STRING, elm_widget_style_get(eo_obj));
4020 EO_DBG_INFO_APPEND(group, "Layer", EINA_VALUE_TYPE_INT,
4021 (int) evas_object_layer_get(eo_obj));
4022 EO_DBG_INFO_APPEND(group, "Scale", EINA_VALUE_TYPE_DOUBLE,
4023 evas_object_scale_get(eo_obj));
4024 EO_DBG_INFO_APPEND(group, "Has focus", EINA_VALUE_TYPE_CHAR,
4025 elm_object_focus_get(eo_obj));
4026 EO_DBG_INFO_APPEND(group, "Disabled", EINA_VALUE_TYPE_CHAR,
4027 elm_widget_disabled_get(eo_obj));
4028 EO_DBG_INFO_APPEND(group, "Mirrored", EINA_VALUE_TYPE_CHAR,
4029 elm_widget_mirrored_get(eo_obj));
4030 EO_DBG_INFO_APPEND(group, "Automatic mirroring", EINA_VALUE_TYPE_CHAR,
4031 elm_widget_mirrored_automatic_get(eo_obj));
4035 elm_widget_is_check(const Evas_Object *obj)
4037 static int abort_on_warn = -1;
4038 if (elm_widget_is(obj))
4041 ERR("Passing Object: %p.", obj);
4042 if (abort_on_warn == -1)
4044 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
4045 else abort_on_warn = 0;
4047 if (abort_on_warn == 1) abort();
4052 elm_widget_type_get(const Evas_Object *obj)
4054 API_ENTRY return NULL;
4056 return eo_class_name_get(eo_class_get(obj));
4060 elm_widget_type_check(const Evas_Object *obj,
4064 const char *provided, *expected = "(unknown)";
4065 static int abort_on_warn = -1;
4067 provided = elm_widget_type_get(obj);
4068 /* TODO: eventually migrate to check_ptr version */
4069 if (evas_object_smart_type_check(obj, type)) return EINA_TRUE;
4070 if (type) expected = type;
4071 if ((!provided) || (!provided[0]))
4073 provided = evas_object_type_get(obj);
4074 if ((!provided) || (!provided[0]))
4075 provided = "(unknown)";
4077 ERR("Passing Object: %p in function: %s, of type: '%s' when expecting"
4078 " type: '%s'", obj, func, provided, expected);
4079 if (abort_on_warn == -1)
4081 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
4082 else abort_on_warn = 0;
4084 if (abort_on_warn == 1) abort();
4088 static Evas_Object *
4089 _widget_name_find(const Evas_Object *obj,
4096 INTERNAL_ENTRY NULL;
4098 if (!_elm_widget_is(obj)) return NULL;
4099 EINA_LIST_FOREACH(sd->subobjs, l, child)
4101 s = evas_object_name_get(child);
4102 if ((s) && (!strcmp(s, name))) return child;
4103 if ((recurse != 0) &&
4104 ((child = _widget_name_find(child, name, recurse - 1))))
4109 s = evas_object_name_get(sd->hover_obj);
4110 if ((s) && (!strcmp(s, name))) return sd->hover_obj;
4111 if ((recurse != 0) &&
4112 ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
4118 EOLIAN static Evas_Object*
4119 _elm_widget_name_find(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, const char *name, int recurse)
4121 if (!name) return NULL;
4122 return _widget_name_find(obj, name, recurse);
4128 * Split string in words
4130 * @param str Source string
4131 * @return List of const words
4133 * @see elm_widget_stringlist_free()
4137 elm_widget_stringlist_get(const char *str)
4139 Eina_List *list = NULL;
4141 if (!str) return NULL;
4142 for (b = s = str; 1; s++)
4144 if ((*s == ' ') || (!*s))
4146 char *t = malloc(s - b + 1);
4149 strncpy(t, b, s - b);
4151 list = eina_list_append(list, eina_stringshare_add(t));
4162 elm_widget_stringlist_free(Eina_List *list)
4165 EINA_LIST_FREE(list, s)
4166 eina_stringshare_del(s);
4170 _elm_widget_focus_hide_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4172 if (!_elm_widget_is(obj))
4174 _if_focused_revert(obj, EINA_TRUE);
4178 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
4180 Evas_Object *o = obj;
4183 if (_elm_widget_is(o)) break;
4184 o = evas_object_smart_parent_get(o);
4188 eo_do(o, elm_obj_widget_focus_mouse_up_handle());
4192 _elm_widget_focus_mouse_up_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4195 if (!_is_focusable(obj)) return;
4197 elm_widget_focus_steal(obj, NULL);
4201 _elm_widget_focus_tree_unfocusable_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4203 if (!elm_widget_parent_get(obj))
4204 elm_widget_focused_object_clear(obj);
4206 _if_focused_revert(obj, EINA_TRUE);
4210 _elm_widget_focus_disabled_handle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4212 elm_widget_focus_tree_unfocusable_handle(obj);
4215 EOLIAN static unsigned int
4216 _elm_widget_focus_order_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4218 return sd->focus_order;
4221 EOLIAN static Evas_Object*
4222 _elm_widget_newest_focus_order_get(const Eo *obj, Elm_Widget_Smart_Data *sd, unsigned int *newest_focus_order, Eina_Bool can_focus_only)
4225 Evas_Object *child, *cur, *best;
4227 if (!evas_object_visible_get(obj)
4228 || (elm_widget_disabled_get(obj))
4229 || (elm_widget_tree_unfocusable_get(obj)))
4233 if (*newest_focus_order < sd->focus_order)
4235 if (!can_focus_only || elm_widget_can_focus_get(obj))
4237 *newest_focus_order = sd->focus_order;
4238 best = (Evas_Object *)obj;
4241 EINA_LIST_FOREACH(sd->subobjs, l, child)
4243 if (!_elm_widget_is(child)) continue;
4245 cur = elm_widget_newest_focus_order_get
4246 (child, newest_focus_order, can_focus_only);
4256 * Get the focus highlight geometry of an widget.
4258 * @param obj Widget object for the focus highlight
4259 * @param x Focus highlight x coordinate
4260 * @param y Focus highlight y coordinate
4261 * @param w Focus highlight object width
4262 * @param h Focus highlight object height
4263 * @param is_next @c EINA_TRUE if this request is for the new focused object,
4264 * @c EINA_FALSE if this request is for the previously focused object. This
4265 * information becomes important when the focus highlight is changed inside one
4273 * Get the 'focus_part' geometry if there is any
4275 * This queries if there is a 'focus_part' request from the edc style. If edc
4276 * style offers 'focus_part' edje data item, this function requests for the
4277 * geometry of a specific part which is described in 'focus_part' edje data.
4279 * @param obj Widget object for the focus highlight
4280 * @param x Focus highlight x coordinate
4281 * @param y Focus highlight y coordinate
4282 * @param w Focus highlight object width
4283 * @param h Focus highlight object height
4285 * x, y, w, h already contain the object's geometry. If there is a 'focus_part'
4286 * support, these values will be updated accordingly or the values will be
4287 * remained as they were.
4292 elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj,
4298 Evas_Coord tx = 0, ty = 0, tw = 0, th = 0;
4299 const char *target_hl_part = NULL;
4300 const Evas_Object *edje_obj = NULL;
4302 if (obj && eo_isa(obj, EDJE_OBJECT_CLASS))
4305 if (!(target_hl_part = edje_object_data_get(edje_obj, "focus_part")))
4308 else if (obj && eo_isa(obj, ELM_LAYOUT_CLASS))
4310 edje_obj = elm_layout_edje_get(obj);
4311 if (!(target_hl_part = elm_layout_data_get(obj, "focus_part")))
4317 edje_object_part_geometry_get(edje_obj, target_hl_part,
4318 &tx, &ty, &tw, &th);
4321 if (tw != *w) *w = tw;
4322 if (th != *h) *h = th;
4326 _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)
4328 Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
4329 Evas_Object *scroller = (Evas_Object *)obj;
4331 evas_object_geometry_get(obj, x, y, w, h);
4332 elm_widget_focus_highlight_focus_part_geometry_get(sd->resize_obj, x, y, w, h);
4334 if (_elm_config->focus_autoscroll_mode != ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN)
4339 if (_elm_scrollable_is(scroller))
4342 elm_interface_scrollable_content_viewport_geometry_get(&ox, &oy, &ow, &oh));
4346 else if ((oy + oh) < (*y + *h))
4347 *y = (oy + oh - *h);
4350 else if ((ox + ow) < (*x + *w))
4351 *x = (ox + ow - *w);
4355 scroller = elm_widget_parent_get(scroller);
4359 EOLIAN static Elm_Object_Item*
4360 _elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
4366 _elm_widget_focus_region_show_mode_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Elm_Focus_Region_Show_Mode mode)
4368 _pd->focus_region_show_mode = mode;
4371 EOLIAN static Elm_Focus_Region_Show_Mode
4372 _elm_widget_focus_region_show_mode_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
4374 return _pd->focus_region_show_mode;
4378 elm_widget_activate(Evas_Object *obj, Elm_Activate act)
4380 Evas_Object *parent;
4383 ELM_WIDGET_CHECK(obj);
4387 eo_do(obj, ret = elm_obj_widget_activate(act));
4391 parent = elm_widget_parent_get(obj);
4393 elm_widget_activate(parent, act);
4401 * Sets the widget and child widget's Evas_Display_Mode.
4403 * @param obj The widget.
4404 * @param dispmode Evas_Display_Mode to set widget's mode.
4406 * Widgets are resized by several reasons.
4407 * Evas_Display_Mode can help for widgets to get one more reason of resize.
4408 * For example, elm conform widget resizes it's contents when keypad state changed.
4409 * After keypad showing, conform widget can change child's Evas_Display_Mode.
4413 _elm_widget_display_mode_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Display_Mode dispmode)
4415 Evas_Display_Mode prev_dispmode;
4419 prev_dispmode = evas_object_size_hint_display_mode_get(obj);
4421 if ((prev_dispmode == dispmode) ||
4422 (prev_dispmode == EVAS_DISPLAY_MODE_DONT_CHANGE)) return;
4424 evas_object_size_hint_display_mode_set(obj, dispmode);
4426 EINA_LIST_FOREACH (sd->subobjs, l, child)
4428 if (elm_widget_is(child))
4429 elm_widget_display_mode_set(child, dispmode);
4434 _elm_widget_orientation_mode_disabled_set(Eo *obj, Elm_Widget_Smart_Data *sd, Eina_Bool disabled)
4436 int orient_mode = -1;
4440 //Get current orient mode from it's parent otherwise, 0.
4441 sd->orient_mode = 0;
4442 ELM_WIDGET_DATA_GET(sd->parent_obj, sd_parent);
4443 if (!sd_parent) orient_mode = 0;
4444 else orient_mode = sd_parent->orient_mode;
4446 eo_do(obj, elm_obj_widget_orientation_set(orient_mode));
4449 EOLIAN static Eina_Bool
4450 _elm_widget_orientation_mode_disabled_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4452 if (sd->orient_mode == -1) return EINA_TRUE;
4453 else return EINA_FALSE;
4457 _elm_widget_orientation_set(Eo *obj, Elm_Widget_Smart_Data *sd, int orient_mode)
4462 sd->orient_mode = orient_mode;
4464 EINA_LIST_FOREACH (sd->subobjs, l, child)
4466 if (elm_widget_is(child))
4467 eo_do(child, elm_obj_widget_orientation_set(orient_mode));
4470 if (orient_mode != -1)
4473 snprintf(buf, sizeof(buf), "elm,state,orient,%d", orient_mode);
4474 eo_do(obj, elm_obj_widget_signal_emit(buf, "elm"));
4481 * Returns the widget's focus move policy.
4483 * @param obj The widget.
4484 * @return focus move policy of the object.
4487 EOLIAN static Elm_Focus_Move_Policy
4488 _elm_widget_focus_move_policy_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
4490 return sd->focus_move_policy;
4496 * Sets the widget's focus move policy.
4498 * @param obj The widget.
4499 * @param policy Elm_Focus_Move_Policy to set object's focus move policy.
4503 _elm_widget_focus_move_policy_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Elm_Focus_Move_Policy policy)
4505 if (sd->focus_move_policy == policy) return;
4506 sd->focus_move_policy = policy;
4509 _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
4512 _track_obj_update(Evas_Object *track, Evas_Object *obj)
4515 Evas_Coord x, y, w, h;
4516 evas_object_geometry_get(obj, &x, &y, &w, &h);
4517 evas_object_move(track, x, y);
4518 evas_object_resize(track, w, h);
4521 if (evas_object_visible_get(obj)) evas_object_show(track);
4522 else evas_object_hide(track);
4526 _track_obj_view_update(void *data, Eo *obj,
4527 const Eo_Event_Description *desc EINA_UNUSED,
4528 void *event_info EINA_UNUSED)
4530 Elm_Widget_Item_Data *item = data;
4531 _track_obj_update(item->track_obj, obj);
4532 return EO_CALLBACK_CONTINUE;
4536 _track_obj_view_del(void *data, Eo *obj EINA_UNUSED,
4537 const Eo_Event_Description *desc EINA_UNUSED,
4538 void *event_info EINA_UNUSED);
4540 EO_CALLBACKS_ARRAY_DEFINE(tracker_callbacks,
4541 { EVAS_OBJECT_EVENT_RESIZE, _track_obj_view_update },
4542 { EVAS_OBJECT_EVENT_MOVE, _track_obj_view_update },
4543 { EVAS_OBJECT_EVENT_SHOW, _track_obj_view_update },
4544 { EVAS_OBJECT_EVENT_HIDE, _track_obj_view_update },
4545 { EVAS_OBJECT_EVENT_DEL, _track_obj_view_del });
4548 _track_obj_view_del(void *data, Eo *obj EINA_UNUSED,
4549 const Eo_Event_Description *desc EINA_UNUSED,
4550 void *event_info EINA_UNUSED)
4552 Elm_Widget_Item_Data *item = data;
4554 while (evas_object_ref_get(item->track_obj) > 0)
4555 evas_object_unref(item->track_obj);
4557 evas_object_event_callback_del(item->track_obj, EVAS_CALLBACK_DEL,
4559 evas_object_del(item->track_obj);
4560 item->track_obj = NULL;
4562 return EO_CALLBACK_CONTINUE;
4566 _track_obj_del(void *data, Evas *e EINA_UNUSED,
4567 Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
4569 Elm_Widget_Item_Data *item = data;
4570 item->track_obj = NULL;
4572 if (!item->view) return;
4574 eo_do(item->view, eo_event_callback_array_del(tracker_callbacks(), item));
4578 _elm_widget_item_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission,
4581 Elm_Widget_Item_Signal_Data *wisd = data;
4582 wisd->func(wisd->data, wisd->item, emission, source);
4586 _elm_widget_item_signal_callback_list_get(Elm_Widget_Item_Data *item, Eina_List *position)
4588 Elm_Widget_Item_Signal_Data *wisd = eina_list_data_get(position);
4591 item->signals = eina_list_remove_list(item->signals, position);
4594 if (_elm_widget_is(item->view))
4595 elm_object_signal_callback_del(item->view,
4596 wisd->emission, wisd->source,
4597 _elm_widget_item_signal_cb);
4598 else if (eo_isa(item->view, EDJE_OBJECT_CLASS))
4599 edje_object_signal_callback_del_full(item->view,
4600 wisd->emission, wisd->source,
4601 _elm_widget_item_signal_cb, wisd);
4603 eina_stringshare_del(wisd->emission);
4604 eina_stringshare_del(wisd->source);
4610 #define ERR_NOT_SUPPORTED(item, method) ERR("%s does not support %s API.", elm_widget_type_get(item->widget), method);
4613 _eo_del_cb(void *data EINA_UNUSED, Eo *eo_item, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
4615 Elm_Widget_Item_Data *item = eo_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS);
4616 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_TRUE);
4618 item->del_func((void *) WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4625 * Allocate a new Elm_Widget_Item-derived structure.
4627 * The goal of this structure is to provide common ground for actions
4628 * that a widget item have, such as the owner widget, callback to
4629 * notify deletion, data pointer and maybe more.
4631 * @param widget the owner widget that holds this item, must be an elm_widget!
4632 * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
4633 * be used to allocate memory.
4635 * @return allocated memory that is already zeroed out, or NULL on errors.
4637 * @see elm_widget_item_new() convenience macro.
4638 * @see elm_widget_item_del() to release memory.
4642 _elm_widget_item_eo_base_constructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4644 Evas_Object *widget;
4645 eo_do (eo_item, widget = eo_parent_get());
4647 if (!_elm_widget_is(widget))
4653 eo_item = eo_do_super_ret(eo_item, ELM_WIDGET_ITEM_CLASS, eo_item, eo_constructor());
4655 EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
4657 item->widget = widget;
4658 item->eo_obj = eo_item;
4659 //TIZEN_ONLY(20170717) : expose highlight information on atspi
4660 item->can_highlight = EINA_TRUE;
4663 eo_do(eo_item, eo_event_callback_add(EO_BASE_EVENT_DEL, _eo_del_cb, NULL));
4669 _elm_widget_item_eo_base_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
4671 Elm_Translate_String_Data *ts;
4673 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4675 evas_object_del(item->view);
4677 eina_stringshare_del(item->access_info);
4678 eina_stringshare_del(item->accessible_name);
4680 while (item->signals)
4681 _elm_widget_item_signal_callback_list_get(item, item->signals);
4683 while (item->translate_strings)
4685 ts = EINA_INLIST_CONTAINER_GET(item->translate_strings,
4686 Elm_Translate_String_Data);
4687 eina_stringshare_del(ts->id);
4688 eina_stringshare_del(ts->domain);
4689 eina_stringshare_del(ts->string);
4690 item->translate_strings = eina_inlist_remove(item->translate_strings,
4691 item->translate_strings);
4694 eina_hash_free(item->labels);
4697 elm_interface_atspi_accessible_description_set(NULL),
4698 elm_interface_atspi_accessible_name_set(NULL),
4699 //TIZEN_ONLY(20190922): add name callback, description callback.
4700 elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
4701 elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
4703 elm_interface_atspi_accessible_translation_domain_set(NULL),
4704 elm_interface_atspi_accessible_relationships_clear(),
4705 // TIZEN_ONLY(20160930) : endless recursion fix
4706 elm_interface_atspi_accessible_attributes_clear()
4711 eina_stringshare_del(item->name);
4713 if (item->atspi_custom_relations)
4714 elm_atspi_relation_set_free(&item->atspi_custom_relations);
4716 //TIZEN_ONLY(20150731) : add i18n support for name and description
4717 if (item->atspi_translation_domain)
4718 eina_stringshare_del(item->atspi_translation_domain);
4720 //Tizen Only(20160728) free attribute list
4721 if (item->attr_list)
4723 Elm_Atspi_Attribute *attr;
4724 EINA_LIST_FREE(item->attr_list, attr)
4726 eina_stringshare_del(attr->key);
4727 eina_stringshare_del(attr->value);
4733 //TIZEN_ONLY(20161013): clean up elm color class feature
4734 if (item->color_classes)
4735 ELM_SAFE_FREE(item->color_classes, eina_hash_free);
4738 EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
4740 eo_do_super(eo_item, ELM_WIDGET_ITEM_CLASS, eo_destructor());
4746 * Releases widget item memory, calling back item_del_pre_hook() and
4747 * item_del_cb() if they exist.
4749 * @param item a valid #Elm_Widget_Item to be deleted.
4751 * If there is an Elm_Widget_Item::del_cb, then it will be called prior
4752 * to memory release. Note that elm_widget_item_pre_notify_del() calls
4753 * this function and then unset it, thus being useful for 2 step
4754 * cleanup whenever the del_cb may use any of the data that must be
4755 * deleted from item.
4757 * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
4760 * Note that if item_del_pre_hook() returns @c EINA_TRUE, item free will be
4761 * deferred, or item will be freed here if it returns @c EINA_FALSE.
4763 * @see elm_widget_item_del() convenience macro.
4767 _elm_widget_item_del(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4769 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4770 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4771 item->on_deletion = EINA_TRUE;
4773 //Widget item delete callback
4775 eo_do(item->eo_obj, del_ok = elm_wdg_item_del_pre());
4777 eo_del(item->eo_obj);
4781 EOLIAN static Eina_Bool
4782 _elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
4790 * Notify object will be deleted without actually deleting it.
4792 * This function will callback Elm_Widget_Item::del_cb if it is set
4793 * and then unset it so it is not called twice (ie: from
4794 * elm_widget_item_del()).
4796 * @param item a valid #Elm_Widget_Item to be notified
4797 * @see elm_widget_item_pre_notify_del() convenience macro.
4801 _elm_widget_item_pre_notify_del(Eo *eo_item, Elm_Widget_Item_Data *item)
4803 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4804 if (!item->del_func) return;
4805 item->del_func((void *)WIDGET_ITEM_DATA_GET(eo_item), item->widget, item->eo_obj);
4806 item->del_func = NULL;
4812 * Set the function to notify when item is being deleted.
4814 * This function will complain if there was a callback set already,
4815 * however it will set the new one.
4817 * The callback will be called from elm_widget_item_pre_notify_del()
4818 * or elm_widget_item_del() will be called with:
4819 * - data: the Elm_Widget_Item::data value.
4820 * - obj: the Elm_Widget_Item::widget evas object.
4821 * - event_info: the item being deleted.
4823 * @param item a valid #Elm_Widget_Item to be notified
4824 * @see elm_widget_item_del_cb_set() convenience macro.
4828 _elm_widget_item_del_cb_set(Eo *eo_item EINA_UNUSED,
4829 Elm_Widget_Item_Data *item,
4832 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
4833 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
4835 if ((item->del_func) && (item->del_func != func))
4836 WRN("You're replacing a previously set del_cb %p of item %p with %p",
4837 item->del_func, item->eo_obj, func);
4839 item->del_func = func;
4845 * Get owner widget of this item.
4847 * @param item a valid #Elm_Widget_Item to get data from.
4848 * @return owner widget of this item.
4851 EOLIAN static Evas_Object *
4852 _elm_widget_item_widget_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
4854 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
4855 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
4857 return item->widget;
4861 _elm_widget_onscreen_is(Evas_Object *widget)
4863 Evas_Object *parent = widget;
4864 Evas_Coord x, y, w, h, wx, wy, ww, wh;
4866 Evas *evas = evas_object_evas_get(widget);
4867 if (!evas) return EINA_FALSE;
4869 // check if on canvas
4870 evas_output_viewport_get(evas, &x, &y, &w, &h);
4871 evas_object_geometry_get(widget, &wx, &wy, &ww, &wh);
4872 if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4873 ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4876 // check if inside scrollable parent viewport
4878 parent = elm_widget_parent_get(parent);
4879 if (parent && !evas_object_visible_get(parent))
4881 if (parent && eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
4883 evas_object_geometry_get(parent, &x, &y, &w, &h);
4884 if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4885 ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4888 } while (parent && (parent != elm_widget_top_get(widget)));
4894 _elm_widget_item_onscreen_is(Elm_Object_Item *item)
4896 Evas_Coord x, y, w, h, wx, wy, ww, wh;
4897 Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4898 if (!id || !id->view) return EINA_FALSE;
4900 if (!evas_object_visible_get(id->view))
4903 if (!_elm_widget_onscreen_is(id->widget))
4906 evas_object_geometry_get(id->view, &x, &y, &w, &h);
4907 evas_object_geometry_get(id->widget, &wx, &wy, &ww, &wh);
4908 if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
4909 ((wy < y) && (wy + wh < y)) || ((wy > y+ h) && (wy + wh > y + h)))
4915 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
4917 _elm_widget_item_highlightable(Elm_Object_Item *item)
4919 Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
4920 if (!id) return EINA_FALSE;
4921 if (!id->can_highlight) return EINA_FALSE;
4922 Evas_Object *widget = id->widget;
4923 Evas_Object *parent = widget;
4924 Elm_Widget_Smart_Data *wd;
4925 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
4927 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
4928 if (!wd->can_highlight) return EINA_FALSE;
4932 parent = elm_widget_parent_get(parent);
4933 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
4935 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
4936 if (!wd->can_highlight) return EINA_FALSE;
4939 while (parent && (parent != elm_widget_top_get(widget)));
4944 EOLIAN static Elm_Atspi_State_Set
4945 _elm_widget_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_item,
4946 Elm_Widget_Item_Data *item)
4948 Elm_Atspi_State_Set states = 0;
4950 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
4952 if (elm_object_item_focus_get(eo_item))
4953 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
4954 if (!elm_object_item_disabled_get(eo_item))
4956 STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
4957 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
4958 STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
4960 if (_elm_widget_item_onscreen_is(eo_item))
4961 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
4963 //TIZEN_ONLY(20170717) : expose highlight information on atspi
4964 if (_elm_widget_item_highlightable(eo_item))
4965 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
4967 STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
4969 if (_elm_object_accessibility_currently_highlighted_get() == (void*)item->eo_obj)
4970 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
4976 _elm_widget_item_elm_interface_atspi_accessible_parent_get(Eo *eo_item, Elm_Widget_Item_Data *item EINA_UNUSED)
4979 eo_do(eo_item, parent = eo_parent_get());
4984 elm_object_item_data_set(Elm_Object_Item *it, void *data)
4986 WIDGET_ITEM_DATA_SET(it, data);
4990 elm_object_item_data_get(const Elm_Object_Item *it)
4992 return (void *) WIDGET_ITEM_DATA_GET(it);
4996 _elm_widget_item_disabled_set(Eo *eo_item EINA_UNUSED,
4997 Elm_Widget_Item_Data *item,
5000 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5001 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5003 if (item->disabled == disabled) return;
5004 item->disabled = !!disabled;
5005 eo_do(item->eo_obj, elm_wdg_item_disable());
5008 EOLIAN static Eina_Bool
5009 _elm_widget_item_disabled_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5011 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5012 return item->disabled;
5016 _elm_widget_item_style_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, const char *style EINA_UNUSED)
5018 ERR_NOT_SUPPORTED(item, "elm_object_style_set()");
5021 EOLIAN static const char *
5022 _elm_widget_item_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5024 ERR_NOT_SUPPORTED(item, "elm_object_style_get()");
5029 _elm_widget_item_disable(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item EINA_UNUSED)
5034 _elm_widget_item_focus_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Eina_Bool focused EINA_UNUSED)
5036 ERR_NOT_SUPPORTED(item, "elm_object_item_focus_set");
5039 EOLIAN static Eina_Bool
5040 _elm_widget_item_focus_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5042 ERR_NOT_SUPPORTED(item, "elm_object_item_focus_get");
5047 _elm_widget_item_domain_translatable_part_text_set(Eo *eo_item EINA_UNUSED,
5048 Elm_Widget_Item_Data *item,
5053 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5054 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5055 Elm_Translate_String_Data *ts;
5059 _part_text_translatable_set(&item->translate_strings, part, EINA_FALSE,
5064 ts = _part_text_translatable_set(&item->translate_strings, part,
5065 EINA_TRUE, EINA_FALSE);
5067 if (!ts->string) ts->string = eina_stringshare_add(label);
5068 else eina_stringshare_replace(&ts->string, label);
5069 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5070 else eina_stringshare_replace(&ts->domain, domain);
5072 if (label[0]) label = dgettext(domain, label);
5075 item->on_translate = EINA_TRUE;
5076 eo_do(item->eo_obj, elm_wdg_item_part_text_set(part, label));
5077 item->on_translate = EINA_FALSE;
5080 EOLIAN static const char *
5081 _elm_widget_item_translatable_part_text_get(const Eo *eo_item EINA_UNUSED,
5082 Elm_Widget_Item_Data *item,
5085 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5086 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5088 Elm_Translate_String_Data *ts;
5089 ts = _translate_string_data_get(item->translate_strings, part);
5090 if (ts) return ts->string;
5095 _elm_widget_item_domain_part_text_translatable_set(Eo *eo_item EINA_UNUSED,
5096 Elm_Widget_Item_Data *item,
5099 Eina_Bool translatable)
5101 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5102 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5103 Elm_Translate_String_Data *ts;
5106 ts = _part_text_translatable_set(&item->translate_strings, part,
5107 translatable, EINA_TRUE);
5109 if (!ts->domain) ts->domain = eina_stringshare_add(domain);
5110 else eina_stringshare_replace(&ts->domain, domain);
5112 eo_do(item->eo_obj, text = elm_wdg_item_part_text_get(part));
5114 if (!text || !text[0]) return;
5116 if (!ts->string) ts->string = eina_stringshare_add(text);
5118 //Try to translate text since we don't know the text is already translated.
5120 text = dgettext(domain, text);
5122 item->on_translate = EINA_TRUE;
5123 eo_do (item->eo_obj, elm_wdg_item_part_text_set(part, text));
5124 item->on_translate = EINA_FALSE;
5128 _elm_widget_item_track_cancel(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5130 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5131 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5133 if (!item->track_obj) return;
5135 while (evas_object_ref_get(item->track_obj) > 0)
5136 evas_object_unref(item->track_obj);
5138 evas_object_del(item->track_obj);
5141 EOLIAN static Evas_Object *
5142 _elm_widget_item_track(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5144 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5145 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5147 if (item->track_obj)
5149 evas_object_ref(item->track_obj);
5150 return item->track_obj;
5155 WRN("view obj of the item(%p) is invalid. Please make sure the view obj is created!", item);
5159 Evas_Object *track =
5160 evas_object_rectangle_add(evas_object_evas_get(item->widget));
5161 evas_object_color_set(track, 0, 0, 0, 0);
5162 evas_object_pass_events_set(track, EINA_TRUE);
5163 _track_obj_update(track, item->view);
5164 evas_object_event_callback_add(track, EVAS_CALLBACK_DEL, _track_obj_del,
5168 eo_event_callback_array_add(tracker_callbacks(), item));
5170 evas_object_ref(track);
5172 item->track_obj = track;
5178 _elm_widget_item_untrack(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5180 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5181 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5183 if (!item->track_obj) return;
5184 evas_object_unref(item->track_obj);
5186 if (evas_object_ref_get(item->track_obj) == 0)
5187 evas_object_del(item->track_obj);
5191 _elm_widget_item_track_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5193 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, 0);
5194 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, 0);
5196 if (!item->track_obj) return 0;
5197 return evas_object_ref_get(item->track_obj);
5200 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
5202 struct _Elm_Widget_Item_Tooltip
5204 Elm_Widget_Item_Data *item;
5205 Elm_Tooltip_Item_Content_Cb func;
5206 Evas_Smart_Cb del_cb;
5210 static Evas_Object *
5211 _elm_widget_item_tooltip_label_create(void *data,
5212 Evas_Object *obj EINA_UNUSED,
5213 Evas_Object *tooltip,
5214 void *item EINA_UNUSED)
5216 Evas_Object *label = elm_label_add(tooltip);
5219 elm_object_style_set(label, "tooltip");
5220 elm_object_text_set(label, data);
5224 static Evas_Object *
5225 _elm_widget_item_tooltip_trans_label_create(void *data,
5226 Evas_Object *obj EINA_UNUSED,
5227 Evas_Object *tooltip,
5228 void *item EINA_UNUSED)
5230 Evas_Object *label = elm_label_add(tooltip);
5233 elm_object_style_set(label, "tooltip");
5234 elm_object_translatable_text_set(label, data);
5239 _elm_widget_item_tooltip_label_del_cb(void *data,
5240 Evas_Object *obj EINA_UNUSED,
5241 void *event_info EINA_UNUSED)
5243 eina_stringshare_del(data);
5249 * Set the text to be shown in the widget item.
5251 * @param item Target item
5252 * @param text The text to set in the content
5254 * Setup the text as tooltip to object. The item can have only one tooltip,
5255 * so any previous tooltip data is removed.
5260 _elm_widget_item_tooltip_text_set(Eo *eo_item EINA_UNUSED,
5261 Elm_Widget_Item_Data *item EINA_UNUSED,
5264 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5265 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5266 EINA_SAFETY_ON_NULL_RETURN(text);
5268 text = eina_stringshare_add(text);
5269 eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5270 _elm_widget_item_tooltip_label_create,
5272 _elm_widget_item_tooltip_label_del_cb));
5276 _elm_widget_item_tooltip_translatable_text_set(Eo *eo_item EINA_UNUSED,
5277 Elm_Widget_Item_Data *item EINA_UNUSED,
5280 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5281 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5282 EINA_SAFETY_ON_NULL_RETURN(text);
5284 text = eina_stringshare_add(text);
5285 eo_do(item->eo_obj, elm_wdg_item_tooltip_content_cb_set(
5286 _elm_widget_item_tooltip_trans_label_create,
5288 _elm_widget_item_tooltip_label_del_cb));
5291 static Evas_Object *
5292 _elm_widget_item_tooltip_create(void *data,
5294 Evas_Object *tooltip)
5296 Elm_Widget_Item_Tooltip *wit = data;
5297 return wit->func((void *)wit->data, obj, tooltip, wit->item->eo_obj);
5301 _elm_widget_item_tooltip_del_cb(void *data,
5303 void *event_info EINA_UNUSED)
5305 Elm_Widget_Item_Tooltip *wit = data;
5306 if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item->eo_obj);
5313 * Set the content to be shown in the tooltip item
5315 * Setup the tooltip to item. The item can have only one tooltip,
5316 * so any previous tooltip data is removed. @p func(with @p data) will
5317 * be called every time that need show the tooltip and it should
5318 * return a valid Evas_Object. This object is then managed fully by
5319 * tooltip system and is deleted when the tooltip is gone.
5321 * @param item the widget item being attached a tooltip.
5322 * @param func the function used to create the tooltip contents.
5323 * @param data what to provide to @a func as callback data/context.
5324 * @param del_cb called when data is not needed anymore, either when
5325 * another callback replaces @func, the tooltip is unset with
5326 * elm_widget_item_tooltip_unset() or the owner @a item
5327 * dies. This callback receives as the first parameter the
5328 * given @a data, and @c event_info is the item.
5333 _elm_widget_item_tooltip_content_cb_set(Eo *eo_item EINA_UNUSED,
5334 Elm_Widget_Item_Data *item,
5335 Elm_Tooltip_Item_Content_Cb func,
5337 Evas_Smart_Cb del_cb)
5339 Elm_Widget_Item_Tooltip *wit;
5341 ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
5342 //ELM_WIDGET_ITEM_RETURN_IF_GOTO(item, error_noitem);
5346 eo_do(item->eo_obj, elm_wdg_item_tooltip_unset());
5350 wit = ELM_NEW(Elm_Widget_Item_Tooltip);
5351 if (!wit) goto error;
5355 wit->del_cb = del_cb;
5357 elm_object_sub_tooltip_content_cb_set
5358 (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
5359 _elm_widget_item_tooltip_del_cb);
5364 if (del_cb) del_cb((void *)data, NULL, item);
5367 if (del_cb) del_cb((void *)data, item->widget, item);
5373 * Unset tooltip from item
5375 * @param item widget item to remove previously set tooltip.
5377 * Remove tooltip from item. The callback provided as del_cb to
5378 * elm_widget_item_tooltip_content_cb_set() will be called to notify
5379 * it is not used anymore.
5381 * @see elm_widget_item_tooltip_content_cb_set()
5386 _elm_widget_item_tooltip_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5388 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5389 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5391 elm_object_tooltip_unset(item->view);
5397 * Sets a different style for this item tooltip.
5399 * @note before you set a style you should define a tooltip with
5400 * elm_widget_item_tooltip_content_cb_set() or
5401 * elm_widget_item_tooltip_text_set()
5403 * @param item widget item with tooltip already set.
5404 * @param style the theme style to use (default, transparent, ...)
5409 _elm_widget_item_tooltip_style_set(Eo *eo_item EINA_UNUSED,
5410 Elm_Widget_Item_Data *item,
5413 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5414 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5416 elm_object_tooltip_style_set(item->view, style);
5419 EOLIAN static Eina_Bool
5420 _elm_widget_item_tooltip_window_mode_set(Eo *eo_item EINA_UNUSED,
5421 Elm_Widget_Item_Data *item,
5424 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5425 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5427 return elm_object_tooltip_window_mode_set(item->view, disable);
5430 EOLIAN static Eina_Bool
5431 _elm_widget_item_tooltip_window_mode_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5433 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5434 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, EINA_FALSE);
5436 return elm_object_tooltip_window_mode_get(item->view);
5442 * Get the style for this item tooltip.
5444 * @param item widget item with tooltip already set.
5445 * @return style the theme style in use, defaults to "default". If the
5446 * object does not have a tooltip set, then NULL is returned.
5450 EOLIAN static const char *
5451 _elm_widget_item_tooltip_style_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5453 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5455 return elm_object_tooltip_style_get(item->view);
5459 _elm_widget_item_cursor_set(Eo *eo_item EINA_UNUSED,
5460 Elm_Widget_Item_Data *item,
5463 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5464 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5466 elm_object_sub_cursor_set(item->view, item->widget, cursor);
5469 EOLIAN static const char *
5470 _elm_widget_item_cursor_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5472 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5473 return elm_object_cursor_get(item->view);
5477 _elm_widget_item_cursor_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5479 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5480 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5482 elm_object_cursor_unset(item->view);
5488 * Sets a different style for this item cursor.
5490 * @note before you set a style you should define a cursor with
5491 * elm_widget_item_cursor_set()
5493 * @param item widget item with cursor already set.
5494 * @param style the theme style to use (default, transparent, ...)
5499 _elm_widget_item_cursor_style_set(Eo *eo_item EINA_UNUSED,
5500 Elm_Widget_Item_Data *item,
5503 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5504 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5506 elm_object_cursor_style_set(item->view, style);
5512 * Get the style for this item cursor.
5514 * @param item widget item with cursor already set.
5515 * @return style the theme style in use, defaults to "default". If the
5516 * object does not have a cursor set, then NULL is returned.
5520 EOLIAN static const char *
5521 _elm_widget_item_cursor_style_get(Eo *eo_item EINA_UNUSED,
5522 Elm_Widget_Item_Data *item)
5524 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5525 return elm_object_cursor_style_get(item->view);
5531 * Set if the cursor set should be searched on the theme or should use
5532 * the provided by the engine, only.
5534 * @note before you set if should look on theme you should define a cursor
5535 * with elm_object_cursor_set(). By default it will only look for cursors
5536 * provided by the engine.
5538 * @param item widget item with cursor already set.
5539 * @param engine_only boolean to define it cursors should be looked only
5540 * between the provided by the engine or searched on widget's theme as well.
5545 _elm_widget_item_cursor_engine_only_set(Eo *eo_item EINA_UNUSED,
5546 Elm_Widget_Item_Data *item,
5547 Eina_Bool engine_only)
5549 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5550 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5552 elm_object_cursor_theme_search_enabled_set(item->view, !engine_only);
5558 * Get the cursor engine only usage for this item cursor.
5560 * @param item widget item with cursor already set.
5561 * @return engine_only boolean to define it cursors should be looked only
5562 * between the provided by the engine or searched on widget's theme as well. If
5563 * the object does not have a cursor set, then EINA_FALSE is returned.
5567 EOLIAN static Eina_Bool
5568 _elm_widget_item_cursor_engine_only_get(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5570 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
5571 return !elm_object_cursor_theme_search_enabled_get(item->view);
5575 _elm_widget_item_part_content_set(Eo *eo_item EINA_UNUSED,
5576 Elm_Widget_Item_Data *item,
5577 const char *part EINA_UNUSED,
5578 Evas_Object *content EINA_UNUSED)
5580 ERR_NOT_SUPPORTED(item, "elm_object_part_content_set()");
5583 EOLIAN static Evas_Object *
5584 _elm_widget_item_part_content_get(Eo *eo_item EINA_UNUSED,
5585 Elm_Widget_Item_Data *item,
5586 const char *part EINA_UNUSED)
5588 ERR_NOT_SUPPORTED(item, "elm_object_part_content_get()");
5592 EOLIAN static Evas_Object *
5593 _elm_widget_item_part_content_unset(Eo *eo_item EINA_UNUSED,
5594 Elm_Widget_Item_Data *item,
5595 const char *part EINA_UNUSED)
5597 ERR_NOT_SUPPORTED(item, "elm_object_part_content_unset()");
5602 _elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
5603 Elm_Widget_Item_Data *item,
5604 const char *part EINA_UNUSED,
5605 const char *label EINA_UNUSED)
5607 ERR_NOT_SUPPORTED(item, "elm_object_part_text_set()");
5610 EOLIAN static const char *
5611 _elm_widget_item_part_text_get(Eo *eo_item EINA_UNUSED,
5612 Elm_Widget_Item_Data *item,
5613 const char *part EINA_UNUSED)
5615 ERR_NOT_SUPPORTED(item, "elm_object_part_text_get()");
5620 _elm_widget_item_part_text_custom_free(void *data)
5622 Elm_Label_Data *label;
5624 eina_stringshare_del(label->part);
5625 eina_stringshare_del(label->text);
5630 _elm_widget_item_part_text_custom_set(Eo *eo_item EINA_UNUSED,
5631 Elm_Widget_Item_Data *item,
5635 Elm_Label_Data *label;
5636 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5637 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5641 eina_hash_stringshared_new(_elm_widget_item_part_text_custom_free);
5642 label = eina_hash_find(item->labels, part);
5645 label = malloc(sizeof(Elm_Label_Data));
5648 ERR("Failed to allocate memory");
5651 label->part = eina_stringshare_add(part);
5652 label->text = eina_stringshare_add(text);
5653 eina_hash_add(item->labels, part, label);
5656 eina_stringshare_replace(&label->text, text);
5659 EOLIAN static const char *
5660 _elm_widget_item_part_text_custom_get(Eo *eo_item EINA_UNUSED,
5661 Elm_Widget_Item_Data *item,
5664 Elm_Label_Data *label;
5665 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5666 label = eina_hash_find(item->labels, part);
5667 return label ? label->text : NULL;
5671 _elm_widget_item_part_text_custom_foreach(const Eina_Hash *labels EINA_UNUSED,
5672 const void *key EINA_UNUSED,
5676 Elm_Label_Data *label;
5677 Elm_Widget_Item_Data *item;
5681 eo_do(item->eo_obj, elm_wdg_item_part_text_set(label->part, label->text));
5687 _elm_widget_item_part_text_custom_update(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5689 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5690 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5692 eina_hash_foreach(item->labels,
5693 _elm_widget_item_part_text_custom_foreach, item);
5697 _elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
5698 Elm_Widget_Item_Data *item EINA_UNUSED,
5699 const char *emission EINA_UNUSED,
5700 const char *source EINA_UNUSED)
5706 _elm_widget_item_signal_callback_add(Eo *eo_item,
5707 Elm_Widget_Item_Data *item,
5708 const char *emission,
5710 Elm_Object_Item_Signal_Cb func,
5713 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5714 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5715 EINA_SAFETY_ON_NULL_RETURN(func);
5717 Elm_Widget_Item_Signal_Data *wisd;
5719 wisd = malloc(sizeof(Elm_Widget_Item_Signal_Data));
5722 wisd->item = eo_item;
5723 wisd->func = (Elm_Widget_Item_Signal_Cb)func;
5725 wisd->emission = eina_stringshare_add(emission);
5726 wisd->source = eina_stringshare_add(source);
5728 if (_elm_widget_is(item->view))
5729 elm_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5730 else if (eo_isa(item->view, EDJE_OBJECT_CLASS))
5731 edje_object_signal_callback_add(item->view, emission, source, _elm_widget_item_signal_cb, wisd);
5734 WRN("The %s widget item doesn't support signal callback add!",
5735 eo_class_name_get(eo_class_get(item->widget)));
5740 item->signals = eina_list_append(item->signals, wisd);
5743 EOLIAN static void *
5744 _elm_widget_item_signal_callback_del(Eo *eo_item EINA_UNUSED,
5745 Elm_Widget_Item_Data *item,
5746 const char *emission,
5748 Elm_Object_Item_Signal_Cb func)
5750 Elm_Widget_Item_Signal_Data *wisd;
5753 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
5754 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item, NULL);
5755 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
5757 EINA_LIST_FOREACH(item->signals, l, wisd)
5759 if ((wisd->func == (Elm_Widget_Item_Signal_Cb)func) &&
5760 !strcmp(wisd->emission, emission) &&
5761 !strcmp(wisd->source, source))
5762 return _elm_widget_item_signal_callback_list_get(item, l);
5769 _elm_widget_item_access_info_set(Eo *eo_item EINA_UNUSED,
5770 Elm_Widget_Item_Data *item,
5773 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5774 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5776 eina_stringshare_del(item->access_info);
5777 if (!txt) item->access_info = NULL;
5778 else item->access_info = eina_stringshare_add(txt);
5782 _elm_widget_item_translate(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5784 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
5785 ELM_WIDGET_ITEM_RETURN_IF_ONDEL(item);
5788 Elm_Translate_String_Data *ts;
5789 EINA_INLIST_FOREACH(item->translate_strings, ts)
5791 if (!ts->string) continue;
5792 const char *s = dgettext(ts->domain, ts->string);
5793 item->on_translate = EINA_TRUE;
5794 eo_do(item->eo_obj, elm_wdg_item_part_text_set(ts->id, s));
5795 item->on_translate = EINA_FALSE;
5801 _elm_widget_item_access_order_set(Eo *eo_item EINA_UNUSED,
5802 Elm_Widget_Item_Data *item,
5805 _elm_access_widget_item_access_order_set(item, objs);
5808 EOLIAN static const Eina_List *
5809 _elm_widget_item_access_order_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5811 return _elm_access_widget_item_access_order_get(item);
5815 _elm_widget_item_access_order_unset(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5817 _elm_access_widget_item_access_order_unset(item);
5820 EOLIAN static Evas_Object*
5821 _elm_widget_item_access_register(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5823 _elm_access_widget_item_register(item);
5824 return item->access_obj;
5828 _elm_widget_item_access_unregister(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5830 _elm_access_widget_item_unregister(item);
5833 EOLIAN static Evas_Object*
5834 _elm_widget_item_access_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item)
5836 return item->access_obj;
5839 EOLIAN static Evas_Object *
5840 _elm_widget_item_focus_next_object_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5842 Evas_Object *ret = NULL;
5844 if (dir == ELM_FOCUS_PREVIOUS)
5845 ret = item->focus_previous;
5846 else if (dir == ELM_FOCUS_NEXT)
5847 ret = item->focus_next;
5848 else if (dir == ELM_FOCUS_UP)
5849 ret = item->focus_up;
5850 else if (dir == ELM_FOCUS_DOWN)
5851 ret = item->focus_down;
5852 else if (dir == ELM_FOCUS_RIGHT)
5853 ret = item->focus_right;
5854 else if (dir == ELM_FOCUS_LEFT)
5855 ret = item->focus_left;
5861 _elm_widget_item_focus_next_object_set(Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Evas_Object *next, Elm_Focus_Direction dir)
5863 if (dir == ELM_FOCUS_PREVIOUS)
5864 item->focus_previous = next;
5865 else if (dir == ELM_FOCUS_NEXT)
5866 item->focus_next = next;
5867 else if (dir == ELM_FOCUS_UP)
5868 item->focus_up = next;
5869 else if (dir == ELM_FOCUS_DOWN)
5870 item->focus_down = next;
5871 else if (dir == ELM_FOCUS_RIGHT)
5872 item->focus_right = next;
5873 else if (dir == ELM_FOCUS_LEFT)
5874 item->focus_left = next;
5877 EOLIAN static Elm_Object_Item*
5878 _elm_widget_item_focus_next_item_get(const Eo *eo_item EINA_UNUSED, Elm_Widget_Item_Data *item, Elm_Focus_Direction dir)
5880 Elm_Object_Item *ret = NULL;
5882 if (dir == ELM_FOCUS_PREVIOUS)
5883 ret = item->item_focus_previous;
5884 else if (dir == ELM_FOCUS_NEXT)
5885 ret = item->item_focus_next;
5886 else if (dir == ELM_FOCUS_UP)
5887 ret = item->item_focus_up;
5888 else if (dir == ELM_FOCUS_DOWN)
5889 ret = item->item_focus_down;
5890 else if (dir == ELM_FOCUS_RIGHT)
5891 ret = item->item_focus_right;
5892 else if (dir == ELM_FOCUS_LEFT)
5893 ret = item->item_focus_left;
5899 _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)
5901 if (dir == ELM_FOCUS_PREVIOUS)
5902 item->item_focus_previous = next_item;
5903 else if (dir == ELM_FOCUS_NEXT)
5904 item->item_focus_next = next_item;
5905 else if (dir == ELM_FOCUS_UP)
5906 item->item_focus_up = next_item;
5907 else if (dir == ELM_FOCUS_DOWN)
5908 item->item_focus_down = next_item;
5909 else if (dir == ELM_FOCUS_RIGHT)
5910 item->item_focus_right = next_item;
5911 else if (dir == ELM_FOCUS_LEFT)
5912 item->item_focus_left = next_item;
5915 /* happy debug functions */
5918 _sub_obj_tree_dump(const Evas_Object *obj,
5923 for (i = 0; i < lvl * 3; i++)
5926 if (_elm_widget_is(obj))
5931 elm_widget_type_get(obj),
5933 EINA_LIST_FOREACH(sd->subobjs, l, obj)
5934 _sub_obj_tree_dump(obj, lvl + 1);
5937 DBG("+ %s(%p)\n", evas_object_type_get(obj), obj);
5941 _sub_obj_tree_dot_dump(const Evas_Object *obj,
5944 if (!_elm_widget_is(obj))
5948 Eina_Bool visible = evas_object_visible_get(obj);
5949 Eina_Bool disabled = elm_widget_disabled_get(obj);
5950 Eina_Bool focused = elm_widget_focus_get(obj);
5951 Eina_Bool can_focus = elm_widget_can_focus_get(obj);
5955 fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
5958 fprintf(output, ", style=bold");
5961 fprintf(output, ", color=gray28");
5963 fprintf(output, " ];\n");
5966 fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
5967 "disabled: %d|focused: %d/%d|focus order:%d}\"",
5968 obj, obj, elm_widget_type_get(obj),
5969 evas_object_name_get(obj), visible, disabled, focused, can_focus,
5973 fprintf(output, ", style=bold");
5976 fprintf(output, ", fontcolor=gray28");
5978 if ((disabled) || (!visible))
5979 fprintf(output, ", color=gray");
5981 fprintf(output, " ];\n");
5985 EINA_LIST_FOREACH(sd->subobjs, l, o)
5986 _sub_obj_tree_dot_dump(o, output);
5992 elm_widget_tree_dump(const Evas_Object *top)
5995 if (!_elm_widget_is(top))
5997 _sub_obj_tree_dump(top, 0);
6005 elm_widget_tree_dot_dump(const Evas_Object *top,
6009 if (!_elm_widget_is(top))
6011 fprintf(output, "graph " " { node [shape=record];\n");
6012 _sub_obj_tree_dot_dump(top, output);
6013 fprintf(output, "}\n");
6022 _elm_widget_eo_base_constructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
6026 sd->on_create = EINA_TRUE;
6027 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
6029 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
6030 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
6031 parent = eo_parent_get());
6032 eo_do(obj, elm_obj_widget_parent_set(parent));
6033 sd->on_create = EINA_FALSE;
6034 //TIZEN_ONLY(20170717) : expose highlight information on atspi
6035 sd->can_highlight = EINA_TRUE;
6037 /* TIZEN_ONLY(20160622): Override Paragraph Direction APIs */
6038 sd->inherit_paragraph_direction = EINA_TRUE;
6041 eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_UNKNOWN));
6043 /* TIZEN_ONLY(20161117): Inherit paragraph direction from widget parent */
6044 if (sd->paragraph_direction != evas_object_paragraph_direction_get(parent))
6046 sd->paragraph_direction = evas_object_paragraph_direction_get(parent);
6047 _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, sd->paragraph_direction);
6048 eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(sd->paragraph_direction));
6056 _elm_widget_eo_base_destructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
6058 sd->on_destroy = EINA_TRUE;
6060 elm_interface_atspi_accessible_description_set(NULL),
6061 elm_interface_atspi_accessible_name_set(NULL),
6062 //TIZEN_ONLY(20190922): add name callback, description callback.
6063 elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
6064 elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
6066 elm_interface_atspi_accessible_translation_domain_set(NULL),
6067 elm_interface_atspi_accessible_relationships_clear(),
6068 // TIZEN_ONLY(20160930) : endless recursion fix
6069 elm_interface_atspi_accessible_attributes_clear()
6072 // TIZEN_ONLY(20150709) : atspi relations api
6073 if (sd->atspi_custom_relations)
6074 elm_atspi_relation_set_free(&sd->atspi_custom_relations);
6076 //TIZEN_ONLY(20150717) add widget name setter
6078 eina_stringshare_del(sd->name);
6081 //TIZEN_ONLY(20150731) : add i18n support for name and description
6082 if (sd->atspi_translation_domain)
6083 eina_stringshare_del(sd->atspi_translation_domain);
6085 //Tizen Only(20160728) free attribute list
6088 Elm_Atspi_Attribute *attr;
6089 EINA_LIST_FREE(sd->attr_list, attr)
6091 eina_stringshare_del(attr->key);
6092 eina_stringshare_del(attr->value);
6098 eo_do_super(obj, ELM_WIDGET_CLASS, eo_destructor());
6099 sd->on_destroy = EINA_FALSE;
6101 elm_interface_atspi_accessible_removed(obj);
6104 EOLIAN static Eina_Bool
6105 _elm_widget_on_focus(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *item EINA_UNUSED)
6107 if (elm_widget_can_focus_get(obj))
6109 if (elm_widget_focus_get(obj))
6111 if (!sd->resize_obj)
6112 evas_object_focus_set(obj, EINA_TRUE);
6113 eo_do(obj, eo_event_callback_call
6114 (ELM_WIDGET_EVENT_FOCUSED, NULL));
6115 if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6116 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_TRUE);
6120 if (!sd->resize_obj)
6121 evas_object_focus_set(obj, EINA_FALSE);
6122 eo_do(obj, eo_event_callback_call
6123 (ELM_WIDGET_EVENT_UNFOCUSED, NULL));
6124 if (_elm_atspi_enabled() && !elm_widget_child_can_focus_get(obj))
6125 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_FOCUSED, EINA_FALSE);
6134 EOLIAN static Eina_Bool
6135 _elm_widget_disable(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6140 EOLIAN static Eina_Bool
6141 _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)
6146 EOLIAN static Eina_Bool
6147 _elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6149 WRN("The %s widget does not implement the \"focus_next/focus_next_manager_is\" functions.",
6150 eo_class_name_get(eo_class_get(obj)));
6155 _elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6157 WRN("The %s widget does not implement the \"focus_direction/focus_direction_manager_is\" functions.",
6158 eo_class_name_get(eo_class_get(obj)));
6162 EOLIAN static Eina_Bool
6163 _elm_widget_activate(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Activate act EINA_UNUSED)
6165 WRN("The %s widget does not implement the \"activate\" functions.",
6166 eo_class_name_get(eo_class_get(obj)));
6171 _elm_widget_class_constructor(Eo_Class *klass)
6173 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
6176 EOLIAN static Eina_Bool
6177 _elm_widget_elm_interface_atspi_component_focus_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6179 if (elm_object_focus_allow_get(obj))
6181 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
6182 if (!ee) return EINA_FALSE;
6183 ecore_evas_activate(ee);
6184 elm_object_focus_set(obj, EINA_TRUE);
6190 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
6191 EOLIAN static Eina_Bool
6192 _elm_widget_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6194 if(!_elm_atspi_enabled())
6197 elm_widget_focus_region_show(obj);
6199 elm_object_accessibility_highlight_set(obj, EINA_TRUE);
6200 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
6202 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6203 evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_HIGHLIGHTED, NULL);
6208 EOLIAN static Eina_Bool
6209 _elm_widget_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6211 if(!_elm_atspi_enabled())
6213 elm_object_accessibility_highlight_set(obj, EINA_FALSE);
6214 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
6216 // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
6217 evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, NULL);
6223 EOLIAN static const char*
6224 _elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
6226 char *accessible_name;
6227 //TIZEN_ONLY(20190922): add name callback, description callback.
6228 const char *ret = NULL;
6229 eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_name_get());
6230 if (ret) return ret;
6233 //TIZEN_ONLY(20150717) add widget name setter
6237 if (_pd->atspi_translation_domain)
6238 return dgettext(_pd->atspi_translation_domain, _pd->name);
6244 ret = elm_object_text_get(obj);
6245 if (!ret) return NULL;
6247 accessible_name = _elm_util_mkup_to_text(ret);
6248 eina_stringshare_del(_pd->accessible_name);
6249 _pd->accessible_name = eina_stringshare_add(accessible_name);
6250 free(accessible_name);
6251 return _pd->accessible_name;
6253 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
6255 _elm_widget_elm_interface_atspi_accessible_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *description)
6257 if (_pd->description)
6258 eina_stringshare_del(_pd->description);
6260 _pd->description = eina_stringshare_add(description);
6263 EOLIAN static const char*
6264 _elm_widget_elm_interface_atspi_accessible_description_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
6267 eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_description_get());
6268 if (ret) return ret;
6271 if (_pd->atspi_translation_domain)
6272 return dgettext(_pd->atspi_translation_domain, _pd->description);
6274 return _pd->description;
6278 //TIZEN_ONLY(20150713) : add atspi name setter to widget_item
6280 _elm_widget_item_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *name)
6283 eina_stringshare_del(_pd->name);
6285 _pd->name = eina_stringshare_add(name);
6289 _elm_widget_item_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6291 //TIZEN_ONLY(20190922): add name callback, description callback.
6292 const char *ret = NULL;
6293 eo_do_super(obj, ELM_WIDGET_ITEM_CLASS, ret = elm_interface_atspi_accessible_name_get());
6294 if (ret) return ret;
6300 if (_pd->atspi_translation_domain)
6301 return dgettext(_pd->atspi_translation_domain, _pd->name);
6309 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
6311 _elm_widget_item_elm_interface_atspi_accessible_description_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data* _pd EINA_UNUSED, const char *description)
6313 if (_pd->description)
6314 eina_stringshare_del(_pd->description);
6316 _pd->description = eina_stringshare_add(description);
6320 _elm_widget_item_elm_interface_atspi_accessible_description_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6323 eo_do_super(obj, ELM_WIDGET_ITEM_CLASS, ret = elm_interface_atspi_accessible_description_get());
6324 if (ret) return ret;
6327 if (_pd->atspi_translation_domain)
6328 return dgettext(_pd->atspi_translation_domain, _pd->description);
6330 return _pd->description;
6333 //TIZEN_ONLY(20150709) : spatially sort atspi children
6334 static int _sort_vertically(const void *data1, const void *data2)
6337 evas_object_geometry_get(data1, NULL, &y1, NULL, NULL);
6338 evas_object_geometry_get(data2, NULL, &y2, NULL, NULL);
6340 return y1 < y2 ? -1 : 1;
6343 static int _sort_horizontally(const void *data1, const void *data2)
6346 evas_object_geometry_get(data1, &x1, NULL, NULL, NULL);
6347 evas_object_geometry_get(data2, &x2, NULL, NULL, NULL);
6349 return x1 < x2 ? -1 : 1;
6352 static Eina_List *_lines_split(Eina_List *children)
6355 Eina_List *lines, *line, *l;
6356 Evas_Coord yl, y, hl, h;
6357 lines = line = NULL;
6359 if (!children) return NULL;
6361 EINA_LIST_FOREACH(children, l, c)
6363 evas_object_geometry_get(c, NULL, &yl, NULL, &hl);
6365 /* remove child if its height == 0 */
6369 EINA_LIST_FREE(children, c)
6371 evas_object_geometry_get(c, NULL, &y, NULL, &h);
6373 /* remove child if its height == 0 */
6374 if (h == 0) continue;
6376 if ((yl + (int)(0.25 * hl)) >= y)
6379 line = eina_list_append(line,c);
6383 // finish current line & start new
6384 lines = eina_list_append(lines, line);
6386 line = eina_list_append(NULL, c);
6390 return eina_list_append(lines, line);
6394 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6396 _proxy_widget_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
6401 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
6402 elm_atspi_bridge_utils_proxy_offset_set(proxy, x, y);
6407 _on_widget_del(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6410 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6411 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
6412 _proxy_widget_move_cb, plug);
6418 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6420 _on_proxy_connected_cb(void *data, Eo *obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
6423 Evas_Object *widget = data;
6425 evas_object_geometry_get(widget, &x, &y, NULL, NULL);
6426 elm_atspi_bridge_utils_proxy_offset_set(obj, x, y);
6428 evas_object_event_callback_add(widget, EVAS_CALLBACK_MOVE, _proxy_widget_move_cb, obj);
6434 EOLIAN static Eina_List*
6435 _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6437 Eina_List *l, *accs = NULL;
6438 Elm_Widget_Smart_Data *wd;
6439 Evas_Object *widget;
6440 // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6444 wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6445 if (!wd) return NULL;
6447 EINA_LIST_FOREACH(wd->subobjs, l, widget)
6449 const char *type = evas_object_type_get(widget);
6451 // Ugly Tizen hack to integrate AT-SPI2 accessibility provided by WebKit/Chromium with elementary one.
6452 // This wrapper class should be implemented in Webkit/Chromium EFL ports
6453 if (type && (!strcmp(type, "EWebView") || !strcmp(type, "WebView"))) {
6454 elm_atspi_ewk_wrapper_a11y_init(obj, widget);
6458 EINA_LIST_FOREACH(wd->subobjs, l, widget)
6460 // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
6461 if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN)) {
6462 eo_do(widget, parent = elm_interface_atspi_accessible_parent_get());
6463 if (parent && (parent != obj)) continue;
6466 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6467 const char *plug_id_2;
6468 if ((plug_id_2 = evas_object_data_get(widget, "___PLUGID")) != NULL)
6470 // TIZEN_ONLY(20160930) : endless recursion fix
6471 eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id_2));
6474 char *svcname, *svcnum;
6476 proxy = evas_object_data_get(widget, "__widget_proxy");
6479 accs = eina_list_append(accs, proxy);
6483 if (_elm_atspi_bridge_plug_id_split(plug_id_2, &svcname, &svcnum))
6485 proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
6486 evas_object_data_set(widget, "__widget_proxy", proxy);
6487 eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
6488 eo_do(proxy, eo_event_callback_add(ELM_ATSPI_PROXY_EVENT_CONNECTED, _on_proxy_connected_cb, widget));
6489 elm_atspi_bridge_utils_proxy_connect(proxy);
6490 accs = eina_list_append(accs, proxy);
6498 if (!elm_object_widget_check(widget)) continue;
6499 if (eo_isa(widget, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6500 accs = eina_list_append(accs, widget);
6502 //TIZEN_ONLY(20150709) : spatially sort atspi children
6503 // sort children using its top-left coordinate
6504 accs = eina_list_sort(accs, -1, _sort_vertically);
6505 Eina_List *line, *lines = _lines_split(accs);
6507 EINA_LIST_FREE(lines, line)
6508 accs = eina_list_merge(accs, eina_list_sort(line, -1, _sort_horizontally));
6514 _elm_widget_elm_interface_atspi_accessible_parent_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd)
6517 eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_parent_get());
6519 return ret ? ret : pd->parent_obj;
6522 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
6524 _elm_widget_highlightable(Evas_Object *obj)
6526 Elm_Widget_Smart_Data *wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
6527 if (!wd) return EINA_FALSE;
6528 if (!wd->can_highlight) return EINA_FALSE;
6529 Evas_Object *parent = elm_widget_parent_get(obj);
6530 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6532 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
6533 if (!wd->can_highlight) return EINA_FALSE;
6537 parent = elm_widget_parent_get(parent);
6538 if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6540 wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
6541 if (!wd->can_highlight) return EINA_FALSE;
6544 while (parent && (parent != elm_widget_top_get(obj)));
6549 EOLIAN static Elm_Atspi_State_Set
6550 _elm_widget_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Widget_Smart_Data *pd)
6552 Elm_Atspi_State_Set states = 0;
6554 eo_do_super(obj, ELM_WIDGET_CLASS, states = elm_interface_atspi_accessible_state_set_get());
6556 if (evas_object_visible_get(obj))
6558 STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
6559 if (_elm_widget_onscreen_is(obj))
6560 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
6562 if (!elm_widget_child_can_focus_get(obj))
6564 if (elm_object_focus_allow_get(obj))
6565 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
6566 if (elm_object_focus_get(obj))
6567 STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
6569 if (!elm_object_disabled_get(obj))
6571 STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
6572 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
6575 //TIZEN_ONLY(20170717) : expose highlight information on atspi
6576 if (_elm_widget_highlightable(obj))
6577 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6579 STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
6581 if (_elm_object_accessibility_currently_highlighted_get() == (void*)pd->obj)
6582 STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
6588 //TIZEN_ONLY(20160729): attributes_get, append APIs added/updated.
6589 EOLIAN static Eina_List*
6590 _elm_widget_elm_interface_atspi_accessible_attributes_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
6592 Eina_List *attr_list = NULL;
6593 // TIZEN_ONLY(20160930) : endless recursion fix
6594 eo_do_super(obj, MY_CLASS, attr_list = elm_interface_atspi_accessible_attributes_get());
6596 //Add type and style information in addition.
6597 Elm_Atspi_Attribute *attr = NULL;
6598 attr = calloc(1, sizeof(Elm_Atspi_Attribute));
6601 attr->key = eina_stringshare_add("type");
6602 attr->value = eina_stringshare_add(elm_widget_type_get(obj));
6603 attr_list = eina_list_append(attr_list, attr);
6606 attr = calloc(1, sizeof(Elm_Atspi_Attribute));
6609 attr->key = eina_stringshare_add("style");
6610 attr->value = eina_stringshare_add(elm_widget_style_get(obj));
6611 attr_list = eina_list_append(attr_list, attr);
6617 //TIZEN_ONLY(20150709) : atspi relations api
6618 EOLIAN static Elm_Atspi_Relation_Set
6619 _elm_widget_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
6621 return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
6624 EOLIAN static Elm_Atspi_Relation_Set
6625 _elm_widget_item_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
6627 return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
6632 _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)
6645 evas_object_geometry_get(sd->view, x, y, w, h);
6648 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->view));
6650 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
6656 EOLIAN static Eina_Bool
6657 _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)
6663 _elm_widget_item_elm_interface_atspi_component_layer_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
6667 return evas_object_layer_get(sd->view);
6670 EOLIAN static Eina_Bool
6671 _elm_widget_item_elm_interface_atspi_component_focus_grab(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd EINA_UNUSED)
6673 elm_object_item_focus_set(obj, EINA_TRUE);
6674 return elm_object_item_focus_get(obj);
6677 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods
6678 EOLIAN static Eina_Bool
6679 _elm_widget_item_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
6682 if (!obj) return EINA_FALSE;
6684 Evas_Object *o = elm_object_parent_widget_get(sd->view);
6685 if (_elm_scrollable_is(o))
6687 Evas_Coord bx, by, bw, bh;
6688 Evas_Coord x, y, w, h;
6689 Evas_Object *w1 = elm_object_parent_widget_get(o);
6690 evas_object_geometry_get(sd->view, &x, &y, &w, &h);
6691 evas_object_geometry_get(o, &bx, &by, &bw, &bh);
6694 switch (_elm_config->focus_autoscroll_mode)
6696 case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
6697 eo_do(w1, elm_interface_scrollable_content_region_show(x, y, w, h));
6699 case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
6700 eo_do(w1, elm_interface_scrollable_region_bring_in(x, y, w, h));
6707 elm_object_accessibility_highlight_set(sd->eo_obj, EINA_TRUE);
6708 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
6714 EOLIAN static Eina_Bool
6715 _elm_widget_item_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
6717 if (!obj) return EINA_FALSE;
6718 elm_object_accessibility_highlight_set(sd->eo_obj, EINA_FALSE);
6719 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
6724 EOLIAN static double
6725 _elm_widget_item_elm_interface_atspi_component_alpha_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd EINA_UNUSED)
6729 if (!sd->view) return -1.0;
6730 evas_object_color_get(sd->view, NULL, NULL, NULL, &alpha);
6731 return (double)alpha / 255.0;
6734 //TIZEN_ONLY(20150717) add widget name setter
6736 _elm_widget_elm_interface_atspi_accessible_name_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data* _pd EINA_UNUSED, const char *name)
6739 eina_stringshare_del(_pd->name);
6741 _pd->name = eina_stringshare_add(name);
6745 //TIZEN_ONLY(20160329): widget: improve accessibile_at_point getter (a8aff0423202b9a55dbb3843205875226678fbd6)
6747 _coordinate_system_based_point_translate(Eo *obj, Eina_Bool screen_coords, int *x, int *y)
6755 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
6758 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
6764 static Evas_Object *
6765 _parent_get(Evas_Object *obj)
6767 Evas_Object *parent;
6769 parent = evas_object_smart_parent_get(obj);
6772 if (strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))))
6773 parent = elm_widget_parent_get(obj);
6780 _is_inside(Evas_Object *obj, int x, int y)
6782 Eina_Bool ret = EINA_TRUE;
6787 if (eo_isa(obj, ELM_WIDGET_ITEM_CLASS))
6789 Elm_Widget_Item_Data *id = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
6790 evas_object_geometry_get(id->view, &cx, &cy, &cw, &ch);
6793 evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
6795 /* check the point is out of bound */
6796 if (x < cx || x > cx + cw || y < cy || y > cy + ch)
6804 _is_ancestor_of(Evas_Object *smart_parent, Evas_Object *obj)
6806 Eina_Bool ret = EINA_FALSE;
6807 Evas_Object *parent = elm_widget_parent_get(obj);
6810 /* No need to check more, the smart_parent is parent of obj */
6811 if (smart_parent == parent)
6816 parent = elm_widget_parent_get(parent);
6823 _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
6825 Eina_List *l, *l2, *children, *valid_children = NULL;
6827 Evas_Object *stack_item;
6829 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6831 Evas_Coord px, py, pw, ph;
6834 _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
6836 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
6838 EINA_LIST_FOREACH(children, l2, child)
6840 if (_is_inside(child, x, y))
6841 valid_children = eina_list_append(valid_children, child);
6843 /* Get evas_object stacked at given x,y coordinates starting from top */
6844 Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
6845 /* Foreach stacked object starting from top */
6846 EINA_LIST_FOREACH(stack, l, stack_item)
6848 /* Foreach at-spi valid children traverse stack_item evas_objects hierarchy */
6849 EINA_LIST_FOREACH(valid_children, l2, child)
6851 Elm_Atspi_Role role;
6852 eo_do(child, role = elm_interface_atspi_accessible_role_get());
6853 if (role == ELM_ATSPI_ROLE_REDUNDANT_OBJECT)
6855 /* The redundant object ignores */
6858 /* Compare object used to compare with stacked evas objects */
6859 compare_obj = child;
6860 /* In case of widget_items compare should be different then elm_widget_ item object */
6861 if (eo_isa(child, ELM_WIDGET_ITEM_CLASS))
6863 Elm_Widget_Item_Data *id = eo_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
6864 compare_obj = id->view;
6866 /* In case of access object compare should be 'wrapped' evas_object */
6867 if (eo_isa(child, ELM_ACCESS_CLASS))
6869 Elm_Access_Info *info = _elm_access_info_get(child);
6870 compare_obj = info->part_object;
6872 /* In case of widget is registerd by elm_access_object_register */
6873 Elm_Access_Info *info = _elm_access_info_get(child);
6874 if (info && info->part_object)
6876 compare_obj = info->part_object;
6879 /* In case of ewk wrapper object compare with internal ewk_view evas_object */
6880 if (eo_isa(child, ELM_ATSPI_EWK_WRAPPER_CLASS))
6882 compare_obj = elm_atspi_ewk_wrapper_ewk_view_get(child);
6885 /* If spacial eo children do not have backing evas_object continue with search */
6889 Evas_Object *smart_parent = stack_item;
6890 while (smart_parent)
6892 if (smart_parent == compare_obj)
6894 eina_list_free(children);
6895 eina_list_free(stack);
6899 // TIZEN_ONLY(20160705) - enable atspi_proxy to work
6900 proxy = evas_object_data_get(smart_parent, "__widget_proxy");
6903 evas_object_geometry_get(smart_parent, &px, &py, &pw, &ph);
6904 if (x >= px && x <= px + pw && y >= py && y <= py +ph)
6906 eina_list_free(children);
6907 eina_list_free(stack);
6913 smart_parent = _parent_get(smart_parent);
6914 if (_is_ancestor_of(smart_parent, obj)) break;
6919 eina_list_free(children);
6920 eina_list_free(stack);
6924 static int _sort_by_repeat_events(const void *data1, const void *data2)
6926 Eina_Bool repeat1, repeat2;
6928 repeat1 = evas_object_repeat_events_get(data1);
6929 repeat2 = evas_object_repeat_events_get(data2);
6931 if (repeat1 != repeat2 && repeat1 == EINA_TRUE) return 1;
6936 _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)
6939 Evas_Object *stack_item;
6941 if(strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))))
6942 return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
6944 _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
6946 Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
6947 stack = eina_list_sort(stack, -1, _sort_by_repeat_events);
6949 EINA_LIST_FOREACH(stack, l, stack_item)
6951 Evas_Object *smart_parent = stack_item;
6952 while (smart_parent)
6954 Evas_Object *ao = elm_access_object_get(smart_parent);
6957 if (eo_isa(smart_parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
6959 Eina_Bool acceptable = EINA_FALSE;
6961 Elm_Atspi_Role role;
6962 eo_do(smart_parent, role = elm_interface_atspi_accessible_role_get());
6965 case ELM_ATSPI_ROLE_FILLER: /* ex: View of colorselector item is layout */
6966 case ELM_ATSPI_ROLE_ICON:
6967 case ELM_ATSPI_ROLE_IMAGE:
6968 case ELM_ATSPI_ROLE_REDUNDANT_OBJECT:
6969 case ELM_ATSPI_ROLE_WINDOW:
6970 DBG("Go for parent: %s (%p)\n", evas_object_type_get(smart_parent), smart_parent);
6974 acceptable = EINA_TRUE;
6978 if (acceptable) return smart_parent;
6981 smart_parent = _parent_get(smart_parent);
6988 //TIZEN_ONLY(20150709) add relations atpi
6989 EOLIAN static Eina_Bool
6990 _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)
6992 return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
6996 _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)
6998 elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7001 EOLIAN static Eina_Bool
7002 _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)
7004 return elm_atspi_relation_set_relation_append(&sd->atspi_custom_relations, type, relation_obj);
7008 _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)
7010 elm_atspi_relation_set_relation_remove(&sd->atspi_custom_relations, type, relation_obj);
7014 //TIZEN_ONLY(20150731) : add i18n support for name and description
7016 _elm_widget_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, const char *domain)
7018 eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7021 EOLIAN static const char*
7022 _elm_widget_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
7024 return _pd->atspi_translation_domain;
7028 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, const char *domain)
7030 eina_stringshare_replace(&_pd->atspi_translation_domain, domain);
7033 EOLIAN static const char*
7034 _elm_widget_item_elm_interface_atspi_accessible_translation_domain_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd)
7036 return _pd->atspi_translation_domain;
7039 //TIZEN_ONLY(20160726): add API elm_atspi_accessible_can_highlight_set/get
7041 _children_highlight_check(Eo *obj)
7043 Eina_List *children, *l;
7046 if (_elm_object_accessibility_currently_highlighted_get() == (void *)obj)
7048 eo_do(obj, elm_interface_atspi_component_highlight_clear());
7052 eo_do(obj, children = elm_interface_atspi_accessible_children_get());
7053 EINA_LIST_FOREACH(children, l, child)
7055 if (_children_highlight_check(child)) return EINA_TRUE;
7062 _elm_widget_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Eina_Bool can_highlight)
7064 if (!can_highlight) _children_highlight_check(obj);
7065 _pd->can_highlight = !!can_highlight;
7068 EOLIAN static Eina_Bool
7069 _elm_widget_elm_interface_atspi_accessible_can_highlight_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
7071 return _elm_widget_highlightable(obj);
7075 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_set(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *_pd, Eina_Bool can_highlight)
7077 if (!can_highlight) _children_highlight_check(obj);
7078 _pd->can_highlight = !!can_highlight;
7081 EOLIAN static Eina_Bool
7082 _elm_widget_item_elm_interface_atspi_accessible_can_highlight_get(Eo *obj, Elm_Widget_Item_Data *_pd EINA_UNUSED)
7084 return _elm_widget_item_highlightable(obj);
7088 //TIZEN_ONLY(20160622): Override Paragraph Direction APIs
7090 _elm_widget_evas_object_paragraph_direction_set_internal(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
7095 if (sd->on_destroy) return;
7097 EINA_LIST_FOREACH(sd->subobjs, l, child)
7099 if (_elm_widget_is(child))
7101 Elm_Widget_Smart_Data *sdc = eo_data_scope_get(child, MY_CLASS);
7103 if (sdc->inherit_paragraph_direction &&
7104 (sdc->paragraph_direction != dir))
7106 sdc->paragraph_direction = dir;
7107 _elm_widget_evas_object_paragraph_direction_set_internal(child, sdc, dir);
7108 eo_do_super(child, MY_CLASS, evas_obj_paragraph_direction_set(dir));
7112 /* FIXME: There is no way to handle non-widget child object.
7113 * If a non-widget child object has smart parent, it will get the direction
7114 * from the smart parent. */
7119 _elm_widget_evas_object_paragraph_direction_set(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_BiDi_Direction dir)
7121 if ((!(sd->inherit_paragraph_direction) && (sd->paragraph_direction == dir)) ||
7122 (sd->inherit_paragraph_direction && (dir == EVAS_BIDI_DIRECTION_INHERIT)))
7125 if (dir == EVAS_BIDI_DIRECTION_INHERIT)
7127 sd->inherit_paragraph_direction = EINA_TRUE;
7128 Evas_BiDi_Direction parent_dir = EVAS_BIDI_DIRECTION_NEUTRAL;
7131 parent_dir = evas_object_paragraph_direction_get(sd->parent_obj);
7133 if (parent_dir != sd->paragraph_direction)
7135 sd->paragraph_direction = parent_dir;
7136 _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, parent_dir);
7141 sd->inherit_paragraph_direction = EINA_FALSE;
7142 sd->paragraph_direction = dir;
7143 _elm_widget_evas_object_paragraph_direction_set_internal(obj, sd, dir);
7146 eo_do_super(obj, MY_CLASS, evas_obj_paragraph_direction_set(dir));
7151 //TIZEN_ONLY(20161013): clean up elm color class feature
7153 _edje_color_class_free(void *data)
7155 Edje_Color_Class *cc = data;
7157 if (cc->name) eina_stringshare_del(cc->name);
7162 _elm_widget_edje_class_get(const Eo_Class *klass, const char *style, const char *part)
7165 Eina_Stringshare *str;
7167 buf = eina_strbuf_new();
7169 eina_strbuf_append(buf, strchr(eo_class_name_get(klass), '_') + 1);
7170 eina_strbuf_tolower(buf);
7174 eina_strbuf_append_printf(buf, "/%s/%s", style, part);
7178 eina_strbuf_append_printf(buf, "/%s", part);
7181 str = eina_stringshare_add(eina_strbuf_string_get(buf));
7183 eina_strbuf_free(buf);
7187 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
7189 _elm_widget_color_class_set_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
7190 int r, int g, int b, int a,
7191 int r2, int g2, int b2, int a2,
7192 int r3, int g3, int b3, int a3)
7194 Eina_Bool int_ret = EINA_TRUE;
7195 Eina_Stringshare *buf;
7196 int temp_color[3][4] = { { r, g, b, a },
7198 { r3, g3, b3, a3 } };
7200 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
7202 #define TEMP_COLOR(x, y) \
7203 ((temp_color[x][y] == -1) ? &temp_color[x][y] : NULL)
7205 edje_object_color_class_get(edje, buf,
7206 TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
7207 TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
7208 TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
7212 #define TEMP_COLOR(x, y) \
7213 ((temp_color[x][y] == -1) ? 0 : temp_color[x][y])
7215 int_ret &= edje_object_color_class_set(edje, buf,
7216 TEMP_COLOR(0, 0), TEMP_COLOR(0, 1), TEMP_COLOR(0, 2), TEMP_COLOR(0, 3),
7217 TEMP_COLOR(1, 0), TEMP_COLOR(1, 1), TEMP_COLOR(1, 2), TEMP_COLOR(1, 3),
7218 TEMP_COLOR(2, 0), TEMP_COLOR(2, 1), TEMP_COLOR(2, 2), TEMP_COLOR(2, 3));
7222 eina_stringshare_del(buf);
7228 _elm_widget_color_class_get_internal(Evas_Object *obj, Evas_Object *edje, const char *color_class,
7229 int *r, int *g, int *b, int *a,
7230 int *r2, int *g2, int *b2, int *a2,
7231 int *r3, int *g3, int *b3, int *a3)
7233 Eina_Bool int_ret = EINA_TRUE;
7234 Eina_Stringshare *buf;
7236 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class);
7238 int_ret &= edje_object_color_class_get(edje, buf,
7243 eina_stringshare_del(buf);
7250 _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)
7253 Eina_Bool int_ret = EINA_TRUE;
7255 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7257 edje = elm_layout_edje_get(obj);
7258 int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7267 _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)
7270 Eina_Bool int_ret = EINA_TRUE;
7272 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7274 edje = elm_layout_edje_get(obj);
7275 int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7277 NULL, NULL, NULL, NULL,
7278 NULL, NULL, NULL, NULL);
7284 _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)
7287 Eina_Bool int_ret = EINA_TRUE;
7289 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7291 edje = elm_layout_edje_get(obj);
7292 int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7301 _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)
7304 Eina_Bool int_ret = EINA_TRUE;
7306 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7308 edje = elm_layout_edje_get(obj);
7309 int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7310 NULL, NULL, NULL, NULL,
7312 NULL, NULL, NULL, NULL);
7318 _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)
7321 Eina_Bool int_ret = EINA_TRUE;
7323 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7325 edje = elm_layout_edje_get(obj);
7326 int_ret &= _elm_widget_color_class_set_internal(obj, edje, color_class,
7335 _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)
7338 Eina_Bool int_ret = EINA_TRUE;
7340 if (!eo_isa(obj, ELM_LAYOUT_CLASS)) return EINA_FALSE;
7342 edje = elm_layout_edje_get(obj);
7343 int_ret &= _elm_widget_color_class_get_internal(obj, edje, color_class,
7344 NULL, NULL, NULL, NULL,
7345 NULL, NULL, NULL, NULL,
7351 #define ELM_COLOR_CLASS_UPDATE(obj, hash, cond) \
7352 Evas_Object *edje = NULL; \
7353 Eina_Iterator *itr; \
7354 Edje_Color_Class *cc; \
7355 Eina_Bool int_ret = EINA_TRUE; \
7356 if (cond) return EINA_FALSE; \
7357 if (eo_isa(obj, ELM_LAYOUT_CLASS)) \
7358 edje = elm_layout_edje_get(obj); \
7359 else if (eo_isa(obj, EDJE_OBJECT_CLASS)) \
7361 if (!edje) return EINA_FALSE; \
7362 itr = eina_hash_iterator_data_new(hash); \
7363 EINA_ITERATOR_FOREACH(itr, cc) \
7365 int_ret &= edje_object_color_class_set(edje, cc->name, \
7366 cc->r, cc->g, cc->b, cc->a, \
7367 cc->r2, cc->g2, cc->b2, cc->a2, \
7368 cc->r3, cc->g3, cc->b3, cc->a3); \
7370 eina_iterator_free(itr); \
7374 #define CHECK_BOUND(x) \
7375 if (x > 0xff) x = 0xff; \
7376 else if (x < 0) x = 0
7378 #define ELM_COLOR_CLASS_SET_START(obj, cr, cg, cb, ca) \
7379 Eina_Bool int_ret = EINA_FALSE; \
7380 Edje_Color_Class *cc = NULL; \
7381 Eina_Stringshare *buf; \
7382 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class); \
7387 _elm_color_unpremul(a, &r, &g, &b); \
7388 if (!sd->color_classes) \
7389 sd->color_classes = eina_hash_string_small_new(_edje_color_class_free); \
7391 cc = eina_hash_find(sd->color_classes, buf); \
7394 cc = calloc(1, sizeof(Edje_Color_Class)); \
7395 cc->name = eina_stringshare_add(buf); \
7399 eina_stringshare_del(buf); \
7400 return EINA_FALSE; \
7402 eina_hash_direct_add(sd->color_classes, cc->name, cc); \
7404 else if ((cc->cr == r) && (cc->cg == g) && \
7405 (cc->cb == b) && (cc->ca == a)) \
7407 eina_stringshare_del(buf); \
7416 #define ELM_COLOR_CLASS_SET_END() \
7417 eina_stringshare_del(buf); \
7420 #define ELM_COLOR_CLASS_GET(obj, cr, cg, cb, ca) \
7421 Eina_Bool int_ret = EINA_FALSE; \
7422 Edje_Color_Class *cc; \
7423 Eina_Stringshare *buf; \
7425 buf = _elm_widget_edje_class_get(eo_class_get(obj), NULL, color_class); \
7426 if ((!sd->color_classes) || !(cc = eina_hash_find(sd->color_classes, buf))) \
7432 int_ret = EINA_FALSE; \
7436 if (r) *r = cc->cr; \
7437 if (g) *g = cc->cg; \
7438 if (b) *b = cc->cb; \
7439 if (a) *a = cc->ca; \
7441 int_ret = EINA_TRUE; \
7443 _elm_color_premul(alpha, r, g, b); \
7444 eina_stringshare_del(buf); \
7448 _elm_widget_item_color_class_update(Elm_Widget_Item_Data *sd)
7450 ELM_COLOR_CLASS_UPDATE(sd->view, sd->color_classes, (!sd) || (!sd->color_classes) || (!sd->view));
7454 _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)
7456 ELM_COLOR_CLASS_SET_START(obj, r, g, b, a);
7458 int_ret &= _elm_widget_item_color_class_update(sd);
7460 ELM_COLOR_CLASS_SET_END();
7464 _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)
7466 ELM_COLOR_CLASS_GET(obj, r, g, b, a);
7470 _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)
7472 ELM_COLOR_CLASS_SET_START(obj, r2, g2, b2, a2);
7474 int_ret &= _elm_widget_item_color_class_update(sd);
7476 ELM_COLOR_CLASS_SET_END();
7480 _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)
7482 ELM_COLOR_CLASS_GET(obj, r2, g2, b2, a2);
7486 _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)
7488 ELM_COLOR_CLASS_SET_START(obj, r3, g3, b3, a3);
7490 int_ret &= _elm_widget_item_color_class_update(sd);
7492 ELM_COLOR_CLASS_SET_END();
7496 _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)
7498 ELM_COLOR_CLASS_GET(obj, r3, g3, b3, a3);
7502 /* TIZEN_ONLY(20161025): Apply color_class parent-child relationship */
7504 _elm_widget_color_class_parent_set(Evas_Object *obj, Evas_Object *parent)
7506 Evas_Object *edje = NULL, *parent_edje = NULL;
7508 if (!obj || !parent) return;
7510 if (eo_isa(obj, ELM_LAYOUT_CLASS))
7511 edje = elm_layout_edje_get(obj);
7512 else if (eo_isa(obj, EDJE_OBJECT_CLASS))
7515 if (eo_isa(parent, ELM_LAYOUT_CLASS))
7516 parent_edje = elm_layout_edje_get(parent);
7517 else if (eo_isa(parent, EDJE_OBJECT_CLASS))
7518 parent_edje = parent;
7520 if (!edje || !parent_edje) return;
7522 edje_object_color_class_parent_set(edje, parent_edje);
7526 _elm_widget_color_class_parent_unset(Evas_Object *obj)
7528 Evas_Object *edje = NULL;
7532 if (eo_isa(obj, ELM_LAYOUT_CLASS))
7533 edje = elm_layout_edje_get(obj);
7534 else if (eo_isa(obj, EDJE_OBJECT_CLASS))
7539 edje_object_color_class_parent_unset(edje);
7543 //TIZEN_ONLY(20160527): widget: add AtspiAction interface to all widgets and widget_items, add handlers for reading stopped/cancelled
7544 EOLIAN const Elm_Atspi_Action *
7545 _elm_widget_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd EINA_UNUSED)
7550 EOLIAN const Elm_Atspi_Action *
7551 _elm_widget_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *pd EINA_UNUSED)
7557 #include "elm_widget_item.eo.c"
7558 #include "elm_widget.eo.c"