atspi: implement HighlightGrab and HighlightClear methods 32/53832/4
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Wed, 9 Dec 2015 14:19:29 +0000 (15:19 +0100)
committerShinwoo Kim <cinoo.kim@samsung.com>
Tue, 29 Mar 2016 07:51:31 +0000 (16:51 +0900)
Conflicts:
src/lib/elm_widget.c
src/lib/elm_widget.eo

Change-Id: Id29ca5b1acc2c617c9d746848df1cad1510b24dd

src/imported/atspi/atspi-constants.h
src/lib/elm_atspi_bridge.c
src/lib/elm_interface_atspi_accessible.h
src/lib/elm_interface_atspi_component.c
src/lib/elm_interface_atspi_component.eo
src/lib/elm_widget.c
src/lib/elm_widget.eo
src/lib/elm_widget_item.eo

index 3675bcc..dd10679 100644 (file)
@@ -412,7 +412,13 @@ typedef enum {
  * @ATSPI_STATE_INVALID: Indicates an invalid state - probably an error 
  * condition.
  * @ATSPI_STATE_ACTIVE: Indicates a window is currently the active window, or
- * is an active subelement within a container or table.
+ * an object is the active subelement within a container or table.
+ * @ATSPI_STATE_ACTIVE should not be used for objects which have
+ * @ATSPI_STATE_FOCUSABLE or @ATSPI_STATE_SELECTABLE: Those objects should use
+ * @ATSPI_STATE_FOCUSED and @ATSPI_STATE_SELECTED respectively.
+ * @ATSPI_STATE_ACTIVE is a means to indicate that an object which is not
+ * focusable and not selectable is the currently-active item within its
+ * parent container.
  * @ATSPI_STATE_ARMED: Indicates that the object is armed.
  * @ATSPI_STATE_BUSY: Indicates the current object is busy, i.e. onscreen
  * representation is in the process of changing, or       the object is
@@ -561,6 +567,15 @@ typedef enum {
  * showing. This means that activation renders conditional content.
  * Note that ordinary tooltips are not considered popups in this
  * context. @Since: 2.12
+ * @ATSPI_STATE_READ_ONLY: Indicates that an object which is ENABLED and
+ * SENSITIVE has a value which can be read, but not modified, by the
+ * user. @Since: 2.16
+ * @ATSPI_STATE_HIGHLIGHTED: Indicates that an object which is HIGHLIGHTABLE
+ * has been graphically marked to assits visally impared users. Only one
+ * object per window can have ATSPI_STATE_HIGHLIGHTED  state.
+ * @ATSPI_STATE_HIGHLIGHTABLE: Indicates that an object can be graphically
+ * marked to assist visially impaired users.
+ * user. @Since: 2.16
  * @ATSPI_STATE_LAST_DEFINED: This value of the enumeration should not be used
  * as a parameter, it indicates the number of items in the #AtspiStateType
  * enumeration.
@@ -614,6 +629,9 @@ typedef enum {
     ATSPI_STATE_VISITED,
     ATSPI_STATE_CHECKABLE,
     ATSPI_STATE_HAS_POPUP,
+    ATSPI_STATE_READ_ONLY,
+    ATSPI_STATE_HIGHLIGHTED,
+    ATSPI_STATE_HIGHLIGHTABLE,
     ATSPI_STATE_LAST_DEFINED,
 } AtspiStateType;
 
@@ -982,8 +1000,13 @@ typedef enum {
  * @ATSPI_ROLE_TEAROFF_MENU_ITEM: Object allows menu to be removed from menubar
  * and shown in its own window.
  * @ATSPI_ROLE_TERMINAL: An object that emulates a terminal.
- * @ATSPI_ROLE_TEXT: An object that presents text to the user, of nonspecific
- * type.
+ * @ATSPI_ROLE_TEXT: An interactive widget that supports multiple lines of text
+ * and optionally accepts user input, but whose purpose is not to solicit user
+ * input. Thus @ATSPI_ROLE_TEXT is appropriate for the text view in a plain text
+ * editor but inappropriate for an input field in a dialog box or web form. For
+ * widgets whose purpose is to solicit input from the user, see @ATSPI_ROLE_ENTRY
+ * and @ATSPI_ROLE_PASSWORD_TEXT. For generic objects which display a brief amount
+ * of textual information, see @ATSPI_ROLE_STATIC.
  * @ATSPI_ROLE_TOGGLE_BUTTON: A specialized push button that can be checked or
  * unchecked, but does not procide a separate indicator for the current
  * state.
@@ -1105,9 +1128,9 @@ typedef enum {
  * particular application.
  * @ATSPI_ROLE_INFO_BAR: An object designed to present a message to the user
  * within an existing window.
- *@ATSPI_ROLE_LEVEL_BAR: A bar that serves as a level indicator to, for
+ * @ATSPI_ROLE_LEVEL_BAR: A bar that serves as a level indicator to, for
  * instance, show the strength of a password or the state of a battery. 
- * Since: 2.8
+ *   Since: 2.8
  *@ATSPI_ROLE_TITLE_BAR: A bar that serves as the title of a window or a
  * dialog. @Since: 2.12
  *@ATSPI_ROLE_BLOCK_QUOTE: An object which contains a text section
@@ -1145,6 +1168,27 @@ typedef enum {
  *@ATSPI_ROLE_TIMER: An object containing a numerical counter which
  * indicates an amount of elapsed time from a start point, or the time
  * remaining until an end point. @Since: 2.12
+ *@ATSPI_ROLE_STATIC: A generic non-container object whose purpose is to display
+ * a brief amount of information to the user and whose role is known by the
+ * implementor but lacks semantic value for the user. Examples in which
+ * @ATSPI_ROLE_STATIC is appropriate include the message displayed in a message
+ * box and an image used as an alternative means to display text.
+ * @ATSPI_ROLE_STATIC should not be applied to widgets which are traditionally
+ * interactive, objects which display a significant amount of content, or any
+ * object which has an accessible relation pointing to another object. The
+ * displayed information, as a general rule, should be exposed through the
+ * accessible name of the object. For labels which describe another widget, see
+ * @ATSPI_ROLE_LABEL. For text views, see @ATSPI_ROLE_TEXT. For generic
+ * containers, see @ATSPI_ROLE_PANEL. For objects whose role is not known by the
+ * implementor, see @ATSPI_ROLE_UNKNOWN. @Since: 2.16.
+ *@ATSPI_ROLE_MATH_FRACTION: An object that represents a mathematical fraction.
+ * @Since: 2.16.
+ *@ATSPI_ROLE_MATH_ROOT: An object that represents a mathematical expression
+ * displayed with a radical. @Since: 2.16.
+ *@ATSPI_ROLE_SUBSCRIPT: An object that contains text that is displayed as a
+ * subscript. @Since: 2.16.
+ *@ATSPI_ROLE_SUPERSCRIPT: An object that contains text that is displayed as a
+ * superscript. @Since: 2.16.
  * @ATSPI_ROLE_LAST_DEFINED: Not a valid role, used for finding end of
  * enumeration.
  *
@@ -1269,6 +1313,11 @@ typedef enum {
     ATSPI_ROLE_MATH,
     ATSPI_ROLE_RATING,
     ATSPI_ROLE_TIMER,
+    ATSPI_ROLE_STATIC,
+    ATSPI_ROLE_MATH_FRACTION,
+    ATSPI_ROLE_MATH_ROOT,
+    ATSPI_ROLE_SUBSCRIPT,
+    ATSPI_ROLE_SUPERSCRIPT,
     ATSPI_ROLE_LAST_DEFINED,
 } AtspiRole;
 
@@ -1277,7 +1326,7 @@ typedef enum {
  *
  * One higher than the highest valid value of #AtspiRole.
  */
-#define ATSPI_ROLE_COUNT (90+1)
+#define ATSPI_ROLE_COUNT (121+1)
 
 typedef enum
 {
index edd10fc..1f6857e 100644 (file)
@@ -437,7 +437,12 @@ const struct atspi_state_desc elm_states_to_atspi_state[] = {
    { ELM_ATSPI_STATE_SELECTABLE_TEXT, ATSPI_STATE_SELECTABLE_TEXT, "selectable-text" },
    { ELM_ATSPI_STATE_IS_DEFAULT, ATSPI_STATE_IS_DEFAULT, "is-default" },
    { ELM_ATSPI_STATE_VISITED, ATSPI_STATE_VISITED, "visited" },
-   { ELM_ATSPI_STATE_LAST_DEFINED, ATSPI_STATE_LAST_DEFINED, "last-defined" },
+   { ELM_ATSPI_STATE_CHECKABLE, ATSPI_STATE_CHECKABLE, "checkable" },
+   { ELM_ATSPI_STATE_HAS_POPUP, ATSPI_STATE_HAS_POPUP, "has-popup" },
+   { ELM_ATSPI_STATE_READ_ONLY, ATSPI_STATE_READ_ONLY, "read-only" },
+   { ELM_ATSPI_STATE_HIGHLIGHTED, ATSPI_STATE_HIGHLIGHTED, "highlighted" },
+   { ELM_ATSPI_STATE_HIGHLIGHTABLE, ATSPI_STATE_HIGHLIGHTABLE, "highlightable" },
+   { ELM_ATSPI_STATE_LAST_DEFINED, ATSPI_STATE_LAST_DEFINED, "last-defined" }
 };
 
 const int elm_relation_to_atspi_relation_mapping[] = {
@@ -3474,6 +3479,48 @@ _component_grab_focus(const Eldbus_Service_Interface *iface EINA_UNUSED, const E
 }
 
 static Eldbus_Message *
+_component_grab_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+   const char *obj_path = eldbus_message_path_get(msg);
+   Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
+   Eo *obj = _bridge_object_from_path(bridge, obj_path);
+   Eldbus_Message *ret;
+   Eina_Bool highlight = EINA_FALSE;
+
+   ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
+
+   eo_do(obj, highlight = elm_interface_atspi_component_highlight_grab());
+
+   ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
+   eldbus_message_arguments_append(ret, "b", highlight);
+
+   return ret;
+}
+
+static Eldbus_Message *
+_component_clear_highlight(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+   const char *obj_path = eldbus_message_path_get(msg);
+   Eo *bridge = eldbus_service_object_data_get(iface, ELM_ATSPI_BRIDGE_CLASS_NAME);
+   Eo *obj = _bridge_object_from_path(bridge, obj_path);
+   Eldbus_Message *ret;
+   Eina_Bool highlight = EINA_FALSE;
+
+   ELM_ATSPI_OBJ_CHECK_OR_RETURN_DBUS_ERROR(obj, ELM_INTERFACE_ATSPI_COMPONENT_MIXIN, msg);
+
+   eo_do(obj, highlight = elm_interface_atspi_component_highlight_clear());
+
+   ret = eldbus_message_method_return_new(msg);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ret, NULL);
+
+   eldbus_message_arguments_append(ret, "b", highlight);
+
+   return ret;
+}
+
+static Eldbus_Message *
 _component_get_alpha(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
 {
    const char *obj_path = eldbus_message_path_get(msg);
@@ -3587,6 +3634,8 @@ static const Eldbus_Method component_methods[] = {
    { "SetExtents", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "width"}, {"i", "height"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_extends, 0 },
    { "SetPosition", ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"u", "coord_type"}), ELDBUS_ARGS({"b", "result"}), _component_set_position, 0 },
    { "SetSize", ELDBUS_ARGS({"i", "width"}, {"i", "height"}), ELDBUS_ARGS({"b", "result"}), _component_set_size, 0 },
+   { "GrabHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_grab_highlight, 0 },
+   { "ClearHighlight", NULL, ELDBUS_ARGS({"b", "result"}), _component_clear_highlight, 0 },
    { NULL, NULL, NULL, NULL, 0 }
 };
 
index dd3112f..47d7e3b 100644 (file)
@@ -191,6 +191,11 @@ enum _Elm_Atspi_State_Type
     ELM_ATSPI_STATE_SELECTABLE_TEXT,
     ELM_ATSPI_STATE_IS_DEFAULT,
     ELM_ATSPI_STATE_VISITED,
+    ELM_ATSPI_STATE_CHECKABLE,
+    ELM_ATSPI_STATE_HAS_POPUP,
+    ELM_ATSPI_STATE_READ_ONLY,
+    ELM_ATSPI_STATE_HIGHLIGHTED,
+    ELM_ATSPI_STATE_HIGHLIGHTABLE,
     ELM_ATSPI_STATE_LAST_DEFINED,
 };
 
index 5d3eb72..7d57bda 100644 (file)
@@ -149,4 +149,20 @@ _elm_interface_atspi_component_focus_grab(Eo *obj EINA_UNUSED, void *_pd EINA_UN
    return evas_object_focus_get(obj);
 }
 
+EOLIAN static Eina_Bool
+_elm_interface_atspi_component_highlight_grab(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED)
+{
+   WRN("The %s object does not implement the \"component_highlight_grab\" function.",
+       eo_class_name_get(eo_class_get(obj)));
+   return EINA_FALSE;
+}
+
+EOLIAN static Eina_Bool
+_elm_interface_atspi_component_highlight_clear(Eo *obj EINA_UNUSED, void *_pd EINA_UNUSED)
+{
+   WRN("The %s object does not implement the \"component_highlight_clear\" function.",
+       eo_class_name_get(eo_class_get(obj)));
+   return EINA_FALSE;
+}
+
 #include "elm_interface_atspi_component.eo.c"
index 089b2f9..67163c7 100644 (file)
@@ -98,5 +98,15 @@ mixin Elm_Interface_Atspi_Component ()
          }
          return: Eo*;
       }
+      highlight_grab @protected {
+         [[ Highlights accessible widget.
+         returns true if highlight grab has successed, false otherwise. ]]
+         return: bool;
+      }
+      highlight_clear @protected {
+         [[ Clears highlight of accessible widget.
+         returns true if clear has successed, false otherwise. ]]
+         return: bool;
+      }
    }
 }
index 58528f4..638585c 100644 (file)
@@ -4670,8 +4670,15 @@ _elm_widget_item_elm_interface_atspi_accessible_state_set_get(Eo *eo_item,
                                                               Elm_Widget_Item_Data *item EINA_UNUSED)
 {
    Elm_Atspi_State_Set states = 0;
+   Evas_Object *win = elm_widget_top_get(item->widget);
+   if (win && eo_isa(win, ELM_WIN_CLASS))
+     {
+        if (_elm_win_accessibility_highlight_get(win) == item->view)
+          STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
+     }
 
    STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSABLE);
+   STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
 
    if (elm_object_item_focus_get(eo_item))
      STATE_TYPE_SET(states, ELM_ATSPI_STATE_FOCUSED);
@@ -5903,6 +5910,14 @@ _elm_widget_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Widget_Sma
 
    eo_do_super(obj, ELM_WIDGET_CLASS, states = elm_interface_atspi_accessible_state_set_get());
 
+   Evas_Object *win = elm_widget_top_get(obj);
+   if (win && eo_isa(win, ELM_WIN_CLASS))
+     {
+        if (_elm_win_accessibility_highlight_get(win) == obj)
+          STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTED);
+     }
+   STATE_TYPE_SET(states, ELM_ATSPI_STATE_HIGHLIGHTABLE);
+
    if (evas_object_visible_get(obj))
      {
         STATE_TYPE_SET(states, ELM_ATSPI_STATE_VISIBLE);
@@ -5995,5 +6010,116 @@ _elm_widget_item_elm_interface_atspi_component_alpha_get(Eo *obj EINA_UNUSED, El
    return (double)alpha / 255.0;
 }
 
+EOLIAN static Eo *
+_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)
+{
+   Eina_List *l, *l2, *children;
+   Eo *child;
+   Evas_Object *stack_item;
+   Eo *compare_obj;
+   int ee_x, ee_y;
+
+   if (screen_coords)
+     {
+        Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
+        if (!ee) return NULL;
+        ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
+        x -= ee_x;
+        y -= ee_y;
+     }
+
+   eo_do(obj, children = elm_interface_atspi_accessible_children_get());
+
+   /* 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 */
+   EINA_LIST_FOREACH(stack, l, stack_item)
+     {
+        /* Foreach at-spi children traverse stack_item evas_objects hierarchy */
+        EINA_LIST_FOREACH(children, l2, child)
+          {
+             /* 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 */
+             if (eo_isa(child, ELM_WIDGET_ITEM_CLASS))
+               {
+                  Elm_Widget_Item_Data *id = eo_data_scope_get(child, ELM_WIDGET_ITEM_CLASS);
+                  compare_obj = id->view;
+               }
+             /* In case of access object compare should be 'wrapped' evas_object */
+             if (eo_isa(child, ELM_ACCESS_CLASS))
+               {
+                  Elm_Access_Info *info = _elm_access_info_get(child);
+                  compare_obj = info->part_object;
+               }
+             /* If spacial eo children do not have backing evas_object continue with search */
+             if (!compare_obj)
+               continue;
+
+             Evas_Object *smart_parent = stack_item;
+             while (smart_parent)
+               {
+                   if (smart_parent == compare_obj)
+                     {
+                        eina_list_free(children);
+                        eina_list_free(stack);
+                        return child;
+                     }
+                   smart_parent = evas_object_smart_parent_get(smart_parent);
+               }
+          }
+     }
+
+   eina_list_free(children);
+   eina_list_free(stack);
+   return NULL;
+}
+
+EOLIAN static Eina_Bool
+_elm_widget_item_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Item_Data *sd)
+{
+   Evas_Object *win = elm_widget_top_get(sd->widget);
+   if (win && eo_isa(win, ELM_WIN_CLASS))
+     {
+        _elm_win_accessibility_highlight_set(win, sd->view);
+        elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
+        return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+EOLIAN static Eina_Bool
+_elm_widget_item_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Item_Data *sd)
+{
+   Evas_Object *win = elm_widget_top_get(sd->widget);
+   if (win && eo_isa(win, ELM_WIN_CLASS))
+     {
+        if (_elm_win_accessibility_highlight_get(win) != sd->view)
+          return EINA_TRUE;
+
+        _elm_win_accessibility_highlight_set(win, NULL);
+        elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
+        return EINA_TRUE;
+     }
+   return EINA_FALSE;
+}
+
+EOLIAN static Eina_Bool
+_elm_widget_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
+{
+   elm_object_accessibility_highlight_set(obj, EINA_TRUE);
+   elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
+   return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
+_elm_widget_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Widget_Smart_Data *pd EINA_UNUSED)
+{
+   elm_object_accessibility_highlight_set(obj, EINA_FALSE);
+   elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
+   return EINA_TRUE;
+}
+
 #include "elm_widget_item.eo.c"
 #include "elm_widget.eo.c"
index 35bed55..11e5bb2 100644 (file)
@@ -772,6 +772,9 @@ abstract Elm.Widget (Evas.Object_Smart, Elm_Interface_Atspi_Accessible, Elm_Inte
       Elm_Interface_Atspi_Accessible.parent.get;
       Elm_Interface_Atspi_Accessible.attributes.get;
       Elm_Interface_Atspi_Component.focus_grab;
+      Elm_Interface_Atspi_Component.accessible_at_point_get;
+      Elm_Interface_Atspi_Component.highlight_grab;
+      Elm_Interface_Atspi_Component.highlight_clear;
    }
    events {
       moved;
index 9953bc8..0269536 100644 (file)
@@ -536,5 +536,7 @@ class Elm.Widget_Item(Eo.Base, Elm_Interface_Atspi_Accessible,
            Elm_Interface_Atspi_Component.alpha.get;
            Elm_Interface_Atspi_Component.layer.get;
            Elm_Interface_Atspi_Component.focus_grab;
+           Elm_Interface_Atspi_Component.highlight_grab;
+           Elm_Interface_Atspi_Component.highlight_clear;
       }
 }