/*---------------------------------------------------------------------------*/
-#define ITF_EVENT_OBJECT "org.freedesktop.atspi.Event.Object"
-#define ITF_EVENT_WINDOW "org.freedesktop.atspi.Event.Window"
-#define ITF_EVENT_DOCUMENT "org.freedesktop.atspi.Event.Document"
-#define ITF_EVENT_FOCUS "org.freedesktop.atspi.Event.Focus"
+#define ITF_EVENT_OBJECT "org.a11y.atspi.Event.Object"
+#define ITF_EVENT_WINDOW "org.a11y.atspi.Event.Window"
+#define ITF_EVENT_DOCUMENT "org.a11y.atspi.Event.Document"
+#define ITF_EVENT_FOCUS "org.a11y.atspi.Event.Focus"
/*---------------------------------------------------------------------------*/
+typedef struct _SpiReentrantCallClosure
+{
+ GMainLoop *loop;
+ DBusMessage *reply;
+} SpiReentrantCallClosure;
+
+static void
+switch_main_context (GMainContext *cnx)
+{
+ GList *list;
+
+ dbus_server_setup_with_g_main (spi_global_app_data->server, cnx);
+ dbus_connection_setup_with_g_main (spi_global_app_data->bus, cnx);
+ for (list = spi_global_app_data->direct_connections; list; list = list->next)
+ dbus_connection_setup_with_g_main (list->data, cnx);
+}
+
static void
set_reply (DBusPendingCall * pending, void *user_data)
{
- void **replyptr = (void **) user_data;
+ SpiReentrantCallClosure* closure = (SpiReentrantCallClosure *) user_data;
- *replyptr = dbus_pending_call_steal_reply (pending);
+ closure->reply = dbus_pending_call_steal_reply (pending);
+ switch_main_context (NULL);
+ g_main_loop_quit (closure->loop);
}
static DBusMessage *
send_and_allow_reentry (DBusConnection * bus, DBusMessage * message)
{
DBusPendingCall *pending;
- DBusMessage *reply = NULL;
+ SpiReentrantCallClosure closure;
+ GMainContext *main_context;
+
+ main_context = (g_getenv ("AT_SPI_CLIENT") ? NULL :
+ spi_global_app_data->main_context);
+ closure.loop = g_main_loop_new (main_context, FALSE);
+ switch_main_context (main_context);
if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
{
+ switch_main_context (NULL);
return NULL;
}
- dbus_pending_call_set_notify (pending, set_reply, (void *) &reply, NULL);
- while (!reply)
- {
- if (!dbus_connection_read_write_dispatch (bus, -1))
- return NULL;
- }
- return reply;
+ dbus_pending_call_set_notify (pending, set_reply, (void *) &closure, NULL);
+ g_main_loop_run (closure.loop);
+
+ g_main_loop_unref (closure.loop);
+ return closure.reply;
}
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Functionality related to sending device events from the application.
+ *
+ * This is used for forwarding key events on to the registry daemon.
+ */
+
static gboolean
Accessibility_DeviceEventController_NotifyListenersSync (const
Accessibility_DeviceEvent
if (spi_dbus_marshal_deviceEvent (message, key_event))
{
DBusMessage *reply =
- send_and_allow_reentry (atk_adaptor_app_data->bus, message);
+ send_and_allow_reentry (spi_global_app_data->bus, message);
if (reply)
{
DBusError error;
return result;
}
-
/*---------------------------------------------------------------------------*/
-/*
- * Emits an AT-SPI event.
- * AT-SPI events names are split into three parts:
- * class:major:minor
- * This is mapped onto D-Bus events as:
- * D-Bus Interface:Signal Name:Detail argument
- *
- * Marshals a basic type into the 'any_data' attribute of
- * the AT-SPI event.
- */
-
static gchar *
-DBusSignalName (const gchar * s)
+convert_signal_name (const gchar * s)
{
gchar *ret = g_strdup (s);
gchar *t;
return ret;
}
-static void
-emit (AtkObject * accessible,
- const char *klass,
- const char *major,
- const char *minor,
- dbus_int32_t detail1,
- dbus_int32_t detail2, const char *type, const void *val)
-{
- gchar *path;
- gchar *cname;
-
- /* TODO this is a hack, used becuase child-added events are not guaranteed.
- * On recieving an event from a non-registered object we check if it can be safely
- * registered before sending the event.
- */
- path = atk_dbus_object_attempt_registration (accessible);
-
- /* Tough decision here
- * We won't send events from accessible
- * objects that have not yet been added to the accessible tree.
- */
- if (path == NULL)
+static const void *
+replace_null (const gint type,
+ const void *val)
+{
+ switch (type)
{
-#ifdef SPI_ATK_DEBUG
- g_debug ("AT-SPI: Event recieved from non-registered object");
-#endif
- return;
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ if (!val)
+ return "";
+ else
+ return val;
+ default:
+ return val;
}
+}
+
+static void
+append_basic (DBusMessageIter *iter,
+ const char *type,
+ const void *val)
+{
+ DBusMessageIter sub;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type, &sub);
+
+ val = replace_null ((int) *type, val);
+ dbus_message_iter_append_basic(&sub, (int) *type, &val);
- cname = DBusSignalName (major);
- spi_dbus_emit_signal (atk_adaptor_app_data->bus, path, klass, cname, minor,
- detail1, detail2, type, val);
- g_free (cname);
- g_free (path);
+ dbus_message_iter_close_container(iter, &sub);
}
-/*---------------------------------------------------------------------------*/
+static void
+append_rect (DBusMessageIter *iter,
+ const char *type,
+ const void *val)
+{
+ DBusMessageIter variant, sub;
+ const AtkRectangle *rect = (const AtkRectangle *) val;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type, &variant);
+
+ dbus_message_iter_open_container (&variant, DBUS_TYPE_STRUCT, NULL, &sub);
+
+ dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->x));
+ dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->y));
+ dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->width));
+ dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->height));
+
+ dbus_message_iter_close_container (&variant, &sub);
+
+ dbus_message_iter_close_container(iter, &variant);
+}
+
+static void
+append_object (DBusMessageIter *iter,
+ const char *type,
+ const void *val)
+{
+ spi_object_append_v_reference (iter, ATK_OBJECT (val));
+}
+
+static gchar *
+signal_name_to_dbus (const gchar *s)
+{
+ gchar *ret = g_strdup (s);
+ gchar *t;
+
+ if (!ret)
+ return NULL;
+ ret [0] = toupper (ret [0]);
+ while ((t = strchr (ret, '-')) != NULL)
+ {
+ memmove (t, t + 1, strlen (t));
+ *t = toupper (*t);
+ }
+ return ret;
+}
/*
- * Emits an AT-SPI event, marshalling a BoundingBox structure into the
- * 'any_data' variant of the event.
+ * Converts names of the form "active-descendant-changed" to
+ * "ActiveDescendantChanged"
*/
-static void
-emit_rect (AtkObject * accessible,
- const char *klass,
- const char *major, const char *minor, AtkRectangle * rect)
+static gchar *
+ensure_proper_format (const char *name)
{
- DBusMessage *sig;
- DBusMessageIter iter, variant, sub;
- gchar *path, *cname;
- dbus_int32_t dummy = 0;
+ gchar *ret = (gchar *) g_malloc (strlen (name) * 2 + 2);
+ gchar *p = ret;
+ gboolean need_upper = TRUE;
- path = atk_dbus_object_to_path (accessible, FALSE);
+ if (!ret)
+ return NULL;
+ while (*name)
+ {
+ if (need_upper)
+ {
+ *p++ = toupper (*name);
+ need_upper = FALSE;
+ }
+ else if (*name == '-')
+ need_upper = TRUE;
+ else if (*name == ':')
+ {
+ need_upper = TRUE;
+ *p++ = *name;
+ }
+ else
+ *p++ = *name;
+ name++;
+ }
+ *p = '\0';
+ return ret;
+}
- /* Tough decision here
- * We won't send events from accessible
- * objects that have not yet been added to the accessible tree.
- */
- if (path == NULL)
- return;
+static gboolean
+signal_is_needed (const gchar *klass, const gchar *major, const gchar *minor)
+{
+ gchar *data [4];
+ GList *iter;
+ event_data *evdata;
+ gboolean ret = FALSE;
+ GList *list;
+
+ data [0] = ensure_proper_format (klass + 21);
+ data [1] = ensure_proper_format (major);
+ data [2] = ensure_proper_format (minor);
+ data [3] = NULL;
+
+ /* Hack: events such as "object::text-changed::insert:system" as
+ generated by Gecko */
+ data [2][strcspn (data [2], ":")] = '\0';
+ for (list = spi_global_app_data->events; list; list = list->next)
+ {
+ evdata = list->data;
+ if (spi_event_is_subtype (data, evdata->data))
+ {
+ ret = TRUE;
+ break;
+ }
+ }
- if (!klass)
- klass = "";
- if (!major)
- major = "";
- if (!minor)
- minor = "";
+ g_free (data [2]);
+ g_free (data [1]);
+ g_free (data [0]);
+ return ret;
+}
+
+/*
+ * Emits an AT-SPI event.
+ * AT-SPI events names are split into three parts:
+ * class:major:minor
+ * This is mapped onto D-Bus events as:
+ * D-Bus Interface:Signal Name:Detail argument
+ *
+ * Marshals a basic type into the 'any_data' attribute of
+ * the AT-SPI event.
+ */
+static void
+emit_event (AtkObject *obj,
+ const char *klass,
+ const char *major,
+ const char *minor,
+ dbus_int32_t detail1,
+ dbus_int32_t detail2,
+ const char *type,
+ const void *val,
+ void (*append_variant) (DBusMessageIter *, const char *, const void *))
+{
+ DBusConnection *bus = spi_global_app_data->bus;
+ const char *path = spi_register_object_to_path (spi_global_register,
+ G_OBJECT (obj));
+
+ gchar *cname, *t;
+ DBusMessage *sig;
+ DBusMessageIter iter, iter_struct;
+
+ if (!klass) klass = "";
+ if (!major) major = "";
+ if (!minor) minor = "";
+ if (!type) type = "u";
+
+ if (!signal_is_needed (klass, major, minor))
+ return;
/*
* This is very annoying, but as '-' isn't a legal signal
* name in D-Bus (Why not??!?) The names need converting
* on this side, and again on the client side.
*/
- cname = DBusSignalName (major);
+ cname = signal_name_to_dbus (major);
+ sig = dbus_message_new_signal(path, klass, cname);
+ g_free(cname);
- sig = dbus_message_new_signal (path, klass, cname);
- g_free (path);
- g_free (cname);
+ dbus_message_iter_init_append(sig, &iter);
- dbus_message_iter_init_append (sig, &iter);
- dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor);
- dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy);
- dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail1);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail2);
+ append_variant (&iter, type, val);
+ spi_object_append_reference (&iter, spi_global_app_data->root);
- dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(iiii)",
- &variant);
- dbus_message_iter_open_container (&variant, DBUS_TYPE_STRUCT, NULL, &sub);
- dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->x));
- dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->y));
- dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->width));
- dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->height));
- dbus_message_iter_close_container (&variant, &sub);
- dbus_message_iter_close_container (&iter, &variant);
+ dbus_connection_send(bus, sig, NULL);
+ dbus_message_unref(sig);
- dbus_connection_send (atk_adaptor_app_data->bus, sig, NULL);
-
- dbus_message_unref (sig);
+ if (g_strcmp0 (cname, "ChildrenChanged") != 0)
+ spi_object_lease_if_needed (G_OBJECT (obj));
}
/*---------------------------------------------------------------------------*/
static void
focus_tracker (AtkObject * accessible)
{
- emit (accessible, ITF_EVENT_FOCUS, "focus", "", 0, 0,
- DBUS_TYPE_INT32_AS_STRING, 0);
+ emit_event (accessible, ITF_EVENT_FOCUS, "focus", "", 0, 0,
+ DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
}
/*---------------------------------------------------------------------------*/
-#define PCHANGE "property-change"
+#define PCHANGE "PropertyChange"
/*
* This handler handles the following ATK signals and
const gchar *pname = NULL;
AtkObject *otemp;
- const gchar *stemp;
+ const gchar *s1, s2;
gint i;
accessible = g_value_get_object (¶m_values[0]);
values = (AtkPropertyValues *) g_value_get_pointer (¶m_values[1]);
pname = values[0].property_name;
- if (strcmp (pname, "accessible-name") == 0 ||
- strcmp (pname, "accessible-description") == 0 ||
- strcmp (pname, "accessible-role") == 0 ||
- strcmp (pname, "accessible-parent") == 0)
- {
- return TRUE;
- }
/* TODO Could improve this control statement by matching
* on only the end of the signal names,
*/
- if (strcmp (pname, "accessible-table-summary") == 0)
+ if (strcmp (pname, "accessible-name") == 0)
+ {
+ s1 = atk_object_get_name (accessible);
+ if (s1 != NULL)
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
+ }
+ else if (strcmp (pname, "accessible-description") == 0)
+ {
+ s1 = atk_object_get_description (accessible);
+ if (s1 != NULL)
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
+ }
+ else if (strcmp (pname, "accessible-parent") == 0)
+ {
+ otemp = atk_object_get_parent (accessible);
+ if (otemp != NULL)
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ "(so)", otemp, append_object);
+ }
+ else if (strcmp (pname, "accessible-role") == 0)
+ {
+ i = atk_object_get_role (accessible);
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ DBUS_TYPE_UINT32_AS_STRING, GINT_TO_POINTER(i), append_basic);
+ }
+ else if (strcmp (pname, "accessible-table-summary") == 0)
{
otemp = atk_table_get_summary (ATK_TABLE (accessible));
- stemp = atk_dbus_object_to_path (otemp, FALSE);
- if (stemp != NULL)
- emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
+ if (otemp != NULL)
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ "(so)", otemp, append_object);
}
else if (strcmp (pname, "accessible-table-column-header") == 0)
{
i = g_value_get_int (&(values->new_value));
otemp = atk_table_get_column_header (ATK_TABLE (accessible), i);
- stemp = atk_dbus_object_to_path (otemp, FALSE);
- if (stemp != NULL)
- emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
+ if (otemp != NULL)
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ "(so)", otemp, append_object);
}
else if (strcmp (pname, "accessible-table-row-header") == 0)
{
i = g_value_get_int (&(values->new_value));
otemp = atk_table_get_row_header (ATK_TABLE (accessible), i);
- stemp = atk_dbus_object_to_path (otemp, FALSE);
- if (stemp != NULL)
- emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp);
+ if (otemp != NULL)
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ "(so)", otemp, append_object);
}
else if (strcmp (pname, "accessible-table-row-description") == 0)
{
i = g_value_get_int (&(values->new_value));
- stemp = atk_table_get_row_description (ATK_TABLE (accessible), i);
- emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
- DBUS_TYPE_STRING_AS_STRING, stemp);
+ s1 = atk_table_get_row_description (ATK_TABLE (accessible), i);
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
}
else if (strcmp (pname, "accessible-table-column-description") == 0)
{
i = g_value_get_int (&(values->new_value));
- stemp = atk_table_get_column_description (ATK_TABLE (accessible), i);
- emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
- DBUS_TYPE_STRING_AS_STRING, stemp);
+ s1 = atk_table_get_column_description (ATK_TABLE (accessible), i);
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, s1, append_basic);
}
else if (strcmp (pname, "accessible-table-caption-object") == 0)
{
otemp = atk_table_get_caption (ATK_TABLE (accessible));
- stemp = atk_object_get_name (otemp);
- emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
- DBUS_TYPE_STRING_AS_STRING, stemp);
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ "(so)", otemp, append_object);
}
else
{
- emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
- DBUS_TYPE_INT32_AS_STRING, 0);
+ emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0,
+ DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
}
return TRUE;
}
* This is because without reference counting defunct objects should be removed.
*/
detail1 = (g_value_get_boolean (¶m_values[2])) ? 1 : 0;
- emit (accessible, ITF_EVENT_OBJECT, STATE_CHANGED, pname, detail1, 0,
- DBUS_TYPE_INT32_AS_STRING, 0);
+ emit_event (accessible, ITF_EVENT_OBJECT, STATE_CHANGED, pname, detail1, 0,
+ DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
g_free (pname);
return TRUE;
}
accessible = ATK_OBJECT (g_value_get_object (¶m_values[0]));
s = atk_object_get_name (accessible);
- emit (accessible, ITF_EVENT_WINDOW, name, "", 0, 0,
- DBUS_TYPE_STRING_AS_STRING, s);
+ emit_event (accessible, ITF_EVENT_WINDOW, name, "", 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, s, append_basic);
return TRUE;
}
accessible = ATK_OBJECT (g_value_get_object (¶m_values[0]));
s = atk_object_get_name (accessible);
- emit (accessible, ITF_EVENT_DOCUMENT, name, "", 0, 0,
- DBUS_TYPE_STRING_AS_STRING, s);
+ emit_event (accessible, ITF_EVENT_DOCUMENT, name, "", 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, s, append_basic);
return TRUE;
}
accessible = ATK_OBJECT (g_value_get_object (¶m_values[0]));
if (G_VALUE_HOLDS_BOXED (param_values + 1))
+ {
atk_rect = g_value_get_boxed (param_values + 1);
- emit_rect (accessible, ITF_EVENT_OBJECT, name, "", atk_rect);
+ emit_event (accessible, ITF_EVENT_OBJECT, name, "", 0, 0,
+ "(iiii)", atk_rect, append_rect);
+ }
return TRUE;
}
AtkObject *child;
GSignalQuery signal_query;
const gchar *name, *minor;
- gchar *s;
gint detail1;
g_signal_query (signal_hint->signal_id, &signal_query);
minor = g_quark_to_string (signal_hint->detail);
detail1 = atk_object_get_index_in_parent (child);
- s = atk_dbus_object_to_path (child, FALSE);
- if (s == NULL)
- {
- g_free (s);
- return TRUE;
- }
- emit (accessible, ITF_EVENT_OBJECT, name, "", detail1, 0,
- DBUS_TYPE_OBJECT_PATH_AS_STRING, s);
- g_free (s);
+ emit_event (accessible, ITF_EVENT_OBJECT, name, "", detail1, 0,
+ "(so)", child, append_object);
return TRUE;
}
if (G_VALUE_TYPE (¶m_values[1]) == G_TYPE_INT)
detail1 = g_value_get_int (¶m_values[1]);
- emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, 0,
- DBUS_TYPE_INT32_AS_STRING, 0);
+ emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, 0,
+ DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
return TRUE;
}
selected =
atk_text_get_text (ATK_TEXT (accessible), detail1, detail1 + detail2);
- emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
- DBUS_TYPE_STRING_AS_STRING, selected);
+ emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
+ DBUS_TYPE_STRING_AS_STRING, selected, append_basic);
return TRUE;
}
if (G_VALUE_TYPE (¶m_values[2]) == G_TYPE_INT)
detail2 = g_value_get_int (¶m_values[2]);
- emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
- DBUS_TYPE_STRING_AS_STRING, "");
+ emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
+ DBUS_TYPE_STRING_AS_STRING, "", append_basic);
return TRUE;
}
/*---------------------------------------------------------------------------*/
/*
+ * Children changed signal converter and forwarder.
+ *
+ * Klass (Interface) org.a11y.atspi.Event.Object
+ * Major is the signal name.
+ * Minor is 'add' or 'remove'
+ * detail1 is the index.
+ * detail2 is 0.
+ * any_data is the child reference.
+ */
+static gboolean
+children_changed_event_listener (GSignalInvocationHint * signal_hint,
+ guint n_param_values,
+ const GValue * param_values, gpointer data)
+{
+ GSignalQuery signal_query;
+ const gchar *name, *minor;
+ gint detail1, detail2 = 0;
+
+ AtkObject *accessible, *ao=NULL;
+ gpointer child;
+
+ g_signal_query (signal_hint->signal_id, &signal_query);
+ name = signal_query.signal_name;
+
+ accessible = ATK_OBJECT (g_value_get_object (¶m_values[0]));
+ minor = g_quark_to_string (signal_hint->detail);
+
+ detail1 = g_value_get_uint (param_values + 1);
+ child = g_value_get_pointer (param_values + 2);
+
+ if (ATK_IS_OBJECT (child))
+ {
+ ao = ATK_OBJECT (child);
+ emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
+ "(so)", ao, append_object);
+ }
+ else if ((minor != NULL) && (strcmp (minor, "add") == 0))
+ {
+ ao = atk_object_ref_accessible_child (accessible,
+ detail1);
+ emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
+ "(so)", ao, append_object);
+ }
+ else
+ {
+ emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2,
+ "(so)", ao, append_object);
+ }
+
+ return TRUE;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void
+toplevel_added_event_listener (AtkObject * accessible,
+ guint index, AtkObject * child)
+{
+ emit_event (accessible, ITF_EVENT_OBJECT, "children-changed", "add", index, 0,
+ "(so)", child, append_object);
+}
+
+static void
+toplevel_removed_event_listener (AtkObject * accessible,
+ guint index, AtkObject * child)
+{
+ emit_event (accessible, ITF_EVENT_OBJECT, "children-changed", "remove", index, 0,
+ "(so)", child, append_object);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
* Generic signal converter and forwarder.
*
- * Klass (Interface) org.freedesktop.atspi.Event.Object
+ * Klass (Interface) org.a11y.atspi.Event.Object
* Major is the signal name.
* Minor is NULL.
* detail1 is 0.
if (n_param_values > 2 && G_VALUE_TYPE (¶m_values[2]) == G_TYPE_INT)
detail2 = g_value_get_int (¶m_values[2]);
- emit (accessible, ITF_EVENT_OBJECT, name, "", detail1, detail2,
- DBUS_TYPE_INT32_AS_STRING, 0);
+ emit_event (accessible, ITF_EVENT_OBJECT, name, "", detail1, detail2,
+ DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
return TRUE;
}
add_signal_listener (generic_event_listener, "Gtk:AtkTable:column-deleted");
add_signal_listener (generic_event_listener, "Gtk:AtkTable:model-changed");
+ /* Children signal listeners */
+ atk_add_global_event_listener (children_changed_event_listener,
+ "Gtk:AtkObject:children-changed");
+
+#if 0
+ g_signal_connect (G_OBJECT (spi_global_app_data->root),
+ "children-changed::add",
+ (GCallback) toplevel_added_event_listener, NULL);
+
+ g_signal_connect (G_OBJECT (spi_global_app_data->root),
+ "children-changed::remove",
+ (GCallback) toplevel_removed_event_listener, NULL);
+#endif
+
/*
* May add the following listeners to implement preemptive key listening for GTK+
*
name = atk_object_get_name (child);
if (atk_state_set_contains_state (stateset, ATK_STATE_ACTIVE))
{
- emit (child, ITF_EVENT_WINDOW, "deactivate", NULL, 0, 0,
- DBUS_TYPE_STRING_AS_STRING, name);
+ emit_event (child, ITF_EVENT_WINDOW, "deactivate", NULL, 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, name, append_basic);
}
g_object_unref (stateset);
- emit (child, ITF_EVENT_WINDOW, "destroy", NULL, 0, 0,
- DBUS_TYPE_STRING_AS_STRING, name);
+ emit_event (child, ITF_EVENT_WINDOW, "destroy", NULL, 0, 0,
+ DBUS_TYPE_STRING_AS_STRING, name, append_basic);
g_object_unref (child);
}
}
+gboolean
+spi_event_is_subtype (gchar **needle, gchar **haystack)
+{
+ while (*haystack && **haystack)
+ {
+ if (g_strcmp0 (*needle, *haystack))
+ return FALSE;
+ needle++;
+ haystack++;
+ }
+ return TRUE;
+}
+
/*END------------------------------------------------------------------------*/