Support sending data with events
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / event.c
index fa7cbbd..0430271 100644 (file)
@@ -353,13 +353,37 @@ ensure_proper_format (const char *name)
   return ret;
 }
 
+void
+append_properties (GArray *properties, event_data *evdata)
+{
+  GSList *ls;
+  gint i;
+
+  for (ls = evdata->properties; ls; ls = ls->next)
+  {
+    gboolean dup = FALSE;
+    for (i = 0; i < properties->len; i++)
+    {
+      if (ls->data == g_array_index (properties, AtspiPropertyDefinition *, i))
+      {
+        dup = TRUE;
+        break;
+      }
+    }
+    if (!dup)
+      g_array_append_val (properties, ls->data);
+  }
+}
+
 static gboolean
-signal_is_needed (const gchar *klass, const gchar *major, const gchar *minor)
+signal_is_needed (const gchar *klass, const gchar *major, const gchar *minor,
+                  GArray **properties)
 {
   gchar *data [4];
   event_data *evdata;
   gboolean ret = FALSE;
   GList *list;
+  GArray *props = NULL;
 
   if (!spi_global_app_data->events_initialized)
     return TRUE;
@@ -379,32 +403,28 @@ signal_is_needed (const gchar *klass, const gchar *major, const gchar *minor)
         !g_strcmp0 (data [2], "accessible-parent") ||
         !g_strcmp0 (data [2], "accessible-role"))) ||
       !g_strcmp0 (data [1], "StateChanged"))
-  {
-    g_free (data [2]);
-    g_free (data [1]);
-    g_free (data [0]);
-    return TRUE;
-  }
+    ret = TRUE;
 
   /* 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 (!props)
+          props = g_array_new (TRUE, TRUE, sizeof (AtspiPropertyDefinition *));
+          append_properties (props, evdata);
         }
     }
 
-#if 0
-  g_print("event: %s %s %s: %d\n", data[0], data[1], data[2], ret);
-#endif
   g_free (data [2]);
   g_free (data [1]);
   g_free (data [0]);
+  *properties = props;
   return ret;
 }
 
@@ -420,6 +440,14 @@ adapt_minor_for_dbus (const char *source)
   return ret;
 }
 
+static void
+open_variant (DBusMessageIter *iter, const char *name, const char *type,
+              DBusMessageIter *out)
+{
+  dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &name);
+  dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, type, out);
+}
+
 /*
  * Emits an AT-SPI event.
  * AT-SPI events names are split into three parts:
@@ -447,14 +475,15 @@ emit_event (AtkObject  *obj,
 
   gchar *cname;
   DBusMessage *sig;
-  DBusMessageIter iter;
+  DBusMessageIter iter, iter_dict, iter_dict_entry, iter_variant, iter_array;
+  GArray *properties = NULL;
   
   if (!klass) klass = "";
   if (!major) major = "";
   if (!minor) minor = "";
   if (!type) type = "u";
 
-  if (!signal_is_needed (klass, major, minor))
+  if (!signal_is_needed (klass, major, minor, &properties))
     return;
 
   path =  spi_register_object_to_path (spi_global_register, G_OBJECT (obj));
@@ -476,7 +505,28 @@ emit_event (AtkObject  *obj,
   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_ARRAY, "{sv}", &iter_dict);
+  /* Add requested properties, unless the object is being marked defunct, in
+     which case it's safest not to touch it */
+  if (minor == NULL || strcmp (minor, "defunct") != 0 || detail1 == 0)
+  {
+    if (properties)
+    {
+      gint i;
+      for (i = 0; i < properties->len; i++)
+      {
+        AtspiPropertyDefinition *prop = g_array_index (properties, AtspiPropertyDefinition *, i);
+        dbus_message_iter_open_container (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL,
+                                          &iter_dict_entry);
+        dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop->name);
+        prop->func (&iter_dict_entry, obj);
+        dbus_message_iter_close_container (&iter_dict, &iter_dict_entry);
+      }
+      g_array_free (properties, TRUE);
+    }
+  }
+    dbus_message_iter_close_container (&iter, &iter_dict);
 
   dbus_connection_send(bus, sig, NULL);
   dbus_message_unref(sig);