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