2 * AT-SPI - Assistive Technology Service Provider Interface
3 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
5 * Copyright 2002 Ximian Inc.
6 * Copyright 2002 Sun Microsystems, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 #include "atspi-private.h"
30 AtspiEventListenerCB event;
31 AtspiDeviceListenerCB device_event;
37 GObjectClass *event_parent_class;
38 GObjectClass *device_parent_class;
40 static guint32 _e_id = 0;
47 atspi_event_handler_new (gpointer method, gpointer user_data)
49 EventHandler *eh = g_new0 (EventHandler, 1);
51 eh->cb.method = method;
52 eh->user_data = user_data;
58 event_list_remove_by_cb (GList *list, gpointer callback)
62 for (l = list; l; l = next)
64 EventHandler *eh = l->data;
67 if (eh->cb.method == callback)
69 list = g_list_delete_link (list, l);
78 * Standard event dispatcher
81 G_DEFINE_TYPE (AtspiEventListener, atspi_event_listener,
85 atspi_event_dispatch (AtspiEventListener *listener,
86 const AtspiEvent *event)
90 /* FIXME: re-entrancy hazard on this list */
91 for (l = listener->callbacks; l; l = l->next)
93 EventHandler *eh = l->data;
94 /* cast hides our private stuff from client handlers */
95 eh->cb.event (event, eh->user_data);
99 static guint listener_id = 0;
100 static GList *device_listeners = NULL;
103 id_is_free (guint id)
107 for (l = device_listeners; l; l = g_list_next (l))
109 AtspiDeviceListener *listener = l->data;
110 if (listener->id == id) return FALSE;
116 remove_listener (GObject *obj, gpointer data)
118 device_listeners = g_list_remove (device_listeners, obj);
122 atspi_event_listener_init (AtspiEventListener *listener)
127 atspi_event_listener_finalize (GObject *object)
129 AtspiEventListener *listener = (AtspiEventListener *) object;
132 for (l = listener->callbacks; l; l = l->next)
137 g_list_free (listener->callbacks);
139 event_parent_class->finalize (object);
143 atspi_event_listener_class_init (AtspiEventListenerClass *klass)
145 GObjectClass *object_class = (GObjectClass *) klass;
147 event_parent_class = g_type_class_peek_parent (klass);
148 object_class->finalize = atspi_event_listener_finalize;
150 klass->event = atspi_event_dispatch;
154 atspi_event_listener_new (void)
156 AtspiEventListener *listener;
158 listener = g_object_new (atspi_event_listener_get_type (), NULL);
164 atspi_event_listener_add_cb (AtspiEventListener *listener,
165 AtspiEventListenerCB callback,
168 g_return_if_fail (ATSPI_IS_EVENT_LISTENER (listener));
170 listener->callbacks = g_list_prepend (listener->callbacks,
171 atspi_event_handler_new ((void *) callback, user_data));
175 atspi_event_listener_remove_cb (AtspiEventListener *listener,
176 AtspiEventListenerCB callback)
178 g_return_if_fail (ATSPI_IS_EVENT_LISTENER (listener));
180 listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback);
184 * Device event handler
187 atspi_device_event_dispatch (AtspiDeviceListener *listener,
188 const AtspiDeviceEvent *event)
191 AtspiDeviceEvent anevent;
192 gboolean handled = FALSE;
194 /* FIXME: re-enterancy hazard on this list */
195 for (l = listener->callbacks; l; l = l->next)
197 EventHandler *eh = l->data;
199 if ((handled = eh->cb.device_event (&anevent, eh->user_data)))
209 atspi_device_listener_init (AtspiDeviceListener *listener)
215 listener->id = listener_id++;
216 } while (!id_is_free (listener->id));
217 new_list = g_list_append (device_listeners, listener);
218 if (new_list) device_listeners = new_list;
222 atspi_device_listener_finalize (GObject *object)
224 AtspiDeviceListener *listener = (AtspiDeviceListener *) object;
227 for (l = listener->callbacks; l; l = l->next)
232 g_list_free (listener->callbacks);
234 device_parent_class->finalize (object);
238 atspi_device_listener_class_init (AtspiDeviceListenerClass *klass)
240 GObjectClass *object_class = (GObjectClass *) klass;
242 device_parent_class = g_type_class_peek_parent (klass);
243 object_class->finalize = atspi_device_listener_finalize;
245 klass->device_event = atspi_device_event_dispatch;
248 G_DEFINE_TYPE (AtspiDeviceListener, atspi_device_listener,
251 AtspiDeviceListener *
252 atspi_device_listener_new (void)
254 AtspiDeviceListener *listener = g_object_new (atspi_device_listener_get_type (), NULL);
260 atspi_device_listener_add_cb (AtspiDeviceListener *listener,
261 AtspiDeviceListenerCB callback,
264 g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener));
266 listener->callbacks = g_list_prepend (listener->callbacks,
267 atspi_event_handler_new ((void *)callback, user_data));
271 atspi_device_listener_remove_cb (AtspiDeviceListener *listener,
272 AtspiDeviceListenerCB callback)
274 g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener));
276 listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback);
279 static const char *device_event_type = "(uinnisb)";
282 read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event)
286 dbus_int16_t hw_code;
287 dbus_int16_t modifiers;
288 dbus_int32_t timestamp;
291 DBusMessageIter iter_struct;
293 dbus_message_iter_recurse (iter, &iter_struct);
295 dbus_message_iter_get_basic (&iter_struct, &type);
297 dbus_message_iter_next (&iter_struct);
299 dbus_message_iter_get_basic (&iter_struct, &id);
301 dbus_message_iter_next (&iter_struct);
303 dbus_message_iter_get_basic (&iter_struct, &hw_code);
304 event->hw_code = hw_code;
305 dbus_message_iter_next (&iter_struct);
307 dbus_message_iter_get_basic (&iter_struct, &modifiers);
308 event->modifiers = modifiers;
309 dbus_message_iter_next (&iter_struct);
311 dbus_message_iter_get_basic (&iter_struct, ×tamp);
312 event->timestamp = timestamp;
313 dbus_message_iter_next (&iter_struct);
315 dbus_message_iter_get_basic (&iter_struct, &event->event_string);
316 dbus_message_iter_next (&iter_struct);
318 dbus_message_iter_get_basic (&iter_struct, &is_text);
319 event->is_text = is_text;
323 * atspi_dbus_handle_DeviceEvent: (skip)
326 atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data)
328 const char *path = dbus_message_get_path (message);
330 AtspiDeviceEvent event;
331 AtspiDeviceListener *listener;
332 DBusMessageIter iter;
333 AtspiDeviceListenerClass *klass;
334 dbus_bool_t retval = FALSE;
339 if (strcmp (dbus_message_get_signature (message), "(uinnisb)") != 0)
341 g_warning ("Atspi: Unknown signature for an event");
345 if (sscanf (path, "/org/a11y/atspi/listeners/%d", &id) != 1)
347 g_warning ("Atspi: Bad listener path: %s\n", path);
351 for (l = device_listeners; l; l = g_list_next (l))
354 if (listener->id == id) break;
361 dbus_message_iter_init (message, &iter);
362 read_device_event_from_iter (&iter, &event);
363 klass = ATSPI_DEVICE_LISTENER_GET_CLASS (listener);
364 if (klass->device_event)
366 retval = (*klass->device_event) (listener, &event);
369 reply = dbus_message_new_method_return (message);
372 dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, DBUS_TYPE_INVALID);
373 dbus_connection_send (_atspi_bus(), reply, NULL);
374 dbus_message_unref (reply);
376 return DBUS_HANDLER_RESULT_HANDLED;
380 _atspi_device_listener_get_path (AtspiDeviceListener *listener)
382 return g_strdup_printf ("/org/a11y/atspi/listeners/%d", listener->id);