X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atspi%2Fatspi-device-listener.c;h=3ac4451258bc8e7d0c4bdbbdb6cdad1e34f072a2;hb=fe9f99e73477e139716655ac657eef387d8524d1;hp=31bb2709e6a9faf3c8c3c24b951d23c94b4a0991;hpb=a5a11bda4217947060717e16cfc1764919d0582b;p=platform%2Fupstream%2Fat-spi2-core.git diff --git a/atspi/atspi-device-listener.c b/atspi/atspi-device-listener.c index 31bb270..3ac4451 100644 --- a/atspi/atspi-device-listener.c +++ b/atspi/atspi-device-listener.c @@ -4,6 +4,7 @@ * * Copyright 2002 Ximian Inc. * Copyright 2002 Sun Microsystems, Inc. + * Copyright 2010, 2011 Novell, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,32 +23,57 @@ */ #include "atspi-private.h" +#include typedef struct { AtspiDeviceListenerCB callback; gpointer user_data; + GDestroyNotify callback_destroyed; } DeviceEventHandler; GObjectClass *device_parent_class; -static guint32 _e_id = 0; - /* * Misc. helpers. */ static DeviceEventHandler * -device_event_handler_new (AtspiDeviceListenerCB callback, gpointer user_data) +device_event_handler_new (AtspiDeviceListenerCB callback, + GDestroyNotify callback_destroyed, + gpointer user_data) { DeviceEventHandler *eh = g_new0 (DeviceEventHandler, 1); eh->callback = callback; + eh->callback_destroyed = callback_destroyed; eh->user_data = user_data; return eh; } +static gboolean +device_remove_datum (const AtspiDeviceEvent *event, void *user_data) +{ + AtspiDeviceListenerSimpleCB cb = user_data; + return cb (event); +} + +static void +device_event_handler_free (DeviceEventHandler *eh) +{ +#if 0 + /* TODO; Test this; it will probably crash with pyatspi for unknown reasons */ + if (eh->callback_destroyed) + { + gpointer rea_callback = (eh->callback == device_remove_datum ? + eh->user_data : eh->callback); + (*eh->callback_destroyed) (real_callback); + } +#endif + g_free (eh); +} + static GList * event_list_remove_by_cb (GList *list, AtspiDeviceListenerCB callback) { @@ -61,7 +87,7 @@ event_list_remove_by_cb (GList *list, AtspiDeviceListenerCB callback) if (eh->callback == callback) { list = g_list_delete_link (list, l); - g_free (eh); + device_event_handler_free (eh); } } @@ -88,10 +114,27 @@ id_is_free (guint id) return TRUE; } -static void -remove_listener (GObject *obj, gpointer data) +static AtspiDeviceEvent * +atspi_device_event_copy (const AtspiDeviceEvent *src) { - device_listeners = g_list_remove (device_listeners, obj); + AtspiDeviceEvent *dst = g_new0 (AtspiDeviceEvent, 1); + dst->type = src->type; + dst->id = src->id; + dst->hw_code = src->hw_code; + dst->modifiers = src->modifiers; + dst->timestamp = src->timestamp; + if (src->event_string) + dst->event_string = g_strdup (src->event_string); + dst->is_text = src->is_text; + return dst; +} + +void +atspi_device_event_free (AtspiDeviceEvent *event) +{ + if (event->event_string) + g_free (event->event_string); + g_free (event); } /* @@ -102,7 +145,6 @@ atspi_device_event_dispatch (AtspiDeviceListener *listener, const AtspiDeviceEvent *event) { GList *l; - AtspiDeviceEvent anevent; gboolean handled = FALSE; /* FIXME: re-enterancy hazard on this list */ @@ -110,7 +152,7 @@ atspi_device_event_dispatch (AtspiDeviceListener *listener, { DeviceEventHandler *eh = l->data; - if ((handled = eh->callback (&anevent, eh->user_data))) + if ((handled = eh->callback (atspi_device_event_copy (event), eh->user_data))) { break; } @@ -122,14 +164,12 @@ atspi_device_event_dispatch (AtspiDeviceListener *listener, static void atspi_device_listener_init (AtspiDeviceListener *listener) { - GList *new_list; do { listener->id = listener_id++; } while (!id_is_free (listener->id)); - new_list = g_list_append (device_listeners, listener); - if (new_list) device_listeners = new_list; + device_listeners = g_list_append (device_listeners, listener); } static void @@ -140,7 +180,7 @@ atspi_device_listener_finalize (GObject *object) for (l = listener->callbacks; l; l = l->next) { - g_free (l->data); + device_event_handler_free (l->data); } g_list_free (listener->callbacks); @@ -164,32 +204,62 @@ G_DEFINE_TYPE (AtspiDeviceListener, atspi_device_listener, /** * atspi_device_listener_new: - * @callback: (scope call): an #AtspiDeviceListenerCB callback function, + * @callback: (scope notified): an #AtspiDeviceListenerCB callback function, * or NULL. * @user_data: (closure): a pointer to data which will be passed to the * callback when invoked. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. It can be NULL. * - * Create a new #AtspiDeviceListener with a specified callback function. + * Creates a new #AtspiDeviceListener with a specified callback function. * - * Returns: a pointer to a newly-created #AtspiDeviceListener. + * Returns: (transfer full): a pointer to a newly-created #AtspiDeviceListener. * **/ AtspiDeviceListener * -atspi_device_listener_new (AtspiDeviceListenerCB callback) +atspi_device_listener_new (AtspiDeviceListenerCB callback, + void *user_data, + GDestroyNotify callback_destroyed) { AtspiDeviceListener *listener = g_object_new (atspi_device_listener_get_type (), NULL); + if (callback) + atspi_device_listener_add_callback (listener, callback, callback_destroyed, + user_data); return listener; } /** + * atspi_device_listener_new_simple: (skip) + * @callback: (scope notified): an #AtspiDeviceListenerCB callback function, + * or NULL. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. It an be NULL. + * + * Creates a new #AtspiDeviceListener with a specified callback function. + * This method is similar to #atspi_device_listener_new, but callback + * takes no user data. + * + * Returns: a pointer to a newly-created #AtspiDeviceListener. + * + **/ +AtspiDeviceListener * +atspi_device_listener_new_simple (AtspiDeviceListenerSimpleCB callback, + GDestroyNotify callback_destroyed) +{ + return atspi_device_listener_new (device_remove_datum, callback, callback_destroyed); +} + +/** * atspi_device_listener_add_callback: * @listener: the #AtspiDeviceListener instance to modify. - * @callback: (scope call): an #AtspiDeviceListenerCB function pointer. + * @callback: (scope notified): an #AtspiDeviceListenerCB function pointer. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. It can be NULL. * @user_data: (closure): a pointer to data which will be passed to the - * callback when invoked. + * callback when invoked. * - * Add an in-process callback function to an existing #AtspiDeviceListener. + * Adds an in-process callback function to an existing #AtspiDeviceListener. * * Returns: #TRUE if successful, otherwise #FALSE. * @@ -197,12 +267,16 @@ atspi_device_listener_new (AtspiDeviceListenerCB callback) void atspi_device_listener_add_callback (AtspiDeviceListener *listener, AtspiDeviceListenerCB callback, + GDestroyNotify callback_destroyed, void *user_data) { g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener)); + DeviceEventHandler *new_handler; + + new_handler = device_event_handler_new (callback, + callback_destroyed, user_data); - listener->callbacks = g_list_prepend (listener->callbacks, - device_event_handler_new ((void *)callback, user_data)); + listener->callbacks = g_list_prepend (listener->callbacks, new_handler); } /** @@ -210,7 +284,8 @@ atspi_device_listener_add_callback (AtspiDeviceListener *listener, * @listener: the #AtspiDeviceListener instance to modify. * @callback: (scope call): an #AtspiDeviceListenerCB function pointer. * - * Remove an in-process callback function from an existing #AtspiDeviceListener. + * Removes an in-process callback function from an existing + * #AtspiDeviceListener. * * Returns: #TRUE if successful, otherwise #FALSE. * @@ -224,17 +299,14 @@ atspi_device_listener_remove_callback (AtspiDeviceListener *listener, listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback); } -static const char *device_event_type = "(uinnisb)"; - static void read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event) { dbus_uint32_t type; dbus_int32_t id; - dbus_int16_t hw_code; - dbus_int16_t modifiers; + dbus_int32_t hw_code; + dbus_int32_t modifiers; dbus_int32_t timestamp; - char *event_string; dbus_bool_t is_text; DBusMessageIter iter_struct; @@ -248,12 +320,13 @@ read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event) event->id = id; dbus_message_iter_next (&iter_struct); + /* TODO: Remove cast from next two on ABI break */ dbus_message_iter_get_basic (&iter_struct, &hw_code); - event->hw_code = hw_code; + event->hw_code = (gushort) hw_code; dbus_message_iter_next (&iter_struct); dbus_message_iter_get_basic (&iter_struct, &modifiers); - event->modifiers = modifiers; + event->modifiers = (gushort) modifiers; dbus_message_iter_next (&iter_struct); dbus_message_iter_get_basic (&iter_struct, ×tamp); @@ -267,11 +340,8 @@ read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event) event->is_text = is_text; } -/* - * atspi_dbus_handle_DeviceEvent: (skip) - */ DBusHandlerResult -atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data) +_atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data) { const char *path = dbus_message_get_path (message); int id; @@ -282,9 +352,8 @@ atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void * dbus_bool_t retval = FALSE; GList *l; DBusMessage *reply; - void *p = &event; - if (strcmp (dbus_message_get_signature (message), "(uinnisb)") != 0) + if (strcmp (dbus_message_get_signature (message), "(uiuuisb)") != 0) { g_warning ("Atspi: Unknown signature for an event"); goto done; @@ -312,6 +381,11 @@ atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void * if (klass->device_event) { retval = (*klass->device_event) (listener, &event); + if (retval != 0 && retval != 1) + { + g_warning ("at-spi: device event handler returned %d; should be 0 or 1", retval); + retval = 0; + } } done: reply = dbus_message_new_method_return (message); @@ -326,6 +400,10 @@ done: gchar * _atspi_device_listener_get_path (AtspiDeviceListener *listener) -{ - return g_strdup_printf ("/org/a11y/atspi/listeners/%d", listener->id); +{ return g_strdup_printf ("/org/a11y/atspi/listeners/%d", listener->id); } + +G_DEFINE_BOXED_TYPE (AtspiDeviceEvent, + atspi_device_event, + atspi_device_event_copy, + atspi_device_event_free)