Some introspection fixes to make vapigen happy
[platform/upstream/at-spi2-core.git] / atspi / atspi-event-listener.c
index 83c9ae0..ba5d126 100644 (file)
@@ -164,7 +164,7 @@ atspi_event_listener_new_simple (AtspiEventListenerSimpleCB callback,
 static GList *event_listeners = NULL;
 
 static gchar *
-convert_name_from_dbus (const char *name)
+convert_name_from_dbus (const char *name, gboolean path_hack)
 {
   gchar *ret = g_malloc (g_utf8_strlen (name, -1) * 2 + 1);
   const char *p = name;
@@ -181,6 +181,11 @@ convert_name_from_dbus (const char *name)
         *q++ = '-';
       *q++ = tolower (*p++);
     }
+    else if (path_hack && *p == '/')
+    {
+      *q++ = ':';
+      p++;
+    }
     else
       *q++ = *p++;
   }
@@ -204,9 +209,9 @@ cache_process_children_changed (AtspiEvent *event)
   {
     if (g_list_find (event->source->children, child))
       return;
-    GList *new_list = g_list_insert (event->source->children, g_object_ref (child), event->detail1);
-    if (new_list)
-      event->source->children = new_list;
+    event->source->children = g_list_insert (event->source->children,
+                                             g_object_ref (child),
+                                             event->detail1);
   }
   else if (g_list_find (event->source->children, child))
   {
@@ -265,6 +270,18 @@ cache_process_property_change (AtspiEvent *event)
       event->source->cached_properties &= ~ATSPI_CACHE_DESCRIPTION;
     }
   }
+  else if (!strcmp (event->type, "object:property-change:accessible-role"))
+  {
+    if (G_VALUE_HOLDS_INT (&event->any_data))
+    {
+      event->source->role = g_value_get_int (&event->any_data);
+      _atspi_accessible_add_cache (event->source, ATSPI_CACHE_ROLE);
+    }
+    else
+    {
+      event->source->cached_properties &= ~ATSPI_CACHE_ROLE;
+    }
+  }
 }
 
 static void
@@ -331,7 +348,7 @@ strdup_and_adjust_for_dbus (const char *s)
 }
 
 static gboolean
-convert_event_type_to_dbus (const char *eventType, char **categoryp, char **namep, char **detailp, char **matchrule)
+convert_event_type_to_dbus (const char *eventType, char **categoryp, char **namep, char **detailp, GPtrArray **matchrule_array)
 {
   gchar *tmp = strdup_and_adjust_for_dbus (eventType);
   char *category = NULL, *name = NULL, *detail = NULL;
@@ -340,31 +357,34 @@ convert_event_type_to_dbus (const char *eventType, char **categoryp, char **name
   if (tmp == NULL) return FALSE;
   category = strtok_r (tmp, ":", &saveptr);
   if (category) category = g_strdup (category);
-  if (!category) goto oom;
   name = strtok_r (NULL, ":", &saveptr);
   if (name)
   {
     name = g_strdup (name);
-    if (!name) goto oom;
     detail = strtok_r (NULL, ":", &saveptr);
     if (detail) detail = g_strdup (detail);
   }
-  if (matchrule)
+  if (matchrule_array)
   {
-    *matchrule = g_strdup_printf ("type='signal',interface='org.a11y.atspi.Event.%s'", category);
-    if (!*matchrule) goto oom;
+    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;
+      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])
     {
-      gchar *new_str = g_strconcat (*matchrule, ",arg0='", detail, "'", NULL);
-      g_free (*matchrule);
-      *matchrule = new_str;
+      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);
@@ -374,12 +394,6 @@ convert_event_type_to_dbus (const char *eventType, char **categoryp, char **name
   else if (detail) g_free (detail);
   g_free (tmp);
   return TRUE;
-oom:
-  if (tmp) g_free (tmp);
-  if (category) g_free (category);
-  if (name) g_free (name);
-  if (detail) g_free (detail);
-  return FALSE;
 }
 
 static void
@@ -520,10 +534,10 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
                                             GError **error)
 {
   EventListenerEntry *e;
-  char *matchrule;
   DBusError d_error;
-  GList *new_list;
   DBusMessage *message, *reply;
+  GPtrArray *matchrule_array;
+  gint i;
 
   if (!callback)
     {
@@ -542,27 +556,28 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
   e->callback_destroyed = callback_destroyed;
   callback_ref (callback == remove_datum ? (gpointer)user_data : (gpointer)callback,
                 callback_destroyed);
-  if (!convert_event_type_to_dbus (event_type, &e->category, &e->name, &e->detail, &matchrule))
+  if (!convert_event_type_to_dbus (event_type, &e->category, &e->name, &e->detail, &matchrule_array))
   {
     g_free (e);
     return FALSE;
   }
-  new_list = g_list_prepend (event_listeners, e);
-  if (!new_list)
-  {
-    listener_entry_free (e);
-    return FALSE;
-  }
-  event_listeners = new_list;
-  dbus_error_init (&d_error);
-  dbus_bus_add_match (_atspi_bus(), matchrule, &d_error);
-  if (d_error.message)
+  event_listeners = g_list_prepend (event_listeners, e);
+  for (i = 0; i < matchrule_array->len; i++)
   {
-    g_warning ("Atspi: Adding match: %s", d_error.message);
-    /* TODO: Set error */
+    char *matchrule = g_ptr_array_index (matchrule_array, i);
+    dbus_error_init (&d_error);
+    dbus_bus_add_match (_atspi_bus(), matchrule, &d_error);
+    if (dbus_error_is_set (&d_error))
+      {
+        g_warning ("Atspi: Adding match: %s", d_error.message);
+        dbus_error_free (&d_error);
+        /* TODO: Set error */
+      }
+
+    g_free (matchrule);
   }
+  g_ptr_array_free (matchrule_array, TRUE);
 
-  dbus_error_init (&d_error);
   message = dbus_message_new_method_call (atspi_bus_registry,
        atspi_path_registry,
        atspi_interface_registry,
@@ -654,10 +669,12 @@ atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
                                               const gchar              *event_type,
                                               GError **error)
 {
-  char *category, *name, *detail, *matchrule;
+  char *category, *name, *detail;
+  GPtrArray *matchrule_array;
+  gint i;
   GList *l;
 
-  if (!convert_event_type_to_dbus (event_type, &category, &name, &detail, &matchrule))
+  if (!convert_event_type_to_dbus (event_type, &category, &name, &detail, &matchrule_array))
   {
     return FALSE;
   }
@@ -676,19 +693,20 @@ atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
         is_superset (detail, e->detail))
     {
       gboolean need_replace;
-      DBusError d_error;
       DBusMessage *message, *reply;
       need_replace = (l == event_listeners);
       l = g_list_remove (l, e);
       if (need_replace)
         event_listeners = l;
-      dbus_error_init (&d_error);
-      dbus_bus_remove_match (_atspi_bus(), matchrule, &d_error);
-      dbus_error_init (&d_error);
+      for (i = 0; i < matchrule_array->len; i++)
+      {
+       char *matchrule = g_ptr_array_index (matchrule_array, i);
+       dbus_bus_remove_match (_atspi_bus(), matchrule, NULL);
+      }
       message = dbus_message_new_method_call (atspi_bus_registry,
            atspi_path_registry,
            atspi_interface_registry,
-           "RegisterEvent");
+           "DeregisterEvent");
       if (!message)
       return FALSE;
       dbus_message_append_args (message, DBUS_TYPE_STRING, &event_type, DBUS_TYPE_INVALID);
@@ -703,7 +721,9 @@ atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
   g_free (category);
   g_free (name);
   if (detail) g_free (detail);
-  g_free (matchrule);
+  for (i = 0; i < matchrule_array->len; i++)
+    g_free (g_ptr_array_index (matchrule_array, i));
+  g_ptr_array_free (matchrule_array, TRUE);
   return TRUE;
 }
 
@@ -751,11 +771,24 @@ atspi_event_free (AtspiEvent *event)
   g_free (event);
 }
 
+static gboolean
+detail_matches_listener (const char *event_detail, const char *listener_detail)
+{
+  if (!listener_detail)
+    return TRUE;
+
+  return !(listener_detail [strcspn (listener_detail, ":")] == '\0'
+               ? strncmp (listener_detail, event_detail,
+                          strcspn (event_detail, ":"))
+               : strcmp (listener_detail, event_detail));
+}
+
 void
 _atspi_send_event (AtspiEvent *e)
 {
   char *category, *name, *detail;
   GList *l;
+  GList *called_listeners = NULL;
 
   /* Ensure that the value is set to avoid a Python exception */
   /* TODO: Figure out how to do this without using a private field */
@@ -775,14 +808,26 @@ _atspi_send_event (AtspiEvent *e)
     EventListenerEntry *entry = l->data;
     if (!strcmp (category, entry->category) &&
         (entry->name == NULL || !strcmp (name, entry->name)) &&
-        (entry->detail == NULL || !strcmp (detail, entry->detail)))
+        detail_matches_listener (detail, entry->detail))
     {
+      GList *l2;
+      for (l2 = called_listeners; l2; l2 = l2->next)
+      {
+        EventListenerEntry *e2 = l2->data;
+        if (entry->callback == e2->callback && entry->user_data == e2->user_data)
+          break;
+      }
+      if (!l2)
+      {
         entry->callback (atspi_event_copy (e), entry->user_data);
+        called_listeners = g_list_prepend (called_listeners, entry);
+      }
     }
   }
   if (detail) g_free (detail);
   g_free (name);
   g_free (category);
+  g_list_free (called_listeners);
 }
 
 DBusHandlerResult
@@ -827,9 +872,9 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
   e.detail2 = detail2;
   dbus_message_iter_next (&iter);
 
-  converted_type = convert_name_from_dbus (category);
-  name = convert_name_from_dbus (member);
-  detail = convert_name_from_dbus (detail);
+  converted_type = convert_name_from_dbus (category, FALSE);
+  name = convert_name_from_dbus (member, FALSE);
+  detail = convert_name_from_dbus (detail, TRUE);
 
   if (strcasecmp  (category, name) != 0)
   {
@@ -870,7 +915,8 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
        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);
-       g_object_unref (accessible);    /* value now owns it */
+       if (accessible)
+         g_object_unref (accessible);  /* value now owns it */
       }
       break;
     }
@@ -897,6 +943,11 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
   {
     cache_process_state_changed (&e);
   }
+  else if (!strncmp (e.type, "focus", 5))
+  {
+    /* BGO#663992 - TODO: figure out the real problem */
+    e.source->cached_properties &= ~(ATSPI_CACHE_STATES);
+  }
 
   _atspi_send_event (&e);