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