diff options
author | Mike Gorse <mgorse@suse.com> | 2012-11-20 16:29:50 -0600 |
---|---|---|
committer | Mike Gorse <mgorse@suse.com> | 2012-11-20 16:29:50 -0600 |
commit | 8846499e0aaae728fb460a8b27f6645dac55e91d (patch) | |
tree | e8317dfbad2bcfab8c12f8fedb8cc063ce71a858 | |
parent | 09915497d014e3ea9a146fa6ef8eb4fa94756708 (diff) | |
download | at-spi2-core-8846499e0aaae728fb460a8b27f6645dac55e91d.tar.gz |
Re-register keystroke listeners if the registry goes away and returns
-rw-r--r-- | atspi/atspi-event-listener-private.h | 3 | ||||
-rw-r--r-- | atspi/atspi-event-listener.c | 47 | ||||
-rw-r--r-- | atspi/atspi-misc.c | 42 | ||||
-rw-r--r-- | atspi/atspi-private.h | 4 | ||||
-rw-r--r-- | atspi/atspi-registry.c | 160 |
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) |