Revert "Block out X11 API with #ifdefs"
[platform/upstream/at-spi2-core.git] / registryd / deviceeventcontroller.c
1 /* AT-SPI - Assistive Technology Service Provider Interface
2  *
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2003 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
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.
12  *
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.
17  *
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.
22  */
23
24 /* deviceeventcontroller.c: implement the DeviceEventController interface */
25
26 #include <config.h>
27
28 #undef  SPI_XKB_DEBUG
29 #undef  SPI_DEBUG
30 #undef  SPI_KEYEVENT_DEBUG
31
32 #include <string.h>
33 #include <ctype.h>
34 #include <stdio.h>
35 #include <sys/time.h>
36
37 #include <glib.h>
38
39 #include <dbus/dbus.h>
40
41 #include "paths.h"
42 #include "keymasks.h"
43 #include "de-types.h"
44 #include "de-marshaller.h"
45 #include "display.h"
46 #include "event-source.h"
47
48 #include "deviceeventcontroller.h"
49 #include "reentrant-list.h"
50
51 #include "introspection.h"
52
53 #define CHECK_RELEASE_DELAY 20
54 #define BIT(c, x)       (c[x/8]&(1<<(x%8)))
55 static SpiDEController *saved_controller;
56
57 /* Our parent Gtk object type */
58 #define PARENT_TYPE G_TYPE_OBJECT
59
60 /* A pointer to our parent object class */
61 static int spi_error_code = 0;
62 struct _SpiPoint {
63     gint x;
64     gint y;
65 };
66 typedef struct _SpiPoint SpiPoint;
67 static unsigned int mouse_mask_state = 0;
68 static unsigned int key_modifier_mask =
69   SPI_KEYMASK_MOD1 | SPI_KEYMASK_MOD2 | SPI_KEYMASK_MOD3 | SPI_KEYMASK_MOD4 |
70   SPI_KEYMASK_MOD5 | SPI_KEYMASK_SHIFT | SPI_KEYMASK_SHIFTLOCK |
71   SPI_KEYMASK_CONTROL | SPI_KEYMASK_NUMLOCK;
72 static unsigned int _numlock_physical_mask = SPI_KEYMASK_MOD2; /* a guess, will be reset */
73
74 static gboolean have_mouse_listener = FALSE;
75 static gboolean have_mouse_event_listener = FALSE;
76
77
78 typedef struct {
79   guint                             ref_count : 30;
80   guint                             pending_add : 1;
81   guint                             pending_remove : 1;
82
83   Accessibility_ControllerEventMask mod_mask;
84   dbus_uint32_t               key_val;  /* KeyCode */
85 } DEControllerGrabMask;
86
87
88 gboolean spi_controller_update_key_grabs               (SpiDEController           *controller,
89                                                                Accessibility_DeviceEvent *recv);
90
91 static gboolean eventtype_seq_contains_event (dbus_uint32_t types,
92                                               const Accessibility_DeviceEvent *event);
93 static gboolean spi_dec_poll_mouse_moving (gpointer data);
94 static gboolean spi_dec_poll_mouse_idle (gpointer data);
95
96 G_DEFINE_TYPE(SpiDEController, spi_device_event_controller, G_TYPE_OBJECT)
97
98 static gint
99 spi_dec_plat_get_keycode (SpiDEController *controller,
100                           gint keysym,
101                           gchar *key_str,
102                           gboolean fix,
103                           guint *modmask)
104 {
105   SpiDEControllerClass *klass;
106   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
107   if (klass->plat.get_keycode)
108     return klass->plat.get_keycode (controller, keysym, key_str, fix, modmask);
109   else
110     return keysym;
111 }
112
113 static guint
114 spi_dec_plat_mouse_check (SpiDEController *controller, 
115                      int *x, int *y, gboolean *moved)
116 {
117   SpiDEControllerClass *klass;
118   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
119   if (klass->plat.mouse_check)
120     return klass->plat.mouse_check (controller, x, y, moved);
121   else
122     return 0;
123 }
124
125 static gboolean
126 spi_dec_plat_grab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask)
127 {
128   SpiDEControllerClass *klass;
129   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
130   if (klass->plat.grab_key)
131     return klass->plat.grab_key (controller, key_val, mod_mask);
132   else
133     return FALSE;
134 }
135
136 static void
137 spi_dec_plat_ungrab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask)
138 {
139   SpiDEControllerClass *klass;
140   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
141   if (klass->plat.ungrab_key)
142     klass->plat.ungrab_key (controller, key_val, mod_mask);
143 }
144
145 static gboolean
146 spi_dec_plat_synth_keycode_press (SpiDEController *controller,
147                          unsigned int keycode)
148 {
149   SpiDEControllerClass *klass;
150   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
151   if (klass->plat.synth_keycode_press)
152     return klass->plat.synth_keycode_press (controller, keycode);
153   else
154     return FALSE;
155 }
156
157 static gboolean
158 spi_dec_plat_synth_keycode_release (SpiDEController *controller,
159                            unsigned int keycode)
160 {
161   SpiDEControllerClass *klass;
162   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
163   if (klass->plat.synth_keycode_release)
164     return klass->plat.synth_keycode_release (controller, keycode);
165   else
166     return FALSE;
167 }
168
169 static gboolean
170 spi_dec_plat_lock_modifiers (SpiDEController *controller, unsigned modifiers)
171 {
172   SpiDEControllerClass *klass;
173   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
174   if (klass->plat.lock_modifiers)
175     return klass->plat.lock_modifiers (controller, modifiers);
176   else
177     return FALSE;
178 }
179
180 static gboolean
181 spi_dec_plat_unlock_modifiers (SpiDEController *controller, unsigned modifiers)
182 {
183   SpiDEControllerClass *klass;
184   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
185   if (klass->plat.unlock_modifiers)
186     return klass->plat.unlock_modifiers (controller, modifiers);
187   else
188     return FALSE;
189 }
190
191 static gboolean
192 spi_dec_plat_synth_keystring (SpiDEController *controller, guint synth_type, gint keycode, const char *keystring)
193 {
194   SpiDEControllerClass *klass;
195   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
196   if (klass->plat.synth_keystring)
197     return klass->plat.synth_keystring (controller, synth_type, keycode, keystring);
198   else
199     return FALSE;
200 }
201
202 static void
203 spi_dec_plat_emit_modifier_event (SpiDEController *controller, guint prev_mask, 
204                              guint current_mask)
205 {
206   SpiDEControllerClass *klass;
207   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
208   if (klass->plat.emit_modifier_event)
209     klass->plat.emit_modifier_event (controller, prev_mask, current_mask);
210 }
211
212 static void
213 spi_dec_plat_generate_mouse_event (SpiDEController *controller,
214                                    gint x,
215                                    gint y,
216                                    const char *eventName)
217 {
218   SpiDEControllerClass *klass;
219   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
220   if (klass->plat.generate_mouse_event)
221     klass->plat.generate_mouse_event (controller, x, y, eventName);
222 }
223
224 DBusMessage *
225 invalid_arguments_error (DBusMessage *message)
226 {
227     DBusMessage *reply;
228     gchar       *errmsg;
229
230     errmsg= g_strdup_printf (
231             "Method \"%s\" with signature \"%s\" on interface \"%s\" was supplied with invalid arguments\n",
232             dbus_message_get_member (message),
233             dbus_message_get_signature (message),
234             dbus_message_get_interface (message));
235     reply = dbus_message_new_error (message,
236                                     DBUS_ERROR_INVALID_ARGS,
237                                     errmsg);
238     g_free (errmsg);
239     return reply;
240 }
241
242 /* Private methods */
243 static dbus_bool_t
244 spi_dbus_add_disconnect_match (DBusConnection *bus, const char *name)
245 {
246   char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name);
247   if (match)
248   {
249     DBusError error;
250     dbus_error_init (&error);
251     dbus_bus_add_match (bus, match, &error);
252     g_free (match);
253     if (dbus_error_is_set (&error))
254       {
255         dbus_error_free (&error);
256         return FALSE;
257       }
258     else
259       {
260         return TRUE;
261       }
262   }
263   else return FALSE;
264 }
265
266 static dbus_bool_t
267 spi_dbus_remove_disconnect_match (DBusConnection *bus, const char *name)
268 {
269   char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name);
270   if (match)
271   {
272     DBusError error;
273     dbus_error_init (&error);
274     dbus_bus_remove_match (bus, match, &error);
275     g_free (match);
276     if (dbus_error_is_set (&error))
277       {
278         dbus_error_free (&error);
279         return FALSE;
280       }
281     else
282       {
283         return TRUE;
284       }
285   }
286   else return FALSE;
287 }
288
289 static DEControllerGrabMask *
290 spi_grab_mask_clone (DEControllerGrabMask *grab_mask)
291 {
292   DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1);
293
294   memcpy (clone, grab_mask, sizeof (DEControllerGrabMask));
295
296   clone->ref_count = 1;
297   clone->pending_add = TRUE;
298   clone->pending_remove = FALSE;
299
300   return clone;
301 }
302
303 static void
304 spi_grab_mask_free (DEControllerGrabMask *grab_mask)
305 {
306   g_free (grab_mask);
307 }
308
309 static gint
310 spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2)
311 {
312   DEControllerGrabMask *l1 = (DEControllerGrabMask *) p1;
313   DEControllerGrabMask *l2 = (DEControllerGrabMask *) p2;
314
315   if (p1 == p2)
316     {
317       return 0;
318     }
319   else
320     { 
321       return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val));
322     }
323 }
324
325 void
326 spi_dec_dbus_emit (SpiDEController *controller, const char *interface,
327                    const char *name, const char *minor, int a1, int a2)
328 {
329   DBusMessage *signal = NULL;
330   DBusMessageIter iter, iter_struct, iter_variant;
331   int nil = 0;
332   const char *path = SPI_DBUS_PATH_ROOT;
333   const char *bus_name = dbus_bus_get_unique_name (controller->bus);
334
335   signal = dbus_message_new_signal (path, interface, name);
336
337   dbus_message_iter_init_append (signal, &iter);
338
339   dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor);
340   dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a1);
341   dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a2);
342   dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant);
343       dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &nil);
344   dbus_message_iter_close_container (&iter, &iter_variant);
345
346   dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
347                                     &iter_struct);
348   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &bus_name);
349   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path);
350   dbus_message_iter_close_container (&iter, &iter_struct);
351
352   dbus_connection_send (controller->bus, signal, NULL);
353   dbus_message_unref (signal);
354 }
355
356 static gboolean
357 spi_dec_poll_mouse_moved (gpointer data)
358 {
359   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(data);
360   int x, y;
361   gboolean moved;
362   guint mask_return;
363
364   mask_return = spi_dec_plat_mouse_check (controller, &x, &y, &moved);
365
366   if ((mask_return & key_modifier_mask) !=
367       (mouse_mask_state & key_modifier_mask)) 
368     {
369       spi_dec_plat_emit_modifier_event (controller, mouse_mask_state, mask_return);
370       mouse_mask_state = mask_return;
371     }
372
373   return moved;
374 }
375
376 static gboolean
377 spi_dec_poll_mouse_idle (gpointer data)
378 {
379   if (!have_mouse_event_listener && !have_mouse_listener)
380     return FALSE;
381   else if (!spi_dec_poll_mouse_moved (data))
382     return TRUE;
383   else
384     {
385       guint id;
386       id = g_timeout_add (20, spi_dec_poll_mouse_moving, data);
387       g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_moving");
388       return FALSE;         
389     }
390 }
391
392 static gboolean
393 spi_dec_poll_mouse_moving (gpointer data)
394 {
395   if (!have_mouse_event_listener && !have_mouse_listener)
396     return FALSE;
397   else if (spi_dec_poll_mouse_moved (data))
398     return TRUE;
399   else
400     {
401       guint id;
402       id = g_timeout_add (100, spi_dec_poll_mouse_idle, data);
403       g_source_set_name_by_id (id, "[at-spi2-core] check_release");
404       return FALSE;
405     }
406 }
407
408 /**
409  * Eventually we can use this to make the marshalling of mask types
410  * more sane, but for now we just use this to detect 
411  * the use of 'virtual' masks such as numlock and convert them to
412  * system-specific mask values (i.e. ModMask).
413  * 
414  **/
415 static Accessibility_ControllerEventMask
416 spi_dec_translate_mask (Accessibility_ControllerEventMask mask)
417 {
418   Accessibility_ControllerEventMask tmp_mask;
419   gboolean has_numlock;
420
421   has_numlock = (mask & SPI_KEYMASK_NUMLOCK);
422   tmp_mask = mask;
423   if (has_numlock)
424     {
425       tmp_mask = mask ^ SPI_KEYMASK_NUMLOCK;
426       tmp_mask |= _numlock_physical_mask;
427     }
428  
429   return tmp_mask;
430 }
431
432 static DEControllerKeyListener *
433 spi_dec_key_listener_new (const char *bus_name,
434                           const char *path,
435                           GSList *keys,
436                           const Accessibility_ControllerEventMask mask,
437                           const dbus_uint32_t types,
438                           const Accessibility_EventListenerMode  *mode)
439 {
440   DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1);
441   key_listener->listener.bus_name = g_strdup(bus_name);
442   key_listener->listener.path = g_strdup(path);
443   key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
444   key_listener->keys = keys;
445   key_listener->mask = spi_dec_translate_mask (mask);
446   key_listener->listener.types = types;
447   if (mode)
448   {
449     key_listener->mode = (Accessibility_EventListenerMode *) g_malloc(sizeof(Accessibility_EventListenerMode));
450     memcpy(key_listener->mode, mode, sizeof(*mode));
451   }
452   else
453     key_listener->mode = NULL;
454
455 #ifdef SPI_DEBUG
456   g_print ("new listener, with mask %x, is_global %d, keys %p (%d)\n",
457            (unsigned int) key_listener->mask,
458            (int) (mode ? mode->global : 0),
459            (void *) key_listener->keys,
460            (int) (key_listener->keys ? g_slist_length(key_listener->keys) : 0));
461 #endif
462
463   return key_listener;  
464 }
465
466 static DEControllerListener *
467 spi_dec_listener_new (const char *bus_name,
468                       const char *path,
469                       dbus_uint32_t types)
470 {
471   DEControllerListener *listener = g_new0 (DEControllerListener, 1);
472   listener->bus_name = g_strdup(bus_name);
473   listener->path = g_strdup(path);
474   listener->type = SPI_DEVICE_TYPE_MOUSE;
475   listener->types = types;
476   return listener;      
477 }
478
479 static DEControllerListener *
480 spi_listener_clone (DEControllerListener *listener)
481 {
482   DEControllerListener *clone = g_new0 (DEControllerListener, 1);
483   clone->bus_name = g_strdup (listener->bus_name);
484   clone->path = g_strdup (listener->path);
485   clone->type = listener->type;
486   clone->types = listener->types;
487   return clone;
488 }
489
490 static GSList *keylist_clone (GSList *s)
491 {
492   GSList *d = NULL;
493   GSList *l;
494
495   for (l = s; l; l = g_slist_next(l))
496   {
497     Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
498     if (kd)
499     {
500       Accessibility_KeyDefinition *kds = (Accessibility_KeyDefinition *)l->data;
501       kd->keycode = kds->keycode;
502       kd->keysym = kds->keysym;
503       kd->keystring = g_strdup(kds->keystring);
504       d = g_slist_append(d, kd);
505     }
506   }
507   return d;
508 }
509
510 static DEControllerKeyListener *
511 spi_key_listener_clone (DEControllerKeyListener *key_listener)
512 {
513   DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1);
514   clone->listener.bus_name = g_strdup (key_listener->listener.bus_name);
515   clone->listener.path = g_strdup (key_listener->listener.path);
516   clone->listener.type = SPI_DEVICE_TYPE_KBD;
517   clone->keys = keylist_clone (key_listener->keys);
518   clone->mask = key_listener->mask;
519   clone->listener.types = key_listener->listener.types;
520   if (key_listener->mode)
521   {
522     clone->mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode));
523     if (clone->mode) memcpy(clone->mode, key_listener->mode, sizeof(Accessibility_EventListenerMode));
524   }
525   else
526     clone->mode = NULL;
527   return clone;
528 }
529
530 static void keylist_free(GSList *keys)
531 {
532   GSList *l;
533
534   for (l = keys; l; l = g_slist_next(l))
535   {
536     Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)l->data;
537     g_free(kd->keystring);
538     g_free(kd);
539   }
540   g_slist_free (keys);
541 }
542
543 static void
544 spi_key_listener_data_free (DEControllerKeyListener *key_listener)
545 {
546   keylist_free(key_listener->keys);
547   if (key_listener->mode) g_free(key_listener->mode);
548   g_free (key_listener->listener.bus_name);
549   g_free (key_listener->listener.path);
550   g_free (key_listener);
551 }
552
553 static void
554 spi_key_listener_clone_free (DEControllerKeyListener *clone)
555 {
556   spi_key_listener_data_free (clone);
557 }
558
559 static void
560 spi_listener_clone_free (DEControllerListener *clone)
561 {
562   g_free (clone->path);
563   g_free (clone->bus_name);
564   g_free (clone);
565 }
566
567 static void
568 spi_dec_listener_free (DEControllerListener    *listener)
569 {
570   if (listener->type == SPI_DEVICE_TYPE_KBD) 
571     spi_key_listener_data_free ((DEControllerKeyListener *) listener);
572   else
573   {
574     g_free (listener->bus_name);
575     g_free (listener->path);
576   }
577 }
578
579 static void
580 _register_keygrab (SpiDEController      *controller,
581                    DEControllerGrabMask *grab_mask)
582 {
583   GList *l;
584
585   l = g_list_find_custom (controller->keygrabs_list, grab_mask,
586                           spi_grab_mask_compare_values);
587   if (l)
588     {
589       DEControllerGrabMask *cur_mask = l->data;
590
591       cur_mask->ref_count++;
592       if (cur_mask->pending_remove)
593         {
594           cur_mask->pending_remove = FALSE;
595         }
596     }
597   else
598     {
599       controller->keygrabs_list =
600         g_list_prepend (controller->keygrabs_list,
601                         spi_grab_mask_clone (grab_mask));
602     }
603 }
604
605 static void
606 _deregister_keygrab (SpiDEController      *controller,
607                      DEControllerGrabMask *grab_mask)
608 {
609   GList *l;
610
611   l = g_list_find_custom (controller->keygrabs_list, grab_mask,
612                           spi_grab_mask_compare_values);
613
614   if (l)
615     {
616       DEControllerGrabMask *cur_mask = l->data;
617
618       cur_mask->ref_count--;
619       if (cur_mask->ref_count <= 0)
620         {
621           cur_mask->pending_remove = TRUE;
622         }
623     }
624 }
625
626 static void
627 handle_keygrab (SpiDEController         *controller,
628                 DEControllerKeyListener *key_listener,
629                 void                   (*process_cb) (SpiDEController *controller,
630                                                       DEControllerGrabMask *grab_mask))
631 {
632   DEControllerGrabMask grab_mask = { 0 };
633
634   grab_mask.mod_mask = key_listener->mask;
635   if (g_slist_length (key_listener->keys) == 0) /* special case means AnyKey/AllKeys */
636     {
637       grab_mask.key_val = AnyKey;
638 #ifdef SPI_DEBUG
639       fprintf (stderr, "AnyKey grab!");
640 #endif
641       process_cb (controller, &grab_mask);
642     }
643   else
644     {
645       GSList *l;
646
647       for (l = key_listener->keys; l; l = g_slist_next(l))
648         {
649           Accessibility_KeyDefinition *keydef = l->data;
650           long key_val;
651           key_val = spi_dec_plat_get_keycode (controller, keydef->keysym, keydef->keystring, FALSE, NULL);
652           if (!key_val)
653             key_val = keydef->keycode;
654           grab_mask.key_val = key_val;
655           process_cb (controller, &grab_mask);
656         }
657     }
658 }
659
660 static gboolean
661 spi_controller_register_global_keygrabs (SpiDEController         *controller,
662                                          DEControllerKeyListener *key_listener)
663 {
664   handle_keygrab (controller, key_listener, _register_keygrab);
665   return spi_controller_update_key_grabs (controller, NULL);
666 }
667
668 static void
669 spi_controller_deregister_global_keygrabs (SpiDEController         *controller,
670                                            DEControllerKeyListener *key_listener)
671 {
672   handle_keygrab (controller, key_listener, _deregister_keygrab);
673   spi_controller_update_key_grabs (controller, NULL);
674 }
675
676 static void
677 append_keystroke_listener (DBusMessageIter *iter, DEControllerKeyListener *listener)
678 {
679   dbus_uint32_t d_uint;
680   DBusMessageIter iter_struct, iter_subarray, iter_substruct;
681   GSList *kl;
682
683   if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
684                                          &iter_struct))
685     return;
686
687   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
688                                   &listener->listener.bus_name);
689   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
690                                   &listener->listener.path);
691   d_uint = listener->listener.type;
692   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
693   d_uint = listener->listener.types;
694   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
695   if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY,
696                                          "(iisi)", &iter_subarray))
697   {
698     dbus_message_iter_close_container (iter, &iter_struct);
699     return;
700   }
701   for (kl = listener->keys; kl; kl = kl->next)
702   {
703     Accessibility_KeyDefinition *kd = kl->data;
704     if (!dbus_message_iter_open_container (&iter_subarray, DBUS_TYPE_STRUCT,
705                                          NULL, &iter_substruct))
706       break;
707     dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keycode);
708     dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keysym);
709     dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_STRING, &kd->keystring);
710     dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->unused);
711     dbus_message_iter_close_container (&iter_subarray, &iter_substruct);
712   }
713   dbus_message_iter_close_container (&iter_struct, &iter_subarray);
714   d_uint = listener->mask;
715   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
716   if (dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT,
717                                          NULL, &iter_substruct))
718   {
719     if (listener->mode)
720     {
721       dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
722                                       &listener->mode->synchronous);
723       dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
724                                       &listener->mode->preemptive);
725       dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
726                                       &listener->mode->global);
727     }
728     else
729     {
730       dbus_bool_t dummy_val = FALSE;
731       dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
732                                       &dummy_val);
733       dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
734                                       &dummy_val);
735       dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN,
736                                       &dummy_val);
737     }
738     dbus_message_iter_close_container (&iter_struct, &iter_substruct);
739   }
740   dbus_message_iter_close_container (iter, &iter_struct);
741 }
742
743 static void
744 notify_keystroke_listener (SpiDEController *controller,
745                            DEControllerKeyListener *listener,
746                            gboolean enable)
747 {
748   const char *path = SPI_DBUS_PATH_DEC;
749   const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
750   const char *name = (enable
751                       ? "KeystrokeListenerRegistered"
752                       : "KeystrokeListenerDeregistered");
753   DBusMessage *signal;
754   DBusMessageIter iter;
755
756   signal = dbus_message_new_signal (path, interface, name);
757   if (!signal)
758     return;
759   dbus_message_iter_init_append (signal, &iter);
760   append_keystroke_listener (&iter, listener);
761   dbus_connection_send (controller->bus, signal, NULL);
762   dbus_message_unref (signal);
763 }
764
765 static void
766 append_mouse_listener (DBusMessageIter *iter, DEControllerListener *listener)
767 {
768   DBusMessageIter iter_struct;
769   dbus_uint32_t d_uint;
770
771   if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
772                                          &iter_struct))
773     return;
774   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING,
775                                   &listener->bus_name);
776   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH,
777                                   &listener->path);
778   d_uint = listener->types;
779   dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint);
780   dbus_message_iter_close_container (iter, &iter_struct);
781 }
782
783 static void
784 notify_mouse_listener (SpiDEController *controller,
785                        DEControllerListener *listener,
786                        gboolean enable)
787 {
788   const char *path = SPI_DBUS_PATH_DEC;
789   const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER;
790   const char *name = (enable
791                       ? "DeviceListenerRegistered"
792                       : "DeviceListenerDeregistered");
793   DBusMessage *signal;
794   DBusMessageIter iter;
795
796   signal = dbus_message_new_signal (path, interface, name);
797   if (!signal)
798     return;
799   dbus_message_iter_init_append (signal, &iter);
800   append_mouse_listener (&iter, listener);
801   dbus_connection_send (controller->bus, signal, NULL);
802   dbus_message_unref (signal);
803 }
804
805 static gboolean
806 spi_controller_register_device_listener (SpiDEController      *controller,
807                                          DEControllerListener *listener)
808 {
809   DEControllerKeyListener *key_listener;
810   gboolean retval;
811   
812   switch (listener->type) {
813   case SPI_DEVICE_TYPE_KBD:
814       key_listener = (DEControllerKeyListener *) listener;
815
816       controller->key_listeners = g_list_prepend (controller->key_listeners,
817                                                   key_listener);
818       spi_dbus_add_disconnect_match (controller->bus, key_listener->listener.bus_name);
819       if (key_listener->mode->global)
820         {
821           retval = spi_controller_register_global_keygrabs (controller, key_listener);
822         }
823       else
824           retval = TRUE;
825       if (retval)
826         notify_keystroke_listener (controller, key_listener, TRUE);
827       break;
828   case SPI_DEVICE_TYPE_MOUSE:
829       controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
830       if (!have_mouse_listener)
831         {
832           have_mouse_listener = TRUE;
833           if (!have_mouse_event_listener) {
834             guint id;
835             id = g_timeout_add (100, spi_dec_poll_mouse_idle, controller);
836             g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle");
837           }
838         }
839       spi_dbus_add_disconnect_match (controller->bus, listener->bus_name);
840       notify_mouse_listener (controller, listener, TRUE);
841       break;
842   default:
843       break;
844   }
845   return FALSE;
846 }
847
848 static void
849 set_reply (DBusPendingCall *pending, void *user_data)
850 {
851     void **replyptr = (void **)user_data;
852
853     *replyptr = dbus_pending_call_steal_reply (pending);
854 }
855
856 static GSList *hung_processes = NULL;
857
858 static void
859 reset_hung_process (DBusPendingCall *pending, void *data)
860 {
861   DBusMessage *message = data;
862   const char *dest = dbus_message_get_destination (message);
863   GSList *l;
864
865   /* At this point we don't care about the result */
866   dbus_pending_call_unref (pending);
867
868   for (l = hung_processes; l; l = l->next)
869   {
870     if (!strcmp (l->data, dest))
871     {
872       g_free (l->data);
873       hung_processes = g_slist_remove (hung_processes, l->data);
874       break;
875     }
876   }
877 }
878
879 static gint
880 time_elapsed (struct timeval *origin)
881 {
882   struct timeval tv;
883
884   gettimeofday (&tv, NULL);
885   return (tv.tv_sec - origin->tv_sec) * 1000 + (tv.tv_usec - origin->tv_usec) / 1000;
886 }
887
888 static void
889 reset_hung_process_from_ping (DBusPendingCall *pending, void *data)
890 {
891   GSList *l;
892
893   for (l = hung_processes; l; l = l->next)
894   {
895     if (!strcmp (l->data, data))
896     {
897       g_free (l->data);
898       hung_processes = g_slist_remove (hung_processes, l->data);
899       break;
900     }
901   }
902   g_free (data);
903   dbus_pending_call_unref (pending);
904 }
905
906 static DBusMessage *
907 send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, int timeout, DBusError *error)
908 {
909     DBusPendingCall *pending;
910     DBusMessage *reply = NULL;
911   struct timeval tv;
912
913     if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
914     {
915         return NULL;
916     }
917     dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
918     gettimeofday (&tv, NULL);
919     while (!reply)
920     {
921       if (!dbus_connection_read_write_dispatch (bus, timeout) ||
922           time_elapsed (&tv) > timeout)
923       {
924         const char *dest = dbus_message_get_destination (message);
925         GSList *l;
926         gchar *bus_name_dup;
927         dbus_message_ref (message);
928         dbus_pending_call_set_notify (pending, reset_hung_process, message,
929                                       (DBusFreeFunction) dbus_message_unref);
930         message = dbus_message_new_method_call (dest, "/",
931                                                 "org.freedesktop.DBus.Peer",
932                                                 "Ping");
933         if (!message)
934           return NULL;
935         dbus_connection_send_with_reply (bus, message, &pending, -1);
936         dbus_message_unref (message);
937         if (!pending)
938           return NULL;
939         bus_name_dup = g_strdup (dest);
940         dbus_pending_call_set_notify (pending, reset_hung_process_from_ping,
941                                       bus_name_dup, NULL);
942         for (l = hung_processes; l; l = l->next)
943           if (!strcmp (l->data, dest))
944             return NULL;
945         hung_processes = g_slist_prepend (hung_processes, g_strdup (dest));
946         return NULL;
947       }
948     }
949     dbus_pending_call_unref (pending);
950     return reply;
951 }
952 static gboolean
953 Accessibility_DeviceEventListener_NotifyEvent(SpiDEController *controller,
954                                               SpiRegistry *registry,
955                                               DEControllerListener *listener,
956                                               const Accessibility_DeviceEvent *key_event)
957 {
958   DBusMessage *message = dbus_message_new_method_call(listener->bus_name,
959                                                       listener->path,
960                                                       SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER,
961                                                       "NotifyEvent");
962   dbus_bool_t consumed = FALSE;
963   GSList *l;
964   gboolean hung = FALSE;
965
966   for (l = hung_processes; l; l = l->next)
967   {
968     if (!strcmp (l->data, listener->bus_name))
969     {
970       dbus_message_set_no_reply (message, TRUE);
971       hung = TRUE;
972       break;
973     }
974   }
975
976   if (spi_dbus_marshal_deviceEvent(message, key_event))
977   {
978     DBusMessage *reply;
979
980     if (hung)
981     {
982       dbus_connection_send (controller->bus, message, NULL);
983       dbus_message_unref (message);
984       return FALSE;
985     }
986
987     reply = send_and_allow_reentry (controller->bus, message, 3000, NULL);
988     if (reply)
989     {
990       dbus_message_get_args(reply, NULL, DBUS_TYPE_BOOLEAN, &consumed, DBUS_TYPE_INVALID);
991       dbus_message_unref(reply);
992     }
993   }
994   dbus_message_unref(message);
995   return consumed;
996 }
997
998 gboolean
999 spi_controller_notify_mouselisteners (SpiDEController                 *controller,
1000                                       const Accessibility_DeviceEvent *event)
1001 {
1002   GList   *l;
1003   GSList  *notify = NULL, *l2;
1004   GList  **listeners = &controller->mouse_listeners;
1005   gboolean is_consumed;
1006 #ifdef SPI_KEYEVENT_DEBUG
1007   gboolean found = FALSE;
1008 #endif
1009   if (!listeners)
1010     {
1011       return FALSE;
1012     }
1013
1014   for (l = *listeners; l; l = l->next)
1015     {
1016        DEControllerListener *listener = l->data;
1017
1018        if (eventtype_seq_contains_event (listener->types, event))
1019          {
1020            /* we clone (don't dup) the listener, to avoid refcount inc. */
1021            notify = g_slist_prepend (notify,
1022                                      spi_listener_clone (listener));
1023 #ifdef SPI_KEYEVENT_DEBUG
1024            found = TRUE;
1025 #endif
1026          }
1027     }
1028
1029 #ifdef SPI_KEYEVENT_DEBUG
1030   if (!found)
1031     {
1032       g_print ("no match for event\n");
1033     }
1034 #endif
1035
1036   is_consumed = FALSE;
1037   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1038     {
1039       DEControllerListener *listener = l2->data;
1040
1041       is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, listener, event);
1042
1043       spi_listener_clone_free ((DEControllerListener *) l2->data);
1044     }
1045
1046   for (; l2; l2 = l2->next)
1047     {
1048       DEControllerListener *listener = l2->data;
1049       spi_listener_clone_free (listener);
1050       /* clone doesn't have its own ref, so don't use spi_device_listener_free */
1051     }
1052
1053   g_slist_free (notify);
1054
1055 #ifdef SPI_DEBUG
1056   if (is_consumed) g_message ("consumed\n");
1057 #endif
1058   return is_consumed;
1059 }
1060
1061 static gboolean
1062 key_set_contains_key (GSList                          *key_set,
1063                           const Accessibility_DeviceEvent *key_event)
1064 {
1065   gint i;
1066   gint len;
1067   GSList *l;
1068
1069   if (!key_set)
1070     {
1071 #ifdef SPI_DEBUG
1072       g_print ("null key set!\n");
1073 #endif
1074       return TRUE;
1075     }
1076
1077   len = g_slist_length (key_set);
1078   
1079   if (len == 0) /* special case, means "all keys/any key" */
1080     {
1081 #ifdef SPI_DEBUG
1082       g_print ("anykey\n");         
1083 #endif
1084       return TRUE;
1085     }
1086
1087   for (l = key_set,i = 0; l; l = g_slist_next(l),i++)
1088     {
1089       Accessibility_KeyDefinition *kd = l->data;
1090 #ifdef SPI_KEYEVENT_DEBUG           
1091       g_print ("key_set[%d] event = %d, code = %d; key_event %d, code %d, string %s\n",
1092                 i,
1093                 (int) kd->keysym,
1094                 (int) kd->keycode,
1095                 (int) key_event->id,
1096                 (int) key_event->hw_code,
1097                 key_event->event_string); 
1098 #endif
1099       if (kd->keysym == (dbus_uint32_t) key_event->id)
1100         {
1101           return TRUE;
1102         }
1103       if (kd->keycode == (dbus_uint32_t) key_event->hw_code)
1104         {
1105           return TRUE;
1106         }
1107       if (key_event->event_string && key_event->event_string[0] &&
1108           !strcmp (kd->keystring, key_event->event_string))
1109         {
1110           return TRUE;
1111         }
1112     }
1113
1114   return FALSE;
1115 }
1116
1117 static gboolean
1118 eventtype_seq_contains_event (dbus_uint32_t types,
1119                                   const Accessibility_DeviceEvent *event)
1120 {
1121   if (types == 0) /* special case, means "all events/any event" */
1122     {
1123       return TRUE;
1124     }
1125
1126   return (types & (1 << event->type));
1127 }
1128
1129 static gboolean
1130 spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event,
1131                                 DEControllerKeyListener         *listener,
1132                                 dbus_bool_t                    is_system_global)
1133 {
1134   if (((key_event->modifiers & 0xFF) == (dbus_uint16_t) (listener->mask & 0xFF)) &&
1135        key_set_contains_key (listener->keys, key_event) &&
1136        eventtype_seq_contains_event (listener->listener.types, key_event) && 
1137       (is_system_global == listener->mode->global))
1138     {
1139       return TRUE;
1140     }
1141   else
1142     {
1143       return FALSE;
1144     }
1145 }
1146
1147 gboolean
1148 spi_controller_notify_keylisteners (SpiDEController                 *controller,
1149                                     Accessibility_DeviceEvent       *key_event,
1150                                     dbus_bool_t                    is_system_global)
1151 {
1152   GList   *l;
1153   GSList  *notify = NULL, *l2;
1154   GList  **key_listeners = &controller->key_listeners;
1155   gboolean is_consumed;
1156
1157   if (!key_listeners)
1158     {
1159       return FALSE;
1160     }
1161
1162   /* set the NUMLOCK event mask bit if appropriate: see bug #143702 */
1163   if (key_event->modifiers & _numlock_physical_mask)
1164       key_event->modifiers |= SPI_KEYMASK_NUMLOCK;
1165
1166   for (l = *key_listeners; l; l = l->next)
1167     {
1168        DEControllerKeyListener *key_listener = l->data;
1169
1170        if (spi_key_event_matches_listener (key_event, key_listener, is_system_global))
1171          {
1172            /* we clone (don't dup) the listener, to avoid refcount inc. */
1173            notify = g_slist_prepend (notify,
1174                                      spi_key_listener_clone (key_listener));
1175          }
1176     }
1177
1178 #ifdef SPI_KEYEVENT_DEBUG
1179   if (!notify)
1180     {
1181       g_print ("no match for event\n");
1182     }
1183 #endif
1184
1185   is_consumed = FALSE;
1186   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1187     {
1188       DEControllerKeyListener *key_listener = l2->data;     
1189
1190       is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, &key_listener->listener, key_event) &&
1191                     key_listener->mode->preemptive;
1192
1193       spi_key_listener_clone_free (key_listener);
1194     }
1195
1196   for (; l2; l2 = l2->next)
1197     {
1198       DEControllerKeyListener *key_listener = l2->data;     
1199       spi_key_listener_clone_free (key_listener);
1200       /* clone doesn't have its own ref, so don't use spi_dec_listener_free */
1201     }
1202
1203   g_slist_free (notify);
1204
1205 #ifdef SPI_DEBUG
1206   if (is_consumed) g_message ("consumed\n");
1207 #endif
1208   return is_consumed;
1209 }
1210
1211 gboolean
1212 spi_clear_error_state (void)
1213 {
1214         gboolean retval = spi_error_code != 0;
1215         spi_error_code = 0;
1216         return retval;
1217 }
1218
1219 gboolean
1220 spi_controller_update_key_grabs (SpiDEController           *controller,
1221                                  Accessibility_DeviceEvent *recv)
1222 {
1223   GList *l, *next;
1224   gboolean   update_failed = FALSE;
1225   long keycode = 0;
1226   
1227   g_return_val_if_fail (controller != NULL, FALSE);
1228
1229   /*
1230    * masks known to work with default RH 7.1+:
1231    * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
1232    * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
1233    * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
1234    * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
1235    *
1236    * ControlMask grabs are broken, must be in use already
1237    */
1238   if (recv)
1239     keycode = spi_dec_plat_get_keycode (controller, recv->id, NULL, TRUE, NULL);
1240   for (l = controller->keygrabs_list; l; l = next)
1241     {
1242       gboolean do_remove;
1243       gboolean re_issue_grab;
1244       DEControllerGrabMask *grab_mask = l->data;
1245
1246       next = l->next;
1247
1248       re_issue_grab = recv &&
1249               (recv->modifiers & grab_mask->mod_mask) &&
1250               (grab_mask->key_val == keycode);
1251
1252 #ifdef SPI_DEBUG
1253       fprintf (stderr, "mask=%lx %lx (%c%c) %s\n",
1254                (long int) grab_mask->key_val,
1255                (long int) grab_mask->mod_mask,
1256                grab_mask->pending_add ? '+' : '.',
1257                grab_mask->pending_remove ? '-' : '.',
1258                re_issue_grab ? "re-issue": "");
1259 #endif
1260
1261       do_remove = FALSE;
1262
1263       if (grab_mask->pending_add && grab_mask->pending_remove)
1264         {
1265           do_remove = TRUE;
1266         }
1267       else if (grab_mask->pending_remove)
1268         {
1269 #ifdef SPI_DEBUG
1270       fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask);
1271 #endif
1272           spi_dec_plat_ungrab_key (controller,
1273                                grab_mask->key_val,
1274                                grab_mask->mod_mask);
1275
1276           do_remove = TRUE;
1277         }
1278       else if (grab_mask->pending_add || re_issue_grab)
1279         {
1280
1281 #ifdef SPI_DEBUG
1282           fprintf (stderr, "grab %d with mask %x\n", grab_mask->key_val, grab_mask->mod_mask);
1283 #endif
1284           update_failed = spi_dec_plat_grab_key (controller,
1285                                                grab_mask->key_val,
1286                                                grab_mask->mod_mask);
1287           if (update_failed) {
1288                   while (grab_mask->ref_count > 0) --grab_mask->ref_count;
1289                   do_remove = TRUE;
1290           }
1291         }
1292
1293       grab_mask->pending_add = FALSE;
1294       grab_mask->pending_remove = FALSE;
1295
1296       if (do_remove)
1297         {
1298           g_assert (grab_mask->ref_count <= 0);
1299
1300           controller->keygrabs_list = g_list_delete_link (
1301             controller->keygrabs_list, l);
1302
1303           spi_grab_mask_free (grab_mask);
1304         }
1305
1306     } 
1307
1308   return ! update_failed;
1309 }
1310
1311 /*
1312  * Implemented GObject::finalize
1313  */
1314 static void
1315 spi_device_event_controller_object_finalize (GObject *object)
1316 {
1317   SpiDEController *controller;
1318   GObjectClass *parent_class = G_OBJECT_CLASS(spi_device_event_controller_parent_class);
1319   SpiDEControllerClass *klass;
1320
1321   controller = SPI_DEVICE_EVENT_CONTROLLER (object);
1322   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
1323 #ifdef SPI_DEBUG
1324   fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
1325 #endif
1326   if (klass->plat.finalize)
1327     klass->plat.finalize (controller);
1328
1329   parent_class->finalize (object);
1330 }
1331
1332 /*
1333  * DBus Accessibility::DEController::RegisterKeystrokeListener
1334  *     method implementation
1335  */
1336 static DBusMessage *
1337 impl_register_keystroke_listener (DBusConnection *bus,
1338                                   DBusMessage *message,
1339                                   void *user_data)
1340 {
1341   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1342   DEControllerKeyListener *dec_listener;
1343   DBusMessageIter iter, iter_array;
1344   const char *path;
1345   GSList *keys = NULL;
1346   dbus_int32_t mask, type;
1347   Accessibility_EventListenerMode *mode;
1348  dbus_bool_t ret;
1349   DBusMessage *reply = NULL;
1350   char *keystring;
1351
1352   if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu(bbb)") != 0)
1353     return invalid_arguments_error (message);
1354
1355   dbus_message_iter_init(message, &iter);
1356   dbus_message_iter_get_basic(&iter, &path);
1357   dbus_message_iter_next(&iter);
1358   dbus_message_iter_recurse(&iter, &iter_array);
1359   while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID)
1360   {
1361     Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
1362     if (!spi_dbus_message_iter_get_struct(&iter_array, DBUS_TYPE_INT32, &kd->keycode, DBUS_TYPE_INT32, &kd->keysym, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_INVALID))
1363     {
1364       break;
1365     }
1366     kd->keystring = g_strdup (keystring);
1367     keys = g_slist_append(keys, kd);
1368   }
1369   dbus_message_iter_next(&iter);
1370   dbus_message_iter_get_basic(&iter, &mask);
1371   dbus_message_iter_next(&iter);
1372   dbus_message_iter_get_basic(&iter, &type);
1373   dbus_message_iter_next(&iter);
1374   mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode));
1375   if (mode)
1376   {
1377     spi_dbus_message_iter_get_struct(&iter, DBUS_TYPE_BOOLEAN, &mode->synchronous, DBUS_TYPE_BOOLEAN, &mode->preemptive, DBUS_TYPE_BOOLEAN, &mode->global, DBUS_TYPE_INVALID);
1378   }
1379 #ifdef SPI_DEBUG
1380   fprintf (stderr, "registering keystroke listener %s:%s with maskVal %lu\n",
1381            dbus_message_get_sender(message), path, (unsigned long) mask);
1382 #endif
1383   dec_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, mode);
1384   g_free (mode);
1385   ret = spi_controller_register_device_listener (
1386           controller, (DEControllerListener *) dec_listener);
1387   reply = dbus_message_new_method_return (message);
1388   if (reply)
1389   {
1390     dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1391   }
1392   return reply;
1393 }
1394
1395 /*
1396  * DBus Accessibility::DEController::RegisterDeviceEventListener
1397  *     method implementation
1398  */
1399 static DBusMessage *
1400 impl_register_device_event_listener (DBusConnection *bus,
1401                                   DBusMessage *message,
1402                                   void *user_data)
1403 {
1404   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1405   DEControllerListener *dec_listener;
1406   const char *path;
1407   dbus_int32_t event_types;
1408   dbus_bool_t ret;
1409   DBusMessage *reply = NULL;
1410
1411   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID))
1412   {
1413     return invalid_arguments_error (message);
1414   }
1415   dec_listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types);
1416   ret =  spi_controller_register_device_listener (
1417           controller, (DEControllerListener *) dec_listener);
1418   reply = dbus_message_new_method_return (message);
1419   if (reply)
1420   {
1421     dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1422   }
1423   return reply;
1424 }
1425
1426 typedef struct {
1427         DBusConnection *bus;
1428         DEControllerListener    *listener;
1429 } RemoveListenerClosure;
1430
1431 static SpiReEntrantContinue
1432 remove_listener_cb (GList * const *list,
1433                     gpointer       user_data)
1434 {
1435   DEControllerListener  *listener = (*list)->data;
1436   RemoveListenerClosure *ctx = user_data;
1437
1438   if (!strcmp(ctx->listener->bus_name, listener->bus_name) &&
1439       !strcmp(ctx->listener->path, listener->path))
1440     {
1441       spi_re_entrant_list_delete_link (list);
1442       spi_dbus_remove_disconnect_match (ctx->bus, listener->bus_name);
1443       spi_dec_listener_free (listener);
1444     }
1445
1446   return SPI_RE_ENTRANT_CONTINUE;
1447 }
1448
1449 static SpiReEntrantContinue
1450 copy_key_listener_cb (GList * const *list,
1451                       gpointer       user_data)
1452 {
1453   DEControllerKeyListener  *key_listener = (*list)->data;
1454   RemoveListenerClosure    *ctx = user_data;
1455
1456   if (!strcmp(ctx->listener->bus_name, key_listener->listener.bus_name) &&
1457       !strcmp(ctx->listener->path, key_listener->listener.path))
1458     {
1459       /* TODO: FIXME aggregate keys in case the listener is registered twice */
1460       DEControllerKeyListener *ctx_key_listener = 
1461         (DEControllerKeyListener *) ctx->listener; 
1462       keylist_free (ctx_key_listener->keys);        
1463       ctx_key_listener->keys = keylist_clone(key_listener->keys);
1464     }
1465
1466   return SPI_RE_ENTRANT_CONTINUE;
1467 }
1468
1469 static void
1470 spi_controller_deregister_device_listener (SpiDEController            *controller,
1471                                            DEControllerListener *listener)
1472 {
1473   RemoveListenerClosure  ctx;
1474
1475   ctx.bus = controller->bus;
1476   ctx.listener = listener;
1477
1478   notify_mouse_listener (controller, listener, FALSE);
1479
1480   spi_re_entrant_list_foreach (&controller->mouse_listeners,
1481                                remove_listener_cb, &ctx);
1482   if (!controller->mouse_listeners)
1483     have_mouse_listener = FALSE;
1484 }
1485
1486 static void
1487 spi_deregister_controller_key_listener (SpiDEController            *controller,
1488                                         DEControllerKeyListener    *key_listener)
1489 {
1490   RemoveListenerClosure  ctx;
1491
1492   ctx.bus = controller->bus;
1493   ctx.listener = (DEControllerListener *) spi_key_listener_clone (key_listener);
1494
1495   notify_keystroke_listener (controller, key_listener, FALSE);
1496
1497   /* special case, copy keyset from existing controller list entry */
1498   if (g_slist_length(key_listener->keys) == 0)
1499     {
1500       spi_re_entrant_list_foreach (&controller->key_listeners,
1501                                   copy_key_listener_cb, &ctx);
1502     }
1503
1504   spi_controller_deregister_global_keygrabs (controller, key_listener);
1505
1506   spi_re_entrant_list_foreach (&controller->key_listeners,
1507                                 remove_listener_cb, &ctx);
1508
1509   spi_key_listener_clone_free ((DEControllerKeyListener *) ctx.listener);
1510 }
1511
1512 void
1513 spi_remove_device_listeners (SpiDEController *controller, const char *bus_name)
1514 {
1515   GList *l, *tmp;
1516
1517   for (l = controller->mouse_listeners; l; l = tmp)
1518   {
1519     DEControllerListener *listener = l->data;
1520     tmp = l->next;
1521     if (!strcmp (listener->bus_name, bus_name))
1522     {
1523       spi_controller_deregister_device_listener (controller, listener);
1524       tmp = controller->mouse_listeners;
1525     }
1526   }
1527   for (l = controller->key_listeners; l; l = tmp)
1528   {
1529     DEControllerKeyListener *key_listener = l->data;
1530     tmp = l->next;
1531     if (!strcmp (key_listener->listener.bus_name, bus_name))
1532     {
1533       /* TODO: untangle the below line(s) */
1534       spi_deregister_controller_key_listener (controller, key_listener);
1535       tmp = controller->key_listeners;
1536     }
1537   }
1538 }
1539
1540 /*
1541  * DBus Accessibility::DEController::DeregisterKeystrokeListener
1542  *     method implementation
1543  */
1544 static DBusMessage *
1545 impl_deregister_keystroke_listener (DBusConnection *bus,
1546                                   DBusMessage *message,
1547                                   void *user_data)
1548 {
1549   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1550   DEControllerKeyListener *key_listener;
1551   DBusMessageIter iter, iter_array;
1552   const char *path;
1553   GSList *keys = NULL;
1554   dbus_int32_t mask, type;
1555   DBusMessage *reply = NULL;
1556
1557   dbus_message_iter_init(message, &iter);
1558   if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu") != 0)
1559   {
1560     g_warning ("Received DeregisterKeystrokeListener with strange signature '%s'", dbus_message_get_signature (message));
1561     return invalid_arguments_error (message);
1562   }
1563
1564   dbus_message_iter_get_basic(&iter, &path);
1565   dbus_message_iter_next(&iter);
1566   dbus_message_iter_recurse(&iter, &iter_array);
1567   while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID)
1568   {
1569     Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
1570   char *keystring;
1571
1572     if (!spi_dbus_message_iter_get_struct(&iter_array, DBUS_TYPE_INT32, &kd->keycode, DBUS_TYPE_INT32, &kd->keysym, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_INVALID))
1573     {
1574       break;
1575     }
1576     kd->keystring = g_strdup (keystring);
1577     keys = g_slist_append(keys, kd);
1578   }
1579   dbus_message_iter_next(&iter);
1580   dbus_message_iter_get_basic(&iter, &mask);
1581   dbus_message_iter_next(&iter);
1582   dbus_message_iter_get_basic(&iter, &type);
1583   dbus_message_iter_next(&iter);
1584   key_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, NULL);
1585 #ifdef SPI_DEREGISTER_DEBUG
1586   fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
1587            (void *) l, (unsigned long) mask->value);
1588 #endif
1589
1590   spi_deregister_controller_key_listener (controller, key_listener);
1591
1592   spi_dec_listener_free ((DEControllerListener *) key_listener);
1593   reply = dbus_message_new_method_return (message);
1594   return reply;
1595 }
1596
1597 /*
1598  * DBus Accessibility::DEController::DeregisterDeviceEventListener
1599  *     method implementation
1600  */
1601 static DBusMessage *
1602 impl_deregister_device_event_listener (DBusConnection *bus,
1603                                   DBusMessage *message,
1604                                   void *user_data)
1605 {
1606   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1607   DEControllerListener *listener;
1608   const char *path;
1609   dbus_int32_t event_types;
1610   DBusMessage *reply = NULL;
1611
1612   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID))
1613   {
1614     return invalid_arguments_error (message);
1615   }
1616   listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types);
1617   spi_controller_deregister_device_listener (
1618           controller, listener);
1619   reply = dbus_message_new_method_return (message);
1620   return reply;
1621 }
1622
1623 static DBusMessage *
1624 impl_get_keystroke_listeners (DBusConnection *bus,
1625                                   DBusMessage *message,
1626                                   void *user_data)
1627 {
1628   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1629   DBusMessageIter iter, iter_array;
1630   DBusMessage *reply = dbus_message_new_method_return (message);
1631   GList *l;
1632
1633   if (!reply)
1634     return NULL;
1635
1636   dbus_message_iter_init_append (reply, &iter);
1637   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1638                                     "(souua(iisi)u(bbb))", &iter_array);
1639   for (l = controller->key_listeners; l; l = l->next)
1640   {
1641     append_keystroke_listener (&iter_array, l->data);
1642   }
1643   dbus_message_iter_close_container (&iter, &iter_array);
1644   return reply;
1645 }
1646
1647 static DBusMessage *
1648 impl_get_device_event_listeners (DBusConnection *bus,
1649                                   DBusMessage *message,
1650                                   void *user_data)
1651 {
1652   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1653   DBusMessageIter iter, iter_array;
1654   GList *l;
1655   DBusMessage *reply = dbus_message_new_method_return (message);
1656
1657   if (!reply)
1658     return NULL;
1659
1660   dbus_message_iter_init_append (reply, &iter);
1661   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1662                                     "(sou)", &iter_array);
1663   for (l = controller->key_listeners; l; l = l->next)
1664   {
1665     append_mouse_listener (&iter_array, l->data);
1666   }
1667   dbus_message_iter_close_container (&iter, &iter_array);
1668   return reply;
1669 }
1670
1671 static unsigned
1672 get_modifier_state (SpiDEController *controller)
1673 {
1674         return mouse_mask_state;
1675 }
1676
1677 gboolean
1678 spi_dec_synth_keysym (SpiDEController *controller, long keysym)
1679 {
1680         long key_synth_code;
1681         unsigned int modifiers, synth_mods, lock_mods;
1682
1683         key_synth_code = spi_dec_plat_get_keycode (controller, keysym, NULL, TRUE, &synth_mods);
1684
1685         if ((key_synth_code == 0) || (synth_mods == 0xFF)) return FALSE;
1686
1687         /* TODO: set the modifiers accordingly! */
1688         modifiers = get_modifier_state (controller);
1689         /* side-effect; we may unset mousebutton modifiers here! */
1690
1691         lock_mods = 0;
1692         if (synth_mods != modifiers) {
1693                 lock_mods = synth_mods & ~modifiers;
1694                 spi_dec_plat_lock_modifiers (controller, lock_mods);
1695         }
1696         spi_dec_plat_synth_keycode_press (controller, key_synth_code);
1697         spi_dec_plat_synth_keycode_release (controller, key_synth_code);
1698
1699         if (synth_mods != modifiers) 
1700                 spi_dec_plat_unlock_modifiers (controller, lock_mods);
1701         return TRUE;
1702 }
1703
1704
1705
1706 /*
1707  * DBus Accessibility::DEController::RegisterKeystrokeListener
1708  *     method implementation
1709  */
1710 static DBusMessage *
1711 impl_generate_keyboard_event (DBusConnection *bus, DBusMessage *message, void *user_data)
1712 {
1713   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1714   dbus_int32_t keycode;
1715   char *keystring;
1716   dbus_uint32_t synth_type;
1717   DBusMessage *reply = NULL;
1718
1719   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &keycode, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_UINT32, &synth_type, DBUS_TYPE_INVALID))
1720   {
1721     return invalid_arguments_error (message);
1722   }
1723
1724 #ifdef SPI_DEBUG
1725         fprintf (stderr, "synthesizing keystroke %ld, type %d\n",
1726                  (long) keycode, (int) synth_type);
1727 #endif
1728   /* TODO: hide/wrap/remove X dependency */
1729
1730   /*
1731    * TODO: when initializing, query for XTest extension before using,
1732    * and fall back to XSendEvent() if XTest is not available.
1733    */
1734   
1735   switch (synth_type)
1736     {
1737       case Accessibility_KEY_PRESS:
1738               spi_dec_plat_synth_keycode_press (controller, keycode);
1739               break;
1740       case Accessibility_KEY_PRESSRELEASE:
1741               spi_dec_plat_synth_keycode_press (controller, keycode);
1742       case Accessibility_KEY_RELEASE:
1743               spi_dec_plat_synth_keycode_release (controller, keycode);
1744               break;
1745       case Accessibility_KEY_SYM:
1746 #ifdef SPI_XKB_DEBUG          
1747               fprintf (stderr, "KeySym synthesis\n");
1748 #endif
1749               /* 
1750                * note: we are using long for 'keycode'
1751                * in our arg list; it can contain either
1752                * a keycode or a keysym.
1753                */
1754               spi_dec_synth_keysym (controller, (KeySym) keycode);
1755               break;
1756       case Accessibility_KEY_STRING:
1757               if (!spi_dec_plat_synth_keystring (controller, synth_type, keycode, keystring))
1758                       fprintf (stderr, "Keystring synthesis failure, string=%s\n",
1759                                keystring);
1760               break;
1761     }
1762   reply = dbus_message_new_method_return (message);
1763   return reply;
1764 }
1765
1766 /* Accessibility::DEController::GenerateMouseEvent */
1767 static DBusMessage *
1768 impl_generate_mouse_event (DBusConnection *bus, DBusMessage *message, void *user_data)
1769 {
1770   dbus_int32_t       x;
1771   dbus_int32_t       y;
1772   char *eventName;
1773   DBusMessage *reply = NULL;
1774
1775   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_STRING, &eventName, DBUS_TYPE_INVALID))
1776   {
1777     return invalid_arguments_error (message);
1778   }
1779
1780 #ifdef SPI_DEBUG
1781   fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
1782            eventName, (long int) x, (long int) y);
1783 #endif
1784   spi_dec_plat_generate_mouse_event (saved_controller, x, y, eventName);
1785   reply = dbus_message_new_method_return (message);
1786   return reply;
1787 }
1788
1789 /* Accessibility::DEController::NotifyListenersSync */
1790 static DBusMessage *
1791 impl_notify_listeners_sync (DBusConnection *bus, DBusMessage *message, void *user_data)
1792 {
1793   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1794   Accessibility_DeviceEvent event;
1795   dbus_bool_t ret;
1796   DBusMessage *reply = NULL;
1797
1798   if (!spi_dbus_demarshal_deviceEvent(message, &event))
1799   {
1800     return invalid_arguments_error (message);
1801   }
1802 #ifdef SPI_DEBUG
1803   g_print ("notifylistening listeners synchronously: controller %p, event id %d\n",
1804            controller, (int) event.id);
1805 #endif
1806   ret = spi_controller_notify_keylisteners (controller,
1807                                              (Accessibility_DeviceEvent *) 
1808                                              &event, FALSE) ?
1809           TRUE : FALSE; 
1810   reply = dbus_message_new_method_return (message);
1811   if (reply)
1812   {
1813     dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1814   }
1815   return reply;
1816 }
1817
1818 static DBusMessage *
1819 impl_notify_listeners_async (DBusConnection *bus, DBusMessage *message, void *user_data)
1820 {
1821   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1822   Accessibility_DeviceEvent event;
1823   DBusMessage *reply = NULL;
1824
1825   if (!spi_dbus_demarshal_deviceEvent(message, &event))
1826   {
1827     return invalid_arguments_error (message);
1828   }
1829 #ifdef SPI_DEBUG
1830   g_print ("notifylistening listeners asynchronously: controller %p, event id %d\n",
1831            controller, (int) event.id);
1832 #endif
1833   spi_controller_notify_keylisteners (controller, (Accessibility_DeviceEvent *)
1834                                       &event, FALSE); 
1835   reply = dbus_message_new_method_return (message);
1836   return reply;
1837 }
1838
1839 static void
1840 spi_device_event_controller_class_init (SpiDEControllerClass *klass)
1841 {
1842   GObjectClass * object_class = (GObjectClass *) klass;
1843
1844   spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
1845
1846   object_class->finalize = spi_device_event_controller_object_finalize;
1847
1848 #ifdef HAVE_X11
1849   if (g_getenv ("DISPLAY"))
1850     spi_dec_setup_x11 (klass);
1851   else
1852 #endif
1853   g_type_class_add_private (object_class, sizeof (long)); /* dummy */
1854 }
1855
1856 static void
1857 spi_device_event_controller_init (SpiDEController *device_event_controller)
1858 {
1859   SpiDEControllerClass *klass;
1860   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (device_event_controller);
1861
1862   /* TODO: shouldn't be gpointer below */
1863   device_event_controller->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_event_controller,
1864                                               SPI_DEVICE_EVENT_CONTROLLER_TYPE,
1865                                               gpointer);
1866   device_event_controller->message_queue = g_queue_new ();
1867   saved_controller = device_event_controller;
1868
1869   if (klass->plat.init)
1870     klass->plat.init (device_event_controller);
1871 }
1872
1873
1874 /*---------------------------------------------------------------------------*/
1875
1876 static const char *introspection_header =
1877 "<?xml version=\"1.0\"?>\n";
1878
1879 static const char *introspection_node_element =
1880 "<node name=\"%s\">\n";
1881
1882 static const char *introspection_footer =
1883 "</node>";
1884
1885 static DBusMessage *
1886 impl_Introspect (DBusConnection * bus,
1887                  DBusMessage * message, void *user_data)
1888 {
1889   GString *output;
1890   gchar *final;
1891
1892   const gchar *pathstr = SPI_DBUS_PATH_DEC;
1893
1894   DBusMessage *reply;
1895
1896   output = g_string_new(introspection_header);
1897
1898   g_string_append_printf(output, introspection_node_element, pathstr);
1899
1900   g_string_append (output, spi_org_a11y_atspi_DeviceEventController);
1901
1902   g_string_append(output, introspection_footer);
1903   final = g_string_free(output, FALSE);
1904
1905   reply = dbus_message_new_method_return (message);
1906   dbus_message_append_args(reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID);
1907
1908   g_free(final);
1909   return reply;
1910 }
1911
1912 /*---------------------------------------------------------------------------*/
1913
1914 static void
1915 handle_dec_method_from_idle (DBusConnection *bus, DBusMessage *message, void *user_data)
1916 {
1917   const gchar *iface   = dbus_message_get_interface (message);
1918   const gchar *member  = dbus_message_get_member (message);
1919   DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1920   DBusMessage *reply = NULL;
1921
1922   if (!strcmp (iface, SPI_DBUS_INTERFACE_DEC))
1923     {
1924       result = DBUS_HANDLER_RESULT_HANDLED;
1925       if      (!strcmp (member, "RegisterKeystrokeListener"))
1926           reply = impl_register_keystroke_listener (bus, message, user_data);
1927       else if (!strcmp (member, "RegisterDeviceEventListener"))
1928           reply = impl_register_device_event_listener (bus, message, user_data);
1929       else if (!strcmp (member, "DeregisterKeystrokeListener"))
1930           reply = impl_deregister_keystroke_listener (bus, message, user_data);
1931       else if (!strcmp (member, "DeregisterDeviceEventListener"))
1932           reply = impl_deregister_device_event_listener (bus, message, user_data);
1933       else if (!strcmp (member, "GetKeystrokeListeners"))
1934           reply = impl_get_keystroke_listeners (bus, message, user_data);
1935       else if (!strcmp (member, "GetDeviceEventListeners"))
1936           reply = impl_get_device_event_listeners (bus, message, user_data);
1937       else if (!strcmp (member, "GenerateKeyboardEvent"))
1938           reply = impl_generate_keyboard_event (bus, message, user_data);
1939       else if (!strcmp (member, "GenerateMouseEvent"))
1940           reply = impl_generate_mouse_event (bus, message, user_data);
1941       else if (!strcmp (member, "NotifyListenersSync"))
1942           reply = impl_notify_listeners_sync (bus, message, user_data);
1943       else if (!strcmp (member, "NotifyListenersAsync"))
1944           reply = impl_notify_listeners_async (bus, message, user_data);
1945       else
1946           result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1947     }
1948
1949   if (!strcmp (iface, "org.freedesktop.DBus.Introspectable"))
1950     {
1951       result = DBUS_HANDLER_RESULT_HANDLED;
1952       if      (!strcmp (member, "Introspect"))
1953           reply = impl_Introspect (bus, message, user_data);
1954       else
1955           result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1956     }
1957
1958   if (result == DBUS_HANDLER_RESULT_HANDLED)
1959     {
1960       if (!reply)
1961         {
1962           reply = dbus_message_new_method_return (message);
1963         }
1964
1965       dbus_connection_send (bus, reply, NULL);
1966       dbus_message_unref (reply);
1967     }
1968 }
1969
1970 static gboolean
1971 message_queue_dispatch (gpointer data)
1972 {
1973   saved_controller->message_queue_idle = 0;
1974   while (!g_queue_is_empty (saved_controller->message_queue))
1975     {
1976       DBusMessage *message = g_queue_pop_head (saved_controller->message_queue);
1977       data = g_queue_pop_head (saved_controller->message_queue);
1978       handle_dec_method_from_idle (saved_controller->bus, message, data);
1979       dbus_message_unref (message);
1980     }
1981   return FALSE;
1982 }
1983
1984 static DBusHandlerResult
1985 handle_dec_method (DBusConnection *bus, DBusMessage *message, void *user_data)
1986 {
1987   const gchar *iface   = dbus_message_get_interface (message);
1988   const gchar *member  = dbus_message_get_member (message);
1989   const gint   type    = dbus_message_get_type (message);
1990
1991   /* Check for basic reasons not to handle */
1992   if (type   != DBUS_MESSAGE_TYPE_METHOD_CALL ||
1993       member == NULL ||
1994       iface  == NULL)
1995       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1996
1997   dbus_message_ref (message);
1998   g_queue_push_tail (saved_controller->message_queue, message);
1999   g_queue_push_tail (saved_controller->message_queue, user_data);
2000   if (!saved_controller->message_queue_idle) {
2001     saved_controller->message_queue_idle = g_idle_add (message_queue_dispatch, NULL);
2002     g_source_set_name_by_id (saved_controller->message_queue_idle, "[at-spi2-core] message_queue_dispatch");
2003   }
2004   return DBUS_HANDLER_RESULT_HANDLED;
2005 }
2006
2007 static DBusObjectPathVTable dec_vtable =
2008 {
2009   NULL,
2010   &handle_dec_method,
2011   NULL, NULL, NULL, NULL
2012 };
2013
2014 SpiDEController *
2015 spi_registry_dec_new (SpiRegistry *reg, DBusConnection *bus)
2016 {
2017   SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
2018
2019   dec->registry = g_object_ref (reg);
2020   reg->dec = g_object_ref (dec);
2021   dec->bus = bus;
2022
2023   dbus_connection_register_object_path (bus, SPI_DBUS_PATH_DEC, &dec_vtable, dec);
2024
2025   return dec;
2026 }
2027
2028 void
2029 spi_device_event_controller_start_poll_mouse (SpiRegistry *registry)
2030 {
2031   if (!have_mouse_event_listener)
2032     {
2033       have_mouse_event_listener = TRUE;
2034       if (!have_mouse_listener) {
2035         guint id;
2036         id = g_timeout_add (100, spi_dec_poll_mouse_idle, registry->dec);
2037         g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle");
2038       }
2039     }
2040 }
2041
2042 void
2043 spi_device_event_controller_stop_poll_mouse (void)
2044 {
2045   have_mouse_event_listener = FALSE;
2046 }