Commit 218af4ee authored by Mike Gorse's avatar Mike Gorse

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.
parent 2e14dcd1
......@@ -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
}
......
......@@ -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))
......
......@@ -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);
......
......@@ -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);
......
......@@ -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_ */
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment