Suppress build warning message
[platform/upstream/elementary.git] / src / lib / elm_widget.c
index a74f65a..ab47a74 100644 (file)
@@ -952,9 +952,10 @@ elm_widget_access(Evas_Object *obj,
 
 //TIZEN_ONLY(20160822): When atspi mode is dynamically switched on/off,
 //register/unregister access objects accordingly.
+// TIZEN_ONLY(20170516): connect to at-spi dbus based on org.a11y.Status.IsEnabled property
 EAPI Eina_Bool
-elm_widget_atspi(Evas_Object *obj,
-                  Eina_Bool is_atspi)
+elm_widget_screen_reader(Evas_Object *obj,
+                  Eina_Bool is_screen_reader)
 {
    const Eina_List *l;
    Evas_Object *child;
@@ -964,7 +965,31 @@ elm_widget_atspi(Evas_Object *obj,
    EINA_LIST_FOREACH(sd->subobjs, l, child)
      {
         if (elm_widget_is(child))
-          ret &= elm_widget_atspi(child, is_atspi);
+          ret &= elm_widget_screen_reader(child, is_screen_reader);
+     }
+   eo_do(obj, elm_obj_widget_screen_reader(is_screen_reader));
+
+   return ret;
+}
+
+EOLIAN static void
+_elm_widget_screen_reader(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_screen_reader EINA_UNUSED)
+{
+}
+
+//TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+EAPI Eina_Bool
+elm_widget_atspi(Evas_Object *obj, Eina_Bool is_atspi)
+{
+   Eina_List *l, *children;
+   Evas_Object *child;
+   Eina_Bool ret = EINA_TRUE;
+
+   API_ENTRY return EINA_FALSE;
+   eo_do(obj, children = elm_interface_atspi_accessible_children_get());
+   EINA_LIST_FOREACH(children, l, child)
+     {
+        ret &= elm_widget_atspi(child, is_atspi);
      }
    eo_do(obj, elm_obj_widget_atspi(is_atspi));
 
@@ -976,6 +1001,8 @@ _elm_widget_atspi(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, E
 {
 }
 //
+//
+//
 
 EOLIAN static void
 _elm_widget_access(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool is_access EINA_UNUSED)
@@ -4780,6 +4807,10 @@ _elm_widget_item_eo_base_destructor(Eo *eo_item, Elm_Widget_Item_Data *item)
          elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
          elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
          //
+
+         //TIZEN_ONLY(20170405) Add gesture method to accessible interface
+         elm_interface_atspi_accessible_gesture_cb_set(NULL, NULL),
+         //
          elm_interface_atspi_accessible_translation_domain_set(NULL),
          elm_interface_atspi_accessible_relationships_clear(),
                 // TIZEN_ONLY(20160930) : endless recursion fix
@@ -4992,31 +5023,126 @@ _elm_widget_item_onscreen_is(Elm_Object_Item *item)
    return EINA_TRUE;
 }
 
+const char*
+_elm_widget_accessible_plain_name_get(Evas_Object *obj, const char* name)
+{
+   char *accessible_plain_name;
+
+   API_ENTRY return NULL;
+
+   accessible_plain_name = _elm_util_mkup_to_text(name);
+   eina_stringshare_del(sd->accessible_name);
+   sd->accessible_name =  eina_stringshare_add(accessible_plain_name);
+   free(accessible_plain_name);
+   return sd->accessible_name;
+}
+
+const char*
+_elm_widget_item_accessible_plain_name_get(Elm_Object_Item *item, const char* name)
+{
+   char *accessible_plain_name;
+
+   Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
+   if (!id) return NULL;
+
+   accessible_plain_name = _elm_util_mkup_to_text(name);
+   eina_stringshare_del(id->accessible_name);
+   id->accessible_name =  eina_stringshare_add(accessible_plain_name);
+   free(accessible_plain_name);
+   return id->accessible_name;
+}
+
+//TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
+static Eina_Bool
+_elm_widget_can_highlight_get_by_class(Eo *obj)
+{
+   if (eo_isa(obj, ELM_WIDGET_ITEM_CLASS))
+     {
+        Elm_Widget_Item_Data *id = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
+        if (!id) return EINA_FALSE;
+        if (!id->can_highlight) return EINA_FALSE;
+     }
+   else
+     {
+        Elm_Widget_Smart_Data *wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
+        if (!wd) return EINA_FALSE;
+        if (!wd->can_highlight) return EINA_FALSE;
+     }
+   return EINA_TRUE;
+}
+//
+
 //TIZEN_ONLY(20161107): enhance elm_atspi_accessible_can_highlight_set to set can_hihglight property to its children
 EAPI Eina_Bool
 _elm_widget_item_highlightable(Elm_Object_Item *item)
 {
+   Eo *parent;
+
    Elm_Widget_Item_Data *id = eo_data_scope_get(item, ELM_WIDGET_ITEM_CLASS);
    if (!id) return EINA_FALSE;
    if (!id->can_highlight) return EINA_FALSE;
-   Evas_Object *widget = id->widget;
-   Evas_Object *parent = widget;
-   Elm_Widget_Smart_Data *wd;
-   if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
+
+   eo_do(item, parent = elm_interface_atspi_accessible_parent_get());
+   while (parent && !eo_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
      {
-        wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
-        if (!wd->can_highlight) return EINA_FALSE;
+        //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
+        if (!_elm_widget_can_highlight_get_by_class(parent)) return EINA_FALSE;
+        //
+        eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
      }
-   do
+   return EINA_TRUE;
+}
+//
+
+//TIZEN_ONLY(20170206): Add check the object is in the scroller content size
+Eina_Bool
+_accessible_object_on_scroll_is(Eo* obj)
+{
+   /* in case of genlist item, the item->view is NULL if item is unrealized.
+      this function is used to check if obj could have HIGHLIGHTABLE or not.
+      the unrealized genlist item should have HIGHLIGHTABLE state.
+      so if obj is NULL return EINA_TRUE */
+   if(!obj) return EINA_TRUE;
+
+   Evas_Object *target = obj;
+   Evas_Object *parent = NULL;
+   Evas_Coord x, y, w, h, wx, wy, ww = 0, wh = 0, nx = 0, ny = 0;
+
+   evas_object_geometry_get(target, &x, &y ,&w, &h);
+
+   if (elm_widget_is(target))
+     parent = elm_widget_parent_get(target);
+   else
+     parent = elm_widget_parent_widget_get(target);
+
+   while (parent)
      {
-        parent = elm_widget_parent_get(parent);
-        if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
+        if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
           {
-             wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
-             if (!wd->can_highlight) return EINA_FALSE;
+             evas_object_geometry_get(parent, &wx, &wy, NULL, NULL);
+             eo_do(parent, elm_interface_scrollable_content_size_get(&ww, &wh));
+             eo_do(parent, elm_interface_scrollable_content_pos_get(&nx, &ny));
+
+             /* widget implements scrollable interface but does not use scoller
+                in this case, use widget geometry */
+             if (ww == 0 || wh == 0)
+               {
+                  INF("%s is zero sized scrollable content", eo_class_name_get(eo_class_get(parent)));
+                  evas_object_geometry_get(parent, NULL, NULL, &ww, &wh);
+               }
+
+             wx -= nx;
+             wy -= ny;
+
+             if (((wx < x) && (wx + ww < x)) || ((wx > x + w) && (wx + ww > x + w)) ||
+                 ((wy < y) && (wy + wh < y)) || ((wy > y + h) && (wy + wh > y + h)))
+               return EINA_FALSE;
+
+             break;
           }
+        parent = elm_widget_parent_get(parent);
      }
-   while (parent && (parent != elm_widget_top_get(widget)));
+
    return EINA_TRUE;
 }
 //
@@ -5035,13 +5161,19 @@ _elm_widget_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_item,
      {
         STATE_TYPE_SET(states, ELM_ATSPI_STATE_ENABLED);
         STATE_TYPE_SET(states, ELM_ATSPI_STATE_SENSITIVE);
-        STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
      }
    if (_elm_widget_item_onscreen_is(eo_item))
      STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
 
+   //TIZEN_ONLY(20170207) : [ATSPI] enhance expose highlight information on atspi
+   /* unrealized genlist item does not have item->view,
+      and item cannot change its visibility, only widget can change the visibility */
+   if (evas_object_visible_get(item->widget))
+     STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
+   //
+
    //TIZEN_ONLY(20170717) : expose highlight information on atspi
-   if (_elm_widget_item_highlightable(eo_item))
+   if (_elm_widget_item_highlightable(eo_item) && _accessible_object_on_scroll_is(item->view))
      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
    else
      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
@@ -6143,6 +6275,9 @@ _elm_widget_eo_base_destructor(Eo *obj, Elm_Widget_Smart_Data *sd EINA_UNUSED)
          elm_interface_atspi_accessible_description_cb_set(NULL, NULL),
          elm_interface_atspi_accessible_name_cb_set(NULL, NULL),
          //
+         //TIZEN_ONLY(20170405) Add gesture method to accessible interface
+         elm_interface_atspi_accessible_gesture_cb_set(NULL, NULL),
+         //
          elm_interface_atspi_accessible_translation_domain_set(NULL),
          elm_interface_atspi_accessible_relationships_clear(),
          // TIZEN_ONLY(20160930) : endless recursion fix
@@ -6267,14 +6402,207 @@ _elm_widget_elm_interface_atspi_component_focus_grab(Eo *obj, Elm_Widget_Smart_D
    return EINA_FALSE;
 }
 
+//TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
+void
+_elm_widget_showing_geometry_get(Eo *obj, int *x, int *y, int *w, int *h)
+{
+   Evas_Object *parent;
+   Evas_Coord px, py, sx, sy, sw, sh;
+
+   *x = 0;
+   *y = 0;
+   *w = 0;
+   *h = 0;
+
+   if (!obj) return;
+
+   evas_object_geometry_get(obj, x, y, w, h);
+
+   if (elm_widget_is(obj))
+     parent = elm_widget_parent_get(obj);
+   else
+     parent = elm_widget_parent_widget_get(obj);
+
+   while (parent)
+     {
+        if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
+          {
+             evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
+             px = *x;
+             py = *y;
+             *x = *x > sx ? *x : sx;
+             *y = *y > sy ? *y : sy;
+             *w = px + *w < sx + sw ? px + *w - *x : sx + sw - *x;
+             *h = py + *h < sy + sh ? py + *h - *y : sy + sh - *y;
+          }
+        parent = elm_widget_parent_get(parent);
+     }
+}
+
+Eina_Bool
+_accessible_object_on_screen_is(Eo *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool is_complete)
+{
+   if(!obj) return EINA_FALSE;
+
+   Evas_Object *target = obj;
+   Evas_Object *parent = NULL;
+   Evas_Coord px, py, sx, sy, sw, sh, ox, oy, ow, oh;
+
+   /* uninitialized data could be read */
+   ow = 0;
+   oh = 0;
+
+   if (elm_widget_is(target))
+     parent = elm_widget_parent_get(target);
+   else
+     parent = elm_widget_parent_widget_get(target);
+
+   while (parent)
+     {
+        if (eo_isa(parent, ELM_INTERFACE_SCROLLABLE_MIXIN))
+          {
+             evas_object_geometry_get(parent, &sx, &sy, &sw, &sh);
+             px = ox = x;
+             py = oy = y;
+             ow = w;
+             oh = h;
+             ox = is_complete ? ox : ox + ow;
+             oy = is_complete ? oy : oy + oh;
+             ox = ox > sx ? ox : sx;
+             oy = oy > sy ? oy : sy;
+             ow = px + ow < sx + sw ? px + ow - ox : sx + sw - ox;
+             oh = py + oh < sy + sh ? py + oh - oy : sy + sh - oy;
+          }
+        if (ow <= 0 || oh <= 0)
+          return EINA_FALSE;
+
+        parent = elm_widget_parent_get(parent);
+     }
+   return EINA_TRUE;
+}
+
+Eina_List *
+_accessible_scrollable_parent_list_get(Eo *obj)
+{
+   if(!obj) return NULL;
+
+   Evas_Object *parent = NULL;
+   Eina_List *plist = NULL;
+
+   if (elm_widget_is(obj))
+     parent = elm_widget_parent_get(obj);
+   else
+     parent = elm_widget_parent_widget_get(obj);
+
+   while (parent)
+     {
+        if (_elm_scrollable_is(parent))
+          plist = eina_list_append(plist, parent);
+
+        parent = elm_widget_parent_get(parent);
+   }
+   return plist;
+}
+
+void
+_accessible_highlight_region_show(Eo* obj)
+{
+   if (!obj) return;
+
+   Evas_Object *target = obj;
+   Evas_Object *parent = NULL;
+   Evas_Object *parent_sub = NULL;
+   Eina_List *plist, *plist_sub;
+   Eina_List *l, *l2;
+
+   Evas_Coord target_x, target_y, target_w, target_h;
+
+   evas_object_geometry_get(target, &target_x, &target_y, &target_w, &target_h);
+
+   plist = _accessible_scrollable_parent_list_get(target);
+   if (!plist) return;
+
+   EINA_LIST_FOREACH(plist, l, parent)
+     {
+        if(!_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_TRUE))
+          {
+             plist_sub = _accessible_scrollable_parent_list_get(parent);
+             plist_sub = eina_list_prepend(plist_sub, parent);
+             EINA_LIST_FOREACH(plist_sub, l2, parent_sub)
+               {
+                  Evas_Coord scroll_x = 0, scroll_y = 0;
+                  Evas_Coord scroll_x_back = 0, scroll_y_back = 0;
+                  Evas_Coord x, y, w, h;
+                  Evas_Coord px, py;
+
+                  eo_do(parent_sub, elm_interface_scrollable_content_region_get(&scroll_x_back, &scroll_y_back, NULL, NULL));
+                  evas_object_geometry_get(parent_sub, &px, &py, NULL, NULL);
+                  x = target_x; y = target_y; w = target_w; h = target_h;
+
+                  x -= (px - scroll_x_back);
+                  y -= (py - scroll_y_back);
+                  switch (_elm_config->focus_autoscroll_mode)
+                    {
+                       case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
+                          eo_do(parent_sub, elm_interface_scrollable_content_region_show(x, y, w, h));
+                          break;
+                       case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
+                          eo_do(parent_sub, elm_interface_scrollable_region_bring_in(x, y, w, h));
+                          break;
+                       default:
+                          break;
+                    }
+                  eo_do(parent_sub, elm_interface_scrollable_content_region_get(&scroll_x, &scroll_y, NULL, NULL));
+
+                  target_x -= (scroll_x - scroll_x_back);
+                  target_y -= (scroll_y - scroll_y_back);
+
+                  if(_accessible_object_on_screen_is(target, target_x, target_y, target_w, target_h, EINA_FALSE))
+                    break;
+               }
+             eina_list_free(plist_sub);
+          }
+     }
+
+   eina_list_free(plist);
+}
+//
+
+//TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
+Eina_Bool
+_elm_widget_accessibility_highlight_grabbing_get(Eo *obj)
+{
+   ELM_WIDGET_DATA_GET(obj, wd);
+   return wd->highlight_grabbing;
+}
+
+void
+_elm_widget_accessibility_highlight_grabbing_set(Eo *obj, Eina_Bool grabbing)
+{
+   ELM_WIDGET_DATA_GET(obj, wd);
+   wd->highlight_grabbing = grabbing;
+}
+//
+
 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods (29e253e2f7ef3c632ac3a64c489bf569df407f30)
 EOLIAN static Eina_Bool
 _elm_widget_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
 {
+   if(!obj) return EINA_FALSE;
    if(!_elm_atspi_enabled())
       return EINA_FALSE;
+   // TIZEN_ONLY(20171020) : atspi : Do not send signal, if current object and highlight object are same
+   if (_elm_object_accessibility_currently_highlighted_get() == obj)
+      return EINA_FALSE;
+   //
 
-   elm_widget_focus_region_show(obj);
+   //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
+   _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_TRUE);
+   //
+
+   //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
+   _accessible_highlight_region_show(obj);
+   //
 
    elm_object_accessibility_highlight_set(obj, EINA_TRUE);
    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
@@ -6282,6 +6610,9 @@ _elm_widget_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Sma
    // TIZEN_ONLY(20161018): add highlighted/unhighlighted signal for atspi
    evas_object_smart_callback_call(obj, SIG_WIDGET_ATSPI_HIGHLIGHTED, NULL);
    //
+   //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
+   _elm_widget_accessibility_highlight_grabbing_set(obj, EINA_FALSE);
+   //
    return EINA_TRUE;
 }
 
@@ -6301,9 +6632,8 @@ _elm_widget_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Sm
 //
 
 EOLIAN static const char*
-_elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd)
+_elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Widget_Smart_Data *_pd)
 {
-   char *accessible_name;
    //TIZEN_ONLY(20190922): add name callback, description callback.
    const char *ret = NULL;
    eo_do_super(obj, ELM_WIDGET_CLASS, ret = elm_interface_atspi_accessible_name_get());
@@ -6321,14 +6651,17 @@ _elm_widget_elm_interface_atspi_accessible_name_get(Eo *obj EINA_UNUSED, Elm_Wid
      }
    //
 
+   //TIZEN_ONLY(20170110) : Ignore text from elm_object_text_set in accessible_name_get
+   Elm_Atspi_Role role;
+   eo_do(obj, role = elm_interface_atspi_accessible_role_get());
+   if(role == ELM_ATSPI_ROLE_DIALOG)
+     return NULL;
+   //
+
    ret = elm_object_text_get(obj);
    if (!ret) return NULL;
 
-   accessible_name = _elm_util_mkup_to_text(ret);
-   eina_stringshare_del(_pd->accessible_name);
-   _pd->accessible_name =  eina_stringshare_add(accessible_name);
-   free(accessible_name);
-   return _pd->accessible_name;
+   return _elm_widget_accessible_plain_name_get(obj, ret);
 }
 //TIZEN_ONLY(20161111) add widget/widget_item description get/set
 EOLIAN void
@@ -6451,7 +6784,7 @@ static Eina_List *_lines_split(Eina_List *children)
         evas_object_geometry_get(c, NULL, &y, NULL, &h);
 
         /* remove child if its height == 0 */
-        if (h == 0) continue;
+        if (h == 0 && !eo_isa(c, ELM_ATSPI_PROXY_CLASS)) continue;
 
         if ((yl + (int)(0.25 * hl)) >= y)
           {
@@ -6511,6 +6844,58 @@ _on_proxy_connected_cb(void *data, Eo *obj, const Eo_Event_Description *desc EIN
 //
 // TIZEN ONLY - END
 
+//TIZEN_ONLY(20170621) handle atspi proxy connection at runtime
+static Eo *
+_plug_type_proxy_get(Eo *obj, Evas_Object *widget)
+{
+   Eo *proxy = NULL;
+   const char *plug_id;
+   char *svcname, *svcnum;
+
+   if ((plug_id = evas_object_data_get(widget, "___PLUGID")) != NULL)
+     {
+        // TIZEN_ONLY(20160930) : endless recursion fix
+        eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id));
+
+        proxy = evas_object_data_get(widget, "__widget_proxy");
+        if (proxy) return proxy;
+
+        if (_elm_atspi_bridge_plug_id_split(plug_id, &svcname, &svcnum))
+          {
+             proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
+             evas_object_data_set(widget, "__widget_proxy", proxy);
+             eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
+             eo_do(proxy, eo_event_callback_add(ELM_ATSPI_PROXY_EVENT_CONNECTED, _on_proxy_connected_cb, widget));
+             elm_atspi_bridge_utils_proxy_connect(proxy);
+             free(svcname);
+             free(svcnum);
+          }
+     }
+
+   return proxy;
+}
+
+EAPI Eo *
+elm_widget_atspi_plug_type_proxy_get(Evas_Object *obj)
+{
+   Elm_Widget_Smart_Data *wd;
+   Evas_Object *widget;
+   Eina_List *l;
+
+   wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
+   if (!wd) return NULL;
+
+   Eo *proxy = NULL;
+   EINA_LIST_FOREACH(wd->subobjs, l, widget)
+     {
+        if (evas_object_data_get(widget, "___PLUGID"))
+           proxy = _plug_type_proxy_get(obj, widget);
+        if (proxy) break;
+     }
+   return proxy;
+}
+//
+
 EOLIAN static Eina_List*
 _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
 {
@@ -6535,6 +6920,7 @@ _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smar
         }
      }
 
+   Eo *proxy = NULL;
    EINA_LIST_FOREACH(wd->subobjs, l, widget)
      {
         // TIZEN_ONLY(20160824): Do not append a child, if its accessible parent is different with widget parent
@@ -6544,34 +6930,15 @@ _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smar
         }
 
         // TIZEN_ONLY(20160705) - enable atspi_proxy to work
-        const char *plug_id_2;
-        if ((plug_id_2 = evas_object_data_get(widget, "___PLUGID")) != NULL)
+        /* This assumes that only one proxy exists in obj */
+        if (!proxy)
           {
-            // TIZEN_ONLY(20160930) : endless recursion fix
-            eo_do_super(obj, MY_CLASS, elm_interface_atspi_accessible_attribute_append("___PlugID", plug_id_2));
-
-             Eo *proxy;
-             char *svcname, *svcnum;
-
-             proxy = evas_object_data_get(widget, "__widget_proxy");
+             proxy = _plug_type_proxy_get(obj, widget);
              if (proxy)
                {
                   accs = eina_list_append(accs, proxy);
                   continue;
                }
-
-             if (_elm_atspi_bridge_plug_id_split(plug_id_2, &svcname, &svcnum))
-               {
-                  proxy = _elm_atspi_bridge_utils_proxy_create(obj, svcname, atoi(svcnum), ELM_ATSPI_PROXY_TYPE_PLUG);
-                  evas_object_data_set(widget, "__widget_proxy", proxy);
-                  eo_do(widget, eo_event_callback_add(EO_EV_DEL, _on_widget_del, proxy));
-                  eo_do(proxy, eo_event_callback_add(ELM_ATSPI_PROXY_EVENT_CONNECTED,  _on_proxy_connected_cb, widget));
-                  elm_atspi_bridge_utils_proxy_connect(proxy);
-                  accs = eina_list_append(accs, proxy);
-                  free(svcname);
-                  free(svcnum);
-               }
-             continue;
           }
         //
         // TIZEN ONLY - END
@@ -6587,6 +6954,30 @@ _elm_widget_elm_interface_atspi_accessible_children_get(Eo *obj, Elm_Widget_Smar
    EINA_LIST_FREE(lines, line)
      accs = eina_list_merge(accs, eina_list_sort(line, -1, _sort_horizontally));
    //
+
+   if (proxy)
+     {
+        Eo *deputy = NULL;
+        accs = eina_list_remove(accs, proxy);
+        EINA_LIST_FOREACH(accs, l, widget)
+          {
+              if (eo_isa(widget, ELM_ACCESS_CLASS))
+                {
+                   Elm_Access_Info *info = _elm_access_info_get(widget);
+                   if (!info) continue;
+                   if (obj == info->part_object)
+                     {
+                        deputy = widget;
+                        break;
+                     }
+                }
+          }
+
+        if (deputy)
+          {
+             accs = eina_list_append_relative(accs, proxy, deputy);
+          }
+     }
    return accs;
 }
 
@@ -6603,25 +6994,20 @@ _elm_widget_elm_interface_atspi_accessible_parent_get(Eo *obj EINA_UNUSED, Elm_W
 EAPI Eina_Bool
 _elm_widget_highlightable(Evas_Object *obj)
 {
+   Eo *parent;
+
    Elm_Widget_Smart_Data *wd = eo_data_scope_get(obj, ELM_WIDGET_CLASS);
    if (!wd) return EINA_FALSE;
    if (!wd->can_highlight) return EINA_FALSE;
-   Evas_Object *parent = elm_widget_parent_get(obj);
-   if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
-     {
-        wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
-        if (!wd->can_highlight) return EINA_FALSE;
-     }
-   do
+
+   eo_do(obj, parent = elm_interface_atspi_accessible_parent_get());
+   while (parent && !eo_isa(parent, ELM_ATSPI_APP_OBJECT_CLASS))
      {
-        parent = elm_widget_parent_get(parent);
-        if (parent && eo_isa(parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
-          {
-             wd = eo_data_scope_get(parent, ELM_WIDGET_CLASS);
-             if (!wd->can_highlight) return EINA_FALSE;
-          }
+        //TIZEN_ONLY(20160929) : atspi: Improves how to find the can_highlight of the widget
+        if (!_elm_widget_can_highlight_get_by_class(parent)) return EINA_FALSE;
+        //
+        eo_do(parent, parent = elm_interface_atspi_accessible_parent_get());
      }
-   while (parent && (parent != elm_widget_top_get(obj)));
    return EINA_TRUE;
 }
 //
@@ -6653,7 +7039,7 @@ _elm_widget_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Widget_Sma
      }
 
    //TIZEN_ONLY(20170717) : expose highlight information on atspi
-   if (_elm_widget_highlightable(obj))
+   if (_elm_widget_highlightable(obj) && _accessible_object_on_scroll_is(obj))
      STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
    else
      STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
@@ -6706,6 +7092,21 @@ _elm_widget_item_elm_interface_atspi_accessible_relation_set_get(Eo *obj EINA_UN
 {
    return elm_atspi_relation_set_clone(&sd->atspi_custom_relations);
 }
+
+EOLIAN static void
+_elm_widget_elm_interface_atspi_accessible_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
+{
+   elm_atspi_relation_set_free(&sd->atspi_custom_relations);
+   sd->atspi_custom_relations = NULL;
+}
+//
+
+EOLIAN static void
+_elm_widget_item_elm_interface_atspi_accessible_relationships_clear(Eo *obj EINA_UNUSED, Elm_Widget_Item_Data *sd)
+{
+   elm_atspi_relation_set_free(&sd->atspi_custom_relations);
+   sd->atspi_custom_relations = NULL;
+}
 //
 
 EOLIAN static void
@@ -6755,40 +7156,38 @@ _elm_widget_item_elm_interface_atspi_component_focus_grab(Eo *obj EINA_UNUSED, E
 }
 
 //TIZEN_ONLY(20160329): atspi: implement HighlightGrab and HighlightClear methods
+
 EOLIAN static Eina_Bool
 _elm_widget_item_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
 {
+   if (!sd) return EINA_FALSE;
+   if (!sd->view) return EINA_FALSE;
+   // TIZEN_ONLY(20171020) : atspi : Do not send signal, if current object and highlight object are same
+   if (_elm_object_accessibility_currently_highlighted_get() == obj)
+      return EINA_FALSE;
+   //
 
-   if (!obj) return EINA_FALSE;
+   //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
+   _elm_widget_accessibility_highlight_grabbing_set(sd->view, EINA_TRUE);
+   //
 
-   Evas_Object *o = elm_object_parent_widget_get(sd->view);
-   if (_elm_scrollable_is(o))
-     {
-        Evas_Coord bx, by, bw, bh;
-        Evas_Coord x, y, w, h;
-        Evas_Object *w1 = elm_object_parent_widget_get(o);
-        evas_object_geometry_get(sd->view, &x, &y, &w, &h);
-        evas_object_geometry_get(o, &bx, &by, &bw, &bh);
-        x -= bx;
-        y -= by;
-        switch (_elm_config->focus_autoscroll_mode)
-          {
-           case ELM_FOCUS_AUTOSCROLL_MODE_SHOW:
-              eo_do(w1, elm_interface_scrollable_content_region_show(x, y, w, h));
-              break;
-           case ELM_FOCUS_AUTOSCROLL_MODE_BRING_IN:
-              eo_do(w1, elm_interface_scrollable_region_bring_in(x, y, w, h));
-              break;
-           default:
-              break;
-          }
-     }
+   //TIZEN_ONLY(20170119): Show the object highlighted by highlight_grab when the object is completely out of the scroll
+   _accessible_highlight_region_show(sd->view);
+   //
 
+   if (!sd->eo_obj) return EINA_FALSE;
    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_TRUE);
+
+   if (!obj) return EINA_FALSE;
    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
 
+   //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
+   evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_HIGHLIGHTED, obj);
+   //
+   //TIZEN_ONLY(20171011) : atspi : During the highlight grab, out signal is not sent.
+   _elm_widget_accessibility_highlight_grabbing_set(sd->view, EINA_FALSE);
+   //
    return EINA_TRUE;
-
 }
 
 EOLIAN static Eina_Bool
@@ -6797,6 +7196,10 @@ _elm_widget_item_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widg
    if (!obj) return EINA_FALSE;
    elm_object_accessibility_highlight_set(sd->eo_obj, EINA_FALSE);
    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
+
+   //TIZEN_ONLY(20170412) Make atspi,(un)highlighted work on widget item
+   evas_object_smart_callback_call(sd->widget, SIG_WIDGET_ATSPI_UNHIGHLIGHTED, obj);
+   //
    return EINA_TRUE;
 }
 //
@@ -6899,6 +7302,122 @@ _is_ancestor_of(Evas_Object *smart_parent, Evas_Object *obj)
    return ret;
 }
 
+static int _sort_by_size(const void *data1, const void *data2)
+{
+   Evas_Coord w, h;
+   Evas_Coord w2, h2;
+
+   evas_object_geometry_get(data1, NULL, NULL, &w, &h);
+   evas_object_geometry_get(data2, NULL, NULL, &w2, &h2);
+
+   if ((w * h) > (w2 * h2)) return 1;
+   return -1;
+}
+
+Eina_Bool
+_elm_widget_atspi_role_acceptable_check(Eo *obj)
+{
+   Elm_Atspi_Role role;
+   eo_do(obj, role = elm_interface_atspi_accessible_role_get());
+
+   switch (role)
+     {
+       case ELM_ATSPI_ROLE_APPLICATION:
+       case ELM_ATSPI_ROLE_FILLER:
+       case ELM_ATSPI_ROLE_SCROLL_PANE:
+       case ELM_ATSPI_ROLE_SPLIT_PANE:
+       case ELM_ATSPI_ROLE_WINDOW:
+       case ELM_ATSPI_ROLE_IMAGE:
+       case ELM_ATSPI_ROLE_LIST:
+       case ELM_ATSPI_ROLE_ICON:
+       case ELM_ATSPI_ROLE_TOOL_BAR:
+       case ELM_ATSPI_ROLE_REDUNDANT_OBJECT:
+       case ELM_ATSPI_ROLE_COLOR_CHOOSER:
+       case ELM_ATSPI_ROLE_TREE_TABLE:
+       case ELM_ATSPI_ROLE_PAGE_TAB_LIST:
+       case ELM_ATSPI_ROLE_PAGE_TAB:
+       case ELM_ATSPI_ROLE_SPIN_BUTTON:
+       case ELM_ATSPI_ROLE_INPUT_METHOD_WINDOW:
+       case ELM_ATSPI_ROLE_EMBEDDED:
+       case ELM_ATSPI_ROLE_INVALID:
+       case ELM_ATSPI_ROLE_NOTIFICATION:
+       case ELM_ATSPI_ROLE_DATE_EDITOR:
+         return EINA_FALSE;
+       default:
+         break;
+     }
+
+   return EINA_TRUE;
+}
+
+static Eo *
+_child_object_at_point_get(Eo *obj, int x, int y)
+{
+   Eina_List *l, *l_next, *children, *valid_children = NULL;
+   Eo *child;
+   Eo *target;
+   int count;
+
+   eo_do(obj, children = elm_interface_atspi_accessible_children_get());
+
+   EINA_LIST_FOREACH(children, l, child)
+     {
+        if (_is_inside(child, x, y))
+          valid_children = eina_list_append(valid_children, child);
+     }
+
+   EINA_LIST_FOREACH_SAFE(valid_children, l, l_next, child)
+     {
+        eo_do(child, children = elm_interface_atspi_accessible_children_get());
+
+        /* do not use unacceptable leaf node */
+        if (!_elm_widget_atspi_role_acceptable_check(child) &&
+            eina_list_count(children) == 0)
+          valid_children = eina_list_remove_list(valid_children, l);
+     }
+
+   count = eina_list_count(valid_children);
+   if (count > 0)
+     {
+        valid_children = eina_list_sort(valid_children, -1, _sort_by_size);
+        target = eina_list_nth(valid_children, 0);
+
+        return _child_object_at_point_get(target, x, y);
+     }
+
+   return obj;
+}
+
+static Eina_Bool
+_acceptable_child_is(Eo *obj)
+{
+   Elm_Atspi_Role role;
+   Eina_List *children;
+   Elm_Atspi_State_Set ss;
+
+   eo_do(obj, role = elm_interface_atspi_accessible_role_get());
+   switch (role)
+     {
+       case ELM_ATSPI_ROLE_IMAGE:
+       case ELM_ATSPI_ROLE_ICON:
+         /* remove unacceptable leaf node */
+         eo_do(obj, children = elm_interface_atspi_accessible_children_get());
+         if (!children) return EINA_FALSE;
+         break;
+
+       case ELM_ATSPI_ROLE_PANEL:
+         /* remove closed panel fron children list */
+         eo_do(obj, ss = elm_interface_atspi_accessible_state_set_get());
+         if (!STATE_TYPE_GET(ss, ELM_ATSPI_STATE_SHOWING)) return EINA_FALSE;
+         break;
+
+       default:
+         break;
+     }
+
+   return EINA_TRUE;
+}
+
 static Eo *
 _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Eina_Bool screen_coords, int x, int y)
 {
@@ -6917,9 +7436,20 @@ _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSE
 
    EINA_LIST_FOREACH(children, l2, child)
      {
-        if (_is_inside(child, x, y))
+        if (_is_inside(child, x, y) && _acceptable_child_is(child))
           valid_children = eina_list_append(valid_children, child);
      }
+
+   /* If there is only one valid child at point, then return it.
+      The evas_tree_objects_at_xy_get could not find proper object,
+      if application does not have well aligned objects. */
+   if (eina_list_count(valid_children) == 1)
+     {
+        eina_list_free(children);
+        child = eina_list_nth(valid_children, 0);
+        return child;
+     }
+
    /* Get evas_object stacked at given x,y coordinates starting from top */
    Eina_List *stack = evas_tree_objects_at_xy_get(evas_object_evas_get(obj), NULL, x, y);
    /* Foreach stacked object starting from top */
@@ -6928,13 +7458,6 @@ _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSE
         /* Foreach at-spi valid children traverse stack_item evas_objects hierarchy */
         EINA_LIST_FOREACH(valid_children, l2, child)
           {
-             Elm_Atspi_Role role;
-             eo_do(child, role = elm_interface_atspi_accessible_role_get());
-             if (role == ELM_ATSPI_ROLE_REDUNDANT_OBJECT)
-               {
-                  /* The redundant object ignores */
-                  continue;
-               }
              /* Compare object used to compare with stacked evas objects */
              compare_obj = child;
              /* In case of widget_items compare should be different then elm_widget_ item  object */
@@ -6942,6 +7465,16 @@ _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSE
                {
                   Elm_Widget_Item_Data *id = eo_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
                   compare_obj = id->view;
+                  if (TIZEN_PROFILE_WEARABLE)
+                    {
+                       Eo* it_view = evas_object_image_source_get(stack_item);
+                       if (it_view && it_view == compare_obj)
+                         {
+                            eina_list_free(children);
+                            eina_list_free(stack);
+                            return child;
+                         }
+                    }
                }
              /* In case of access object compare should be 'wrapped' evas_object */
              if (eo_isa(child, ELM_ACCESS_CLASS))
@@ -7006,12 +7539,24 @@ _accessible_at_point_top_down_get(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSE
 
 static int _sort_by_repeat_events(const void *data1, const void *data2)
 {
+   Evas_Object *ao1, *ao2;
    Eina_Bool repeat1, repeat2;
 
+   ao1 = elm_access_object_get(data1);
+   ao2 = elm_access_object_get(data2);
+
    repeat1 = evas_object_repeat_events_get(data1);
    repeat2 = evas_object_repeat_events_get(data2);
 
-   if (repeat1 != repeat2 && repeat1 == EINA_TRUE) return 1;
+   if (repeat1 != repeat2)
+     {
+        if (repeat1 && !ao1) return 1;
+     }
+   else
+     {
+        if (repeat1 && !ao1 && ao2) return 1;
+     }
+
    return -1;
 }
 
@@ -7037,7 +7582,9 @@ _elm_widget_elm_interface_atspi_component_accessible_at_point_get(Eo *obj, Elm_W
    Eina_List *l;
    Evas_Object *stack_item;
 
-   if(strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))))
+   if(strcmp("Elm_Win", eo_class_name_get(eo_class_get(obj))) &&
+      strcmp("Elm_Popup", eo_class_name_get(eo_class_get(obj))) &&
+      strcmp("Elm_Panel", eo_class_name_get(eo_class_get(obj))))
      return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
 
    _coordinate_system_based_point_translate(obj, screen_coords, &x, &y);
@@ -7050,13 +7597,18 @@ _elm_widget_elm_interface_atspi_component_accessible_at_point_get(Eo *obj, Elm_W
         Evas_Object *smart_parent = stack_item;
         while (smart_parent)
           {
+             /* If parent equals to obj, it is not necessary to go upper.
+                So the top down logic would be better than NULL return. */
+             if (smart_parent == obj)
+               return _accessible_at_point_top_down_get(obj, _pd, screen_coords, x, y);
+
              Evas_Object *ao = elm_access_object_get(smart_parent);
              if (ao) return ao;
 
              if (eo_isa(smart_parent, ELM_INTERFACE_ATSPI_ACCESSIBLE_MIXIN))
                {
                   Eina_Bool acceptable = EINA_FALSE;
-
+                  Eo *item_child;
                   Elm_Atspi_Role role;
                   eo_do(smart_parent, role = elm_interface_atspi_accessible_role_get());
                   switch (role)
@@ -7070,7 +7622,13 @@ _elm_widget_elm_interface_atspi_component_accessible_at_point_get(Eo *obj, Elm_W
                        break;
 
                      case ELM_ATSPI_ROLE_LIST:
-                       return _item_at_point_get(smart_parent, x, y);
+                       item_child = _item_at_point_get(smart_parent, x, y);
+                       if (TIZEN_PROFILE_WEARABLE)
+                         {
+                            item_child = _child_object_at_point_get(item_child, x, y);
+                            return item_child;
+                         }
+                       return item_child;
                        break;
 
                      default: