Merge branch 'upstream/2.26.1' into tizen
[platform/upstream/at-spi2-core.git] / atspi / atspi-registry.c
index 67a7590..759a1aa 100644 (file)
 
 #include "atspi-private.h"
 
+typedef struct
+{
+  AtspiDeviceListener *listener;
+  GArray             *key_set;
+  AtspiKeyMaskType         modmask;
+  AtspiKeyEventMask        event_types;
+  gint sync_type;
+} DeviceListenerEntry;
+
+static GList *device_listeners;
+
 /**
  * atspi_get_desktop_count:
  *
@@ -72,7 +83,8 @@ atspi_get_desktop (gint i)
  * this implementation always returns a #Garray with a single
  * #AtspiAccessible desktop.
  *
- * Returns: (transfer full): a #GArray of desktops.
+ * Returns: (element-type AtspiAccessible*) (transfer full): a #GArray of
+ * desktops.
  **/
 GArray *
 atspi_get_desktop_list ()
@@ -86,6 +98,69 @@ atspi_get_desktop_list ()
   return array;
 }
 
+static gboolean
+notify_keystroke_listener (DeviceListenerEntry *e)
+{
+  gchar *path = _atspi_device_listener_get_path (e->listener);
+  dbus_uint32_t d_modmask = e->modmask;
+  dbus_uint32_t d_event_types = e->event_types;
+  AtspiEventListenerMode     listener_mode;
+  gboolean                          retval = FALSE;
+  DBusError d_error;
+
+  listener_mode.synchronous =
+         (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0);
+  listener_mode.preemptive =
+         (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0);
+  listener_mode.global =
+         (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0);
+
+  dbus_error_init (&d_error);
+  dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry,
+                               atspi_path_dec, atspi_interface_dec,
+                               "RegisterKeystrokeListener", &d_error,
+                               "oa(iisi)uu(bbb)=>b", path, e->key_set,
+                               d_modmask, d_event_types, &listener_mode,
+                               &retval);
+  if (dbus_error_is_set (&d_error))
+    {
+      g_warning ("RegisterKeystrokeListener failed: %s", d_error.message);
+      dbus_error_free (&d_error);
+    }
+
+  g_free (path);
+
+  return retval;
+}
+
+static void
+device_listener_entry_free (DeviceListenerEntry *e)
+{
+  g_array_free (e->key_set, TRUE);
+  g_free (e);
+}
+
+static void
+unregister_listener (gpointer data, GObject *object)
+{
+  GList *l;
+  AtspiDeviceListener *listener = ATSPI_DEVICE_LISTENER (object);
+
+  for (l = device_listeners; l;)
+    {
+      DeviceListenerEntry *e = l->data;
+      if (e->listener == listener)
+        {
+          GList *next = l->next;
+          device_listener_entry_free (e);
+          device_listeners = g_list_delete_link (device_listeners, l);
+          l = next;
+        }
+      else
+        l = l->next;
+    }
+}
+
 /**
  * atspi_register_keystroke_listener:
  * @listener:  a pointer to the #AtspiDeviceListener for which
@@ -123,31 +198,28 @@ atspi_register_keystroke_listener (AtspiDeviceListener  *listener,
                                         GArray             *key_set,
                                         AtspiKeyMaskType         modmask,
                                         AtspiKeyEventMask        event_types,
-                                        gint sync_type, GError **error)
+                                        AtspiKeyListenerSyncType sync_type,
+                                         GError **error)
 {
-  GArray *d_key_set;
-  gchar *path = _atspi_device_listener_get_path (listener);
-  gint                                i;
-  dbus_uint32_t d_modmask = modmask;
-  dbus_uint32_t d_event_types = event_types;
-  AtspiEventListenerMode     listener_mode;
-  gboolean                          retval = FALSE;
-  DBusError d_error;
+  DeviceListenerEntry *e;
 
-  if (!listener)
-    {
-      return retval;
-    }
+  g_return_val_if_fail (listener != NULL, FALSE);
 
-  /* copy the keyval filter values from the C api into the DBind KeySet */
+  e = g_new0 (DeviceListenerEntry, 1);
+  e->listener = listener;
+  e->modmask = modmask;
+  e->event_types = event_types;
+  e->sync_type = sync_type;
   if (key_set)
     {
-      d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), key_set->len);
-      d_key_set->len = key_set->len;
-      for (i = 0; i < key_set->len; ++i)
+      gint i;
+      e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition),
+                                      key_set->len);
+      e->key_set->len = key_set->len;
+      for (i = 0; i < key_set->len; i++)
         {
          AtspiKeyDefinition *kd =  ((AtspiKeyDefinition *) key_set->data) + i;
-         AtspiKeyDefinition *d_kd =  ((AtspiKeyDefinition *) d_key_set->data) + i;
+         AtspiKeyDefinition *d_kd =  ((AtspiKeyDefinition *) e->key_set->data) + i;
           d_kd->keycode = kd->keycode;
          d_kd->keysym = kd->keysym;
          if (kd->keystring)
@@ -162,28 +234,12 @@ atspi_register_keystroke_listener (AtspiDeviceListener  *listener,
     }
   else
     {
-      d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
-    }
-       
-  listener_mode.synchronous =
-         (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0);
-  listener_mode.preemptive =
-         (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0);
-  listener_mode.global =
-         (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0);
-
-  dbus_error_init (&d_error);
-  dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterKeystrokeListener", &d_error, "oa(iisi)uu(bbb)=>b", path, d_key_set, d_modmask, d_event_types, &listener_mode, &retval);
-  if (dbus_error_is_set (&d_error))
-    {
-      g_warning ("RegisterKeystrokeListener failed: %s", d_error.message);
-      dbus_error_free (&d_error);
+      e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
     }
 
-  g_array_free (d_key_set, TRUE);
-  g_free (path);
-
-  return retval;
+  g_object_weak_ref (G_OBJECT (listener), unregister_listener, NULL);
+  device_listeners = g_list_prepend (device_listeners, e);
+  return notify_keystroke_listener (e);
 }
 
 /**
@@ -214,17 +270,19 @@ atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
                                      GError             **error)
 {
   GArray *d_key_set;
-  gchar *path = _atspi_device_listener_get_path (listener);
+  gchar *path;
   gint i;
   dbus_uint32_t d_modmask = modmask;
   dbus_uint32_t d_event_types = event_types;
   DBusError d_error;
+  GList *l;
 
   dbus_error_init (&d_error);
   if (!listener)
     {
       return FALSE;
     }
+  path = _atspi_device_listener_get_path (listener);
 
   /* copy the keyval filter values from the C api into the DBind KeySet */
   if (key_set)
@@ -263,6 +321,24 @@ atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
       dbus_error_free (&d_error);
     }
 
+  unregister_listener (listener, NULL);
+  for (l = device_listeners; l;)
+    {
+      /* TODO: This code is all wrong / doesn't match what is in
+ *       deviceeventcontroller.c. It would be nice to deprecate these methods
+ *       in favor of methods that return an ID for the registration that can
+ *       be passed to a deregister function, for instance. */
+      DeviceListenerEntry *e = l->data;
+      if (e->modmask == modmask && e->event_types == event_types)
+        {
+          GList *next = l->next;
+          device_listener_entry_free (e);
+          device_listeners = g_list_delete_link (device_listeners, l);
+          l = next;
+        }
+      else
+        l = l->next;
+    }
   g_array_free (d_key_set, TRUE);
   g_free (path);
   return TRUE;
@@ -274,7 +350,7 @@ atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
  *             the events.
  * @event_types: an #AtspiDeviceEventMask mask indicating which
  *             types of key events are requested (%ATSPI_KEY_PRESSED, etc.).
- * @filter: Unused parameter.
+ * @filter: (allow-none): Unused parameter.
  * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
  *             
  * Registers a listener for device events, for instance button events.
@@ -288,7 +364,7 @@ atspi_register_device_event_listener (AtspiDeviceListener  *listener,
 {
   gboolean                          retval = FALSE;
   dbus_uint32_t d_event_types = event_types;
-  gchar *path = _atspi_device_listener_get_path (listener);
+  gchar *path;
   DBusError d_error;
 
   dbus_error_init (&d_error);
@@ -296,6 +372,7 @@ atspi_register_device_event_listener (AtspiDeviceListener  *listener,
     {
       return retval;
     }
+  path = _atspi_device_listener_get_path (listener);
 
     dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_types, &retval);
     if (dbus_error_is_set (&d_error))
@@ -312,7 +389,7 @@ atspi_register_device_event_listener (AtspiDeviceListener  *listener,
  * atspi_deregister_device_event_listener:
  * @listener: a pointer to the #AtspiDeviceListener for which
  *            device events are requested.
- * @filter: Unused parameter.
+ * @filter: (allow-none): Unused parameter.
  * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
  *
  * Removes a device event listener from the registry's listener queue,
@@ -325,7 +402,7 @@ atspi_deregister_device_event_listener (AtspiDeviceListener *listener,
                                   void                     *filter, GError **error)
 {
   dbus_uint32_t event_types = 0;
-  gchar *path = _atspi_device_listener_get_path (listener);
+  gchar *path;
   DBusError d_error;
 
   dbus_error_init (&d_error);
@@ -334,6 +411,7 @@ atspi_deregister_device_event_listener (AtspiDeviceListener *listener,
     {
       return FALSE;
     }
+  path = _atspi_device_listener_get_path (listener);
 
   event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT);
   event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT);
@@ -452,4 +530,16 @@ atspi_key_definition_free (AtspiKeyDefinition *kd)
   g_free (kd);
 }
 
+void
+_atspi_reregister_device_listeners ()
+{
+  GList *l;
+  DeviceListenerEntry *e;
+
+  for (l = device_listeners; l; l = l->next)
+    {
+      e = l->data;
+      notify_keystroke_listener (e);
+    }
+}
 G_DEFINE_BOXED_TYPE (AtspiKeyDefinition, atspi_key_definition, atspi_key_definition_copy, atspi_key_definition_free)