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