+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;
+ }
+}
+