[at-spi2-core] Allow applications to query keyboard and mouse listeners



commit be3d5baf37515a76cd3db243665c84e26f30422f
Author: Mike Gorse <mgorse novell com>
Date:   Thu Jan 5 14:36:18 2012 -0600

    Allow applications to query keyboard and mouse listeners
    
    Add methods to list the currently-active keyboard and mouse listeners
    and signals to be fired when listeners are registered or deregistered.
    
    Part of the fix for http://bugzilla.gnome.org/show_bug.cgi?id=666870

 atspi/atspi-gmain.c               |    2 -
 registryd/deviceeventcontroller.c |  183 ++++++++++++++++++++++++++++++++++++-
 registryd/introspection.c         |   24 +++++
 3 files changed, 205 insertions(+), 4 deletions(-)
---
diff --git a/atspi/atspi-gmain.c b/atspi/atspi-gmain.c
index bb68c65..6498c0a 100644
--- a/atspi/atspi-gmain.c
+++ b/atspi/atspi-gmain.c
@@ -351,8 +351,6 @@ connection_setup_add_timeout (ConnectionSetup *cs,
   if (!dbus_timeout_get_enabled (timeout))
     return;
   
-  g_assert (dbus_timeout_get_data (timeout) == NULL);
-
   handler = g_new0 (TimeoutHandler, 1);
   handler->cs = cs;
   handler->timeout = timeout;
diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c
index 4910555..283322c 100644
--- a/registryd/deviceeventcontroller.c
+++ b/registryd/deviceeventcontroller.c
@@ -981,11 +981,129 @@ spi_controller_deregister_global_keygrabs (SpiDEController         *controller,
     spi_controller_update_key_grabs (controller, NULL);
 }
 
+static void
+append_keystroke_listener (DBusMessageIter *iter, DEControllerKeyListener *listener)
+{
+  dbus_uint32_t d_uint;
+  DBusMessageIter iter_struct, iter_subarray, iter_substruct;
+  GList *l;
+  GSList *kl;
+
+  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
+                                         &iter_struct))
+    return;
+
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
+                                  &listener->listener.bus_name);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
+                                  &listener->listener.path);
+  d_uint = listener->listener.type;
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
+  d_uint = listener->listener.types;
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
+  if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY,
+                                         "(iisi)", &iter_subarray))
+  {
+    dbus_message_iter_close_container (iter, &iter_struct);
+    return;
+  }
+  for (kl = listener->keys; kl; kl = kl->next)
+  {
+    Accessibility_KeyDefinition *kd = kl->data;
+    if (!dbus_message_iter_open_container (&iter_subarray, DBUS_TYPE_STRUCT,
+                                         NULL, &iter_substruct))
+      break;
+    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keycode);
+    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keysym);
+    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_STRING, &kd->keystring);
+    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->unused);
+    dbus_message_iter_close_container (&iter_subarray, &iter_substruct);
+  }
+  dbus_message_iter_close_container (&iter_struct, &iter_subarray);
+  d_uint = listener->mask;
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
+  if (dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT,
+                                         NULL, &iter_substruct))
+  {
+    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
+                                    &listener->mode->synchronous);
+    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
+                                    &listener->mode->preemptive);
+    dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
+                                    &listener->mode->global);
+    dbus_message_iter_close_container (&iter_struct, &iter_substruct);
+  }
+  dbus_message_iter_close_container (iter, &iter_struct);
+}
+
+static void
+notify_keystroke_listener (SpiDEController *controller,
+                           DEControllerKeyListener *listener,
+                           gboolean enable)
+{
+  const char *path = SPI_DBUS_PATH_DEC;
+  const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
+  const char *name = (enable
+                      ? "KeystrokeListenerRegistered"
+                      : "KeystrokeListenerDeregistered");
+  DBusMessage *signal;
+  DBusMessageIter iter;
+
+  signal = dbus_message_new_signal (path, interface, name);
+  if (!signal)
+    return;
+  dbus_message_iter_init_append (signal, &iter);
+  append_keystroke_listener (&iter, listener);
+  dbus_connection_send (controller->bus, signal, NULL);
+  dbus_message_unref (signal);
+}
+
+static void
+append_mouse_listener (DBusMessageIter *iter, DEControllerListener *listener)
+{
+  DBusMessageIter iter_struct;
+  dbus_uint32_t d_uint;
+
+  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
+                                         &iter_struct))
+    return;
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
+                                  &listener->bus_name);
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
+                                  &listener->path);
+  d_uint = listener->types;
+  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
+  dbus_message_iter_close_container (iter, &iter_struct);
+}
+
+static void
+notify_mouse_listener (SpiDEController *controller,
+                       DEControllerListener *listener,
+                       gboolean enable)
+{
+  const char *path = SPI_DBUS_PATH_DEC;
+  const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
+  const char *name = (enable
+                      ? "DeviceListenerRegistered"
+                      : "DeviceListenerDeregistered");
+  DBusMessage *signal;
+  DBusMessageIter iter;
+
+  signal = dbus_message_new_signal (path, interface, name);
+  if (!signal)
+    return;
+  dbus_message_iter_init_append (signal, &iter);
+  append_mouse_listener (&iter, listener);
+  dbus_connection_send (controller->bus, signal, NULL);
+  dbus_message_unref (signal);
+}
+
 static gboolean
 spi_controller_register_device_listener (SpiDEController      *controller,
 					 DEControllerListener *listener)
 {
   DEControllerKeyListener *key_listener;
+  gboolean retval;
   
   switch (listener->type) {
   case SPI_DEVICE_TYPE_KBD:
@@ -996,10 +1114,12 @@ spi_controller_register_device_listener (SpiDEController      *controller,
       spi_dbus_add_disconnect_match (controller->bus, key_listener->listener.bus_name);
       if (key_listener->mode->global)
         {
-	  return spi_controller_register_global_keygrabs (controller, key_listener);	
+	  retval = spi_controller_register_global_keygrabs (controller, key_listener);
 	}
       else
-	      return TRUE;
+	  retval = TRUE;
+      if (retval)
+	notify_keystroke_listener (controller, key_listener, TRUE);
       break;
   case SPI_DEVICE_TYPE_MOUSE:
       controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
@@ -1010,6 +1130,7 @@ spi_controller_register_device_listener (SpiDEController      *controller,
             g_timeout_add (100, spi_dec_poll_mouse_idle, controller);
         }
       spi_dbus_add_disconnect_match (controller->bus, listener->bus_name);
+      notify_mouse_listener (controller, listener, TRUE);
       break;
   default:
       break;
@@ -2042,6 +2163,8 @@ spi_controller_deregister_device_listener (SpiDEController            *controlle
   ctx.bus = controller->bus;
   ctx.listener = listener;
 
+  notify_mouse_listener (controller, listener, FALSE);
+
   spi_re_entrant_list_foreach (&controller->mouse_listeners,
 			       remove_listener_cb, &ctx);
   if (!controller->mouse_listeners)
@@ -2057,6 +2180,8 @@ spi_deregister_controller_key_listener (SpiDEController            *controller,
   ctx.bus = controller->bus;
   ctx.listener = (DEControllerListener *) spi_key_listener_clone (key_listener);
 
+  notify_keystroke_listener (controller, key_listener, FALSE);
+
   /* special case, copy keyset from existing controller list entry */
   if (g_slist_length(key_listener->keys) == 0)
     {
@@ -2180,6 +2305,56 @@ impl_deregister_device_event_listener (DBusConnection *bus,
   return reply;
 }
 
+static DBusMessage *
+impl_get_keystroke_listeners (DBusConnection *bus,
+				  DBusMessage *message,
+				  void *user_data)
+{
+  SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
+  DEControllerKeyListener *dec_listener;
+  DBusMessageIter iter, iter_array;
+  DBusMessage *reply = dbus_message_new_method_return (message);
+  GList *l;
+
+  if (!reply)
+    return NULL;
+
+  dbus_message_iter_init_append (reply, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+                                    "(souua(iisi)u(bbb))", &iter_array);
+  for (l = controller->key_listeners; l; l = l->next)
+  {
+    append_keystroke_listener (&iter_array, l->data);
+  }
+  dbus_message_iter_close_container (&iter, &iter_array);
+  return reply;
+}
+
+static DBusMessage *
+impl_get_device_event_listeners (DBusConnection *bus,
+				  DBusMessage *message,
+				  void *user_data)
+{
+  SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
+  DEControllerKeyListener *dec_listener;
+  DBusMessageIter iter, iter_array;
+  GList *l;
+  DBusMessage *reply = dbus_message_new_method_return (message);
+
+  if (!reply)
+    return NULL;
+
+  dbus_message_iter_init_append (reply, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+                                    "(sou)", &iter_array);
+  for (l = controller->key_listeners; l; l = l->next)
+  {
+    append_mouse_listener (&iter_array, l->data);
+  }
+  dbus_message_iter_close_container (&iter, &iter_array);
+  return reply;
+}
+
 static unsigned int dec_xkb_get_slowkeys_delay (SpiDEController *controller)
 {
   unsigned int retval = 0;
@@ -2881,6 +3056,10 @@ handle_dec_method_from_idle (DBusConnection *bus, DBusMessage *message, void *us
           reply = impl_deregister_keystroke_listener (bus, message, user_data);
       else if (!strcmp (member, "DeregisterDeviceEventListener"))
           reply = impl_deregister_device_event_listener (bus, message, user_data);
+      else if (!strcmp (member, "GetKeystrokeListeners"))
+          reply = impl_get_keystroke_listeners (bus, message, user_data);
+      else if (!strcmp (member, "GetDeviceEventListeners"))
+          reply = impl_get_device_event_listeners (bus, message, user_data);
       else if (!strcmp (member, "GenerateKeyboardEvent"))
           reply = impl_generate_keyboard_event (bus, message, user_data);
       else if (!strcmp (member, "GenerateMouseEvent"))
diff --git a/registryd/introspection.c b/registryd/introspection.c
index b5daee5..edcf60d 100644
--- a/registryd/introspection.c
+++ b/registryd/introspection.c
@@ -799,6 +799,14 @@ const char *spi_org_a11y_atspi_DeviceEventController =
 "    <arg direction=\"in\" name=\"types\" type=\"u\" />"
 "  </method>"
 ""
+"  <method name=\"GetKeystrokeListeners\">"
+"    <arg direction=\"out\" type=\"a(souua(iisi)u(bbb))\" />"
+"  </method>"
+""
+"  <method name=\"GetDeviceEventListeners\">"
+"    <arg direction=\"out\" type=\"a(sou)\" />"
+"  </method>"
+""
 "  <method name=\"GenerateKeyboardEvent\">"
 "    <arg direction=\"in\" name=\"keycode\" type=\"i\" />"
 "    <arg direction=\"in\" name=\"keystring\" type=\"s\" />"
@@ -834,6 +842,22 @@ const char *spi_org_a11y_atspi_DeviceEventListener =
 "    <arg direction=\"out\" type=\"b\" />"
 "  </method>"
 ""
+"  <signal name=\"KeystrokeListenerRegistered\">"
+"    <arg name=\"listener\" type=\"(souua(iisi)u(bbb))\" />"
+"  </signal>"
+""
+"  <signal name=\"KeystrokeListenerDeregistered\">"
+"    <arg name=\"listener\" type=\"(souua(iisi)u(bbb))\" />"
+"  </signal>"
+""
+"  <signal name=\"DeviceListenerRegistered\">"
+"    <arg name=\"listener\" type=\"(sou)\" />"
+"  </signal>"
+""
+"  <signal name=\"DeviceListenerDeregistered\">"
+"    <arg name=\"listener\" type=\"(sou)\" />"
+"  </signal>"
+""
 "</interface>"
 "";
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]