Add relations info to the screen reader text
authorMichal Jagiello <m.jagiello@samsung.com>
Thu, 12 Mar 2015 11:41:13 +0000 (12:41 +0100)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Tue, 17 Mar 2015 11:11:14 +0000 (12:11 +0100)
Change-Id: Ib4297b386aaf70f26c35c98f203545ff718d7db0

include/screen_reader.h
include/screen_reader_spi.h
src/screen_reader_spi.c
src/screen_reader_vconf.c

index 2202c16..7f86170 100644 (file)
@@ -14,6 +14,8 @@
 
 #define FOCUS_SIG "focused"
 
+#define EDITING_STARTED "Editing"
+
 #define FOCUS_CHANGED_SIG "object:state-changed:focused"
 #define VALUE_CHANGED_SIG "object:property-change:accessible-value"
 #define CARET_MOVED_SIG "object:text-caret-moved"
@@ -56,9 +58,7 @@ typedef struct _Service_Data
        bool update_language_list;
 
        //Set by spi
-       AtspiEventListener *state_changed_listener;
-       AtspiEventListener *value_changed_listener;
-       AtspiEventListener *caret_moved_listener;
+       AtspiEventListener *spi_listener;
 
        AtspiAccessible  *currently_focused;
        AtspiAccessible  *mouse_down_widget;
index 9dd47e8..e1f6506 100644 (file)
@@ -15,5 +15,6 @@ void spi_init(Service_Data *sd);
 void spi_on_state_changed_cb(AtspiEvent *event, void *user_data);
 void spi_on_caret_move_cb(AtspiEvent *event, void *user_data);
 void spi_on_access_value_changed_cb(AtspiEvent *event, void *user_data);
+void spi_event_listener_cb(AtspiEvent *event, void *user_data);
 
 #endif /* SCREEN_READER_SPI_H_ */
index 83f7630..2f065d8 100644 (file)
@@ -18,6 +18,8 @@
 #define NO_VALUE_INTERFACE "No value interface present"
 #define NO_TEXT_INTERFACE "No text interface present"
 
+#define EPS 0.000000001
+
 /** @brief Service_Data used as screen reader internal data struct*/
 static Service_Data *service_data;
 
@@ -56,183 +58,244 @@ Eina_Bool double_click_timer_cb(void *data)
     return EINA_FALSE;
 }
 
-/**
-  * @brief Atspi tracking-signal callback passing current focused
-  * accessible description to TTS
-  *
-  * @param AtspiEvent instance
-  * @param user_data screen-reader internal data
-  *
-**/
-void spi_on_state_changed_cb(AtspiEvent *event, void *user_data)
+static char *spi_get_atspi_accessible_basic_text_description(AtspiAccessible *obj)
 {
-    DEBUG("START");
-    DEBUG("STATE CHANGED");
-    Service_Data *sd = user_data;
-    char *text_to_read;
+    if(!obj) return NULL;
 
-    display_info(event);
-    if(strcmp(event->type, sd->tracking_signal_name) == 0 && event->detail1 == 1)
-      {
-         char *name;
-         char *description;
-         char *role_name;
-         sd->currently_focused = event->source;
+    char *name;
+    char *description;
+    char *role_name;
+    char *return_text = NULL;
 
-         description = atspi_accessible_get_description(sd->currently_focused, NULL);
-         name = atspi_accessible_get_name(sd->currently_focused, NULL);
-         role_name = atspi_accessible_get_role_name(sd->currently_focused, NULL);
+    description = atspi_accessible_get_description(obj, NULL);
+    name = atspi_accessible_get_name(obj, NULL);
+    role_name = atspi_accessible_get_role_name(obj, NULL);
 
-         DEBUG("->->->->->-> WIDGET GAINED HIGHLIGHT: %s <-<-<-<-<-<-<-", name);
+    if (strncmp(description, "\0", 1))
+        return_text = strdup(description);
+    else if (strncmp(name, "\0", 1))
+        return_text = strdup(name);
+    else
+        return_text = strdup(role_name);
 
-         if (strncmp(description, "\0", 1))
-           text_to_read = description;
-         else if (strncmp(name, "\0", 1))
-           text_to_read = name;
-         else
-           text_to_read = role_name;
-
-         tts_speak(text_to_read, EINA_FALSE);
-         free(name);
-         free(description);
-         free(role_name);
-      }
+    free(name);
+    free(description);
+    free(role_name);
 
-    DEBUG("END");
+    return return_text;
 }
 
-/**
-  * @brief Atspi caret-moved callback passing text to TTS
-  *
-  * @param AtspiEvent instance
-  * @param user_data screen-reader internal data
-  *
-**/
-void spi_on_caret_move_cb(AtspiEvent *event, void *user_data)
+static char *spi_on_state_changed_get_text(AtspiEvent *event, void *user_data)
 {
-    DEBUG("START");
-    DEBUG("CARET MOVED");
-    Service_Data *sd = user_data;
-    int char_count;
-    gint caret_pos;
-    char *text_to_read;
+    Service_Data *sd = (Service_Data*)user_data;
+    char *return_text = NULL;
+    sd->currently_focused = event->source;
 
-    display_info(event);
-    if(strcmp(event->type, CARET_MOVED_SIG) == 0)
-      {
-         sd->currently_focused = event->source;
+    DEBUG("->->->->->-> WIDGET GAINED HIGHLIGHT <-<-<-<-<-<-<-");
+    return_text = spi_get_atspi_accessible_basic_text_description(sd->currently_focused);
 
-         AtspiText *text_interface = atspi_accessible_get_text(sd->currently_focused);
-         if(text_interface)
-           {
-              DEBUG("->->->->->-> WIDGET CARET MOVED: %s <-<-<-<-<-<-<-",
-                    atspi_accessible_get_name(sd->currently_focused, NULL));
+    return return_text;
+}
 
-              char_count = (int)atspi_text_get_character_count(text_interface, NULL);
-              caret_pos = atspi_text_get_caret_offset(text_interface, NULL);
-              if(!caret_pos)
+static char *spi_on_caret_move_get_text(AtspiEvent *event, void *user_data)
+{
+    Service_Data *sd = (Service_Data*)user_data;
+    sd->currently_focused = event->source;
+    char *return_text;
+
+    AtspiText *text_interface = atspi_accessible_get_text(sd->currently_focused);
+    if(text_interface)
+        {
+          DEBUG("->->->->->-> WIDGET CARET MOVED: %s <-<-<-<-<-<-<-",
+                atspi_accessible_get_name(sd->currently_focused, NULL));
+
+          int char_count = (int)atspi_text_get_character_count(text_interface, NULL);
+          int caret_pos = atspi_text_get_caret_offset(text_interface, NULL);
+          if(!caret_pos)
+            {
+               DEBUG("MIN POSITION REACHED");
+               if(asprintf(&return_text, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MIN_POS_REACHED) < 0)
+                 {
+                    ERROR(MEMORY_ERROR);
+                    return NULL;
+                 }
+            }
+         else if(char_count == caret_pos)
+           {
+              DEBUG("MAX POSITION REACHED");
+              if(asprintf(&return_text, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MAX_POS_REACHED) < 0)
                 {
-                   DEBUG("MIN POSITION REACHED");
-                   if(asprintf(&text_to_read, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MIN_POS_REACHED) < 0)
-                     {
-                        ERROR(MEMORY_ERROR);
-                        return;
-                     }
+                   ERROR(MEMORY_ERROR);
+                   return NULL;
                 }
-             else if(char_count == caret_pos)
-               {
-                  DEBUG("MAX POSITION REACHED");
-                  if(asprintf(&text_to_read, "%s %s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL), MAX_POS_REACHED) < 0)
-                    {
-                       ERROR(MEMORY_ERROR);
-                       return;
-                    }
-               }
-             else
-               {
-                  if(asprintf(&text_to_read, "%s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL)) < 0)
-                    {
-                      ERROR(MEMORY_ERROR);
-                      return;
-                    }
-               }
            }
          else
            {
-              ERROR(MEMORY_ERROR);
-              return;
+              if(asprintf(&return_text, "%s", (char*)atspi_text_get_text(text_interface, caret_pos, caret_pos + 1, NULL)) < 0)
+                {
+                  ERROR(MEMORY_ERROR);
+                  return NULL;
+                }
            }
-         tts_speak(text_to_read, EINA_FALSE);
-         free(text_to_read);
-      }
+        }
+    else
+        {
+          ERROR(MEMORY_ERROR);
+          return NULL;
+        }
+    return return_text;
+}
+
+static char *spi_on_value_changed_get_text(AtspiEvent *event, void *user_data)
+{
+    Service_Data *sd = (Service_Data*)user_data;
+    char *text_to_read;
 
-    DEBUG("END");
+    sd->currently_focused = event->source;
+
+    AtspiValue *value_interface = atspi_accessible_get_value(sd->currently_focused);
+    if(value_interface)
+    {
+      DEBUG("->->->->->-> WIDGET VALUE CHANGED: %s <-<-<-<-<-<-<-",
+            atspi_accessible_get_name(sd->currently_focused, NULL));
+
+      double current_temp_value = (double)atspi_value_get_current_value(value_interface, NULL);
+      if(abs(current_temp_value - atspi_value_get_maximum_value(value_interface, NULL)) < EPS)
+        {
+           DEBUG("MAX VALUE REACHED");
+           if(asprintf(&text_to_read, "%.2f %s", current_temp_value, MAX_REACHED) < 0)
+             {
+                ERROR(MEMORY_ERROR);
+                return NULL;
+             }
+        }
+      else if(abs(current_temp_value - atspi_value_get_minimum_value(value_interface, NULL)) < EPS)
+        {
+           DEBUG("MIN VALUE REACHED");
+           if(asprintf(&text_to_read, "%.2f %s", current_temp_value, MIN_REACHED) < 0)
+             {
+                ERROR(MEMORY_ERROR);
+                return NULL;
+             }
+        }
+      else
+        {
+           if(asprintf(&text_to_read, "%.2f", current_temp_value) < 0)
+             {
+                ERROR(MEMORY_ERROR);
+                return NULL;
+             }
+        }
+    }
+
+    return text_to_read;
 }
 
-/**
-  * @brief Atspi value-changed callback passing text to TTS
-  *
-  * @param AtspiEvent instance
-  * @param user_data screen-reader internal data
-  *
-**/
-void spi_on_access_value_changed_cb(AtspiEvent *event, void *user_data)
+static void spi_object_append_relations_to_text_to_read(AtspiAccessible *obj,
+                                                        char **text_to_read)
+{
+    if(!obj || !text_to_read || !*text_to_read)
+    {
+        ERROR("Invalid parameter");
+        return;
+    }
+
+    GError *error = NULL;
+
+    GArray *relations = atspi_accessible_get_relation_set(obj, &error);
+    if(error != NULL)
+    {
+        ERROR("Can not get atspi object relations: %s", error->message);
+        g_error_free(error);
+        return;
+    }
+
+    int i = 0;
+    for(; i < relations->len; ++i)
+    {
+        AtspiRelation *relation = g_array_index(relations, AtspiRelation*, i);
+        if(!relation) continue;
+
+        AtspiRelationType relation_type = atspi_relation_get_relation_type(relation);
+        if(relation_type == ATSPI_RELATION_LABEL_FOR ||
+            relation_type == ATSPI_RELATION_LABELLED_BY)
+        {
+            int relation_objects = atspi_relation_get_n_targets(relation);
+            int j;
+            for(j = 0; j < relation_objects; ++j)
+            {
+                AtspiAccessible *relation_object = atspi_relation_get_target(relation, j);
+                if(!relation_object || obj == relation_object) continue;
+
+                char *relation_obj_text = spi_get_atspi_accessible_basic_text_description(relation_object);
+
+                char *text = NULL;
+                if(asprintf(&text, "%s %s", *text_to_read, relation_obj_text) == -1)
+                    continue;
+                free(relation_obj_text);
+                free(*text_to_read);
+                *text_to_read = text;
+                g_object_unref(relation_object);
+            }
+        }
+    }
+
+    g_array_free(relations, TRUE);
+}
+
+char *spi_event_get_text_to_read(AtspiEvent *event, void *user_data)
 {
-    DEBUG("START");
-    DEBUG("STATE CHANGED");
-    Service_Data *sd = user_data;
-    double current_temp_value;
+    Service_Data *sd = (Service_Data*)user_data;
     char *text_to_read;
-    float epsilon = 0.000000001;
 
-    display_info(event);
-    if(strcmp(event->type, VALUE_CHANGED_SIG) == 0)
-      {
-         sd->currently_focused = event->source;
+    if(!sd->tracking_signal_name)
+    {
+        ERROR("Invalid tracking signal name");
+        return NULL;
+    }
+
+    if(!strncmp(event->type, sd->tracking_signal_name, strlen(event->type)) && event->detail1 == 1)
+    {
+        text_to_read = spi_on_state_changed_get_text(event, user_data);
+    }
+    else if(!strncmp(event->type, CARET_MOVED_SIG, strlen(event->type)))
+    {
+        text_to_read = spi_on_caret_move_get_text(event, user_data);
+    }
+    else if(!strncmp(event->type, VALUE_CHANGED_SIG, strlen(event->type)))
+    {
+        text_to_read = spi_on_value_changed_get_text(event, user_data);
+    }
+    else
+    {
+        DEBUG("Unhandled event type: %s %d:%d", event->type, event->detail1, event->detail2);
+        return NULL;
+    }
+
+    spi_object_append_relations_to_text_to_read(sd->currently_focused, &text_to_read);
+    DEBUG("%p %s", sd->currently_focused, text_to_read);
+
+    return text_to_read;
+}
 
-         AtspiValue *value_interface = atspi_accessible_get_value(sd->currently_focused);
-         if(value_interface)
-           {
-              DEBUG("->->->->->-> WIDGET VALUE CHANGED: %s <-<-<-<-<-<-<-",
-                    atspi_accessible_get_name(sd->currently_focused, NULL));
+void spi_event_listener_cb(AtspiEvent *event, void *user_data)
+{
+    display_info(event);
 
-              current_temp_value = (double)atspi_value_get_current_value(value_interface, NULL);
-              if(abs(current_temp_value - atspi_value_get_maximum_value(value_interface, NULL)) < epsilon)
-                {
-                   DEBUG("MAX VALUE REACHED");
-                   if(asprintf(&text_to_read, "%.2f %s", current_temp_value, MAX_REACHED) < 0)
-                     {
-                        ERROR(MEMORY_ERROR);
-                        return;
-                     }
-                }
-              else if(abs(current_temp_value - atspi_value_get_minimum_value(value_interface, NULL)) < epsilon)
-                {
-                   DEBUG("MIN VALUE REACHED");
-                   if(asprintf(&text_to_read, "%.2f %s", current_temp_value, MIN_REACHED) < 0)
-                     {
-                        ERROR(MEMORY_ERROR);
-                        return;
-                     }
-                }
-              else
-                {
-                   if(asprintf(&text_to_read, "%.2f", current_temp_value) < 0)
-                     {
-                        ERROR(MEMORY_ERROR);
-                        return;
-                     }
-                }
-           }
-         else
-           {
-              ERROR(MEMORY_ERROR);
-              return;
-           }
-         tts_speak(text_to_read, EINA_FALSE);
-         free(text_to_read);
-      }
-    DEBUG("END");
+    if(!user_data)
+    {
+        ERROR("Invalid parameter");
+        return;
+    }
+
+    char *text_to_read = spi_event_get_text_to_read(event, user_data);
+    if(!text_to_read)
+    {
+        ERROR("Can not prepare text to read");
+        return;
+    }
+    tts_speak(text_to_read, EINA_FALSE);
+    free(text_to_read);
 }
 
 /**
@@ -243,50 +306,44 @@ void spi_on_access_value_changed_cb(AtspiEvent *event, void *user_data)
 **/
 void spi_init(Service_Data *sd)
 {
+    if(!sd)
+    {
+        ERROR("Invalid parameter");
+        return;
+    }
 
     DEBUG( "--------------------- SPI_init START ---------------------");
     service_data = sd;
 
     DEBUG( ">>> Creating listeners <<<");
 
-    sd->state_changed_listener = atspi_event_listener_new(spi_on_state_changed_cb, service_data, NULL);
-    if(sd->state_changed_listener == NULL)
-      {
-         DEBUG("FAILED TO CREATE spi state changed listener")
-      }
-
-    sd->caret_moved_listener = atspi_event_listener_new(spi_on_caret_move_cb, service_data, NULL);
-    if(sd->caret_moved_listener == NULL)
-      {
-         DEBUG("FAILED TO CREATE spi state changed listener")
-      }
-
-    sd->value_changed_listener = atspi_event_listener_new(spi_on_access_value_changed_cb, service_data, NULL);
-    if(sd->value_changed_listener == NULL)
+    sd->spi_listener = atspi_event_listener_new(spi_event_listener_cb, service_data, NULL);
+    if(sd->spi_listener == NULL)
       {
          DEBUG("FAILED TO CREATE spi state changed listener")
       }
 
     // ---------------------------------------------------------------------------------------------------
 
-    gboolean ret1 = atspi_event_listener_register(sd->state_changed_listener, sd->tracking_signal_name, NULL);
+    gboolean ret1 = atspi_event_listener_register(sd->spi_listener, sd->tracking_signal_name, NULL);
     if(ret1 == false)
       {
-         DEBUG("FAILED TO REGISTER spi focus listener");
+         DEBUG("FAILED TO REGISTER spi focus/highlight listener");
       }
 
-    gboolean ret2 = atspi_event_listener_register(sd->caret_moved_listener, CARET_MOVED_SIG, NULL);
+    gboolean ret2 = atspi_event_listener_register(sd->spi_listener, CARET_MOVED_SIG, NULL);
     if(ret2 == false)
       {
          DEBUG("FAILED TO REGISTER spi caret moved listener");
       }
 
-    gboolean ret3 = atspi_event_listener_register(sd->value_changed_listener, VALUE_CHANGED_SIG, NULL);
+    gboolean ret3 = atspi_event_listener_register(sd->spi_listener, VALUE_CHANGED_SIG, NULL);
     if(ret3 == false)
       {
          DEBUG("FAILED TO REGISTER spi value changed listener");
       }
 
+
     if(ret1 == true && ret2 == true && ret3 == true)
       {
          DEBUG("spi listener REGISTERED");
index 574d8b2..c0826e8 100644 (file)
@@ -88,22 +88,22 @@ bool set_tracking_listener(Service_Data *sd, const char *signal_name)
                return true;
        }
 
-       gboolean ret = atspi_event_listener_deregister(sd->state_changed_listener, sd->tracking_signal_name, NULL);
+       gboolean ret = atspi_event_listener_deregister(sd->spi_listener, sd->tracking_signal_name, NULL);
        if(ret == false)
        {
                DEBUG("Tracking signal listerner deregister successful");
        }
 
-       sd->state_changed_listener = NULL;
+       sd->spi_listener = NULL;
        sd->tracking_signal_name = strdup(new_tracking_signal);
 
-       sd->state_changed_listener = atspi_event_listener_new(spi_on_state_changed_cb, sd, NULL);
-       if(sd->state_changed_listener == NULL)
+       sd->spi_listener = atspi_event_listener_new(spi_event_listener_cb, sd, NULL);
+       if(sd->spi_listener == NULL)
        {
                DEBUG("FAILED TO CREATE spi state changed listener")
        }
 
-       gboolean ret1 = atspi_event_listener_register(sd->state_changed_listener, sd->tracking_signal_name, NULL);
+       gboolean ret1 = atspi_event_listener_register(sd->spi_listener, sd->tracking_signal_name, NULL);
        if(ret1 == false)
        {
                DEBUG("FAILED TO REGISTER spi focus listener");