[at-spi2-core] More updates related to reading position notifications



commit 218af4ee001d1093c0328a55a00e0ae9e4fc3262
Author: Mike Gorse <mgorse alum wpi edu>
Date:   Sun May 5 16:20:08 2019 -0500

    More updates related to reading position notifications
    
    Allow a client to receive notifications through AtspiEventListeners. This
    involves special casing, since the event is generated by the screen reader,
    not the GUI, and is, thus, handled by a different DBus interface, but, from
    the client's perspective, it looks like a normal AT-SPI event.
    Also renamed atspi_text_notify_read_position to
    atspi_text_notify_reading_position and fixed a few warnings.

 atspi/atspi-constants.h            |   2 +-
 atspi/atspi-event-listener.c       | 146 +++++++++++++++++++++++--------------
 atspi/atspi-misc.c                 |  11 +++
 atspi/atspi-text.c                 |  15 ++--
 atspi/atspi-text.h                 |   2 +-
 doc/libatspi/libatspi-sections.txt |   2 +-
 6 files changed, 114 insertions(+), 64 deletions(-)
---
diff --git a/atspi/atspi-constants.h b/atspi/atspi-constants.h
index 369235c..ea95baf 100644
--- a/atspi/atspi-constants.h
+++ b/atspi/atspi-constants.h
@@ -1463,7 +1463,7 @@ typedef enum {
 #define ATSPI_DBUS_INTERFACE_SOCKET "org.a11y.atspi.Socket"
 
 #define ATSPI_DBUS_PATH_SCREEN_READER "/org/a11y/atspi/screenreader"
-#define ATSPI_DBUS_INTERFACE_SCREEN_READER "org.a11y.Atspi.ScreenReader"
+#define ATSPI_DBUS_INTERFACE_SCREEN_READER "org.a11y.atspi.ScreenReader"
 
 #ifdef __cplusplus
 }
diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c
index ae4a7b4..a89464d 100644
--- a/atspi/atspi-event-listener.c
+++ b/atspi/atspi-event-listener.c
@@ -170,12 +170,15 @@ static GList *event_listeners = NULL;
 static gchar *
 convert_name_from_dbus (const char *name, gboolean path_hack)
 {
-  gchar *ret = g_malloc (g_utf8_strlen (name, -1) * 2 + 1);
+  gchar *ret;
   const char *p = name;
-  gchar *q = ret;
+  gchar *q;
 
-  if (!ret)
-    return NULL;
+  if (!name)
+    return g_strdup ("");
+
+ ret = g_malloc (g_utf8_strlen (name, -1) * 2 + 1);
+  q = ret;
 
   while (*p)
   {
@@ -379,24 +382,32 @@ convert_event_type_to_dbus (const char *eventType, char **categoryp, char **name
   if (matchrule_array)
   {
     gchar *matchrule;
-    matchrule = g_strdup_printf ("type='signal',interface='org.a11y.atspi.Event.%s'", category);
-    if (name && name [0])
-    {
-      gchar *new_str = g_strconcat (matchrule, ",member='", name, "'", NULL);
-      g_free (matchrule);
-      matchrule = new_str;
-    }
     (*matchrule_array) = g_ptr_array_new ();
-    if (detail && detail [0])
+    if (!strcmp (eventType, "object:text-reading-position"))
     {
-      gchar *new_str = g_strconcat (matchrule, ",arg0='", detail, "'", NULL);
-      g_ptr_array_add (*matchrule_array, new_str);
-      new_str = g_strconcat (matchrule, ",arg0path='", detail, "/'", NULL);
-      g_ptr_array_add (*matchrule_array, new_str);
-      g_free (matchrule);
+      matchrule = g_strdup 
("type='signal',interface='org.a11y.atspi.ScreenReader',member='ReadingPosition',sender='org.a11y.Atspi.ScreenReader'");
+      g_ptr_array_add (*matchrule_array, matchrule);
     }
     else
-      g_ptr_array_add (*matchrule_array, matchrule);
+    {
+    matchrule = g_strdup_printf ("type='signal',interface='org.a11y.atspi.Event.%s'", category);
+      if (name && name [0])
+      {
+        gchar *new_str = g_strconcat (matchrule, ",member='", name, "'", NULL);
+        g_free (matchrule);
+        matchrule = new_str;
+      }
+      if (detail && detail [0])
+      {
+        gchar *new_str = g_strconcat (matchrule, ",arg0='", detail, "'", NULL);
+        g_ptr_array_add (*matchrule_array, new_str);
+        new_str = g_strconcat (matchrule, ",arg0path='", detail, "/'", NULL);
+        g_ptr_array_add (*matchrule_array, new_str);
+        g_free (matchrule);
+      }
+      else
+        g_ptr_array_add (*matchrule_array, matchrule);
+    }
   }
   if (categoryp) *categoryp = category;
   else g_free (category);
@@ -459,6 +470,7 @@ listener_entry_free (EventListenerEntry *e)
  *            object:text-selection-changed
  *            object:text-changed
  *            object:text-caret-moved
+ *            object:text-reading-position
  *            object:row-inserted
  *            object:row-reordered
  *            object:row-deleted
@@ -507,6 +519,9 @@ listener_entry_free (EventListenerEntry *e)
  *            In general, listening to
  *            toolkit-specific events is not recommended.
  *
+ * Currently, object:text-reading-position needs to be specified explicitly
+ * (it is not implied by object:text), since it is generated by the screen
+ * reader and is thus a special case internally.
  *
  * Returns: #TRUE if successful, otherwise #FALSE.
  **/
@@ -962,11 +977,22 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
   dbus_int32_t detail1, detail2;
   char *p;
   GHashTable *cache = NULL;
+  gboolean is_reading_position = 0;
 
-  if (strcmp (signature, "siiv(so)") != 0 &&
+  if (dbus_message_is_signal (message, ATSPI_DBUS_INTERFACE_SCREEN_READER,
+      "ReadingPosition"))
+  {
+    if (strcmp (signature, "(so)ii") != 0)
+    {
+      g_warning ("Got invalid signature '%s' for ReadingPosition signal", signature);
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+    is_reading_position = TRUE;
+  }
+  else if (strcmp (signature, "siiv(so)") != 0 &&
       strcmp (signature, "siiva{sv}") != 0)
   {
-    g_warning ("Got invalid signature %s for signal %s from interface %s\n", signature, member, category);
+   g_warning ("Got invalid signature %s for signal %s from interface %s\n", signature, member, category);
     return DBUS_HANDLER_RESULT_HANDLED;
   }
 
@@ -981,9 +1007,16 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
     category++;
+    if (!strcmp (category, "ScreenReader"))
+      category = "Object"; /* hack -- assume this is ReadingPosition */
+  }
+  if (is_reading_position)
+    e.source = _atspi_dbus_return_accessible_from_iter (&iter);
+  else
+  {
+    dbus_message_iter_get_basic (&iter, &detail);
+    dbus_message_iter_next (&iter);
   }
-  dbus_message_iter_get_basic (&iter, &detail);
-  dbus_message_iter_next (&iter);
   dbus_message_iter_get_basic (&iter, &detail1);
   e.detail1 = detail1;
   dbus_message_iter_next (&iter);
@@ -992,7 +1025,10 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
   dbus_message_iter_next (&iter);
 
   converted_type = convert_name_from_dbus (category, FALSE);
-  name = convert_name_from_dbus (member, FALSE);
+  if (is_reading_position)
+    name = g_strdup ("text-reading-position");
+  else
+    name = convert_name_from_dbus (member, FALSE);
   detail = convert_name_from_dbus (detail, TRUE);
 
   if (strcasecmp  (category, name) != 0)
@@ -1015,54 +1051,58 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
     converted_type = p;
   }
   e.type = converted_type;
-  e.source = _atspi_ref_accessible (dbus_message_get_sender(message), dbus_message_get_path(message));
+  if (!is_reading_position)
+    e.source = _atspi_ref_accessible (dbus_message_get_sender(message), dbus_message_get_path(message));
   if (e.source == NULL)
   {
-    g_warning ("Got no valid source accessible for signal for signal %s from interface %s\n", member, 
category);
+    g_warning ("Got no valid source accessible for signal %s from interface %s\n", member, category);
     g_free (converted_type);
     g_free (name);
     g_free (detail);
     return DBUS_HANDLER_RESULT_HANDLED;
   }
 
-  dbus_message_iter_recurse (&iter, &iter_variant);
-  switch (dbus_message_iter_get_arg_type (&iter_variant))
+  if (!is_reading_position)
   {
-    case DBUS_TYPE_STRUCT:
+    dbus_message_iter_recurse (&iter, &iter_variant);
+    switch (dbus_message_iter_get_arg_type (&iter_variant))
     {
-      AtspiRect rect;
-      if (demarshal_rect (&iter_variant, &rect))
+      case DBUS_TYPE_STRUCT:
       {
-       g_value_init (&e.any_data, ATSPI_TYPE_RECT);
-       g_value_set_boxed (&e.any_data, &rect);
+        AtspiRect rect;
+        if (demarshal_rect (&iter_variant, &rect))
+        {
+          g_value_init (&e.any_data, ATSPI_TYPE_RECT);
+          g_value_set_boxed (&e.any_data, &rect);
+        }
+        else
+        {
+          AtspiAccessible *accessible;
+         accessible = _atspi_dbus_return_accessible_from_iter (&iter_variant);
+          g_value_init (&e.any_data, ATSPI_TYPE_ACCESSIBLE);
+          g_value_set_instance (&e.any_data, accessible);
+          if (accessible)
+            g_object_unref (accessible);       /* value now owns it */
+        }
+        break;
       }
-      else
+      case DBUS_TYPE_STRING:
       {
-        AtspiAccessible *accessible;
-       accessible = _atspi_dbus_return_accessible_from_iter (&iter_variant);
-       g_value_init (&e.any_data, ATSPI_TYPE_ACCESSIBLE);
-       g_value_set_instance (&e.any_data, accessible);
-       if (accessible)
-         g_object_unref (accessible);  /* value now owns it */
+        dbus_message_iter_get_basic (&iter_variant, &p);
+        g_value_init (&e.any_data, G_TYPE_STRING);
+        g_value_set_string (&e.any_data, p);
+        break;
       }
+    default:
       break;
     }
-    case DBUS_TYPE_STRING:
+
+    dbus_message_iter_next (&iter);
+    if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY)
     {
-      dbus_message_iter_get_basic (&iter_variant, &p);
-      g_value_init (&e.any_data, G_TYPE_STRING);
-      g_value_set_string (&e.any_data, p);
-      break;
+      /* new form -- parse properties sent with event */
+      cache = _atspi_dbus_update_cache_from_dict (e.source, &iter);
     }
-  default:
-    break;
-  }
-
-  dbus_message_iter_next (&iter);
-  if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY)
-  {
-    /* new form -- parse properties sent with event */
-    cache = _atspi_dbus_update_cache_from_dict (e.source, &iter);
   }
 
   if (!strncmp (e.type, "object:children-changed", 23))
diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c
index fdc25bb..f0c8fdc 100644
--- a/atspi/atspi-misc.c
+++ b/atspi/atspi-misc.c
@@ -71,6 +71,7 @@ const char *atspi_interface_table = ATSPI_DBUS_INTERFACE_TABLE;
 const char *atspi_interface_table_cell = ATSPI_DBUS_INTERFACE_TABLE_CELL;
 const char *atspi_interface_text = ATSPI_DBUS_INTERFACE_TEXT;
 const char *atspi_interface_cache = ATSPI_DBUS_INTERFACE_CACHE;
+const char *atspi_interface_screen_reader = ATSPI_DBUS_INTERFACE_SCREEN_READER;
 const char *atspi_interface_value = ATSPI_DBUS_INTERFACE_VALUE;
 
 static const char *interfaces[] =
@@ -740,6 +741,11 @@ process_deferred_message (BusDataClosure *closure)
   {
     _atspi_dbus_handle_event (closure->bus, closure->message, closure->data);
   }
+  if (dbus_message_is_signal (closure->message, atspi_interface_screen_reader,
+      "ReadingPosition"))
+  {
+    _atspi_dbus_handle_event (closure->bus, closure->message, closure->data);
+  }
   if (dbus_message_is_method_call (closure->message, atspi_interface_device_event_listener, "NotifyEvent"))
   {
     _atspi_dbus_handle_DeviceEvent (closure->bus,
@@ -837,6 +843,11 @@ atspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data)
   {
     return defer_message (bus, message, data);
   }
+  if (dbus_message_is_signal (message, atspi_interface_screen_reader,
+      "ReadingPosition"))
+  {
+    return defer_message (bus, message, data);
+  }
   if (dbus_message_is_signal (message, "org.freedesktop.DBus", "NameOwnerChanged"))
   {
     defer_message (bus, message, data);
diff --git a/atspi/atspi-text.c b/atspi/atspi-text.c
index 2409560..2c50a5b 100644
--- a/atspi/atspi-text.c
+++ b/atspi/atspi-text.c
@@ -963,7 +963,7 @@ atspi_text_scroll_substring_to_point (AtspiText *obj,
 }
 
 /**
- * atspi_text_notify_read_position:
+ * atspi_text_notify_reading_position:
  * @obj: the #AtspiText object being read.
  * @offset: the offset of the text currently being read.
  *
@@ -972,10 +972,9 @@ atspi_text_scroll_substring_to_point (AtspiText *obj,
  * the screen reader and highlight the text that is currently being read.
  */
 void
-atspi_text_notify_read_position (AtspiText *obj,
-                                gint offset)
+atspi_text_notify_reading_position (AtspiText *obj,
+                                    gint offset)
 {
-  DBusConnection *bus = _atspi_bus ();
   DBusMessage *signal;
   AtspiAccessible *accessible;
   gint len;
@@ -994,14 +993,14 @@ atspi_text_notify_read_position (AtspiText *obj,
   if (!quark_text_len)
     quark_text_len = g_quark_from_string ("accessible-text-len");
 
-  plen = g_object_get_qdata (accessible, quark_text_len);
+  plen = g_object_get_qdata (G_OBJECT (accessible), quark_text_len);
   if (plen)
-    len = (gint)plen;
+    len = (gint) (gint64)plen;
   else
     {
       len = atspi_text_get_character_count (obj, NULL);
-      plen = (gpointer)len;
-      g_object_set_qdata (accessible, quark_text_len, plen);
+      plen = (gpointer) (gint64)len;
+      g_object_set_qdata (G_OBJECT (accessible), quark_text_len, plen);
     }
 
   remaining = (len >= 0 ? len - offset : 0);
diff --git a/atspi/atspi-text.h b/atspi/atspi-text.h
index fcc4259..3afc4dd 100644
--- a/atspi/atspi-text.h
+++ b/atspi/atspi-text.h
@@ -141,7 +141,7 @@ gboolean atspi_text_scroll_substring_to (AtspiText *obj, gint start_offset, gint
 
 gboolean atspi_text_scroll_substring_to_point (AtspiText *obj, gint start_offset, gint end_offset, 
AtspiCoordType coords, gint x, gint y, GError **error);
 
-void atspi_text_notify_read_position (AtspiText *obj, gint offset);
+void atspi_text_notify_reading_position (AtspiText *obj, gint offset);
 G_END_DECLS
 
 #endif /* _ATSPI_TEXT_H_ */
diff --git a/doc/libatspi/libatspi-sections.txt b/doc/libatspi/libatspi-sections.txt
index 951e801..af2ab71 100644
--- a/doc/libatspi/libatspi-sections.txt
+++ b/doc/libatspi/libatspi-sections.txt
@@ -32,7 +32,7 @@ atspi_text_get_text_attribute_value
 atspi_text_get_text_attributes
 atspi_text_scroll_substring_to
 atspi_text_scroll_substring_to_point
-atspi_text_notify_read_position
+atspi_text_notify_reading_position
 <SUBSECTION Standard>
 ATSPI_TEXT
 ATSPI_IS_TEXT


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]