summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Gorse <mgorse@suse.com>2012-11-20 16:29:50 -0600
committerMike Gorse <mgorse@suse.com>2012-11-20 16:29:50 -0600
commit8846499e0aaae728fb460a8b27f6645dac55e91d (patch)
treee8317dfbad2bcfab8c12f8fedb8cc063ce71a858
parent09915497d014e3ea9a146fa6ef8eb4fa94756708 (diff)
downloadat-spi2-core-8846499e0aaae728fb460a8b27f6645dac55e91d.tar.gz
Re-register keystroke listeners if the registry goes away and returns
-rw-r--r--atspi/atspi-event-listener-private.h3
-rw-r--r--atspi/atspi-event-listener.c47
-rw-r--r--atspi/atspi-misc.c42
-rw-r--r--atspi/atspi-private.h4
-rw-r--r--atspi/atspi-registry.c160
5 files changed, 208 insertions, 48 deletions
diff --git a/atspi/atspi-event-listener-private.h b/atspi/atspi-event-listener-private.h
index 0b29111f..260db743 100644
--- a/atspi/atspi-event-listener-private.h
+++ b/atspi/atspi-event-listener-private.h
@@ -38,6 +38,9 @@ void _atspi_send_event (AtspiEvent *e);
DBusHandlerResult _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data);
+void
+_atspi_reregister_event_listeners ();
+
G_END_DECLS
#endif /* _ATSPI_EVENT_LISTENER_H_ */
diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c
index ba5d1262..91520540 100644
--- a/atspi/atspi-event-listener.c
+++ b/atspi/atspi-event-listener.c
@@ -31,6 +31,7 @@ typedef struct
AtspiEventListenerCB callback;
void *user_data;
GDestroyNotify callback_destroyed;
+ char *event_type;
char *category;
char *name;
char *detail;
@@ -400,6 +401,7 @@ static void
listener_entry_free (EventListenerEntry *e)
{
gpointer callback = (e->callback == remove_datum ? (gpointer)e->user_data : (gpointer)e->callback);
+ g_free (e->event_type);
g_free (e->category);
g_free (e->name);
if (e->detail) g_free (e->detail);
@@ -511,6 +513,25 @@ atspi_event_listener_register (AtspiEventListener *listener,
event_type, error);
}
+static gboolean
+notify_event_registered (EventListenerEntry *e)
+{
+ DBusMessage *message, *reply;
+
+ message = dbus_message_new_method_call (atspi_bus_registry,
+ atspi_path_registry,
+ atspi_interface_registry,
+ "RegisterEvent");
+ if (!message)
+ return FALSE;
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &e->event_type, DBUS_TYPE_INVALID);
+ reply = _atspi_dbus_send_with_reply_and_block (message, NULL);
+
+ if (reply)
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
/**
* atspi_event_listener_register_from_callback:
* @callback: (scope notified): the #AtspiEventListenerCB to be registered
@@ -551,6 +572,7 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
}
e = g_new (EventListenerEntry, 1);
+ e->event_type = g_strdup (event_type);
e->callback = callback;
e->user_data = user_data;
e->callback_destroyed = callback_destroyed;
@@ -578,20 +600,23 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
}
g_ptr_array_free (matchrule_array, TRUE);
- message = dbus_message_new_method_call (atspi_bus_registry,
- atspi_path_registry,
- atspi_interface_registry,
- "RegisterEvent");
- if (!message)
- return FALSE;
- dbus_message_append_args (message, DBUS_TYPE_STRING, &event_type, DBUS_TYPE_INVALID);
- reply = _atspi_dbus_send_with_reply_and_block (message, error);
- if (reply)
- dbus_message_unref (reply);
-
+ notify_event_registered (e);
return TRUE;
}
+void
+_atspi_reregister_event_listeners ()
+{
+ GList *l;
+ EventListenerEntry *e;
+
+ for (l = event_listeners; l; l = l->next)
+ {
+ e = l->data;
+ notify_event_registered (e);
+ }
+}
+
/**
* atspi_event_listener_register_no_data:
* @callback: (scope notified): the #AtspiEventListenerSimpleCB to be
diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c
index 4f090601..548cfdeb 100644
--- a/atspi/atspi-misc.c
+++ b/atspi/atspi-misc.c
@@ -328,6 +328,35 @@ handle_remove_accessible (DBusConnection *bus, DBusMessage *message, void *user_
return DBUS_HANDLER_RESULT_HANDLED;
}
+static DBusHandlerResult
+handle_name_owner_changed (DBusConnection *bus, DBusMessage *message, void *user_data)
+{
+ const char *name, *new, *old;
+ static gboolean registry_lost = FALSE;
+
+ if (!dbus_message_get_args (message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &old,
+ DBUS_TYPE_STRING, &new,
+ DBUS_TYPE_INVALID))
+ {
+ return;
+ }
+
+ if (!strcmp (name, "org.a11y.atspi.Registry"))
+ {
+ if (registry_lost && !old[0])
+ {
+ _atspi_reregister_event_listeners ();
+ _atspi_reregister_device_listeners ();
+ registry_lost = FALSE;
+ }
+ else if (!new[0])
+ registry_lost = TRUE;
+ }
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
static gboolean
add_app_to_desktop (AtspiAccessible *a, const char *bus_name)
{
@@ -702,6 +731,10 @@ process_deferred_message (BusDataClosure *closure)
{
handle_remove_accessible (closure->bus, closure->message, closure->data);
}
+ if (dbus_message_is_signal (closure->message, "org.freedesktop.DBus", "NameOwnerChanged"))
+ {
+ handle_name_owner_changed (closure->bus, closure->message, closure->data);
+ }
}
static GQueue *deferred_messages = NULL;
@@ -768,6 +801,11 @@ atspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data)
{
return defer_message (bus, message, data);
}
+ if (dbus_message_is_signal (message, "org.freedesktop.DBus", "NameOwnerChanged"))
+ {
+ defer_message (bus, message, data);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -865,6 +903,10 @@ atspi_init (void)
dbus_bus_add_match (bus, match, NULL);
g_free (match);
+ dbus_bus_add_match (bus,
+ "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'",
+ NULL);
+
no_cache = g_getenv ("ATSPI_NO_CACHE");
if (no_cache && g_strcmp0 (no_cache, "0") != 0)
atspi_no_cache = TRUE;
diff --git a/atspi/atspi-private.h b/atspi/atspi-private.h
index 9977be7d..c68e4be9 100644
--- a/atspi/atspi-private.h
+++ b/atspi/atspi-private.h
@@ -34,4 +34,8 @@
#include "atspi.h"
+G_BEGIN_DECLS
+void _atspi_reregister_device_listeners ();
+G_END_DECLS
+
#endif /* _ATSPI_PRIVATE_H_ */
diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c
index 67a7590e..28a76e11 100644
--- a/atspi/atspi-registry.c
+++ b/atspi/atspi-registry.c
@@ -26,6 +26,17 @@
#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:
*
@@ -86,6 +97,70 @@ atspi_get_desktop_list ()
return array;
}
+static gboolean
+notify_keystroke_listener (DeviceListenerEntry *e)
+{
+ gchar *path = _atspi_device_listener_get_path (e->listener);
+ gint i;
+ 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,
+ e->modmask, e->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
@@ -125,29 +200,25 @@ atspi_register_keystroke_listener (AtspiDeviceListener *listener,
AtspiKeyEventMask event_types,
gint 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 +233,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);
}
/**
@@ -219,6 +274,7 @@ atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
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)
@@ -263,6 +319,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;
@@ -452,4 +526,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)