Updated NEWS; fixed bug causing multiple event emission if
[platform/core/uifw/at-spi2-atk.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, 2002 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 #define  SPI_DEBUG
30 #undef  SPI_KEYEVENT_DEBUG
31
32 #include <string.h>
33 #include <ctype.h>
34 #include <stdio.h>
35 #include <bonobo/bonobo-exception.h>
36
37 #include <X11/Xlib.h>
38 #include <X11/extensions/XTest.h>
39 #include <X11/XKBlib.h>
40 #define XK_MISCELLANY
41 #include <X11/keysymdef.h>
42 #include <gdk/gdk.h>
43 #include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
44 #include <gdk/gdkkeysyms.h>
45 #include <gdk/gdkwindow.h>
46
47 #include "../libspi/spi-private.h"
48 #include "deviceeventcontroller.h"
49
50 /* Our parent Gtk object type */
51 #define PARENT_TYPE BONOBO_TYPE_OBJECT
52
53 /* A pointer to our parent object class */
54 static GObjectClass *spi_device_event_controller_parent_class;
55 static int spi_error_code = 0;
56 static GdkPoint last_mouse_pos_static = {0, 0}; 
57 static GdkPoint *last_mouse_pos = &last_mouse_pos_static;
58 static unsigned int mouse_mask_state = 0;
59 static unsigned int mouse_button_mask =
60   Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
61 static unsigned int key_modifier_mask =
62   Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | LockMask | ControlMask;
63
64 static GQuark spi_dec_private_quark = 0;
65
66 int (*x_default_error_handler) (Display *display, XErrorEvent *error_event);
67
68 typedef enum {
69   SPI_DEVICE_TYPE_KBD,
70   SPI_DEVICE_TYPE_MOUSE,
71   SPI_DEVICE_TYPE_LAST_DEFINED
72 } SpiDeviceTypeCategory;
73
74 typedef struct {
75   guint                             ref_count : 30;
76   guint                             pending_add : 1;
77   guint                             pending_remove : 1;
78
79   Accessibility_ControllerEventMask mod_mask;
80   CORBA_unsigned_long               key_val;  /* KeyCode */
81 } DEControllerGrabMask;
82
83 typedef struct {
84   CORBA_Object          object;
85   SpiDeviceTypeCategory type;
86   Accessibility_EventTypeSeq    *typeseq;
87 } DEControllerListener;
88
89 typedef struct {
90   DEControllerListener listener;
91
92   Accessibility_KeySet             *keys;
93   Accessibility_ControllerEventMask mask;
94   Accessibility_EventListenerMode  *mode;       
95 } DEControllerKeyListener;
96
97 typedef struct {
98         unsigned int last_press_keycode;
99         unsigned int last_release_keycode;
100         struct timeval last_press_time;
101         struct timeval last_release_time;
102         int have_xkb;
103         int xkb_major_extension_opcode;
104         int xkb_base_event_code;
105         int xkb_base_error_code;
106         unsigned int xkb_latch_mask;
107         unsigned int pending_xkb_mod_relatch_mask;
108         XkbDescPtr xkb_desc;
109 } DEControllerPrivateData;
110
111 static void     spi_controller_register_with_devices          (SpiDEController           *controller);
112 static gboolean spi_controller_update_key_grabs               (SpiDEController           *controller,
113                                                                Accessibility_DeviceEvent *recv);
114 static gboolean spi_controller_register_device_listener       (SpiDEController           *controller,
115                                                                DEControllerListener      *l,
116                                                                CORBA_Environment         *ev);
117 static void     spi_device_event_controller_forward_key_event (SpiDEController           *controller,
118                                                                const XEvent              *event);
119 static void     spi_deregister_controller_device_listener (SpiDEController            *controller,
120                                                            DEControllerListener *listener,
121                                                            CORBA_Environment          *ev);
122 static void     spi_deregister_controller_key_listener (SpiDEController         *controller,
123                                                         DEControllerKeyListener *key_listener,
124                                                         CORBA_Environment       *ev);
125 static gboolean spi_controller_notify_mouselisteners (SpiDEController                 *controller,
126                                                       const Accessibility_DeviceEvent *event,
127                                                       CORBA_Environment               *ev);
128
129 static gboolean spi_eventtype_seq_contains_event (Accessibility_EventTypeSeq      *type_seq,
130                                                   const Accessibility_DeviceEvent *event);
131 static gboolean spi_clear_error_state (void);
132 static gboolean spi_dec_poll_mouse_moved (gpointer data);
133 static gboolean spi_dec_poll_mouse_moving (gpointer data);
134 static gboolean spi_dec_poll_mouse_idle (gpointer data);
135
136 #define spi_get_display() GDK_DISPLAY()
137
138 /* Private methods */
139
140 static KeyCode
141 keycode_for_keysym (long keysym)
142 {
143   return XKeysymToKeycode (spi_get_display (), (KeySym) keysym);
144 }
145
146 static DEControllerGrabMask *
147 spi_grab_mask_clone (DEControllerGrabMask *grab_mask)
148 {
149   DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1);
150
151   memcpy (clone, grab_mask, sizeof (DEControllerGrabMask));
152
153   clone->ref_count = 1;
154   clone->pending_add = TRUE;
155   clone->pending_remove = FALSE;
156
157   return clone;
158 }
159
160 static void
161 spi_grab_mask_free (DEControllerGrabMask *grab_mask)
162 {
163   g_free (grab_mask);
164 }
165
166 static gint
167 spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2)
168 {
169   DEControllerGrabMask *l1 = (DEControllerGrabMask *) p1;
170   DEControllerGrabMask *l2 = (DEControllerGrabMask *) p2;
171
172   if (p1 == p2)
173     {
174       return 0;
175     }
176   else
177     { 
178       return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val));
179     }
180 }
181
182 static gint poll_count = 0;
183
184 static gboolean
185 spi_dec_poll_mouse_moved (gpointer data)
186 {
187   SpiRegistry *registry = SPI_REGISTRY (data);
188   SpiDEController *controller = registry->de_controller;
189   CORBA_Environment ev;
190   Accessibility_Event e;
191   Accessibility_DeviceEvent mouse_e;
192   Window root_return, child_return;
193   int win_x_return,win_y_return;
194   int x, y;
195   int poll_count_modulus = 10;
196   unsigned int mask_return;
197   gchar event_name[24];
198   gboolean is_consumed;
199   Display *display = spi_get_display ();
200
201   if (display != NULL)
202     XQueryPointer(display, DefaultRootWindow (display),
203                   &root_return, &child_return,
204                   &x, &y,
205                   &win_x_return, &win_y_return, &mask_return);
206   
207   /* 
208    * Since many clients grab the pointer, and X goes an automatic
209    * pointer grab on mouse-down, we often must detect mouse button events
210    * by polling rather than via a button grab. 
211    * The while loop (rather than if) is used since it's possible that 
212    * multiple buttons have changed state since we last checked.
213    */
214   if (mask_return != mouse_mask_state) 
215     {
216       while ((mask_return & mouse_button_mask) !=
217              (mouse_mask_state & mouse_button_mask)) 
218         {
219           int button_number = 0;
220           gboolean is_down = False;
221
222           if (!(mask_return & Button1Mask) &&
223               (mouse_mask_state & Button1Mask)) 
224             {
225               mouse_mask_state &= ~Button1Mask;
226               button_number = 1;
227             } 
228           else if ((mask_return & Button1Mask) &&
229               !(mouse_mask_state & Button1Mask)) 
230             {
231               mouse_mask_state |= Button1Mask;
232               button_number = 1;
233               is_down = True;
234             } 
235           else if (!(mask_return & Button2Mask) &&
236                        (mouse_mask_state & Button2Mask)) 
237             {
238               mouse_mask_state &= ~Button2Mask;
239               button_number = 2;
240             } 
241           else if ((mask_return & Button2Mask) &&
242                        !(mouse_mask_state & Button2Mask)) 
243             {
244               mouse_mask_state |= Button2Mask;
245               button_number = 2;
246               is_down = True;
247             } 
248           else if (!(mask_return & Button3Mask) &&
249                    (mouse_mask_state & Button3Mask)) 
250             {
251               mouse_mask_state &= ~Button3Mask;
252               button_number = 3;
253             } 
254           else if ((mask_return & Button3Mask) &&
255                    !(mouse_mask_state & Button3Mask)) 
256             {
257               mouse_mask_state |= Button3Mask;
258               button_number = 3;
259               is_down = True;
260             } 
261           else if (!(mask_return & Button4Mask) &&
262                    (mouse_mask_state & Button1Mask)) 
263             {
264               mouse_mask_state &= ~Button4Mask;
265               button_number = 4;
266             } 
267           else if ((mask_return & Button4Mask) &&
268                    !(mouse_mask_state & Button1Mask)) 
269             {
270               mouse_mask_state |= Button4Mask;
271               button_number = 4;
272               is_down = True;
273             } 
274           else if (!(mask_return & Button5Mask) &&
275                    (mouse_mask_state & Button5Mask)) 
276             {
277               mouse_mask_state &= ~Button5Mask;
278               button_number = 5;
279             }
280           else if ((mask_return & Button5Mask) &&
281                    !(mouse_mask_state & Button5Mask)) 
282             {
283               mouse_mask_state |= Button5Mask;
284               button_number = 5;
285               is_down = True;
286             }
287           if (button_number) {
288 #ifdef SPI_DEBUG                  
289             fprintf (stderr, "Button %d %s\n",
290                      button_number, (is_down) ? "Pressed" : "Released");
291 #endif
292             snprintf (event_name, 22, "mouse:button:%d%c", button_number,
293                       (is_down) ? 'p' : 'r');
294             /* TODO: distinguish between physical and 
295              * logical buttons 
296              */
297             mouse_e.type      = (is_down) ? 
298               Accessibility_BUTTON_PRESSED_EVENT :
299               Accessibility_BUTTON_RELEASED_EVENT;
300             mouse_e.id        = button_number;
301             mouse_e.hw_code   = button_number;
302             mouse_e.modifiers = (CORBA_unsigned_short) mouse_mask_state; 
303             mouse_e.timestamp = 0;
304             mouse_e.event_string = "";
305             mouse_e.is_text   = CORBA_FALSE;
306             is_consumed = 
307               spi_controller_notify_mouselisteners (controller, 
308                                                     &mouse_e, 
309                                                     &ev);
310             e.type = event_name;
311             e.source = BONOBO_OBJREF (registry->desktop);
312             e.detail1 = last_mouse_pos->x;
313             e.detail2 = last_mouse_pos->y;
314             spi_init_any_nil (&e.any_data);
315             CORBA_exception_init (&ev);
316             if (!is_consumed)
317               Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
318                                                   &e,
319                                                   &ev);  
320           }
321         }
322       
323       if ((mask_return & key_modifier_mask) !=
324       (mouse_mask_state & key_modifier_mask)) {
325 #ifdef SPI_DEBUG
326         fprintf (stderr, "MODIFIER CHANGE EVENT!\n");
327 #endif
328         e.type = "keyboard:modifiers";  
329         e.source = BONOBO_OBJREF (registry->desktop);
330         e.detail1 = mouse_mask_state;
331         e.detail2 = mask_return;
332         spi_init_any_nil (&e.any_data);
333         CORBA_exception_init (&ev);
334         Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
335                                             &e,
336                                             &ev);
337       }
338       mouse_mask_state = mask_return;
339     }  
340   
341   if (poll_count++ == poll_count_modulus) {
342     poll_count = 0;
343     e.type = "mouse:abs";  
344     e.source = BONOBO_OBJREF (registry->desktop);
345     e.detail1 = x;
346     e.detail2 = y;
347     spi_init_any_nil (&e.any_data);
348     CORBA_exception_init (&ev);
349     Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
350                                         &e,
351                                         &ev);
352   }
353   if (x != last_mouse_pos->x || y != last_mouse_pos->y) {
354     e.type = "mouse:rel";  
355     e.source = BONOBO_OBJREF (registry->desktop);
356     e.detail1 = x - last_mouse_pos->x;
357     e.detail2 = y - last_mouse_pos->y;
358     spi_init_any_nil (&e.any_data);
359     CORBA_exception_init (&ev);
360     last_mouse_pos->x = x;
361     last_mouse_pos->y = y;
362     Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
363                                         &e,
364                                         &ev);
365     return TRUE;
366   }
367   return FALSE;
368 }
369
370 static gboolean
371 spi_dec_poll_mouse_idle (gpointer data)
372 {
373   if (! spi_dec_poll_mouse_moved (data)) 
374     return TRUE;
375   else
376     {
377       g_timeout_add (20, spi_dec_poll_mouse_moving, data);          
378       return FALSE;         
379     }
380 }
381
382 static gboolean
383 spi_dec_poll_mouse_moving (gpointer data)
384 {
385   if (spi_dec_poll_mouse_moved (data))
386     return TRUE;
387   else
388     {
389       g_timeout_add (100, spi_dec_poll_mouse_idle, data);           
390       return FALSE;
391     }
392 }
393
394 static int
395 spi_dec_ungrab_mouse (gpointer data)
396 {
397         Display *display = spi_get_display ();
398         if (display)
399           {
400             XUngrabButton (spi_get_display (), AnyButton, AnyModifier,
401                            XDefaultRootWindow (spi_get_display ()));
402           }
403         return FALSE;
404 }
405
406 static void
407 spi_dec_init_mouse_listener (SpiRegistry *registry)
408 {
409   Display *display = spi_get_display ();
410   g_timeout_add (100, spi_dec_poll_mouse_idle, registry);
411
412   if (display)
413     {
414       XGrabButton (display, AnyButton, AnyModifier,
415                    gdk_x11_get_default_root_xwindow (),
416                    True, ButtonPressMask | ButtonReleaseMask,
417                    GrabModeSync, GrabModeAsync, None, None);
418       XSync (display, False);
419 #ifdef SPI_DEBUG
420       fprintf (stderr, "mouse buttons grabbed\n");
421 #endif
422     }
423 }
424
425 static DEControllerKeyListener *
426 spi_dec_key_listener_new (CORBA_Object                            l,
427                           const Accessibility_KeySet             *keys,
428                           const Accessibility_ControllerEventMask mask,
429                           const Accessibility_EventTypeSeq    *typeseq,
430                           const Accessibility_EventListenerMode  *mode,
431                           CORBA_Environment                      *ev)
432 {
433   DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1);
434   key_listener->listener.object = bonobo_object_dup_ref (l, ev);
435   key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
436   key_listener->keys = ORBit_copy_value (keys, TC_Accessibility_KeySet);
437   key_listener->mask = mask;
438   key_listener->listener.typeseq = ORBit_copy_value (typeseq, TC_Accessibility_EventTypeSeq);
439   if (mode)
440     key_listener->mode = ORBit_copy_value (mode, TC_Accessibility_EventListenerMode);
441   else
442     key_listener->mode = NULL;
443
444 #ifdef SPI_DEBUG
445   g_print ("new listener, with mask %x, is_global %d, keys %p (%d)\n",
446            (unsigned int) key_listener->mask,
447            (int) (mode ? mode->global : 0),
448            (void *) key_listener->keys,
449            (int) (key_listener->keys ? key_listener->keys->_length : 0));
450 #endif
451
452   return key_listener;  
453 }
454
455 static DEControllerListener *
456 spi_dec_listener_new (CORBA_Object                            l,
457                       const Accessibility_EventTypeSeq    *typeseq,
458                       CORBA_Environment                      *ev)
459 {
460   DEControllerListener *listener = g_new0 (DEControllerListener, 1);
461   listener->object = bonobo_object_dup_ref (l, ev);
462   listener->type = SPI_DEVICE_TYPE_MOUSE;
463   listener->typeseq = ORBit_copy_value (typeseq, TC_Accessibility_EventTypeSeq);
464   return listener;      
465 }
466
467 static DEControllerListener *
468 spi_listener_clone (DEControllerListener *listener, CORBA_Environment *ev)
469 {
470   DEControllerListener *clone = g_new0 (DEControllerListener, 1);
471   clone->object =
472           CORBA_Object_duplicate (listener->object, ev);
473   clone->type = listener->type;
474   clone->typeseq = ORBit_copy_value (listener->typeseq, TC_Accessibility_EventTypeSeq);
475   return clone;
476 }
477
478 static DEControllerKeyListener *
479 spi_key_listener_clone (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
480 {
481   DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1);
482   clone->listener.object =
483           CORBA_Object_duplicate (key_listener->listener.object, ev);
484   clone->listener.type = SPI_DEVICE_TYPE_KBD;
485   clone->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
486   clone->mask = key_listener->mask;
487   clone->listener.typeseq = ORBit_copy_value (key_listener->listener.typeseq, TC_Accessibility_EventTypeSeq);
488   if (key_listener->mode)
489     clone->mode = ORBit_copy_value (key_listener->mode, TC_Accessibility_EventListenerMode);
490   else
491     clone->mode = NULL;
492   return clone;
493 }
494
495 static void
496 spi_key_listener_data_free (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
497 {
498   CORBA_free (key_listener->listener.typeseq);
499   CORBA_free (key_listener->keys);
500   g_free (key_listener);
501 }
502
503 static void
504 spi_key_listener_clone_free (DEControllerKeyListener *clone, CORBA_Environment *ev)
505 {
506   CORBA_Object_release (clone->listener.object, ev);
507   spi_key_listener_data_free (clone, ev);
508 }
509
510 static void
511 spi_listener_clone_free (DEControllerListener *clone, CORBA_Environment *ev)
512 {
513   CORBA_Object_release (clone->object, ev);
514   CORBA_free (clone->typeseq);
515   g_free (clone);
516 }
517
518 static void
519 spi_dec_listener_free (DEControllerListener    *listener,
520                        CORBA_Environment       *ev)
521 {
522   bonobo_object_release_unref (listener->object, ev);
523   if (listener->type == SPI_DEVICE_TYPE_KBD) 
524     spi_key_listener_data_free ((DEControllerKeyListener *) listener, ev);
525 }
526
527 static void
528 _register_keygrab (SpiDEController      *controller,
529                    DEControllerGrabMask *grab_mask)
530 {
531   GList *l;
532
533   l = g_list_find_custom (controller->keygrabs_list, grab_mask,
534                           spi_grab_mask_compare_values);
535   if (l)
536     {
537       DEControllerGrabMask *cur_mask = l->data;
538
539       cur_mask->ref_count++;
540       if (cur_mask->pending_remove)
541         {
542           cur_mask->pending_remove = FALSE;
543         }
544     }
545   else
546     {
547       controller->keygrabs_list =
548         g_list_prepend (controller->keygrabs_list,
549                         spi_grab_mask_clone (grab_mask));
550     }
551 }
552
553 static void
554 _deregister_keygrab (SpiDEController      *controller,
555                      DEControllerGrabMask *grab_mask)
556 {
557   GList *l;
558
559   l = g_list_find_custom (controller->keygrabs_list, grab_mask,
560                           spi_grab_mask_compare_values);
561
562   if (l)
563     {
564       DEControllerGrabMask *cur_mask = l->data;
565
566       cur_mask->ref_count--;
567       if (cur_mask->ref_count <= 0)
568         {
569           cur_mask->pending_remove = TRUE;
570         }
571     }
572   else
573     {
574       DBG (1, g_warning ("De-registering non-existant grab"));
575     }
576 }
577
578 static void
579 handle_keygrab (SpiDEController         *controller,
580                 DEControllerKeyListener *key_listener,
581                 void                   (*process_cb) (SpiDEController *controller,
582                                                       DEControllerGrabMask *grab_mask))
583 {
584   DEControllerGrabMask grab_mask = { 0 };
585
586   grab_mask.mod_mask = key_listener->mask;
587   if (key_listener->keys->_length == 0) /* special case means AnyKey/AllKeys */
588     {
589       grab_mask.key_val = AnyKey;
590 #ifdef SPI_DEBUG
591       fprintf (stderr, "AnyKey grab!");
592 #endif
593       process_cb (controller, &grab_mask);
594     }
595   else
596     {
597       int i;
598
599       for (i = 0; i < key_listener->keys->_length; ++i)
600         {
601           Accessibility_KeyDefinition keydef = key_listener->keys->_buffer[i];  
602           long int key_val = keydef.keysym;
603           /* X Grabs require keycodes, not keysyms */
604           if (keydef.keystring && keydef.keystring[0])
605             {
606               key_val = XStringToKeysym(keydef.keystring);                  
607             }
608           if (key_val > 0)
609             {
610               key_val = XKeysymToKeycode (spi_get_display (), (KeySym) key_val);
611             }
612           else
613             {
614               key_val = keydef.keycode;
615             }
616           grab_mask.key_val = key_val;
617           process_cb (controller, &grab_mask);
618         }
619     }
620 }
621
622 static gboolean
623 spi_controller_register_global_keygrabs (SpiDEController         *controller,
624                                          DEControllerKeyListener *key_listener)
625 {
626   handle_keygrab (controller, key_listener, _register_keygrab);
627   return spi_controller_update_key_grabs (controller, NULL);
628 }
629
630 static void
631 spi_controller_deregister_global_keygrabs (SpiDEController         *controller,
632                                            DEControllerKeyListener *key_listener)
633 {
634   handle_keygrab (controller, key_listener, _deregister_keygrab);
635   spi_controller_update_key_grabs (controller, NULL);
636 }
637
638 static gboolean
639 spi_controller_register_device_listener (SpiDEController      *controller,
640                                          DEControllerListener *listener,
641                                          CORBA_Environment    *ev)
642 {
643   DEControllerKeyListener *key_listener;
644   
645   switch (listener->type) {
646   case SPI_DEVICE_TYPE_KBD:
647       key_listener = (DEControllerKeyListener *) listener;
648
649       controller->key_listeners = g_list_prepend (controller->key_listeners,
650                                                   key_listener);
651       if (key_listener->mode->global)
652         {
653           return spi_controller_register_global_keygrabs (controller, key_listener);    
654         }
655       else
656               return TRUE;
657       break;
658   case SPI_DEVICE_TYPE_MOUSE:
659       controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
660       break;
661   default:
662       DBG (1, g_warning ("listener registration for unknown device type.\n"));
663       break;
664   }
665   return FALSE; 
666 }
667
668 static gboolean
669 spi_controller_notify_mouselisteners (SpiDEController                 *controller,
670                                       const Accessibility_DeviceEvent *event,
671                                       CORBA_Environment               *ev)
672 {
673   GList   *l;
674   GSList  *notify = NULL, *l2;
675   GList  **listeners = &controller->mouse_listeners;
676   gboolean is_consumed;
677
678   if (!listeners)
679     {
680       return FALSE;
681     }
682
683   for (l = *listeners; l; l = l->next)
684     {
685        DEControllerListener *listener = l->data;
686
687        if (spi_eventtype_seq_contains_event (listener->typeseq, event))
688          {
689            Accessibility_DeviceEventListener ls = listener->object;
690
691            if (ls != CORBA_OBJECT_NIL)
692              {
693                /* we clone (don't dup) the listener, to avoid refcount inc. */
694                notify = g_slist_prepend (notify,
695                                          spi_listener_clone (listener, ev));
696              }
697          }
698     }
699
700 #ifdef SPI_KEYEVENT_DEBUG
701   if (!notify)
702     {
703       g_print ("no match for event\n");
704     }
705 #endif
706
707   is_consumed = FALSE;
708   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
709     {
710       DEControllerListener *listener = l2->data;            
711       Accessibility_DeviceEventListener ls = listener->object;
712
713       CORBA_exception_init (ev);
714       is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, event, ev);
715       if (BONOBO_EX (ev))
716         {
717           is_consumed = FALSE;
718           DBG (2, g_warning ("error notifying listener, removing it\n"));
719           spi_deregister_controller_device_listener (controller, listener,
720                                                      ev);
721           CORBA_exception_free (ev);
722         }
723       
724       spi_listener_clone_free ((DEControllerListener *) l2->data, ev);
725     }
726
727   for (; l2; l2 = l2->next)
728     {
729       DEControllerListener *listener = l2->data;            
730       spi_listener_clone_free (listener, ev);
731       /* clone doesn't have its own ref, so don't use spi_device_listener_free */
732     }
733
734   g_slist_free (notify);
735
736 #ifdef SPI_DEBUG
737   if (is_consumed) g_message ("consumed\n");
738 #endif
739   return is_consumed;
740 }
741
742 static void
743 spi_device_event_controller_forward_mouse_event (SpiDEController *controller,
744                                                  XEvent *xevent)
745 {
746   Accessibility_Event e;
747   Accessibility_DeviceEvent mouse_e;
748   CORBA_Environment ev;
749   gchar event_name[24];
750   gboolean is_consumed = FALSE;
751   gboolean xkb_mod_unlatch_occurred;
752   DEControllerPrivateData *priv;
753   XButtonEvent *xbutton_event = (XButtonEvent *) xevent;
754
755   int button = xbutton_event->button;
756   
757   unsigned int mouse_button_state = xbutton_event->state;
758   
759   switch (button)
760     {
761     case 1:
762             mouse_button_state |= Button1Mask;
763             break;
764     case 2:
765             mouse_button_state |= Button2Mask;
766             break;
767     case 3:
768             mouse_button_state |= Button3Mask;
769             break;
770     case 4:
771             mouse_button_state |= Button4Mask;
772             break;
773     case 5:
774             mouse_button_state |= Button5Mask;
775             break;
776     }
777   last_mouse_pos->x = ((XButtonEvent *) xevent)->x_root;
778   last_mouse_pos->y = ((XButtonEvent *) xevent)->y_root;
779
780 #ifdef SPI_DEBUG  
781   fprintf (stderr, "mouse button %d %s (%x)\n",
782            xbutton_event->button, 
783            (xevent->type == ButtonPress) ? "Press" : "Release",
784            mouse_button_state);
785 #endif
786   snprintf (event_name, 22, "mouse:button:%d%c", button,
787             (xevent->type == ButtonPress) ? 'p' : 'r');
788
789   /* TODO: distinguish between physical and logical buttons */
790   mouse_e.type      = (xevent->type == ButtonPress) ? 
791                       Accessibility_BUTTON_PRESSED_EVENT :
792                       Accessibility_BUTTON_RELEASED_EVENT;
793   mouse_e.id        = button;
794   mouse_e.hw_code   = button;
795   mouse_e.modifiers = (CORBA_unsigned_short) xbutton_event->state;
796   mouse_e.timestamp = (CORBA_unsigned_long) xbutton_event->time;
797   mouse_e.event_string = "";
798   mouse_e.is_text   = CORBA_FALSE;
799   if ((mouse_button_state & mouse_button_mask) != 
800       (mouse_mask_state & mouse_button_mask)) 
801     { 
802       mouse_mask_state = mouse_button_state;
803       is_consumed = 
804         spi_controller_notify_mouselisteners (controller, &mouse_e, &ev);
805       e.type = CORBA_string_dup (event_name);
806       e.source = BONOBO_OBJREF (controller->registry->desktop);
807       e.detail1 = last_mouse_pos->x;
808       e.detail2 = last_mouse_pos->y;
809       spi_init_any_nil (&e.any_data);
810       CORBA_exception_init (&ev);
811       
812       Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
813                                           &e,
814                                           &ev);
815     }
816   xkb_mod_unlatch_occurred = (xevent->type == ButtonPress ||
817                               xevent->type == ButtonRelease);
818       
819   /* if client wants to consume this event, and XKB latch state was
820    *   unset by this button event, we reset it
821    */
822   if (is_consumed && xkb_mod_unlatch_occurred)
823     {
824       priv = g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);     
825       priv->pending_xkb_mod_relatch_mask |= priv->xkb_latch_mask; 
826     }
827   
828   XAllowEvents (spi_get_display (),
829                 (is_consumed) ? SyncPointer : ReplayPointer,
830                 CurrentTime);
831 }
832
833 static GdkFilterReturn
834 global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
835 {
836   XEvent *xevent = gdk_xevent;
837   SpiDEController *controller;
838   DEControllerPrivateData *priv;
839   Display *display = spi_get_display ();
840   controller = SPI_DEVICE_EVENT_CONTROLLER (data);
841   priv = (DEControllerPrivateData *)
842           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);  
843
844   if (xevent->type == KeyPress || xevent->type == KeyRelease)
845     {
846       spi_device_event_controller_forward_key_event (controller, xevent);
847       return GDK_FILTER_CONTINUE;
848     }
849   if (xevent->type == ButtonPress || xevent->type == ButtonRelease)
850     {
851       spi_device_event_controller_forward_mouse_event (controller, xevent);
852     }
853   if (xevent->type == priv->xkb_base_event_code)
854     {
855       XkbAnyEvent * xkb_ev = (XkbAnyEvent *) xevent;
856
857       if (xkb_ev->xkb_type == XkbStateNotify)
858         {
859           XkbStateNotifyEvent *xkb_snev =
860                   (XkbStateNotifyEvent *) xkb_ev;
861           priv->xkb_latch_mask = xkb_snev->latched_mods;
862           if (priv->pending_xkb_mod_relatch_mask)
863             {
864               unsigned int feedback_mask;
865 #ifdef SPI_XKB_DEBUG
866               fprintf (stderr, "relatching %x\n",
867                        priv->pending_xkb_mod_relatch_mask);
868 #endif
869               /* temporarily turn off the latch bell, if it's on */
870               XkbGetControls (display,
871                               XkbAccessXFeedbackMask,
872                               priv->xkb_desc);
873               feedback_mask = priv->xkb_desc->ctrls->ax_options;
874               if (feedback_mask & XkbAX_StickyKeysFBMask)
875               {
876                 XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
877                                                  0, False};      
878                 priv->xkb_desc->ctrls->ax_options
879                               &= ~(XkbAX_StickyKeysFBMask);
880                 XkbChangeControls (display, priv->xkb_desc, &changes);
881               }
882               XkbLatchModifiers (display,
883                                  XkbUseCoreKbd,
884                                  priv->pending_xkb_mod_relatch_mask,
885                                  priv->pending_xkb_mod_relatch_mask);
886               if (feedback_mask & XkbAX_StickyKeysFBMask)
887               { 
888                 XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
889                                                  0, False};      
890                 priv->xkb_desc->ctrls->ax_options = feedback_mask;
891                 XkbChangeControls (display, priv->xkb_desc, &changes);
892               }
893 #ifdef SPI_XKB_DEBUG
894               fprintf (stderr, "relatched %x\n",
895                        priv->pending_xkb_mod_relatch_mask);
896 #endif
897               priv->pending_xkb_mod_relatch_mask = 0;
898             }
899         }
900         else
901                DBG (2, g_warning ("XKB event %d\n", xkb_ev->xkb_type));
902     }
903   
904   return GDK_FILTER_CONTINUE;
905 }
906
907 int
908 _spi_controller_device_error_handler (Display *display, XErrorEvent *error)
909 {
910   if (error->error_code == BadAccess) 
911     {  
912       g_message ("Could not complete key grab: grab already in use.\n");
913       spi_error_code = BadAccess;
914       return 0;
915     }
916   else 
917     {
918       return (*x_default_error_handler) (display, error);
919     }
920 }
921
922 static void
923 spi_controller_register_with_devices (SpiDEController *controller)
924 {
925   DEControllerPrivateData *priv = (DEControllerPrivateData *) 
926           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);     
927   /* FIXME: should check for extension first! */
928   XTestGrabControl (spi_get_display (), True);
929   priv->xkb_desc = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd);
930
931   /* calls to device-specific implementations and routines go here */
932   /* register with: keyboard hardware code handler */
933   /* register with: (translated) keystroke handler */
934
935   priv->have_xkb = XkbQueryExtension (spi_get_display (),
936                                       &priv->xkb_major_extension_opcode,
937                                       &priv->xkb_base_event_code,
938                                       &priv->xkb_base_error_code, NULL, NULL);
939   if (priv->have_xkb)
940     {
941       XkbSelectEvents (spi_get_display (),
942                        XkbUseCoreKbd,
943                        XkbStateNotifyMask, XkbStateNotifyMask);     
944     }   
945   gdk_window_add_filter (NULL, global_filter_fn, controller);
946
947   gdk_window_set_events (gdk_get_default_root_window (),
948                          GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
949
950   x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler);
951 }
952
953 static gboolean
954 spi_key_set_contains_key (Accessibility_KeySet            *key_set,
955                           const Accessibility_DeviceEvent *key_event)
956 {
957   gint i;
958   gint len;
959
960   if (!key_set)
961     {
962       g_print ("null key set!");
963       return TRUE;
964     }
965
966   len = key_set->_length;
967   
968   if (len == 0) /* special case, means "all keys/any key" */
969     {
970       g_print ("anykey\n");         
971       return TRUE;
972     }
973
974   for (i = 0; i < len; ++i)
975     {
976 #ifdef SPI_KEYEVENT_DEBUG           
977       g_print ("key_set[%d] = %d; key_event %d, code %d, string %s\n",
978                 i, (int) key_set->_buffer[i].keycode,
979                (int) key_event->id, (int) key_event->hw_code,
980                key_event->event_string); 
981 #endif
982       if (key_set->_buffer[i].keysym == (CORBA_long) key_event->id)
983         {
984           return TRUE;
985         }
986       if (key_set->_buffer[i].keycode == (CORBA_long) key_event->hw_code)
987         {
988           return TRUE;
989         }
990       if (key_event->event_string && key_event->event_string[0] &&
991           !strcmp (key_set->_buffer[i].keystring, key_event->event_string))
992         {
993           return TRUE;
994         }
995     }
996   
997   return FALSE;
998 }
999
1000 static gboolean
1001 spi_eventtype_seq_contains_event (Accessibility_EventTypeSeq      *type_seq,
1002                                   const Accessibility_DeviceEvent *event)
1003 {
1004   gint i;
1005   gint len;
1006
1007
1008   if (!type_seq)
1009     {
1010       g_print ("null type seq!");
1011       return TRUE;
1012     }
1013
1014   len = type_seq->_length;
1015   
1016   if (len == 0) /* special case, means "all events/any event" */
1017     {
1018       return TRUE;
1019     }
1020
1021   for (i = 0; i < len; ++i)
1022     {
1023 #ifdef SPI_DEBUG            
1024       g_print ("type_seq[%d] = %d; event type = %d\n", i,
1025                (int) type_seq->_buffer[i], (int) event->type);
1026 #endif      
1027       if (type_seq->_buffer[i] == (CORBA_long) event->type)
1028         {
1029           return TRUE;
1030         }
1031     }
1032   
1033   return FALSE;
1034 }
1035
1036 static gboolean
1037 spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event,
1038                                 DEControllerKeyListener         *listener,
1039                                 CORBA_boolean                    is_system_global)
1040 {
1041   if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFFFF)) &&
1042        spi_key_set_contains_key (listener->keys, key_event) &&
1043        spi_eventtype_seq_contains_event (listener->listener.typeseq, key_event) && 
1044       (is_system_global == listener->mode->global))
1045     {
1046       return TRUE;
1047     }
1048   else
1049     {
1050       return FALSE;
1051     }
1052 }
1053
1054 static gboolean
1055 spi_controller_notify_keylisteners (SpiDEController                 *controller,
1056                                     const Accessibility_DeviceEvent *key_event,
1057                                     CORBA_boolean                    is_system_global,
1058                                     CORBA_Environment               *ev)
1059 {
1060   GList   *l;
1061   GSList  *notify = NULL, *l2;
1062   GList  **key_listeners = &controller->key_listeners;
1063   gboolean is_consumed;
1064
1065   if (!key_listeners)
1066     {
1067       return FALSE;
1068     }
1069
1070   for (l = *key_listeners; l; l = l->next)
1071     {
1072        DEControllerKeyListener *key_listener = l->data;
1073
1074        if (spi_key_event_matches_listener (key_event, key_listener, is_system_global))
1075          {
1076            Accessibility_DeviceEventListener ls = key_listener->listener.object;
1077
1078            if (ls != CORBA_OBJECT_NIL)
1079              {
1080                /* we clone (don't dup) the listener, to avoid refcount inc. */
1081                notify = g_slist_prepend (notify,
1082                                          spi_key_listener_clone (key_listener, ev));
1083              }
1084          }
1085     }
1086
1087 #ifdef SPI_KEYEVENT_DEBUG
1088   if (!notify)
1089     {
1090       g_print ("no match for event\n");
1091     }
1092 #endif
1093
1094   is_consumed = FALSE;
1095   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1096     {
1097       DEControllerKeyListener *key_listener = l2->data;     
1098       Accessibility_DeviceEventListener ls = key_listener->listener.object;
1099
1100       is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, key_event, ev);
1101
1102       if (BONOBO_EX (ev))
1103         {
1104           is_consumed = FALSE;
1105           spi_deregister_controller_key_listener (controller, key_listener,
1106                                                   ev);
1107           CORBA_exception_free (ev);
1108         }
1109
1110       spi_key_listener_clone_free (key_listener, ev);
1111     }
1112
1113   for (; l2; l2 = l2->next)
1114     {
1115       DEControllerKeyListener *key_listener = l2->data;     
1116       spi_key_listener_clone_free (key_listener, ev);
1117       /* clone doesn't have its own ref, so don't use spi_dec_listener_free */
1118     }
1119
1120   g_slist_free (notify);
1121
1122 #ifdef SPI_DEBUG
1123   if (is_consumed) g_message ("consumed\n");
1124 #endif
1125   return is_consumed;
1126 }
1127
1128 static gboolean
1129 spi_clear_error_state ()
1130 {
1131         gboolean retval = spi_error_code != 0;
1132         spi_error_code = 0;
1133         return retval;
1134 }
1135
1136 static Accessibility_DeviceEvent
1137 spi_keystroke_from_x_key_event (XKeyEvent *x_key_event)
1138 {
1139   Accessibility_DeviceEvent key_event;
1140   KeySym keysym;
1141   const int cbuf_bytes = 20;
1142   char cbuf [cbuf_bytes];
1143   
1144   keysym = XLookupKeysym (x_key_event, 0);
1145   key_event.id = (CORBA_long)(keysym);
1146   key_event.hw_code = (CORBA_short) x_key_event->keycode;
1147   if (((XEvent *) x_key_event)->type == KeyPress)
1148     {
1149       key_event.type = Accessibility_KEY_PRESSED;
1150     }
1151   else
1152     {
1153       key_event.type = Accessibility_KEY_RELEASED;
1154     } 
1155   key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
1156   key_event.is_text = CORBA_FALSE;
1157   switch (keysym)
1158     {
1159       case ' ':
1160         key_event.event_string = CORBA_string_dup ("space");
1161         break;
1162       case XK_Tab:
1163 #ifdef SPI_KEYEVENT_DEBUG
1164         fprintf(stderr, "Tab\n");
1165 #endif
1166         key_event.event_string = CORBA_string_dup ("Tab");
1167         break;
1168       case XK_BackSpace:
1169         key_event.event_string = CORBA_string_dup ("Backspace");
1170         break;
1171       case XK_Return:
1172         key_event.event_string = CORBA_string_dup ("Return");
1173         break;
1174       case XK_Home:
1175         key_event.event_string = CORBA_string_dup ("Home");
1176         break;
1177       case XK_Page_Down:
1178         key_event.event_string = CORBA_string_dup ("Page_Down");
1179         break;
1180       case XK_Page_Up:
1181         key_event.event_string = CORBA_string_dup ("Page_Up");
1182         break;
1183       case XK_F1:
1184         key_event.event_string = CORBA_string_dup ("F1");
1185         break;
1186       case XK_F2:
1187         key_event.event_string = CORBA_string_dup ("F2");
1188         break;
1189       case XK_F3:
1190         key_event.event_string = CORBA_string_dup ("F3");
1191         break;
1192       case XK_F4:
1193         key_event.event_string = CORBA_string_dup ("F4");
1194         break;
1195       case XK_F5:
1196         key_event.event_string = CORBA_string_dup ("F5");
1197         break;
1198       case XK_F6:
1199         key_event.event_string = CORBA_string_dup ("F6");
1200         break;
1201       case XK_F7:
1202         key_event.event_string = CORBA_string_dup ("F7");
1203         break;
1204       case XK_F8:
1205         key_event.event_string = CORBA_string_dup ("F8");
1206         break;
1207       case XK_F9:
1208         key_event.event_string = CORBA_string_dup ("F9");
1209         break;
1210       case XK_F10:
1211         key_event.event_string = CORBA_string_dup ("F10");
1212         break;
1213       case XK_F11:
1214         key_event.event_string = CORBA_string_dup ("F11");
1215         break;
1216       case XK_F12:
1217         key_event.event_string = CORBA_string_dup ("F12");
1218         break;
1219       case XK_End:
1220         key_event.event_string = CORBA_string_dup ("End");
1221         break;
1222       case XK_Escape:
1223         key_event.event_string = CORBA_string_dup ("Escape");
1224         break;
1225       case XK_Up:
1226         key_event.event_string = CORBA_string_dup ("Up");
1227         break;
1228       case XK_Down:
1229         key_event.event_string = CORBA_string_dup ("Down");
1230         break;
1231       case XK_Left:
1232         key_event.event_string = CORBA_string_dup ("Left");
1233         break;
1234       case XK_Right:
1235         key_event.event_string = CORBA_string_dup ("Right");
1236         break;
1237       default:
1238         if (XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL) > 0)
1239           {
1240             key_event.event_string = CORBA_string_dup (cbuf);
1241             if (isgraph (keysym))
1242               {
1243                 key_event.is_text = CORBA_TRUE; /* FIXME: incorrect for some composed chars? */
1244               }
1245           }
1246         else
1247           {
1248             key_event.event_string = CORBA_string_dup ("");
1249           }
1250     }
1251
1252   key_event.timestamp = (CORBA_unsigned_long) x_key_event->time;
1253 #ifdef SPI_KEYEVENT_DEBUG
1254   fprintf (stderr,
1255      "Key %lu pressed (%c), modifiers %d\n",
1256      (unsigned long) keysym,
1257      keysym ? (int) keysym : '*',
1258      (int) x_key_event->state);
1259 #endif
1260 #ifdef SPI_DEBUG
1261   fprintf (stderr, "%s%c",
1262      (x_key_event->state & Mod1Mask)?"Alt-":"",
1263      ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
1264      g_ascii_toupper (keysym) : g_ascii_tolower (keysym));
1265 #endif /* SPI_DEBUG */
1266   return key_event;     
1267 }
1268
1269 static gboolean
1270 spi_controller_update_key_grabs (SpiDEController           *controller,
1271                                  Accessibility_DeviceEvent *recv)
1272 {
1273   GList *l, *next;
1274   gboolean   update_failed = FALSE;
1275   
1276   g_return_val_if_fail (controller != NULL, FALSE);
1277
1278   /*
1279    * masks known to work with default RH 7.1+:
1280    * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
1281    * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
1282    * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
1283    * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
1284    *
1285    * ControlMask grabs are broken, must be in use already
1286    */
1287   for (l = controller->keygrabs_list; l; l = next)
1288     {
1289       gboolean do_remove;
1290       gboolean re_issue_grab;
1291       DEControllerGrabMask *grab_mask = l->data;
1292
1293       next = l->next;
1294
1295       re_issue_grab = recv &&
1296 /*            (recv->type == Accessibility_KEY_RELEASED) && - (?) */
1297               (recv->modifiers & grab_mask->mod_mask) &&
1298               (grab_mask->key_val == keycode_for_keysym (recv->id));
1299
1300 #ifdef SPI_DEBUG
1301       fprintf (stderr, "mask=%lx %lx (%c%c) %s\n",
1302                (long int) grab_mask->key_val,
1303                (long int) grab_mask->mod_mask,
1304                grab_mask->pending_add ? '+' : '.',
1305                grab_mask->pending_remove ? '-' : '.',
1306                re_issue_grab ? "re-issue": "");
1307 #endif
1308
1309       do_remove = FALSE;
1310
1311       if (grab_mask->pending_add && grab_mask->pending_remove)
1312         {
1313           do_remove = TRUE;
1314         }
1315       else if (grab_mask->pending_remove)
1316         {
1317 #ifdef SPI_DEBUG
1318       fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask);
1319 #endif
1320           XUngrabKey (spi_get_display (),
1321                       grab_mask->key_val,
1322                       grab_mask->mod_mask,
1323                       gdk_x11_get_default_root_xwindow ());
1324
1325           do_remove = TRUE;
1326         }
1327       else if (grab_mask->pending_add || re_issue_grab)
1328         {
1329
1330 #ifdef SPI_DEBUG
1331           fprintf (stderr, "grab %d with mask %x\n", grab_mask->key_val, grab_mask->mod_mask);
1332 #endif
1333           XGrabKey (spi_get_display (),
1334                     grab_mask->key_val,
1335                     grab_mask->mod_mask,
1336                     gdk_x11_get_default_root_xwindow (),
1337                     True,
1338                     GrabModeSync,
1339                     GrabModeSync);
1340           XSync (spi_get_display (), False);
1341           update_failed = spi_clear_error_state ();
1342           if (update_failed) {
1343                   while (grab_mask->ref_count > 0) --grab_mask->ref_count;
1344                   do_remove = TRUE;
1345           }
1346         }
1347
1348       grab_mask->pending_add = FALSE;
1349       grab_mask->pending_remove = FALSE;
1350
1351       if (do_remove)
1352         {
1353           g_assert (grab_mask->ref_count <= 0);
1354
1355           controller->keygrabs_list = g_list_delete_link (
1356             controller->keygrabs_list, l);
1357
1358           spi_grab_mask_free (grab_mask);
1359         }
1360
1361     } 
1362
1363   return ! update_failed;
1364 }
1365
1366 /*
1367  * Implemented GObject::finalize
1368  */
1369 static void
1370 spi_device_event_controller_object_finalize (GObject *object)
1371 {
1372   SpiDEController *controller;
1373   DEControllerPrivateData *private;
1374   controller = SPI_DEVICE_EVENT_CONTROLLER (object);
1375
1376 #ifdef SPI_DEBUG
1377   fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
1378 #endif
1379   /* disconnect any special listeners, get rid of outstanding keygrabs */
1380   XUngrabKey (spi_get_display (), AnyKey, AnyModifier, DefaultRootWindow (spi_get_display ()));
1381
1382   private = g_object_get_data (G_OBJECT (controller), "spi-dec-private");
1383   if (private->xkb_desc)
1384           XkbFreeKeyboard (private->xkb_desc, 0, True);
1385   g_free (private);
1386   spi_device_event_controller_parent_class->finalize (object);
1387 }
1388
1389 /*
1390  * CORBA Accessibility::DEController::registerKeystrokeListener
1391  *     method implementation
1392  */
1393 static CORBA_boolean
1394 impl_register_keystroke_listener (PortableServer_Servant                  servant,
1395                                   const Accessibility_DeviceEventListener l,
1396                                   const Accessibility_KeySet             *keys,
1397                                   const Accessibility_ControllerEventMask mask,
1398                                   const Accessibility_EventTypeSeq       *type,
1399                                   const Accessibility_EventListenerMode  *mode,
1400                                   CORBA_Environment                      *ev)
1401 {
1402   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
1403           bonobo_object_from_servant (servant));
1404   DEControllerKeyListener *dec_listener;
1405 #ifdef SPI_DEBUG
1406   fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n",
1407            (void *) l, (unsigned long) mask);
1408 #endif
1409   dec_listener = spi_dec_key_listener_new (l, keys, mask, type, mode, ev);
1410   return spi_controller_register_device_listener (
1411           controller, (DEControllerListener *) dec_listener, ev);
1412 }
1413
1414
1415 /*
1416  * CORBA Accessibility::DEController::registerDeviceEventListener
1417  *     method implementation
1418  */
1419 static CORBA_boolean
1420 impl_register_device_listener (PortableServer_Servant                  servant,
1421                                const Accessibility_DeviceEventListener l,
1422                                const Accessibility_EventTypeSeq       *event_types,
1423                                CORBA_Environment                      *ev)
1424 {
1425   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
1426           bonobo_object_from_servant (servant));
1427   DEControllerListener *dec_listener;
1428
1429   dec_listener = spi_dec_listener_new (l, event_types, ev);
1430   return spi_controller_register_device_listener (
1431           controller, (DEControllerListener *) dec_listener, ev);
1432 }
1433
1434 typedef struct {
1435         CORBA_Environment       *ev;
1436         DEControllerListener    *listener;
1437 } RemoveListenerClosure;
1438
1439 static SpiReEntrantContinue
1440 remove_listener_cb (GList * const *list,
1441                     gpointer       user_data)
1442 {
1443   DEControllerListener  *listener = (*list)->data;
1444   RemoveListenerClosure *ctx = user_data;
1445
1446   if (CORBA_Object_is_equivalent (ctx->listener->object,
1447                                   listener->object, ctx->ev))
1448     {
1449       spi_re_entrant_list_delete_link (list);
1450       spi_dec_listener_free (listener, ctx->ev);
1451     }
1452
1453   return SPI_RE_ENTRANT_CONTINUE;
1454 }
1455
1456 static SpiReEntrantContinue
1457 copy_key_listener_cb (GList * const *list,
1458                       gpointer       user_data)
1459 {
1460   DEControllerKeyListener  *key_listener = (*list)->data;
1461   RemoveListenerClosure    *ctx = user_data;
1462
1463   if (CORBA_Object_is_equivalent (ctx->listener->object,
1464                                   key_listener->listener.object, ctx->ev))
1465     {
1466       /* TODO: FIXME aggregate keys in case the listener is registered twice */
1467       DEControllerKeyListener *ctx_key_listener = 
1468         (DEControllerKeyListener *) ctx->listener; 
1469       CORBA_free (ctx_key_listener->keys);          
1470       ctx_key_listener->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
1471     }
1472
1473   return SPI_RE_ENTRANT_CONTINUE;
1474 }
1475
1476 static void
1477 spi_deregister_controller_device_listener (SpiDEController            *controller,
1478                                            DEControllerListener *listener,
1479                                            CORBA_Environment          *ev)
1480 {
1481   RemoveListenerClosure  ctx;
1482
1483   ctx.ev = ev;
1484   ctx.listener = listener;
1485
1486   spi_re_entrant_list_foreach (&controller->mouse_listeners,
1487                                remove_listener_cb, &ctx);
1488 }
1489
1490 static void
1491 spi_deregister_controller_key_listener (SpiDEController            *controller,
1492                                         DEControllerKeyListener    *key_listener,
1493                                         CORBA_Environment          *ev)
1494 {
1495   RemoveListenerClosure  ctx;
1496
1497   ctx.ev = ev;
1498   ctx.listener = (DEControllerListener *) key_listener;
1499
1500   /* special case, copy keyset from existing controller list entry */
1501   if (key_listener->keys->_length == 0) 
1502     {
1503       spi_re_entrant_list_foreach (&controller->key_listeners,
1504                                   copy_key_listener_cb, &ctx);
1505     }
1506   
1507   spi_controller_deregister_global_keygrabs (controller, key_listener);
1508
1509   spi_re_entrant_list_foreach (&controller->key_listeners,
1510                                 remove_listener_cb, &ctx);
1511
1512 }
1513
1514 /*
1515  * CORBA Accessibility::DEController::deregisterKeystrokeListener
1516  *     method implementation
1517  */
1518 static void
1519 impl_deregister_keystroke_listener (PortableServer_Servant                  servant,
1520                                     const Accessibility_DeviceEventListener l,
1521                                     const Accessibility_KeySet             *keys,
1522                                     const Accessibility_ControllerEventMask mask,
1523                                     const Accessibility_EventTypeSeq       *type,
1524                                     CORBA_Environment                      *ev)
1525 {
1526   DEControllerKeyListener  *key_listener;
1527   SpiDEController *controller;
1528
1529   controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
1530
1531   key_listener = spi_dec_key_listener_new (l, keys, mask, type, NULL, ev);
1532
1533 #ifdef SPI_DEREGISTER_DEBUG
1534   fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
1535            (void *) l, (unsigned long) mask->value);
1536 #endif
1537
1538   spi_deregister_controller_key_listener (controller, key_listener, ev);
1539
1540   spi_dec_listener_free ((DEControllerListener *) key_listener, ev);
1541 }
1542
1543 /*
1544  * CORBA Accessibility::DEController::deregisterDeviceEventListener
1545  *     method implementation
1546  */
1547 static void
1548 impl_deregister_device_listener (PortableServer_Servant                  servant,
1549                                  const Accessibility_DeviceEventListener l,
1550                                  const Accessibility_EventTypeSeq       *event_types,
1551                                  CORBA_Environment                      *ev)
1552 {
1553   SpiDEController *controller;
1554   DEControllerListener *listener = 
1555           spi_dec_listener_new (l, event_types, ev);
1556
1557   controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
1558
1559   spi_deregister_controller_device_listener (controller, listener, ev);
1560
1561   spi_dec_listener_free (listener, ev);
1562 }
1563
1564 static unsigned int dec_xkb_get_slowkeys_delay (SpiDEController *controller)
1565 {
1566   unsigned int retval = 0;
1567   DEControllerPrivateData *priv = (DEControllerPrivateData *)
1568           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
1569 #ifdef HAVE_XKB
1570 #ifdef XKB_HAS_GET_SLOW_KEYS_DELAY      
1571   retval = XkbGetSlowKeysDelay (spi_get_display (),
1572                                 XkbUseCoreKbd, &bounce_delay);
1573 #else
1574   if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
1575     {
1576       Status s = XkbGetControls (spi_get_display (),
1577                                  XkbAllControlsMask, priv->xkb_desc);
1578       if (s == Success)
1579         {
1580          if (priv->xkb_desc->ctrls->enabled_ctrls & XkbSlowKeysMask)
1581                  retval = priv->xkb_desc->ctrls->slow_keys_delay;
1582         }
1583     }
1584 #endif
1585 #endif
1586 #ifdef SPI_XKB_DEBUG
1587         fprintf (stderr, "SlowKeys delay: %d\n", (int) retval);
1588 #endif
1589         return retval;
1590 }
1591
1592 static unsigned int dec_xkb_get_bouncekeys_delay (SpiDEController *controller)
1593 {
1594   unsigned int retval = 0;
1595   DEControllerPrivateData *priv = (DEControllerPrivateData *)
1596           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
1597 #ifdef HAVE_XKB
1598 #ifdef XKB_HAS_GET_BOUNCE_KEYS_DELAY    
1599   retval = XkbGetBounceKeysDelay (spi_get_display (),
1600                                   XkbUseCoreKbd, &bounce_delay);
1601 #else
1602   if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
1603     {
1604       Status s = XkbGetControls (spi_get_display (),
1605                                  XkbAllControlsMask, priv->xkb_desc);
1606       if (s == Success)
1607         {
1608           if (priv->xkb_desc->ctrls->enabled_ctrls & XkbBounceKeysMask)
1609                   retval = priv->xkb_desc->ctrls->debounce_delay;
1610         }
1611     }
1612 #endif
1613 #endif
1614 #ifdef SPI_XKB_DEBUG
1615   fprintf (stderr, "BounceKeys delay: %d\n", (int) retval);
1616 #endif
1617   return retval;
1618 }
1619
1620 static gboolean
1621 dec_synth_keycode_press (SpiDEController *controller,
1622                          unsigned int keycode)
1623 {
1624         unsigned int time = CurrentTime;
1625         unsigned int bounce_delay;
1626         unsigned int elapsed_msec;
1627         struct timeval tv;
1628         DEControllerPrivateData *priv =
1629                 (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller),
1630                                                                 spi_dec_private_quark);
1631         if (keycode == priv->last_release_keycode)
1632         {
1633                 bounce_delay = dec_xkb_get_bouncekeys_delay (controller); 
1634                 if (bounce_delay)
1635                 {
1636                         gettimeofday (&tv, NULL);
1637                         elapsed_msec =
1638                                 (tv.tv_sec - priv->last_release_time.tv_sec) * 1000
1639                                 + (tv.tv_usec - priv->last_release_time.tv_usec) / 1000;
1640 #ifdef SPI_XKB_DEBUG                    
1641                         fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec,
1642                                  (long) (tv.tv_usec - priv->last_release_time.tv_usec));
1643 #endif
1644 #ifdef THIS_IS_BROKEN
1645                         if (elapsed_msec < bounce_delay)
1646                                 time = bounce_delay - elapsed_msec + 1;
1647 #else
1648                         time = bounce_delay + 10;
1649                         /* fudge for broken XTest */
1650 #endif
1651 #ifdef SPI_XKB_DEBUG                    
1652                         fprintf (stderr, "waiting %d ms\n", time);
1653 #endif
1654                 }
1655         }
1656         XTestFakeKeyEvent (spi_get_display (), keycode, True, time);
1657         priv->last_press_keycode = keycode;
1658         XSync (spi_get_display (), False);
1659         gettimeofday (&priv->last_press_time, NULL);
1660         return TRUE;
1661 }
1662
1663 static gboolean
1664 dec_synth_keycode_release (SpiDEController *controller,
1665                            unsigned int keycode)
1666 {
1667         unsigned int time = CurrentTime;
1668         unsigned int slow_delay;
1669         unsigned int elapsed_msec;
1670         struct timeval tv;
1671         DEControllerPrivateData *priv =
1672                 (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller),
1673                                                                 spi_dec_private_quark);
1674         if (keycode == priv->last_press_keycode)
1675         {
1676                 slow_delay = dec_xkb_get_slowkeys_delay (controller);
1677                 if (slow_delay)
1678                 {
1679                         gettimeofday (&tv, NULL);
1680                         elapsed_msec =
1681                                 (tv.tv_sec - priv->last_press_time.tv_sec) * 1000
1682                                 + (tv.tv_usec - priv->last_press_time.tv_usec) / 1000;
1683 #ifdef SPI_XKB_DEBUG                    
1684                         fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec,
1685                                  (long) (tv.tv_usec - priv->last_press_time.tv_usec));
1686 #endif
1687 #ifdef THIS_IS_BROKEN_DUNNO_WHY
1688                         if (elapsed_msec < slow_delay)
1689                                 time = slow_delay - elapsed_msec + 1;
1690 #else
1691                         time = slow_delay + 10;
1692                         /* our XTest seems broken, we have to add slop as above */
1693 #endif
1694 #ifdef SPI_XKB_DEBUG                    
1695                         fprintf (stderr, "waiting %d ms\n", time);
1696 #endif
1697                 }
1698         }
1699         XTestFakeKeyEvent (spi_get_display (), keycode, False, time);
1700         priv->last_release_keycode = keycode;
1701         XSync (spi_get_display (), False);
1702         gettimeofday (&priv->last_release_time, NULL);
1703         return TRUE;
1704 }
1705
1706 /*
1707  * CORBA Accessibility::DEController::registerKeystrokeListener
1708  *     method implementation
1709  */
1710 static void
1711 impl_generate_keyboard_event (PortableServer_Servant           servant,
1712                               const CORBA_long                 keycode,
1713                               const CORBA_char                *keystring,
1714                               const Accessibility_KeySynthType synth_type,
1715                               CORBA_Environment               *ev)
1716 {
1717   SpiDEController *controller =
1718         SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
1719   long key_synth_code;
1720   unsigned int slow_keys_delay;
1721   unsigned int press_time;
1722   unsigned int release_time;
1723
1724 #ifdef SPI_DEBUG
1725         fprintf (stderr, "synthesizing keystroke %ld, type %d\n",
1726                  (long) keycode, (int) synth_type);
1727 #endif
1728   /* TODO: hide/wrap/remove X dependency */
1729
1730   /*
1731    * TODO: when initializing, query for XTest extension before using,
1732    * and fall back to XSendEvent() if XTest is not available.
1733    */
1734   
1735   /* TODO: implement keystring mode also */
1736   gdk_error_trap_push ();
1737   
1738   switch (synth_type)
1739     {
1740       case Accessibility_KEY_PRESS:
1741               dec_synth_keycode_press (controller, keycode);
1742               break;
1743       case Accessibility_KEY_PRESSRELEASE:
1744               dec_synth_keycode_press (controller, keycode);
1745       case Accessibility_KEY_RELEASE:
1746               dec_synth_keycode_release (controller, keycode);
1747               break;
1748       case Accessibility_KEY_SYM:
1749 #ifdef SPI_XKB_DEBUG          
1750               fprintf (stderr, "KeySym synthesis\n");
1751 #endif
1752               key_synth_code = keycode_for_keysym (keycode);
1753               dec_synth_keycode_press (controller, key_synth_code);
1754               dec_synth_keycode_release (controller, key_synth_code);
1755               break;
1756       case Accessibility_KEY_STRING:
1757               fprintf (stderr, "Not yet implemented\n");
1758               break;
1759     }
1760   if (gdk_error_trap_pop ())
1761     {
1762       DBG (-1, g_warning ("Error emitting keystroke"));
1763     }
1764 }
1765
1766 /* Accessibility::DEController::generateMouseEvent */
1767 static void
1768 impl_generate_mouse_event (PortableServer_Servant servant,
1769                            const CORBA_long       x,
1770                            const CORBA_long       y,
1771                            const CORBA_char      *eventName,
1772                            CORBA_Environment     *ev)
1773 {
1774   int button;
1775   gboolean error = FALSE;
1776   Display *display = spi_get_display ();
1777 #ifdef SPI_DEBUG
1778   fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
1779            eventName, (long int) x, (long int) y);
1780 #endif
1781   switch (eventName[0])
1782     {
1783       case 'b':
1784         switch (eventName[1])
1785           {
1786           /* TODO: check number of buttons before parsing */
1787           case '1':
1788                     button = 1;
1789                     break;
1790           case '2':
1791                   button = 2;
1792                   break;
1793           case '3':
1794                   button = 3;
1795                   break;
1796           default:
1797                   error = TRUE;
1798           }
1799         if (!error)
1800           {
1801             if (x != -1 && y != -1)
1802               {
1803                 XTestFakeMotionEvent (display, DefaultScreen (display),
1804                                       x, y, 0);
1805               }
1806             XTestFakeButtonEvent (display, button, !(eventName[2] == 'r'), 0);
1807             if (eventName[2] == 'c')
1808               XTestFakeButtonEvent (display, button, FALSE, 1);
1809             else if (eventName[2] == 'd')
1810               {
1811               XTestFakeButtonEvent (display, button, FALSE, 1);
1812               XTestFakeButtonEvent (display, button, TRUE, 2);
1813               XTestFakeButtonEvent (display, button, FALSE, 3);
1814               }
1815           }
1816         break;
1817       case 'r': /* relative motion */ 
1818         XTestFakeRelativeMotionEvent (display, x, y, 0);
1819         break;
1820       case 'a': /* absolute motion */
1821         XTestFakeMotionEvent (display, DefaultScreen (display),
1822                               x, y, 0);
1823         break;
1824     }
1825 }
1826
1827 /* Accessibility::DEController::notifyListenersSync */
1828 static CORBA_boolean
1829 impl_notify_listeners_sync (PortableServer_Servant           servant,
1830                             const Accessibility_DeviceEvent *event,
1831                             CORBA_Environment               *ev)
1832 {
1833   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
1834     bonobo_object_from_servant (servant));
1835 #ifdef SPI_DEBUG
1836   g_print ("notifylistening listeners synchronously: controller %p, event id %d\n",
1837            controller, (int) event->id);
1838 #endif
1839   return spi_controller_notify_keylisteners (controller, event, CORBA_FALSE, ev) ?
1840           CORBA_TRUE : CORBA_FALSE; 
1841 }
1842
1843 /* Accessibility::DEController::notifyListenersAsync */
1844 static void
1845 impl_notify_listeners_async (PortableServer_Servant           servant,
1846                              const Accessibility_DeviceEvent *event,
1847                              CORBA_Environment               *ev)
1848 {
1849   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
1850     bonobo_object_from_servant (servant));
1851 #ifdef SPI_DEBUG
1852   fprintf (stderr, "notifying listeners asynchronously\n");
1853 #endif
1854   spi_controller_notify_keylisteners (controller, event, CORBA_FALSE, ev); 
1855 }
1856
1857 static void
1858 spi_device_event_controller_class_init (SpiDEControllerClass *klass)
1859 {
1860   GObjectClass * object_class = (GObjectClass *) klass;
1861   POA_Accessibility_DeviceEventController__epv *epv = &klass->epv;
1862
1863   spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
1864   
1865   object_class->finalize = spi_device_event_controller_object_finalize;
1866         
1867   epv->registerKeystrokeListener   = impl_register_keystroke_listener;
1868   epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener;
1869   epv->registerDeviceEventListener = impl_register_device_listener;
1870   epv->deregisterDeviceEventListener = impl_deregister_device_listener;
1871   epv->generateKeyboardEvent       = impl_generate_keyboard_event;
1872   epv->generateMouseEvent          = impl_generate_mouse_event;
1873   epv->notifyListenersSync         = impl_notify_listeners_sync;
1874   epv->notifyListenersAsync        = impl_notify_listeners_async;
1875
1876   if (!spi_dec_private_quark)
1877           spi_dec_private_quark = g_quark_from_static_string ("spi-dec-private");
1878 }
1879
1880 static void
1881 spi_device_event_controller_init (SpiDEController *device_event_controller)
1882 {
1883   DEControllerPrivateData *private;     
1884   device_event_controller->key_listeners   = NULL;
1885   device_event_controller->mouse_listeners = NULL;
1886   device_event_controller->keygrabs_list   = NULL;
1887
1888   /*
1889    * TODO: fixme, this module makes the foolish assumptions that
1890    * registryd uses the same display as the apps, and that the
1891    * DISPLAY environment variable is set.
1892    */
1893   gdk_init (NULL, NULL);
1894   
1895   private = g_new0 (DEControllerPrivateData, 1);
1896   gettimeofday (&private->last_press_time, NULL);
1897   gettimeofday (&private->last_release_time, NULL);
1898   g_object_set_qdata (G_OBJECT (device_event_controller),
1899                       spi_dec_private_quark,
1900                       private);
1901   
1902   spi_controller_register_with_devices (device_event_controller);
1903 }
1904
1905 static void
1906 spi_device_event_controller_forward_key_event (SpiDEController *controller,
1907                                                const XEvent    *event)
1908 {
1909   gboolean is_consumed = FALSE;
1910   CORBA_Environment ev;
1911   Accessibility_DeviceEvent key_event;
1912
1913   g_assert (event->type == KeyPress || event->type == KeyRelease);
1914
1915   CORBA_exception_init (&ev);
1916
1917   key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event);
1918
1919   spi_controller_update_key_grabs (controller, &key_event);
1920
1921   /* relay to listeners, and decide whether to consume it or not */
1922   is_consumed = spi_controller_notify_keylisteners (
1923           controller, &key_event, CORBA_TRUE, &ev);
1924
1925   if (is_consumed)
1926     {
1927       XAllowEvents (spi_get_display (), AsyncKeyboard, CurrentTime);
1928     }
1929   else
1930     {
1931       XAllowEvents (spi_get_display (), ReplayKeyboard, CurrentTime);
1932     }
1933 }
1934
1935 SpiDEController *
1936 spi_device_event_controller_new (SpiRegistry *registry)
1937 {
1938   SpiDEController *retval = g_object_new (
1939     SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
1940   DEControllerPrivateData *private;
1941   
1942   retval->registry = SPI_REGISTRY (bonobo_object_ref (
1943           BONOBO_OBJECT (registry)));
1944
1945   spi_dec_init_mouse_listener (registry);
1946   /* TODO: kill mouse listener on finalize */  
1947   return retval;
1948 }
1949
1950 BONOBO_TYPE_FUNC_FULL (SpiDEController,
1951                        Accessibility_DeviceEventController,
1952                        PARENT_TYPE,
1953                        spi_device_event_controller);