Add function to generate description from nested object hierarchy 22/37922/4
authorPatryk Kaczmarek <patryk.k@samsung.com>
Wed, 8 Apr 2015 11:27:52 +0000 (13:27 +0200)
committerPatryk Kaczmarek <patryk.k@samsung.com>
Wed, 22 Apr 2015 17:37:01 +0000 (19:37 +0200)
    * Generate nested description from object with filler role
    * Tests fixed

Change-Id: I09b507bf7acc0e05550bcf937f8ad7aa968bf65d
Signed-off-by: Patryk Kaczmarek <patryk.k@samsung.com>
src/screen_reader_spi.c
tests/atspi/atspi.c
tests/atspi/atspi.h
tests/screen_reader_test_suite.c

index 89f33a2..0662ea8 100644 (file)
@@ -53,6 +53,49 @@ gboolean double_click_timer_cb(void *data)
     return FALSE;
 }
 
+bool allow_recursive_name(AtspiAccessible *obj)
+{
+    AtspiRole r = atspi_accessible_get_role(obj, NULL);
+    if (r == ATSPI_ROLE_FILLER)
+        return true;
+    return false;
+}
+
+char *generate_description_for_subtree(AtspiAccessible *obj)
+{
+    if (!allow_recursive_name(obj))
+        return strdup("");
+
+    if (!obj)
+        return strdup("");
+    int child_count = atspi_accessible_get_child_count(obj, NULL);
+
+    if (!child_count)
+        return strdup("");
+
+    int i;
+    char *name = NULL;
+    char *below = NULL;
+    char ret[256] = "\0";
+    AtspiAccessible *child = NULL;
+    for (i=0; i < child_count; i++) {
+      child = atspi_accessible_get_child_at_index(obj, i, NULL);
+      name = atspi_accessible_get_name(child, NULL);
+      if (strncmp(name, "\0", 1)) {
+        strncat(ret, name, sizeof(ret) - strlen(ret) - 1);
+      }
+      strncat(ret, " ", 1);
+      below = generate_description_for_subtree(child);
+      if (strncmp(below, "\0", 1)) {
+        strncat(ret, below, sizeof(ret) - strlen(ret) - 1);
+      }
+      g_object_unref(child);
+      free(below);
+      free(name);
+    }
+    return strdup(ret);
+}
+
 static char *spi_get_atspi_accessible_basic_text_description(AtspiAccessible *obj)
 {
     if(!obj) return NULL;
@@ -60,22 +103,27 @@ static char *spi_get_atspi_accessible_basic_text_description(AtspiAccessible *ob
     char *name;
     char *description;
     char *role_name;
+    char *other;
     char *return_text = NULL;
 
     description = atspi_accessible_get_description(obj, NULL);
     name = atspi_accessible_get_name(obj, NULL);
     role_name = atspi_accessible_get_role_name(obj, NULL);
+    other = generate_description_for_subtree(obj);
 
     if (strncmp(description, "\0", 1))
         return_text = strdup(description);
     else if (strncmp(name, "\0", 1))
         return_text = strdup(name);
+    else if (strncmp(other, "\0", 1))
+        return_text = strdup(other);
     else
         return_text = strdup(role_name);
 
     free(name);
     free(description);
     free(role_name);
+    free(other);
 
     return return_text;
 }
index 42d514d..80bd00c 100644 (file)
@@ -11,6 +11,7 @@ static AtspiEditableText *editable_text = NULL;
 
 G_DEFINE_TYPE(AtspiAccessible, atspi_accessible, G_TYPE_OBJECT);
 G_DEFINE_TYPE(AtspiComponent, atspi_component, G_TYPE_OBJECT);
+G_DEFINE_TYPE(AtspiStateSet, atspi_state_set, G_TYPE_OBJECT);
 
 void atspi_rect_free (AtspiRect *rect)
 {
@@ -66,6 +67,8 @@ gchar * atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error)
             return strdup("Check box");
         case ATSPI_ROLE_ENTRY:
             return strdup("Entry");
+        case ATSPI_ROLE_FILLER:
+            return strdup("filler");
         default:
             return strdup("\0");
     }
@@ -150,12 +153,21 @@ gboolean atspi_event_listener_deregister (AtspiEventListener *listener,
 
 AtspiStateSet * atspi_accessible_get_state_set (AtspiAccessible *obj)
 {
-    return NULL;
+    if (!obj || !obj->states) return NULL;
+    return obj->states;
 }
 
 gboolean atspi_state_set_contains (AtspiStateSet *set, AtspiStateType state)
 {
-    return TRUE;
+    if (!set)
+      return FALSE;
+    return (set->states & ((gint64)1 << state)) ? TRUE : FALSE;
+}
+
+void atspi_state_set_add (AtspiStateSet *set, AtspiStateType state)
+{
+    if (!set) return;
+    set->states |= (((gint64)1) << state);
 }
 
 gboolean atspi_component_grab_highlight (AtspiComponent *obj, GError **error)
@@ -173,6 +185,26 @@ gboolean atspi_component_clear_highlight (AtspiComponent *obj, GError **error)
     return FALSE;
 }
 
+GArray *atspi_state_set_get_states (AtspiStateSet *set)
+{
+  gint i = 0;
+  guint64 val = 1;
+  GArray *ret;
+
+  g_return_val_if_fail (set != NULL, NULL);
+  ret = g_array_new (TRUE, TRUE, sizeof (AtspiStateType));
+  if (!ret)
+    return NULL;
+  for (i = 0; i < 64; i++)
+  {
+    if (set->states & val)
+      ret = g_array_append_val (ret, i);
+    val <<= 1;
+  }
+  return ret;
+
+}
+
 AtspiRole atspi_accessible_get_role (AtspiAccessible *obj, GError **error)
 {
     if(!obj) return ATSPI_ROLE_INVALID;
@@ -199,6 +231,17 @@ AtspiComponent * atspi_accessible_get_component (AtspiAccessible *obj)
     return component;
 }
 
+AtspiStateSet * atspi_state_set_new (GArray *states)
+{
+    AtspiStateSet *set = g_object_new (ATSPI_STATE_OBJECT_TYPE, NULL);
+    if (!set) return NULL;
+    int i;
+    for (i = 0; i < states->len; i++) {
+      atspi_state_set_add (set, g_array_index (states, AtspiStateType, i));
+    }
+    return set;
+}
+
 AtspiRect *atspi_component_get_extents (AtspiComponent *component, AtspiCoordType ctype, GError **error)
 {
     if(!component) return NULL;
@@ -253,6 +296,18 @@ AtspiAccessible *atspi_create_accessible()
 {
     AtspiAccessible *obj = g_object_new(ATSPI_ACCESSIBLE_OBJECT_TYPE, 0);
     obj->children = NULL;
+
+    GArray *states = g_array_new (TRUE, TRUE, sizeof (AtspiStateType));
+    AtspiStateType s[] = {
+         ATSPI_STATE_VISIBLE,
+         ATSPI_STATE_SHOWING,
+         ATSPI_STATE_LAST_DEFINED
+    };
+    int i;
+    for (i=0; i<sizeof(s); i++)
+      g_array_append_val (states, s[i]);
+    obj->states = atspi_state_set_new(states);
+
     return obj;
 }
 
@@ -286,6 +341,14 @@ void atpis_accessible_remove_children(AtspiAccessible *obj)
     g_list_free(obj->children);
 }
 
+static void atspi_state_set_init(AtspiStateSet* set)
+{
+}
+
+static void atspi_state_set_class_init(AtspiStateSetClass *_class)
+{
+}
+
 static void atspi_accessible_class_init(AtspiAccessibleClass *_class)
 {
 }
index 56c91fe..089f68f 100644 (file)
 #define ATSPI_COMPONENT_IS_OBJECT_CLASS(_class)     (G_TYPE_CHECK_CLASS_TYPE ((_class), ATSPI_COMPONENT_OBJECT_TYPE))
 #define ATSPI_COMPONENT_GET_CLASS(obj)              (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_COMPONENT_OBJECT_TYPE, AtspiAccessibleClass))
 
+#define ATSPI_STATE_OBJECT_TYPE                     (atspi_state_set_get_type ())
+#define ATSPI_STATE(obj)                            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_STATE_OBJECT_TYPE, AtspiStateSet))
+#define ATSPI_STATE_IS_OBJECT(obj)                  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_STATE_OBJECT_TYPE))
+#define ATSPI_STATE_CLASS(_class)                   (G_TYPE_CHECK_CLASS_CAST ((_class), ATSPI_STATE_OBJECT_TYPE, AtspiStateSetClass))
+#define ATSPI_STATE_IS_OBJECT_CLASS(_class)         (G_TYPE_CHECK_CLASS_TYPE ((_class), ATSPI_STATE_OBJECT_TYPE))
+#define ATSPI_STATE_GET_CLASS(obj)                  (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_STATE_OBJECT_TYPE, AtspiStateSetClass))
+
+
 typedef struct _AtspiApplication AtspiApplication;
 typedef struct _AtspiObject AtspiObject;
 typedef struct _AtspiAccessible AtspiAccessible;
@@ -37,9 +45,9 @@ typedef struct _AtspiRelation AtspiRelation;
 
 typedef struct _AtspiAccessibleClass AtspiAccessibleClass;
 typedef struct _AtspiComponentClass AtspiComponentClass;
+typedef struct _AtspiStateSetClass AtspiStateSetClass;
 
-typedef void (*AtspiEventListenerCB) (const AtspiEvent *event, void *user_data);
-
+typedef void (*AtspiEventListenerCB) (AtspiEvent *event, void *user_data);
 
 typedef enum
 {
@@ -283,6 +291,11 @@ struct _AtspiStateSet
   gint64 states;
 };
 
+struct _AtspiStateSetClass
+{
+    GObjectClass parent_class;
+};
+
 struct _AtspiEventListener
 {
   GObject parent;
@@ -358,6 +371,9 @@ gboolean atspi_event_listener_deregister (AtspiEventListener *listener,
                                           GError **error);
 AtspiStateSet * atspi_accessible_get_state_set (AtspiAccessible *obj);
 gboolean atspi_state_set_contains (AtspiStateSet *set, AtspiStateType state);
+void atspi_state_set_add (AtspiStateSet *set, AtspiStateType state);
+GArray *atspi_state_set_get_states (AtspiStateSet *set);
+AtspiStateSet * atspi_state_set_new (GArray *states);
 
 void atspi_alloc_memory(void);
 
index e04d6d3..ecef9a2 100644 (file)
@@ -96,6 +96,38 @@ START_TEST(spi_on_state_change_name)
 }
 END_TEST
 
+START_TEST(spi_on_state_change_name_tree)
+{
+    Service_Data *sd = get_pointer_to_service_data_struct();
+    AtspiEvent event;
+    AtspiAccessible *accessible = atspi_create_accessible();
+    AtspiAccessible *child1 = atspi_create_accessible();
+    AtspiAccessible *child11 = atspi_create_accessible();
+    AtspiAccessible *child12 = atspi_create_accessible();
+    AtspiAccessible *child2 = atspi_create_accessible();
+    accessible->role = ATSPI_ROLE_FILLER;
+    child1->role = ATSPI_ROLE_FILLER;
+    child11->role = ATSPI_ROLE_FILLER;
+    child12->role = ATSPI_ROLE_FILLER;
+    child2->role = ATSPI_ROLE_FILLER;
+    child1->name = "one";
+    child11->name = "two";
+    child12->name = "two1";
+    child2->name = "three";
+    atspi_accessible_add_child(accessible, child1);
+    atspi_accessible_add_child(child1, child11);
+    atspi_accessible_add_child(child1, child12);
+    atspi_accessible_add_child(accessible, child2);
+    event.type = "test_event";
+    sd->tracking_signal_name = "test_event";
+    event.detail1 = 1;
+    event.source = accessible;
+    char *return_value = spi_event_get_text_to_read(&event, sd);
+    fail_if(!return_value || strcmp(return_value, "one two two1 three "));
+    free(return_value);
+    atspi_delete_accessible(accessible);
+}
+END_TEST
 START_TEST(spi_on_state_change_description)
 {
     Service_Data *sd = get_pointer_to_service_data_struct();
@@ -382,6 +414,7 @@ Suite *screen_reader_suite(void)
     tcase_add_test(tc_spi_screen_reader_init, spi_init_null_parameter);
     tcase_add_test(tc_spi_screen_reader_init, spi_init_service_data_parameter);
     tcase_add_test(tc_spi_screen_reader_on_state_changed, spi_on_state_change_name);
+    tcase_add_test(tc_spi_screen_reader_on_state_changed, spi_on_state_change_name_tree);
     tcase_add_test(tc_spi_screen_reader_on_state_changed, spi_on_state_change_description);
     tcase_add_test(tc_spi_screen_reader_on_state_changed, spi_on_state_change_role);
     tcase_add_test(tc_spi_screen_reader_on_caret_move, spi_on_caret_move);