Merge branch 'upstream/2.26.1' into tizen
[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         dbus_bool_t result;
931         gchar *bus_name_dup;
932         dbus_message_ref (message);
933         dbus_pending_call_set_notify (pending, reset_hung_process, message,
934                                       (DBusFreeFunction) dbus_message_unref);
935         message = dbus_message_new_method_call (dest, "/",
936                                                 "org.freedesktop.DBus.Peer",
937                                                 "Ping");
938         if (!message)
939           return NULL;
940         result = dbus_connection_send_with_reply (bus, message, &pending, -1);
941         dbus_message_unref (message);
942         if (!result || !pending)
943           return NULL;
944         bus_name_dup = g_strdup (dest);
945         dbus_pending_call_set_notify (pending, reset_hung_process_from_ping,
946                                       bus_name_dup, NULL);
947         for (l = hung_processes; l; l = l->next)
948           if (!strcmp (l->data, dest))
949             return NULL;
950         hung_processes = g_slist_prepend (hung_processes, g_strdup (dest));
951         return NULL;
952       }
953     }
954     dbus_pending_call_unref (pending);
955     return reply;
956 }
957 static gboolean
958 Accessibility_DeviceEventListener_NotifyEvent(SpiDEController *controller,
959                                               SpiRegistry *registry,
960                                               DEControllerListener *listener,
961                                               const Accessibility_DeviceEvent *key_event)
962 {
963   DBusMessage *message = dbus_message_new_method_call(listener->bus_name,
964                                                       listener->path,
965                                                       SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER,
966                                                       "NotifyEvent");
967   dbus_bool_t consumed = FALSE;
968   GSList *l;
969   gboolean hung = FALSE;
970
971   for (l = hung_processes; l; l = l->next)
972   {
973     if (!strcmp (l->data, listener->bus_name))
974     {
975       dbus_message_set_no_reply (message, TRUE);
976       hung = TRUE;
977       break;
978     }
979   }
980
981   if (spi_dbus_marshal_deviceEvent(message, key_event))
982   {
983     DBusMessage *reply;
984
985     if (hung)
986     {
987       dbus_connection_send (controller->bus, message, NULL);
988       dbus_message_unref (message);
989       return FALSE;
990     }
991
992     reply = send_and_allow_reentry (controller->bus, message, 3000, NULL);
993     if (reply)
994     {
995       dbus_message_get_args(reply, NULL, DBUS_TYPE_BOOLEAN, &consumed, DBUS_TYPE_INVALID);
996       dbus_message_unref(reply);
997     }
998   }
999   dbus_message_unref(message);
1000   return consumed;
1001 }
1002
1003 gboolean
1004 spi_controller_notify_mouselisteners (SpiDEController                 *controller,
1005                                       const Accessibility_DeviceEvent *event)
1006 {
1007   GList   *l;
1008   GSList  *notify = NULL, *l2;
1009   GList  **listeners = &controller->mouse_listeners;
1010   gboolean is_consumed;
1011 #ifdef SPI_KEYEVENT_DEBUG
1012   gboolean found = FALSE;
1013 #endif
1014   if (!listeners)
1015     {
1016       return FALSE;
1017     }
1018
1019   for (l = *listeners; l; l = l->next)
1020     {
1021        DEControllerListener *listener = l->data;
1022
1023        if (eventtype_seq_contains_event (listener->types, event))
1024          {
1025            /* we clone (don't dup) the listener, to avoid refcount inc. */
1026            notify = g_slist_prepend (notify,
1027                                      spi_listener_clone (listener));
1028 #ifdef SPI_KEYEVENT_DEBUG
1029            found = TRUE;
1030 #endif
1031          }
1032     }
1033
1034 #ifdef SPI_KEYEVENT_DEBUG
1035   if (!found)
1036     {
1037       g_print ("no match for event\n");
1038     }
1039 #endif
1040
1041   is_consumed = FALSE;
1042   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1043     {
1044       DEControllerListener *listener = l2->data;
1045
1046       is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, listener, event);
1047
1048       spi_listener_clone_free ((DEControllerListener *) l2->data);
1049     }
1050
1051   for (; l2; l2 = l2->next)
1052     {
1053       DEControllerListener *listener = l2->data;
1054       spi_listener_clone_free (listener);
1055       /* clone doesn't have its own ref, so don't use spi_device_listener_free */
1056     }
1057
1058   g_slist_free (notify);
1059
1060 #ifdef SPI_DEBUG
1061   if (is_consumed) g_message ("consumed\n");
1062 #endif
1063   return is_consumed;
1064 }
1065
1066 static gboolean
1067 key_set_contains_key (GSList                          *key_set,
1068                           const Accessibility_DeviceEvent *key_event)
1069 {
1070   gint i;
1071   gint len;
1072   GSList *l;
1073
1074   if (!key_set)
1075     {
1076 #ifdef SPI_DEBUG
1077       g_print ("null key set!\n");
1078 #endif
1079       return TRUE;
1080     }
1081
1082   len = g_slist_length (key_set);
1083   
1084   if (len == 0) /* special case, means "all keys/any key" */
1085     {
1086 #ifdef SPI_DEBUG
1087       g_print ("anykey\n");         
1088 #endif
1089       return TRUE;
1090     }
1091
1092   for (l = key_set,i = 0; l; l = g_slist_next(l),i++)
1093     {
1094       Accessibility_KeyDefinition *kd = l->data;
1095 #ifdef SPI_KEYEVENT_DEBUG           
1096       g_print ("key_set[%d] event = %d, code = %d; key_event %d, code %d, string %s\n",
1097                 i,
1098                 (int) kd->keysym,
1099                 (int) kd->keycode,
1100                 (int) key_event->id,
1101                 (int) key_event->hw_code,
1102                 key_event->event_string); 
1103 #endif
1104       if (kd->keysym == (dbus_uint32_t) key_event->id)
1105         {
1106           return TRUE;
1107         }
1108       if (kd->keycode == (dbus_uint32_t) key_event->hw_code)
1109         {
1110           return TRUE;
1111         }
1112       if (key_event->event_string && key_event->event_string[0] &&
1113           !strcmp (kd->keystring, key_event->event_string))
1114         {
1115           return TRUE;
1116         }
1117     }
1118
1119   return FALSE;
1120 }
1121
1122 static gboolean
1123 eventtype_seq_contains_event (dbus_uint32_t types,
1124                                   const Accessibility_DeviceEvent *event)
1125 {
1126   if (types == 0) /* special case, means "all events/any event" */
1127     {
1128       return TRUE;
1129     }
1130
1131   return (types & (1 << event->type));
1132 }
1133
1134 static gboolean
1135 spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event,
1136                                 DEControllerKeyListener         *listener,
1137                                 dbus_bool_t                    is_system_global)
1138 {
1139   if (((key_event->modifiers & 0xFF) == (dbus_uint16_t) (listener->mask & 0xFF)) &&
1140        key_set_contains_key (listener->keys, key_event) &&
1141        eventtype_seq_contains_event (listener->listener.types, key_event) && 
1142       (is_system_global == listener->mode->global))
1143     {
1144       return TRUE;
1145     }
1146   else
1147     {
1148       return FALSE;
1149     }
1150 }
1151
1152 gboolean
1153 spi_controller_notify_keylisteners (SpiDEController                 *controller,
1154                                     Accessibility_DeviceEvent       *key_event,
1155                                     dbus_bool_t                    is_system_global)
1156 {
1157   GList   *l;
1158   GSList  *notify = NULL, *l2;
1159   GList  **key_listeners = &controller->key_listeners;
1160   gboolean is_consumed;
1161
1162   if (!key_listeners)
1163     {
1164       return FALSE;
1165     }
1166
1167   /* set the NUMLOCK event mask bit if appropriate: see bug #143702 */
1168   if (key_event->modifiers & _numlock_physical_mask)
1169       key_event->modifiers |= SPI_KEYMASK_NUMLOCK;
1170
1171   for (l = *key_listeners; l; l = l->next)
1172     {
1173        DEControllerKeyListener *key_listener = l->data;
1174
1175        if (spi_key_event_matches_listener (key_event, key_listener, is_system_global))
1176          {
1177            /* we clone (don't dup) the listener, to avoid refcount inc. */
1178            notify = g_slist_prepend (notify,
1179                                      spi_key_listener_clone (key_listener));
1180          }
1181     }
1182
1183 #ifdef SPI_KEYEVENT_DEBUG
1184   if (!notify)
1185     {
1186       g_print ("no match for event\n");
1187     }
1188 #endif
1189
1190   is_consumed = FALSE;
1191   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1192     {
1193       DEControllerKeyListener *key_listener = l2->data;     
1194
1195       is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, &key_listener->listener, key_event) &&
1196                     key_listener->mode->preemptive;
1197
1198       spi_key_listener_clone_free (key_listener);
1199     }
1200
1201   for (; l2; l2 = l2->next)
1202     {
1203       DEControllerKeyListener *key_listener = l2->data;     
1204       spi_key_listener_clone_free (key_listener);
1205       /* clone doesn't have its own ref, so don't use spi_dec_listener_free */
1206     }
1207
1208   g_slist_free (notify);
1209
1210 #ifdef SPI_DEBUG
1211   if (is_consumed) g_message ("consumed\n");
1212 #endif
1213   return is_consumed;
1214 }
1215
1216 gboolean
1217 spi_clear_error_state (void)
1218 {
1219         gboolean retval = spi_error_code != 0;
1220         spi_error_code = 0;
1221         return retval;
1222 }
1223
1224 gboolean
1225 spi_controller_update_key_grabs (SpiDEController           *controller,
1226                                  Accessibility_DeviceEvent *recv)
1227 {
1228   GList *l, *next;
1229   gboolean   update_failed = FALSE;
1230   long keycode = 0;
1231   
1232   g_return_val_if_fail (controller != NULL, FALSE);
1233
1234   /*
1235    * masks known to work with default RH 7.1+:
1236    * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
1237    * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
1238    * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
1239    * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
1240    *
1241    * ControlMask grabs are broken, must be in use already
1242    */
1243   if (recv)
1244     keycode = spi_dec_plat_get_keycode (controller, recv->id, NULL, TRUE, NULL);
1245   for (l = controller->keygrabs_list; l; l = next)
1246     {
1247       gboolean do_remove;
1248       gboolean re_issue_grab;
1249       DEControllerGrabMask *grab_mask = l->data;
1250
1251       next = l->next;
1252
1253       re_issue_grab = recv &&
1254               (recv->modifiers & grab_mask->mod_mask) &&
1255               (grab_mask->key_val == keycode);
1256
1257 #ifdef SPI_DEBUG
1258       fprintf (stderr, "mask=%lx %lx (%c%c) %s\n",
1259                (long int) grab_mask->key_val,
1260                (long int) grab_mask->mod_mask,
1261                grab_mask->pending_add ? '+' : '.',
1262                grab_mask->pending_remove ? '-' : '.',
1263                re_issue_grab ? "re-issue": "");
1264 #endif
1265
1266       do_remove = FALSE;
1267
1268       if (grab_mask->pending_add && grab_mask->pending_remove)
1269         {
1270           do_remove = TRUE;
1271         }
1272       else if (grab_mask->pending_remove)
1273         {
1274 #ifdef SPI_DEBUG
1275       fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask);
1276 #endif
1277           spi_dec_plat_ungrab_key (controller,
1278                                grab_mask->key_val,
1279                                grab_mask->mod_mask);
1280
1281           do_remove = TRUE;
1282         }
1283       else if (grab_mask->pending_add || re_issue_grab)
1284         {
1285
1286 #ifdef SPI_DEBUG
1287           fprintf (stderr, "grab %d with mask %x\n", grab_mask->key_val, grab_mask->mod_mask);
1288 #endif
1289           update_failed = spi_dec_plat_grab_key (controller,
1290                                                grab_mask->key_val,
1291                                                grab_mask->mod_mask);
1292           if (update_failed) {
1293                   while (grab_mask->ref_count > 0) --grab_mask->ref_count;
1294                   do_remove = TRUE;
1295           }
1296         }
1297
1298       grab_mask->pending_add = FALSE;
1299       grab_mask->pending_remove = FALSE;
1300
1301       if (do_remove)
1302         {
1303           g_assert (grab_mask->ref_count <= 0);
1304
1305           controller->keygrabs_list = g_list_delete_link (
1306             controller->keygrabs_list, l);
1307
1308           spi_grab_mask_free (grab_mask);
1309         }
1310
1311     } 
1312
1313   return ! update_failed;
1314 }
1315
1316 /*
1317  * Implemented GObject::finalize
1318  */
1319 static void
1320 spi_device_event_controller_object_finalize (GObject *object)
1321 {
1322   SpiDEController *controller;
1323   GObjectClass *parent_class = G_OBJECT_CLASS(spi_device_event_controller_parent_class);
1324   SpiDEControllerClass *klass;
1325
1326   controller = SPI_DEVICE_EVENT_CONTROLLER (object);
1327   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller);
1328 #ifdef SPI_DEBUG
1329   fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
1330 #endif
1331   if (klass->plat.finalize)
1332     klass->plat.finalize (controller);
1333
1334   parent_class->finalize (object);
1335 }
1336
1337 /*
1338  * DBus Accessibility::DEController::RegisterKeystrokeListener
1339  *     method implementation
1340  */
1341 static DBusMessage *
1342 impl_register_keystroke_listener (DBusConnection *bus,
1343                                   DBusMessage *message,
1344                                   void *user_data)
1345 {
1346   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1347   DEControllerKeyListener *dec_listener;
1348   DBusMessageIter iter, iter_array;
1349   const char *path;
1350   GSList *keys = NULL;
1351   dbus_int32_t mask, type;
1352   Accessibility_EventListenerMode *mode;
1353  dbus_bool_t ret;
1354   DBusMessage *reply = NULL;
1355   char *keystring;
1356
1357   if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu(bbb)") != 0)
1358     return invalid_arguments_error (message);
1359
1360   dbus_message_iter_init(message, &iter);
1361   dbus_message_iter_get_basic(&iter, &path);
1362   dbus_message_iter_next(&iter);
1363   dbus_message_iter_recurse(&iter, &iter_array);
1364   while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID)
1365   {
1366     Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
1367     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))
1368     {
1369       g_free (kd);
1370       break;
1371     }
1372     kd->keystring = g_strdup (keystring);
1373     keys = g_slist_append(keys, kd);
1374   }
1375   dbus_message_iter_next(&iter);
1376   dbus_message_iter_get_basic(&iter, &mask);
1377   dbus_message_iter_next(&iter);
1378   dbus_message_iter_get_basic(&iter, &type);
1379   dbus_message_iter_next(&iter);
1380   mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode));
1381   if (mode)
1382   {
1383     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);
1384   }
1385 #ifdef SPI_DEBUG
1386   fprintf (stderr, "registering keystroke listener %s:%s with maskVal %lu\n",
1387            dbus_message_get_sender(message), path, (unsigned long) mask);
1388 #endif
1389   dec_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, mode);
1390   g_free (mode);
1391   ret = spi_controller_register_device_listener (
1392           controller, (DEControllerListener *) dec_listener);
1393   reply = dbus_message_new_method_return (message);
1394   if (reply)
1395   {
1396     dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1397   }
1398   return reply;
1399 }
1400
1401 /*
1402  * DBus Accessibility::DEController::RegisterDeviceEventListener
1403  *     method implementation
1404  */
1405 static DBusMessage *
1406 impl_register_device_event_listener (DBusConnection *bus,
1407                                   DBusMessage *message,
1408                                   void *user_data)
1409 {
1410   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1411   DEControllerListener *dec_listener;
1412   const char *path;
1413   dbus_int32_t event_types;
1414   dbus_bool_t ret;
1415   DBusMessage *reply = NULL;
1416
1417   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID))
1418   {
1419     return invalid_arguments_error (message);
1420   }
1421   dec_listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types);
1422   ret =  spi_controller_register_device_listener (
1423           controller, (DEControllerListener *) dec_listener);
1424   reply = dbus_message_new_method_return (message);
1425   if (reply)
1426   {
1427     dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1428   }
1429   return reply;
1430 }
1431
1432 typedef struct {
1433         DBusConnection *bus;
1434         DEControllerListener    *listener;
1435 } RemoveListenerClosure;
1436
1437 static SpiReEntrantContinue
1438 remove_listener_cb (GList * const *list,
1439                     gpointer       user_data)
1440 {
1441   DEControllerListener  *listener = (*list)->data;
1442   RemoveListenerClosure *ctx = user_data;
1443
1444   if (!strcmp(ctx->listener->bus_name, listener->bus_name) &&
1445       !strcmp(ctx->listener->path, listener->path))
1446     {
1447       spi_re_entrant_list_delete_link (list);
1448       spi_dbus_remove_disconnect_match (ctx->bus, listener->bus_name);
1449       spi_dec_listener_free (listener);
1450     }
1451
1452   return SPI_RE_ENTRANT_CONTINUE;
1453 }
1454
1455 static SpiReEntrantContinue
1456 copy_key_listener_cb (GList * const *list,
1457                       gpointer       user_data)
1458 {
1459   DEControllerKeyListener  *key_listener = (*list)->data;
1460   RemoveListenerClosure    *ctx = user_data;
1461
1462   if (!strcmp(ctx->listener->bus_name, key_listener->listener.bus_name) &&
1463       !strcmp(ctx->listener->path, key_listener->listener.path))
1464     {
1465       /* TODO: FIXME aggregate keys in case the listener is registered twice */
1466       DEControllerKeyListener *ctx_key_listener = 
1467         (DEControllerKeyListener *) ctx->listener; 
1468       keylist_free (ctx_key_listener->keys);        
1469       ctx_key_listener->keys = keylist_clone(key_listener->keys);
1470     }
1471
1472   return SPI_RE_ENTRANT_CONTINUE;
1473 }
1474
1475 static void
1476 spi_controller_deregister_device_listener (SpiDEController            *controller,
1477                                            DEControllerListener *listener)
1478 {
1479   RemoveListenerClosure  ctx;
1480
1481   ctx.bus = controller->bus;
1482   ctx.listener = listener;
1483
1484   notify_mouse_listener (controller, listener, FALSE);
1485
1486   spi_re_entrant_list_foreach (&controller->mouse_listeners,
1487                                remove_listener_cb, &ctx);
1488   if (!controller->mouse_listeners)
1489     have_mouse_listener = FALSE;
1490 }
1491
1492 static void
1493 spi_deregister_controller_key_listener (SpiDEController            *controller,
1494                                         DEControllerKeyListener    *key_listener)
1495 {
1496   RemoveListenerClosure  ctx;
1497
1498   ctx.bus = controller->bus;
1499   ctx.listener = (DEControllerListener *) spi_key_listener_clone (key_listener);
1500
1501   notify_keystroke_listener (controller, key_listener, FALSE);
1502
1503   /* special case, copy keyset from existing controller list entry */
1504   if (g_slist_length(key_listener->keys) == 0)
1505     {
1506       spi_re_entrant_list_foreach (&controller->key_listeners,
1507                                   copy_key_listener_cb, &ctx);
1508     }
1509
1510   spi_controller_deregister_global_keygrabs (controller, key_listener);
1511
1512   spi_re_entrant_list_foreach (&controller->key_listeners,
1513                                 remove_listener_cb, &ctx);
1514
1515   spi_key_listener_clone_free ((DEControllerKeyListener *) ctx.listener);
1516 }
1517
1518 void
1519 spi_remove_device_listeners (SpiDEController *controller, const char *bus_name)
1520 {
1521   GList *l, *tmp;
1522
1523   for (l = controller->mouse_listeners; l; l = tmp)
1524   {
1525     DEControllerListener *listener = l->data;
1526     tmp = l->next;
1527     if (!strcmp (listener->bus_name, bus_name))
1528     {
1529       spi_controller_deregister_device_listener (controller, listener);
1530       tmp = controller->mouse_listeners;
1531     }
1532   }
1533   for (l = controller->key_listeners; l; l = tmp)
1534   {
1535     DEControllerKeyListener *key_listener = l->data;
1536     tmp = l->next;
1537     if (!strcmp (key_listener->listener.bus_name, bus_name))
1538     {
1539       /* TODO: untangle the below line(s) */
1540       spi_deregister_controller_key_listener (controller, key_listener);
1541       tmp = controller->key_listeners;
1542     }
1543   }
1544 }
1545
1546 /*
1547  * DBus Accessibility::DEController::DeregisterKeystrokeListener
1548  *     method implementation
1549  */
1550 static DBusMessage *
1551 impl_deregister_keystroke_listener (DBusConnection *bus,
1552                                   DBusMessage *message,
1553                                   void *user_data)
1554 {
1555   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1556   DEControllerKeyListener *key_listener;
1557   DBusMessageIter iter, iter_array;
1558   const char *path;
1559   GSList *keys = NULL;
1560   dbus_int32_t mask, type;
1561   DBusMessage *reply = NULL;
1562
1563   dbus_message_iter_init(message, &iter);
1564   if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu") != 0)
1565   {
1566     g_warning ("Received DeregisterKeystrokeListener with strange signature '%s'", dbus_message_get_signature (message));
1567     return invalid_arguments_error (message);
1568   }
1569
1570   dbus_message_iter_get_basic(&iter, &path);
1571   dbus_message_iter_next(&iter);
1572   dbus_message_iter_recurse(&iter, &iter_array);
1573   while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID)
1574   {
1575     Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition));
1576   char *keystring;
1577
1578     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))
1579     {
1580       g_free(kd);
1581       break;
1582     }
1583     kd->keystring = g_strdup (keystring);
1584     keys = g_slist_append(keys, kd);
1585   }
1586   dbus_message_iter_next(&iter);
1587   dbus_message_iter_get_basic(&iter, &mask);
1588   dbus_message_iter_next(&iter);
1589   dbus_message_iter_get_basic(&iter, &type);
1590   dbus_message_iter_next(&iter);
1591   key_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, NULL);
1592 #ifdef SPI_DEREGISTER_DEBUG
1593   fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
1594            (void *) l, (unsigned long) mask->value);
1595 #endif
1596
1597   spi_deregister_controller_key_listener (controller, key_listener);
1598
1599   spi_dec_listener_free ((DEControllerListener *) key_listener);
1600   reply = dbus_message_new_method_return (message);
1601   return reply;
1602 }
1603
1604 /*
1605  * DBus Accessibility::DEController::DeregisterDeviceEventListener
1606  *     method implementation
1607  */
1608 static DBusMessage *
1609 impl_deregister_device_event_listener (DBusConnection *bus,
1610                                   DBusMessage *message,
1611                                   void *user_data)
1612 {
1613   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1614   DEControllerListener *listener;
1615   const char *path;
1616   dbus_int32_t event_types;
1617   DBusMessage *reply = NULL;
1618
1619   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID))
1620   {
1621     return invalid_arguments_error (message);
1622   }
1623   listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types);
1624   spi_controller_deregister_device_listener (
1625           controller, listener);
1626   reply = dbus_message_new_method_return (message);
1627   return reply;
1628 }
1629
1630 static DBusMessage *
1631 impl_get_keystroke_listeners (DBusConnection *bus,
1632                                   DBusMessage *message,
1633                                   void *user_data)
1634 {
1635   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1636   DBusMessageIter iter, iter_array;
1637   DBusMessage *reply = dbus_message_new_method_return (message);
1638   GList *l;
1639
1640   if (!reply)
1641     return NULL;
1642
1643   dbus_message_iter_init_append (reply, &iter);
1644   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1645                                     "(souua(iisi)u(bbb))", &iter_array);
1646   for (l = controller->key_listeners; l; l = l->next)
1647   {
1648     append_keystroke_listener (&iter_array, l->data);
1649   }
1650   dbus_message_iter_close_container (&iter, &iter_array);
1651   return reply;
1652 }
1653
1654 static DBusMessage *
1655 impl_get_device_event_listeners (DBusConnection *bus,
1656                                   DBusMessage *message,
1657                                   void *user_data)
1658 {
1659   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1660   DBusMessageIter iter, iter_array;
1661   GList *l;
1662   DBusMessage *reply = dbus_message_new_method_return (message);
1663
1664   if (!reply)
1665     return NULL;
1666
1667   dbus_message_iter_init_append (reply, &iter);
1668   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
1669                                     "(sou)", &iter_array);
1670   for (l = controller->key_listeners; l; l = l->next)
1671   {
1672     append_mouse_listener (&iter_array, l->data);
1673   }
1674   dbus_message_iter_close_container (&iter, &iter_array);
1675   return reply;
1676 }
1677
1678 static unsigned
1679 get_modifier_state (SpiDEController *controller)
1680 {
1681         return mouse_mask_state;
1682 }
1683
1684 gboolean
1685 spi_dec_synth_keysym (SpiDEController *controller, long keysym)
1686 {
1687         long key_synth_code;
1688         unsigned int modifiers, synth_mods, lock_mods;
1689
1690         key_synth_code = spi_dec_plat_get_keycode (controller, keysym, NULL, TRUE, &synth_mods);
1691
1692         if ((key_synth_code == 0) || (synth_mods == 0xFF)) return FALSE;
1693
1694         /* TODO: set the modifiers accordingly! */
1695         modifiers = get_modifier_state (controller);
1696         /* side-effect; we may unset mousebutton modifiers here! */
1697
1698         lock_mods = 0;
1699         if (synth_mods != modifiers) {
1700                 lock_mods = synth_mods & ~modifiers;
1701                 spi_dec_plat_lock_modifiers (controller, lock_mods);
1702         }
1703         spi_dec_plat_synth_keycode_press (controller, key_synth_code);
1704         spi_dec_plat_synth_keycode_release (controller, key_synth_code);
1705
1706         if (synth_mods != modifiers) 
1707                 spi_dec_plat_unlock_modifiers (controller, lock_mods);
1708         return TRUE;
1709 }
1710
1711
1712
1713 /*
1714  * DBus Accessibility::DEController::RegisterKeystrokeListener
1715  *     method implementation
1716  */
1717 static DBusMessage *
1718 impl_generate_keyboard_event (DBusConnection *bus, DBusMessage *message, void *user_data)
1719 {
1720   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1721   dbus_int32_t keycode;
1722   char *keystring;
1723   dbus_uint32_t synth_type;
1724   DBusMessage *reply = NULL;
1725
1726   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &keycode, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_UINT32, &synth_type, DBUS_TYPE_INVALID))
1727   {
1728     return invalid_arguments_error (message);
1729   }
1730
1731 #ifdef SPI_DEBUG
1732         fprintf (stderr, "synthesizing keystroke %ld, type %d\n",
1733                  (long) keycode, (int) synth_type);
1734 #endif
1735   /* TODO: hide/wrap/remove X dependency */
1736
1737   /*
1738    * TODO: when initializing, query for XTest extension before using,
1739    * and fall back to XSendEvent() if XTest is not available.
1740    */
1741   
1742   switch (synth_type)
1743     {
1744       case Accessibility_KEY_PRESS:
1745               spi_dec_plat_synth_keycode_press (controller, keycode);
1746               break;
1747       case Accessibility_KEY_PRESSRELEASE:
1748               spi_dec_plat_synth_keycode_press (controller, keycode);
1749       case Accessibility_KEY_RELEASE:
1750               spi_dec_plat_synth_keycode_release (controller, keycode);
1751               break;
1752       case Accessibility_KEY_SYM:
1753 #ifdef SPI_XKB_DEBUG          
1754               fprintf (stderr, "KeySym synthesis\n");
1755 #endif
1756               /* 
1757                * note: we are using long for 'keycode'
1758                * in our arg list; it can contain either
1759                * a keycode or a keysym.
1760                */
1761               spi_dec_synth_keysym (controller, keycode);
1762               break;
1763       case Accessibility_KEY_STRING:
1764               if (!spi_dec_plat_synth_keystring (controller, synth_type, keycode, keystring))
1765                       fprintf (stderr, "Keystring synthesis failure, string=%s\n",
1766                                keystring);
1767               break;
1768     }
1769   reply = dbus_message_new_method_return (message);
1770   return reply;
1771 }
1772
1773 /* Accessibility::DEController::GenerateMouseEvent */
1774 static DBusMessage *
1775 impl_generate_mouse_event (DBusConnection *bus, DBusMessage *message, void *user_data)
1776 {
1777   dbus_int32_t       x;
1778   dbus_int32_t       y;
1779   char *eventName;
1780   DBusMessage *reply = NULL;
1781
1782   if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_STRING, &eventName, DBUS_TYPE_INVALID))
1783   {
1784     return invalid_arguments_error (message);
1785   }
1786
1787 #ifdef SPI_DEBUG
1788   fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
1789            eventName, (long int) x, (long int) y);
1790 #endif
1791   spi_dec_plat_generate_mouse_event (saved_controller, x, y, eventName);
1792   reply = dbus_message_new_method_return (message);
1793   return reply;
1794 }
1795
1796 /* Accessibility::DEController::NotifyListenersSync */
1797 static DBusMessage *
1798 impl_notify_listeners_sync (DBusConnection *bus, DBusMessage *message, void *user_data)
1799 {
1800   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1801   Accessibility_DeviceEvent event;
1802   dbus_bool_t ret;
1803   DBusMessage *reply = NULL;
1804
1805   if (!spi_dbus_demarshal_deviceEvent(message, &event))
1806   {
1807     return invalid_arguments_error (message);
1808   }
1809 #ifdef SPI_DEBUG
1810   g_print ("notifylistening listeners synchronously: controller %p, event id %d\n",
1811            controller, (int) event.id);
1812 #endif
1813   ret = spi_controller_notify_keylisteners (controller,
1814                                              (Accessibility_DeviceEvent *) 
1815                                              &event, FALSE) ?
1816           TRUE : FALSE; 
1817   reply = dbus_message_new_method_return (message);
1818   if (reply)
1819   {
1820     dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID);
1821   }
1822   return reply;
1823 }
1824
1825 static DBusMessage *
1826 impl_notify_listeners_async (DBusConnection *bus, DBusMessage *message, void *user_data)
1827 {
1828   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data);
1829   Accessibility_DeviceEvent event;
1830   DBusMessage *reply = NULL;
1831
1832   if (!spi_dbus_demarshal_deviceEvent(message, &event))
1833   {
1834     return invalid_arguments_error (message);
1835   }
1836 #ifdef SPI_DEBUG
1837   g_print ("notifylistening listeners asynchronously: controller %p, event id %d\n",
1838            controller, (int) event.id);
1839 #endif
1840   spi_controller_notify_keylisteners (controller, (Accessibility_DeviceEvent *)
1841                                       &event, FALSE); 
1842   reply = dbus_message_new_method_return (message);
1843   return reply;
1844 }
1845
1846 static void
1847 spi_device_event_controller_class_init (SpiDEControllerClass *klass)
1848 {
1849   GObjectClass * object_class = (GObjectClass *) klass;
1850
1851   spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
1852
1853   object_class->finalize = spi_device_event_controller_object_finalize;
1854
1855 #ifdef HAVE_X11
1856   if (g_getenv ("DISPLAY"))
1857     spi_dec_setup_x11 (klass);
1858   else
1859 #endif
1860   g_type_class_add_private (object_class, sizeof (long)); /* dummy */
1861 }
1862
1863 static void
1864 spi_device_event_controller_init (SpiDEController *device_event_controller)
1865 {
1866   SpiDEControllerClass *klass;
1867   klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (device_event_controller);
1868
1869   /* TODO: shouldn't be gpointer below */
1870   device_event_controller->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_event_controller,
1871                                               SPI_DEVICE_EVENT_CONTROLLER_TYPE,
1872                                               gpointer);
1873   device_event_controller->message_queue = g_queue_new ();
1874   saved_controller = device_event_controller;
1875
1876   if (klass->plat.init)
1877     klass->plat.init (device_event_controller);
1878 }
1879
1880
1881 /*---------------------------------------------------------------------------*/
1882
1883 static const char *introspection_header =
1884 "<?xml version=\"1.0\"?>\n";
1885
1886 static const char *introspection_node_element =
1887 "<node name=\"%s\">\n";
1888
1889 static const char *introspection_footer =
1890 "</node>";
1891
1892 static DBusMessage *
1893 impl_Introspect (DBusConnection * bus,
1894                  DBusMessage * message, void *user_data)
1895 {
1896   GString *output;
1897   gchar *final;
1898
1899   const gchar *pathstr = SPI_DBUS_PATH_DEC;
1900
1901   DBusMessage *reply;
1902
1903   output = g_string_new(introspection_header);
1904
1905   g_string_append_printf(output, introspection_node_element, pathstr);
1906
1907   g_string_append (output, spi_org_a11y_atspi_DeviceEventController);
1908
1909   g_string_append(output, introspection_footer);
1910   final = g_string_free(output, FALSE);
1911
1912   reply = dbus_message_new_method_return (message);
1913   dbus_message_append_args(reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID);
1914
1915   g_free(final);
1916   return reply;
1917 }
1918
1919 /*---------------------------------------------------------------------------*/
1920
1921 static void
1922 handle_dec_method_from_idle (DBusConnection *bus, DBusMessage *message, void *user_data)
1923 {
1924   const gchar *iface   = dbus_message_get_interface (message);
1925   const gchar *member  = dbus_message_get_member (message);
1926   DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1927   DBusMessage *reply = NULL;
1928
1929   if (!strcmp (iface, SPI_DBUS_INTERFACE_DEC))
1930     {
1931       result = DBUS_HANDLER_RESULT_HANDLED;
1932       if      (!strcmp (member, "RegisterKeystrokeListener"))
1933           reply = impl_register_keystroke_listener (bus, message, user_data);
1934       else if (!strcmp (member, "RegisterDeviceEventListener"))
1935           reply = impl_register_device_event_listener (bus, message, user_data);
1936       else if (!strcmp (member, "DeregisterKeystrokeListener"))
1937           reply = impl_deregister_keystroke_listener (bus, message, user_data);
1938       else if (!strcmp (member, "DeregisterDeviceEventListener"))
1939           reply = impl_deregister_device_event_listener (bus, message, user_data);
1940       else if (!strcmp (member, "GetKeystrokeListeners"))
1941           reply = impl_get_keystroke_listeners (bus, message, user_data);
1942       else if (!strcmp (member, "GetDeviceEventListeners"))
1943           reply = impl_get_device_event_listeners (bus, message, user_data);
1944       else if (!strcmp (member, "GenerateKeyboardEvent"))
1945           reply = impl_generate_keyboard_event (bus, message, user_data);
1946       else if (!strcmp (member, "GenerateMouseEvent"))
1947           reply = impl_generate_mouse_event (bus, message, user_data);
1948       else if (!strcmp (member, "NotifyListenersSync"))
1949           reply = impl_notify_listeners_sync (bus, message, user_data);
1950       else if (!strcmp (member, "NotifyListenersAsync"))
1951           reply = impl_notify_listeners_async (bus, message, user_data);
1952       else
1953           result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1954     }
1955
1956   if (!strcmp (iface, "org.freedesktop.DBus.Introspectable"))
1957     {
1958       result = DBUS_HANDLER_RESULT_HANDLED;
1959       if      (!strcmp (member, "Introspect"))
1960           reply = impl_Introspect (bus, message, user_data);
1961       else
1962           result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1963     }
1964
1965   if (result == DBUS_HANDLER_RESULT_HANDLED)
1966     {
1967       if (!reply)
1968         {
1969           reply = dbus_message_new_method_return (message);
1970         }
1971
1972       dbus_connection_send (bus, reply, NULL);
1973       dbus_message_unref (reply);
1974     }
1975 }
1976
1977 static gboolean
1978 message_queue_dispatch (gpointer data)
1979 {
1980   saved_controller->message_queue_idle = 0;
1981   while (!g_queue_is_empty (saved_controller->message_queue))
1982     {
1983       DBusMessage *message = g_queue_pop_head (saved_controller->message_queue);
1984       data = g_queue_pop_head (saved_controller->message_queue);
1985       handle_dec_method_from_idle (saved_controller->bus, message, data);
1986       dbus_message_unref (message);
1987     }
1988   return FALSE;
1989 }
1990
1991 static DBusHandlerResult
1992 handle_dec_method (DBusConnection *bus, DBusMessage *message, void *user_data)
1993 {
1994   const gchar *iface   = dbus_message_get_interface (message);
1995   const gchar *member  = dbus_message_get_member (message);
1996   const gint   type    = dbus_message_get_type (message);
1997
1998   /* Check for basic reasons not to handle */
1999   if (type   != DBUS_MESSAGE_TYPE_METHOD_CALL ||
2000       member == NULL ||
2001       iface  == NULL)
2002       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2003
2004   dbus_message_ref (message);
2005   g_queue_push_tail (saved_controller->message_queue, message);
2006   g_queue_push_tail (saved_controller->message_queue, user_data);
2007   if (!saved_controller->message_queue_idle) {
2008     saved_controller->message_queue_idle = g_idle_add (message_queue_dispatch, NULL);
2009     g_source_set_name_by_id (saved_controller->message_queue_idle, "[at-spi2-core] message_queue_dispatch");
2010   }
2011   return DBUS_HANDLER_RESULT_HANDLED;
2012 }
2013
2014 static DBusObjectPathVTable dec_vtable =
2015 {
2016   NULL,
2017   &handle_dec_method,
2018   NULL, NULL, NULL, NULL
2019 };
2020
2021 SpiDEController *
2022 spi_registry_dec_new (SpiRegistry *reg, DBusConnection *bus)
2023 {
2024   SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
2025
2026   dec->registry = g_object_ref (reg);
2027   reg->dec = g_object_ref (dec);
2028   dec->bus = bus;
2029
2030   dbus_connection_register_object_path (bus, SPI_DBUS_PATH_DEC, &dec_vtable, dec);
2031
2032   return dec;
2033 }
2034
2035 void
2036 spi_device_event_controller_start_poll_mouse (SpiRegistry *registry)
2037 {
2038   if (!have_mouse_event_listener)
2039     {
2040       have_mouse_event_listener = TRUE;
2041       if (!have_mouse_listener) {
2042         guint id;
2043         id = g_timeout_add (100, spi_dec_poll_mouse_idle, registry->dec);
2044         g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle");
2045       }
2046     }
2047 }
2048
2049 void
2050 spi_device_event_controller_stop_poll_mouse (void)
2051 {
2052   have_mouse_event_listener = FALSE;
2053 }