[at-spi2-core] Add atspi_event_listener_register_with_app



commit 7b4d74532e39a2c6a473945506b1cfebbbd1666e
Author: Mike Gorse <mgorse suse com>
Date:   Fri Jul 1 21:14:14 2022 -0500

    Add atspi_event_listener_register_with_app
    
    Allows an event listener to be registered only for a given application.
    
    Fixes #52

 atspi/atspi-event-listener.c       | 122 +++++++++++++++++++++++++++++--------
 atspi/atspi-event-listener.h       |  16 +++++
 doc/libatspi/libatspi-sections.txt |   1 +
 registryd/registry.c               |  32 ++++++++--
 xml/Registry.xml                   |   2 +
 5 files changed, 142 insertions(+), 31 deletions(-)
---
diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c
index c45ad91b..a79957c9 100644
--- a/atspi/atspi-event-listener.c
+++ b/atspi/atspi-event-listener.c
@@ -38,6 +38,7 @@ typedef struct
   char *name;
   char *detail;
   GArray *properties;
+  AtspiAccessible *app;
 } EventListenerEntry;
 
 G_DEFINE_TYPE (AtspiEventListener, atspi_event_listener, G_TYPE_OBJECT)
@@ -336,7 +337,7 @@ demarshal_rect (DBusMessageIter *iter, AtspiRect *rect)
 }
 
 static gboolean
-convert_event_type_to_dbus (const char *eventType, char **categoryp, char **namep, char **detailp, GPtrArray 
**matchrule_array)
+convert_event_type_to_dbus (const char *eventType, char **categoryp, char **namep, char **detailp, 
AtspiAccessible *app, GPtrArray **matchrule_array)
 {
   gchar *tmp = _atspi_strdup_and_adjust_for_dbus (eventType);
   char *category = NULL, *name = NULL, *detail = NULL;
@@ -357,6 +358,14 @@ convert_event_type_to_dbus (const char *eventType, char **categoryp, char **name
     gchar *matchrule;
     (*matchrule_array) = g_ptr_array_new ();
     matchrule = g_strdup_printf ("type='signal',interface='org.a11y.atspi.Event.%s'", category);
+    if (app)
+    {
+             gchar *new_str = g_strconcat (matchrule, ",sender='",
+                                           app->parent.app->bus_name, "'",
+                                           NULL);
+             g_free (matchrule);
+             matchrule = new_str;
+    }
     if (name && name [0])
     {
              gchar *new_str = g_strconcat (matchrule, ",member='", name, "'", NULL);
@@ -399,6 +408,9 @@ listener_entry_free (EventListenerEntry *e)
 
   g_array_free (e->properties, TRUE);
 
+  if (e->app)
+    g_object_unref (e->app);
+
   g_free (e);
 }
 
@@ -521,7 +533,7 @@ atspi_event_listener_register (AtspiEventListener *listener,
  * for a description of the format and legal event types.
 * @properties: (element-type gchar*) (transfer none) (allow-none): a list of
  *             properties that should be sent along with the event. The
- *             properties are valued for the duration of the event callback.k
+ *             properties are valued for the duration of the event callback.
  *             TODO: Document.
  *
  * Adds an in-process callback function to an existing #AtspiEventListener.
@@ -545,23 +557,49 @@ atspi_event_listener_register_full (AtspiEventListener *listener,
                                                            error);
 }
 
+/**
+ * atspi_event_listener_register_with_app:
+ * @listener: The #AtspiEventListener to register against an event type.
+ * @event_type: a character string indicating the type of events for which
+ *            notification is requested.  See #atspi_event_listener_register
+ * for a description of the format and legal event types.
+* @properties: (element-type gchar*) (transfer none) (allow-none): a list of
+ *             properties that should be sent along with the event. The
+ *             properties are valued for the duration of the event callback.
+ * @app: (allow-none): the application whose events should be reported, or
+ *      %null for all applications.
+ *
+ * Adds an in-process callback function to an existing #AtspiEventListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_register_with_app (AtspiEventListener *listener,
+                                       const gchar              *event_type,
+                                       GArray *properties,
+                                       AtspiAccessible *app,
+                                       GError **error)
+{
+  return atspi_event_listener_register_from_callback_with_app (listener->callback,
+                                                               listener->user_data,
+                                                               listener->cb_destroyed,
+                                                               event_type,
+                                                               properties,
+                                                               app,
+                                                               error);
+}
+
 static gboolean
 notify_event_registered (EventListenerEntry *e)
 {
+  const char *app_path = (e->app? e->app->parent.app->bus_name: "");
 
-  if (e->properties)
-    dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry,
-                                atspi_path_registry,
-                                atspi_interface_registry,
-                                "RegisterEvent",
-                                NULL, "sas", e->event_type,
-                                 e->properties);
-  else
-    dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry,
-                                atspi_path_registry,
-                                atspi_interface_registry,
-                                "RegisterEvent",
-                                NULL, "s", e->event_type);
+  dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry,
+                              atspi_path_registry,
+                              atspi_interface_registry,
+                              "RegisterEvent",
+                              NULL, "sass", e->event_type,
+                               e->properties, app_path);
 
   return TRUE;
 }
@@ -588,11 +626,11 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
                                             const gchar              *event_type,
                                             GError **error)
 {
-  return atspi_event_listener_register_from_callback_full (callback,
-                                                           user_data,
-                                                           callback_destroyed,
-                                                           event_type, NULL,
-                                                           error);
+  return atspi_event_listener_register_from_callback_with_app (callback,
+                                                               user_data,
+                                                               callback_destroyed,
+                                                               event_type, NULL,
+                                                               NULL, error);
 }
 
 static GArray *
@@ -631,6 +669,35 @@ atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback,
                                                  const gchar              *event_type,
                                                  GArray *properties,
                                                  GError **error)
+{
+  return atspi_event_listener_register_from_callback_with_app (callback,
+                                                               user_data,
+                                                               callback_destroyed,
+                                                               event_type, NULL,
+                                                               NULL, error);
+}
+
+/**
+ * atspi_event_listener_register_from_callback_with_app:
+ * @callback: (scope async): an #AtspiEventListenerCB function pointer.
+ * @user_data: (closure callback)
+ * @callback_destroyed: (destroy callback)
+ * @event_type:
+ * @properties: (element-type utf8)
+* @app: (allow-none)
+ * @error:
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+gboolean
+atspi_event_listener_register_from_callback_with_app (AtspiEventListenerCB callback,
+                                                     void *user_data,
+                                                     GDestroyNotify callback_destroyed,
+                                                     const gchar              *event_type,
+                                                     GArray *properties,
+                                                     AtspiAccessible *app,
+                                                     GError **error)
 {
   EventListenerEntry *e;
   DBusError d_error;
@@ -648,19 +715,21 @@ atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback,
     return FALSE;
   }
 
-  e = g_new (EventListenerEntry, 1);
+  e = g_new0 (EventListenerEntry, 1);
   e->event_type = g_strdup (event_type);
   e->callback = callback;
   e->user_data = user_data;
   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_array))
+  if (!convert_event_type_to_dbus (event_type, &e->category, &e->name, &e->detail, app, &matchrule_array))
   {
     g_free (e->event_type);
     g_free (e);
     return FALSE;
   }
+  if (app)
+    e->app = g_object_ref (app);
   e->properties = copy_event_properties (properties);
   event_listeners = g_list_prepend (event_listeners, e);
   for (i = 0; i < matchrule_array->len; i++)
@@ -778,7 +847,7 @@ atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback,
   gint i;
   GList *l;
 
-  if (!convert_event_type_to_dbus (event_type, &category, &name, &detail, &matchrule_array))
+  if (!convert_event_type_to_dbus (event_type, &category, &name, &detail, NULL, &matchrule_array))
   {
     return FALSE;
   }
@@ -920,7 +989,8 @@ _atspi_send_event (AtspiEvent *e)
     g_value_set_int (&e->any_data, 0);
   }
 
-  if (!convert_event_type_to_dbus (e->type, &category, &name, &detail, NULL))
+  if (!convert_event_type_to_dbus (e->type, &category, &name, &detail, NULL,
+                                   NULL))
   {
     g_warning ("AT-SPI: Couldn't parse event: %s\n", e->type);
     return;
@@ -931,7 +1001,9 @@ _atspi_send_event (AtspiEvent *e)
     EventListenerEntry *entry = l->data;
     if (!strcmp (category, entry->category) &&
         (entry->name == NULL || !strcmp (name, entry->name)) &&
-        detail_matches_listener (detail, entry->detail))
+        detail_matches_listener (detail, entry->detail) &&
+        (entry->app == NULL || !strcmp (entry->app->parent.app->bus_name,
+                                        e->source->parent.app->bus_name)))
     {
       GList *l2;
       for (l2 = called_listeners; l2; l2 = l2->next)
diff --git a/atspi/atspi-event-listener.h b/atspi/atspi-event-listener.h
index b7ad3277..687e1e78 100644
--- a/atspi/atspi-event-listener.h
+++ b/atspi/atspi-event-listener.h
@@ -98,6 +98,13 @@ atspi_event_listener_register_full (AtspiEventListener *listener,
                                       GArray *properties,
                                      GError **error);
 
+gboolean
+atspi_event_listener_register_with_app (AtspiEventListener *listener,
+                                       const gchar              *event_type,
+                                        GArray *properties,
+                                        AtspiAccessible *app,
+                                       GError **error);
+
 gboolean
 atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
                                             void *user_data,
@@ -113,6 +120,15 @@ atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback,
                                                   GArray *properties,
                                                  GError **error);
 
+gboolean
+atspi_event_listener_register_from_callback_with_app (AtspiEventListenerCB callback,
+                                                     void *user_data,
+                                                     GDestroyNotify callback_destroyed,
+                                                     const gchar              *event_type,
+                                                      GArray *properties,
+                                                      AtspiAccessible *app,
+                                                     GError **error);
+
 gboolean
 atspi_event_listener_register_no_data (AtspiEventListenerSimpleCB callback,
                                 GDestroyNotify callback_destroyed,
diff --git a/doc/libatspi/libatspi-sections.txt b/doc/libatspi/libatspi-sections.txt
index f8c407fb..b99b9046 100644
--- a/doc/libatspi/libatspi-sections.txt
+++ b/doc/libatspi/libatspi-sections.txt
@@ -447,6 +447,7 @@ atspi_event_listener_register_from_callback
 atspi_event_listener_register_from_callback_full
 atspi_event_listener_register_no_data
 atspi_event_listener_register_full
+atspi_event_listener_register_with_app
 atspi_event_listener_deregister
 atspi_event_listener_deregister_from_callback
 atspi_event_listener_deregister_no_data
diff --git a/registryd/registry.c b/registryd/registry.c
index e22fbcbc..b09c0e31 100644
--- a/registryd/registry.c
+++ b/registryd/registry.c
@@ -33,7 +33,8 @@
 typedef struct event_data event_data;
 struct event_data
 {
-  gchar *bus_name;
+  gchar *listener_bus_name;
+  gchar *app_bus_name;
   gchar **data;
   GSList *properties;
 };
@@ -242,11 +243,12 @@ remove_events (SpiRegistry *registry, const char *bus_name, const char *event)
     {
       event_data *evdata = list->data;
       list = list->next;
-      if (!g_strcmp0 (evdata->bus_name, bus_name) &&
+      if (!g_strcmp0 (evdata->listener_bus_name, bus_name) &&
           event_is_subtype (evdata->data, remove_data))
         {
           g_strfreev (evdata->data);
-          g_free (evdata->bus_name);
+          g_free (evdata->listener_bus_name);
+          g_free (evdata->app_bus_name);
           g_slist_free_full (evdata->properties, g_free);
           registry->events = g_list_remove (registry->events, evdata);
           g_free (evdata);
@@ -840,7 +842,8 @@ impl_register_event (DBusConnection *bus, DBusMessage *message, void *user_data)
   const char *signature = dbus_message_get_signature (message);
 
   if (strcmp (signature, "sas") != 0 &&
-      strcmp (signature, "s") != 0)
+      strcmp (signature, "s") != 0 &&
+      strcmp (signature, "sass") != 0)
   {
     g_warning ("got RegisterEvent with invalid signature '%s'", signature);
     return NULL;
@@ -853,7 +856,7 @@ impl_register_event (DBusConnection *bus, DBusMessage *message, void *user_data)
 
   evdata = g_new0 (event_data, 1);
   data = g_strsplit (name, ":", 3);
-  evdata->bus_name = g_strdup (sender);
+  evdata->listener_bus_name = g_strdup (sender);
   evdata->data = data;
 
   if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY)
@@ -867,7 +870,18 @@ impl_register_event (DBusConnection *bus, DBusMessage *message, void *user_data)
                                            g_strdup (property));
       dbus_message_iter_next (&iter_array);
     }
+    dbus_message_iter_next (&iter);
   }
+
+  if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
+  {
+    const char *app;
+    dbus_message_iter_get_basic (&iter, &app);
+    if (app[0])
+      evdata->app_bus_name = g_strdup (app);
+    dbus_message_iter_next (&iter);
+  }
+
   registry->events = g_list_append (registry->events, evdata);
 
   if (needs_mouse_poll (evdata->data))
@@ -881,6 +895,8 @@ impl_register_event (DBusConnection *bus, DBusMessage *message, void *user_data)
   if (signal)
   {
     GSList *ls = evdata->properties;
+    if (evdata->app_bus_name)
+      dbus_message_set_destination (message, evdata->app_bus_name);
     dbus_message_iter_init_append (signal, &iter);
     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender);
     dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &name);
@@ -926,6 +942,7 @@ impl_get_registered_events (DBusConnection *bus, DBusMessage *message, void *use
   DBusMessage *reply;
   DBusMessageIter iter, iter_struct, iter_array;
   GList *list;
+  const char *sender = dbus_message_get_sender (message);
 
   reply = dbus_message_new_method_return (message);
   if (!reply)
@@ -937,11 +954,14 @@ impl_get_registered_events (DBusConnection *bus, DBusMessage *message, void *use
     {
       gchar *str;
       evdata = list->data;
+      if (evdata->app_bus_name && strcmp (evdata->app_bus_name, sender) != 0)
+        continue;
+
       str = g_strconcat (evdata->data [0],
                          ":", (evdata->data [1]? evdata->data [1]: ""),
                          ":", (evdata->data [1] && evdata->data [2]? evdata->data [2]: ""), NULL);
       dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
-      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &evdata->bus_name);
+      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &evdata->listener_bus_name);
       dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &str);
       dbus_message_iter_close_container (&iter_array, &iter_struct);
       g_free (str);
diff --git a/xml/Registry.xml b/xml/Registry.xml
index 65737bdc..1161794d 100644
--- a/xml/Registry.xml
+++ b/xml/Registry.xml
@@ -4,6 +4,8 @@
 
   <method name="RegisterEvent">
     <arg direction="in" name="event" type="s">
+    <arg direction="in" name="properties" type="as">
+    <arg direction="in" name="app_bus_name" type="s">
     </arg>
   </method>
 


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