2003-12-03 Padraig O'Briain <padraig.obriain@sun.com>
[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, 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 #include <bonobo/bonobo-exception.h>
37
38 #include <X11/Xlib.h>
39 #include <X11/extensions/XTest.h>
40 #include <X11/XKBlib.h>
41 #define XK_MISCELLANY
42 #include <X11/keysymdef.h>
43
44 #ifdef HAVE_XEVIE
45 #include <X11/Xproto.h>
46 #include <X11/X.h>
47 #include <X11/extensions/Xevie.h>
48 #endif /* HAVE_XEVIE */
49
50 #include <gdk/gdk.h>
51 #include <gdk/gdkx.h> /* TODO: hide dependency (wrap in single porting file) */
52 #include <gdk/gdkkeysyms.h>
53 #include <gdk/gdkwindow.h>
54
55 #include "../libspi/spi-private.h"
56 #include "deviceeventcontroller.h"
57
58 #define CHECK_RELEASE_DELAY 20
59 #define BIT(c, x)       (c[x/8]&(1<<(x%8)))
60 static guint check_release_handler = 0;
61 static Accessibility_DeviceEvent pressed_event;
62 static SpiDEController *saved_controller; 
63 static void wait_for_release_event (GdkEvent *event, SpiDEController *controller);
64
65 /* Our parent Gtk object type */
66 #define PARENT_TYPE BONOBO_TYPE_OBJECT
67
68 /* A pointer to our parent object class */
69 static GObjectClass *spi_device_event_controller_parent_class;
70 static int spi_error_code = 0;
71 static GdkPoint last_mouse_pos_static = {0, 0}; 
72 static GdkPoint *last_mouse_pos = &last_mouse_pos_static;
73 static unsigned int mouse_mask_state = 0;
74 static unsigned int mouse_button_mask =
75   Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
76 static unsigned int key_modifier_mask =
77   Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | LockMask | ControlMask | SPI_KEYMASK_NUMLOCK;
78 static unsigned int _numlock_physical_mask = Mod2Mask; /* a guess, will be reset */
79
80 static GQuark spi_dec_private_quark = 0;
81
82 int (*x_default_error_handler) (Display *display, XErrorEvent *error_event);
83
84 typedef enum {
85   SPI_DEVICE_TYPE_KBD,
86   SPI_DEVICE_TYPE_MOUSE,
87   SPI_DEVICE_TYPE_LAST_DEFINED
88 } SpiDeviceTypeCategory;
89
90 typedef struct {
91   guint                             ref_count : 30;
92   guint                             pending_add : 1;
93   guint                             pending_remove : 1;
94
95   Accessibility_ControllerEventMask mod_mask;
96   CORBA_unsigned_long               key_val;  /* KeyCode */
97 } DEControllerGrabMask;
98
99 typedef struct {
100   CORBA_Object          object;
101   SpiDeviceTypeCategory type;
102   Accessibility_EventTypeSeq    *typeseq;
103 } DEControllerListener;
104
105 typedef struct {
106   DEControllerListener listener;
107
108   Accessibility_KeySet             *keys;
109   Accessibility_ControllerEventMask mask;
110   Accessibility_EventListenerMode  *mode;       
111 } DEControllerKeyListener;
112
113 typedef struct {
114   unsigned int last_press_keycode;
115   unsigned int last_release_keycode;
116   struct timeval last_press_time;
117   struct timeval last_release_time;
118   int have_xkb;
119   int xkb_major_extension_opcode;
120   int xkb_base_event_code;
121   int xkb_base_error_code;
122   unsigned int xkb_latch_mask;
123   unsigned int pending_xkb_mod_relatch_mask;
124   XkbDescPtr xkb_desc;
125 } DEControllerPrivateData;
126
127 static void     spi_controller_register_with_devices          (SpiDEController           *controller);
128 static gboolean spi_controller_update_key_grabs               (SpiDEController           *controller,
129                                                                Accessibility_DeviceEvent *recv);
130 static gboolean spi_controller_register_device_listener       (SpiDEController           *controller,
131                                                                DEControllerListener      *l,
132                                                                CORBA_Environment         *ev);
133 static gboolean spi_device_event_controller_forward_key_event (SpiDEController           *controller,
134                                                                const XEvent              *event);
135 static void     spi_deregister_controller_device_listener (SpiDEController            *controller,
136                                                            DEControllerListener *listener,
137                                                            CORBA_Environment          *ev);
138 static void     spi_deregister_controller_key_listener (SpiDEController         *controller,
139                                                         DEControllerKeyListener *key_listener,
140                                                         CORBA_Environment       *ev);
141 static gboolean spi_controller_notify_mouselisteners (SpiDEController                 *controller,
142                                                       const Accessibility_DeviceEvent *event,
143                                                       CORBA_Environment               *ev);
144
145 static gboolean spi_eventtype_seq_contains_event (Accessibility_EventTypeSeq      *type_seq,
146                                                   const Accessibility_DeviceEvent *event);
147 static gboolean spi_clear_error_state (void);
148 static gboolean spi_dec_poll_mouse_moved (gpointer data);
149 static gboolean spi_dec_poll_mouse_moving (gpointer data);
150 static gboolean spi_dec_poll_mouse_idle (gpointer data);
151
152 #define spi_get_display() GDK_DISPLAY()
153
154 /* Private methods */
155
156 static unsigned int
157 keysym_mod_mask (KeySym keysym, KeyCode keycode)
158 {
159         /* we really should use XKB and look directly at the keymap */
160         /* this is very inelegant */
161         Display *display = spi_get_display ();
162         unsigned int mods_rtn = 0;
163         unsigned int retval = 0;
164         KeySym sym_rtn;
165
166         if (XkbLookupKeySym (display, keycode, 0, &mods_rtn, &sym_rtn) &&
167             (sym_rtn == keysym)) {
168                 retval = 0;
169         }
170         else if (XkbLookupKeySym (display, keycode, ShiftMask, &mods_rtn, &sym_rtn) &&
171                  (sym_rtn == keysym)) {
172                 retval = ShiftMask;
173         }
174         else if (XkbLookupKeySym (display, keycode, Mod2Mask, &mods_rtn, &sym_rtn) &&
175                  (sym_rtn == keysym)) {
176                 retval = Mod2Mask;
177         }
178         else if (XkbLookupKeySym (display, keycode, Mod3Mask, &mods_rtn, &sym_rtn) &&
179                  (sym_rtn == keysym)) {
180                 retval = Mod3Mask;
181         }
182         else if (XkbLookupKeySym (display, keycode, 
183                                   ShiftMask | Mod2Mask, &mods_rtn, &sym_rtn) &&
184                  (sym_rtn == keysym)) {
185                 retval = (Mod2Mask | ShiftMask);
186         }
187         else if (XkbLookupKeySym (display, keycode, 
188                                   ShiftMask | Mod3Mask, &mods_rtn, &sym_rtn) &&
189                  (sym_rtn == keysym)) {
190                 retval = (Mod3Mask | ShiftMask);
191         }
192         else if (XkbLookupKeySym (display, keycode, 
193                                   ShiftMask | Mod4Mask, &mods_rtn, &sym_rtn) &&
194                  (sym_rtn == keysym)) {
195                 retval = (Mod4Mask | ShiftMask);
196         }
197         else
198                 retval = 0xFFFF;
199         return retval;
200 }
201
202 static KeyCode
203 keycode_for_keysym (long keysym, unsigned int *modmask)
204 {
205         KeyCode keycode = 0;
206         keycode = XKeysymToKeycode (spi_get_display (), (KeySym) keysym);
207         if (modmask) 
208                 *modmask = keysym_mod_mask (keysym, keycode);
209         return keycode;
210 }
211
212 static DEControllerGrabMask *
213 spi_grab_mask_clone (DEControllerGrabMask *grab_mask)
214 {
215   DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1);
216
217   memcpy (clone, grab_mask, sizeof (DEControllerGrabMask));
218
219   clone->ref_count = 1;
220   clone->pending_add = TRUE;
221   clone->pending_remove = FALSE;
222
223   return clone;
224 }
225
226 static void
227 spi_grab_mask_free (DEControllerGrabMask *grab_mask)
228 {
229   g_free (grab_mask);
230 }
231
232 static gint
233 spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2)
234 {
235   DEControllerGrabMask *l1 = (DEControllerGrabMask *) p1;
236   DEControllerGrabMask *l2 = (DEControllerGrabMask *) p2;
237
238   if (p1 == p2)
239     {
240       return 0;
241     }
242   else
243     { 
244       return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val));
245     }
246 }
247
248 static void
249 spi_dec_set_unlatch_pending (SpiDEController *controller, unsigned mask)
250 {
251   DEControllerPrivateData *priv = 
252     g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
253 #ifdef SPI_XKB_DEBUG
254   if (priv->xkb_latch_mask) fprintf (stderr, "unlatch pending! %x\n", 
255                                      priv->xkb_latch_mask);
256 #endif
257   priv->pending_xkb_mod_relatch_mask |= priv->xkb_latch_mask; 
258 }
259  
260 static void
261 spi_dec_clear_unlatch_pending (SpiDEController *controller)
262 {
263   DEControllerPrivateData *priv = 
264     g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
265   priv->xkb_latch_mask = 0; 
266 }
267  
268 static gboolean
269 spi_dec_button_update_and_emit (SpiDEController *controller, 
270                                 guint mask_return)
271 {
272   CORBA_Environment ev;
273   Accessibility_Event e;
274   Accessibility_DeviceEvent mouse_e;
275   gchar event_name[24];
276   gboolean is_consumed = FALSE;
277
278   if ((mask_return & mouse_button_mask) !=
279       (mouse_mask_state & mouse_button_mask)) 
280     {
281       int button_number = 0;
282       gboolean is_down = False;
283       
284       if (!(mask_return & Button1Mask) &&
285           (mouse_mask_state & Button1Mask)) 
286         {
287           mouse_mask_state &= ~Button1Mask;
288           button_number = 1;
289         } 
290       else if ((mask_return & Button1Mask) &&
291                !(mouse_mask_state & Button1Mask)) 
292         {
293           mouse_mask_state |= Button1Mask;
294           button_number = 1;
295           is_down = True;
296         } 
297       else if (!(mask_return & Button2Mask) &&
298                (mouse_mask_state & Button2Mask)) 
299         {
300           mouse_mask_state &= ~Button2Mask;
301           button_number = 2;
302         } 
303       else if ((mask_return & Button2Mask) &&
304                !(mouse_mask_state & Button2Mask)) 
305         {
306           mouse_mask_state |= Button2Mask;
307           button_number = 2;
308           is_down = True;
309         } 
310       else if (!(mask_return & Button3Mask) &&
311                (mouse_mask_state & Button3Mask)) 
312         {
313           mouse_mask_state &= ~Button3Mask;
314           button_number = 3;
315         } 
316       else if ((mask_return & Button3Mask) &&
317                !(mouse_mask_state & Button3Mask)) 
318         {
319           mouse_mask_state |= Button3Mask;
320           button_number = 3;
321           is_down = True;
322         } 
323       else if (!(mask_return & Button4Mask) &&
324                (mouse_mask_state & Button4Mask)) 
325         {
326           mouse_mask_state &= ~Button4Mask;
327           button_number = 4;
328         } 
329       else if ((mask_return & Button4Mask) &&
330                !(mouse_mask_state & Button4Mask)) 
331         {
332           mouse_mask_state |= Button4Mask;
333           button_number = 4;
334           is_down = True;
335         } 
336       else if (!(mask_return & Button5Mask) &&
337                (mouse_mask_state & Button5Mask)) 
338         {
339           mouse_mask_state &= ~Button5Mask;
340           button_number = 5;
341         }
342       else if ((mask_return & Button5Mask) &&
343                !(mouse_mask_state & Button5Mask)) 
344         {
345           mouse_mask_state |= Button5Mask;
346           button_number = 5;
347           is_down = True;
348         }
349       if (button_number) {
350 #ifdef SPI_DEBUG                  
351         fprintf (stderr, "Button %d %s\n",
352                  button_number, (is_down) ? "Pressed" : "Released");
353 #endif
354         snprintf (event_name, 22, "mouse:button:%d%c", button_number,
355                   (is_down) ? 'p' : 'r');
356         /* TODO: FIXME distinguish between physical and 
357          * logical buttons 
358          */
359         mouse_e.type      = (is_down) ? 
360           Accessibility_BUTTON_PRESSED_EVENT :
361           Accessibility_BUTTON_RELEASED_EVENT;
362         mouse_e.id        = button_number;
363         mouse_e.hw_code   = button_number;
364         mouse_e.modifiers = (CORBA_unsigned_short) mouse_mask_state; 
365         mouse_e.timestamp = 0;
366         mouse_e.event_string = "";
367         mouse_e.is_text   = CORBA_FALSE;
368         is_consumed = 
369           spi_controller_notify_mouselisteners (controller, 
370                                                 &mouse_e, 
371                                                 &ev);
372         e.type = event_name;
373         e.source = BONOBO_OBJREF (controller->registry->desktop);
374         e.detail1 = last_mouse_pos->x;
375         e.detail2 = last_mouse_pos->y;
376         spi_init_any_nil (&e.any_data);
377         CORBA_exception_init (&ev);
378         if (!is_consumed)
379           {
380             Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
381                                                 &e,
382                                                 &ev);  
383           }
384         else
385           spi_dec_set_unlatch_pending (controller, mask_return);
386       }
387       return TRUE;
388     }
389   else
390     {
391       return FALSE;
392     }
393 }
394
395
396 static guint
397 spi_dec_mouse_check (SpiDEController *controller, 
398                      int *x, int *y, gboolean *moved)
399 {
400   Accessibility_Event e;
401   CORBA_Environment ev;
402   int win_x_return,win_y_return;
403   unsigned int mask_return;
404   Window root_return, child_return;
405   Display *display = spi_get_display ();
406
407   if (display != NULL)
408     XQueryPointer(display, DefaultRootWindow (display),
409                   &root_return, &child_return,
410                   x, y,
411                   &win_x_return, &win_y_return, &mask_return);
412   /* 
413    * Since many clients grab the pointer, and X goes an automatic
414    * pointer grab on mouse-down, we often must detect mouse button events
415    * by polling rather than via a button grab. 
416    * The while loop (rather than if) is used since it's possible that 
417    * multiple buttons have changed state since we last checked.
418    */
419   if (mask_return != mouse_mask_state) 
420     {
421       while (spi_dec_button_update_and_emit (controller, mask_return));
422     }
423
424   if (*x != last_mouse_pos->x || *y != last_mouse_pos->y) 
425     {
426       e.type = "mouse:abs";  
427       e.source = BONOBO_OBJREF (controller->registry->desktop);
428       e.detail1 = *x;
429       e.detail2 = *y;
430       spi_init_any_nil (&e.any_data);
431       CORBA_exception_init (&ev);
432       Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
433                                           &e,
434                                           &ev);
435       e.type = "mouse:rel";  
436       e.source = BONOBO_OBJREF (controller->registry->desktop);
437       e.detail1 = *x - last_mouse_pos->x;
438       e.detail2 = *y - last_mouse_pos->y;
439       spi_init_any_nil (&e.any_data);
440       CORBA_exception_init (&ev);
441       last_mouse_pos->x = *x;
442       last_mouse_pos->y = *y;
443       Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
444                                           &e,
445                                           &ev);
446       *moved = True;
447     }
448   else
449     {
450       *moved = False;
451     }
452
453   return mask_return;
454 }
455
456 static void
457 spi_dec_emit_modifier_event (SpiDEController *controller, guint prev_mask, 
458                              guint current_mask)
459 {
460   Accessibility_Event e;
461   CORBA_Environment ev;
462
463 #ifdef SPI_XKB_DEBUG
464   fprintf (stderr, "MODIFIER CHANGE EVENT! %x to %x\n", 
465            prev_mask, current_mask);
466 #endif
467
468   /* set bits for the virtual modifiers like NUMLOCK */
469   if (prev_mask & _numlock_physical_mask) 
470     prev_mask |= SPI_KEYMASK_NUMLOCK;
471   if (current_mask & _numlock_physical_mask) 
472     current_mask |= SPI_KEYMASK_NUMLOCK;
473
474   e.type = "keyboard:modifiers";  
475   e.source = BONOBO_OBJREF (controller->registry->desktop);
476   e.detail1 = prev_mask & key_modifier_mask;
477   e.detail2 = current_mask & key_modifier_mask;
478   spi_init_any_nil (&e.any_data);
479   CORBA_exception_init (&ev);
480   Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
481                                       &e,
482                                       &ev);
483 }
484
485 static gboolean
486 spi_dec_poll_mouse_moved (gpointer data)
487 {
488   SpiRegistry *registry = SPI_REGISTRY (data);
489   SpiDEController *controller = registry->de_controller;
490   int x, y;  
491   gboolean moved;
492   guint mask_return;
493
494   mask_return = spi_dec_mouse_check (controller, &x, &y, &moved);
495   
496   if ((mask_return & key_modifier_mask) !=
497       (mouse_mask_state & key_modifier_mask)) 
498     {
499       spi_dec_emit_modifier_event (controller, mouse_mask_state, mask_return);
500       mouse_mask_state = mask_return;
501     }
502
503   return moved;
504 }
505
506 static gboolean
507 spi_dec_poll_mouse_idle (gpointer data)
508 {
509   if (! spi_dec_poll_mouse_moved (data)) 
510     return TRUE;
511   else
512     {
513       g_timeout_add (20, spi_dec_poll_mouse_moving, data);          
514       return FALSE;         
515     }
516 }
517
518 static gboolean
519 spi_dec_poll_mouse_moving (gpointer data)
520 {
521   if (spi_dec_poll_mouse_moved (data))
522     return TRUE;
523   else
524     {
525       g_timeout_add (100, spi_dec_poll_mouse_idle, data);           
526       return FALSE;
527     }
528 }
529
530 #ifdef WE_NEED_UGRAB_MOUSE
531 static int
532 spi_dec_ungrab_mouse (gpointer data)
533 {
534         Display *display = spi_get_display ();
535         if (display)
536           {
537             XUngrabButton (spi_get_display (), AnyButton, AnyModifier,
538                            XDefaultRootWindow (spi_get_display ()));
539           }
540         return FALSE;
541 }
542 #endif
543
544 static void
545 spi_dec_init_mouse_listener (SpiRegistry *registry)
546 {
547   Display *display = spi_get_display ();
548   g_timeout_add (100, spi_dec_poll_mouse_idle, registry);
549
550   if (display)
551     {
552       if (XGrabButton (display, AnyButton, AnyModifier,
553                        gdk_x11_get_default_root_xwindow (),
554                        True, ButtonPressMask | ButtonReleaseMask,
555                        GrabModeSync, GrabModeAsync, None, None) != Success) {
556 #ifdef SPI_DEBUG
557         fprintf (stderr, "WARNING: could not grab mouse buttons!\n");
558 #endif
559         ;
560       }
561       XSync (display, False);
562 #ifdef SPI_DEBUG
563       fprintf (stderr, "mouse buttons grabbed\n");
564 #endif
565     }
566 }
567
568 /**
569  * Eventually we can use this to make the marshalling of mask types
570  * more sane, but for now we just use this to detect 
571  * the use of 'virtual' masks such as Mumlock and convert them to
572  * system-specific mask values (i.e. ModMask).
573  * 
574  **/
575 static Accessibility_ControllerEventMask
576 spi_dec_translate_mask (Accessibility_ControllerEventMask mask)
577 {
578   if (mask == SPI_KEYMASK_NUMLOCK) {
579     mask = _numlock_physical_mask;
580   }
581   return mask;
582 }
583
584 static DEControllerKeyListener *
585 spi_dec_key_listener_new (CORBA_Object                            l,
586                           const Accessibility_KeySet             *keys,
587                           const Accessibility_ControllerEventMask mask,
588                           const Accessibility_EventTypeSeq    *typeseq,
589                           const Accessibility_EventListenerMode  *mode,
590                           CORBA_Environment                      *ev)
591 {
592   DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1);
593   key_listener->listener.object = bonobo_object_dup_ref (l, ev);
594   key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
595   key_listener->keys = ORBit_copy_value (keys, TC_Accessibility_KeySet);
596   key_listener->mask = spi_dec_translate_mask (mask);
597   key_listener->listener.typeseq = ORBit_copy_value (typeseq, TC_Accessibility_EventTypeSeq);
598   if (mode)
599     key_listener->mode = ORBit_copy_value (mode, TC_Accessibility_EventListenerMode);
600   else
601     key_listener->mode = NULL;
602
603 #ifdef SPI_DEBUG
604   g_print ("new listener, with mask %x, is_global %d, keys %p (%d)\n",
605            (unsigned int) key_listener->mask,
606            (int) (mode ? mode->global : 0),
607            (void *) key_listener->keys,
608            (int) (key_listener->keys ? key_listener->keys->_length : 0));
609 #endif
610
611   return key_listener;  
612 }
613
614 static DEControllerListener *
615 spi_dec_listener_new (CORBA_Object                            l,
616                       const Accessibility_EventTypeSeq    *typeseq,
617                       CORBA_Environment                      *ev)
618 {
619   DEControllerListener *listener = g_new0 (DEControllerListener, 1);
620   listener->object = bonobo_object_dup_ref (l, ev);
621   listener->type = SPI_DEVICE_TYPE_MOUSE;
622   listener->typeseq = ORBit_copy_value (typeseq, TC_Accessibility_EventTypeSeq);
623   return listener;      
624 }
625
626 static DEControllerListener *
627 spi_listener_clone (DEControllerListener *listener, CORBA_Environment *ev)
628 {
629   DEControllerListener *clone = g_new0 (DEControllerListener, 1);
630   clone->object =
631           CORBA_Object_duplicate (listener->object, ev);
632   clone->type = listener->type;
633   clone->typeseq = ORBit_copy_value (listener->typeseq, TC_Accessibility_EventTypeSeq);
634   return clone;
635 }
636
637 static DEControllerKeyListener *
638 spi_key_listener_clone (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
639 {
640   DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1);
641   clone->listener.object =
642           CORBA_Object_duplicate (key_listener->listener.object, ev);
643   clone->listener.type = SPI_DEVICE_TYPE_KBD;
644   clone->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
645   clone->mask = key_listener->mask;
646   clone->listener.typeseq = ORBit_copy_value (key_listener->listener.typeseq, TC_Accessibility_EventTypeSeq);
647   if (key_listener->mode)
648     clone->mode = ORBit_copy_value (key_listener->mode, TC_Accessibility_EventListenerMode);
649   else
650     clone->mode = NULL;
651   return clone;
652 }
653
654 static void
655 spi_key_listener_data_free (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
656 {
657   CORBA_free (key_listener->listener.typeseq);
658   CORBA_free (key_listener->keys);
659   g_free (key_listener);
660 }
661
662 static void
663 spi_key_listener_clone_free (DEControllerKeyListener *clone, CORBA_Environment *ev)
664 {
665   CORBA_Object_release (clone->listener.object, ev);
666   spi_key_listener_data_free (clone, ev);
667 }
668
669 static void
670 spi_listener_clone_free (DEControllerListener *clone, CORBA_Environment *ev)
671 {
672   CORBA_Object_release (clone->object, ev);
673   CORBA_free (clone->typeseq);
674   g_free (clone);
675 }
676
677 static void
678 spi_dec_listener_free (DEControllerListener    *listener,
679                        CORBA_Environment       *ev)
680 {
681   bonobo_object_release_unref (listener->object, ev);
682   if (listener->type == SPI_DEVICE_TYPE_KBD) 
683     spi_key_listener_data_free ((DEControllerKeyListener *) listener, ev);
684 }
685
686 static void
687 _register_keygrab (SpiDEController      *controller,
688                    DEControllerGrabMask *grab_mask)
689 {
690   GList *l;
691
692   l = g_list_find_custom (controller->keygrabs_list, grab_mask,
693                           spi_grab_mask_compare_values);
694   if (l)
695     {
696       DEControllerGrabMask *cur_mask = l->data;
697
698       cur_mask->ref_count++;
699       if (cur_mask->pending_remove)
700         {
701           cur_mask->pending_remove = FALSE;
702         }
703     }
704   else
705     {
706       controller->keygrabs_list =
707         g_list_prepend (controller->keygrabs_list,
708                         spi_grab_mask_clone (grab_mask));
709     }
710 }
711
712 static void
713 _deregister_keygrab (SpiDEController      *controller,
714                      DEControllerGrabMask *grab_mask)
715 {
716   GList *l;
717
718   l = g_list_find_custom (controller->keygrabs_list, grab_mask,
719                           spi_grab_mask_compare_values);
720
721   if (l)
722     {
723       DEControllerGrabMask *cur_mask = l->data;
724
725       cur_mask->ref_count--;
726       if (cur_mask->ref_count <= 0)
727         {
728           cur_mask->pending_remove = TRUE;
729         }
730     }
731   else
732     {
733       DBG (1, g_warning ("De-registering non-existant grab"));
734     }
735 }
736
737 static void
738 handle_keygrab (SpiDEController         *controller,
739                 DEControllerKeyListener *key_listener,
740                 void                   (*process_cb) (SpiDEController *controller,
741                                                       DEControllerGrabMask *grab_mask))
742 {
743   DEControllerGrabMask grab_mask = { 0 };
744
745   grab_mask.mod_mask = key_listener->mask;
746   if (key_listener->keys->_length == 0) /* special case means AnyKey/AllKeys */
747     {
748       grab_mask.key_val = AnyKey;
749 #ifdef SPI_DEBUG
750       fprintf (stderr, "AnyKey grab!");
751 #endif
752       process_cb (controller, &grab_mask);
753     }
754   else
755     {
756       int i;
757
758       for (i = 0; i < key_listener->keys->_length; ++i)
759         {
760           Accessibility_KeyDefinition keydef = key_listener->keys->_buffer[i];  
761           long int key_val = keydef.keysym;
762           /* X Grabs require keycodes, not keysyms */
763           if (keydef.keystring && keydef.keystring[0])
764             {
765               key_val = XStringToKeysym(keydef.keystring);                  
766             }
767           if (key_val > 0)
768             {
769               key_val = XKeysymToKeycode (spi_get_display (), (KeySym) key_val);
770             }
771           else
772             {
773               key_val = keydef.keycode;
774             }
775           grab_mask.key_val = key_val;
776           process_cb (controller, &grab_mask);
777         }
778     }
779 }
780
781 static gboolean
782 spi_controller_register_global_keygrabs (SpiDEController         *controller,
783                                          DEControllerKeyListener *key_listener)
784 {
785   handle_keygrab (controller, key_listener, _register_keygrab);
786   if (controller->xevie_display == NULL)
787     return spi_controller_update_key_grabs (controller, NULL);
788   else
789     return TRUE;
790 }
791
792 static void
793 spi_controller_deregister_global_keygrabs (SpiDEController         *controller,
794                                            DEControllerKeyListener *key_listener)
795 {
796   handle_keygrab (controller, key_listener, _deregister_keygrab);
797   if (controller->xevie_display == NULL)
798     spi_controller_update_key_grabs (controller, NULL);
799 }
800
801 static gboolean
802 spi_controller_register_device_listener (SpiDEController      *controller,
803                                          DEControllerListener *listener,
804                                          CORBA_Environment    *ev)
805 {
806   DEControllerKeyListener *key_listener;
807   
808   switch (listener->type) {
809   case SPI_DEVICE_TYPE_KBD:
810       key_listener = (DEControllerKeyListener *) listener;
811
812       controller->key_listeners = g_list_prepend (controller->key_listeners,
813                                                   key_listener);
814       if (key_listener->mode->global)
815         {
816           return spi_controller_register_global_keygrabs (controller, key_listener);    
817         }
818       else
819               return TRUE;
820       break;
821   case SPI_DEVICE_TYPE_MOUSE:
822       controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
823       break;
824   default:
825       DBG (1, g_warning ("listener registration for unknown device type.\n"));
826       break;
827   }
828   return FALSE; 
829 }
830
831 static gboolean
832 spi_controller_notify_mouselisteners (SpiDEController                 *controller,
833                                       const Accessibility_DeviceEvent *event,
834                                       CORBA_Environment               *ev)
835 {
836   GList   *l;
837   GSList  *notify = NULL, *l2;
838   GList  **listeners = &controller->mouse_listeners;
839   gboolean is_consumed;
840   gboolean found = FALSE;
841
842   if (!listeners)
843     {
844       return FALSE;
845     }
846
847   for (l = *listeners; l; l = l->next)
848     {
849        DEControllerListener *listener = l->data;
850
851        if (spi_eventtype_seq_contains_event (listener->typeseq, event))
852          {
853            Accessibility_DeviceEventListener ls = listener->object;
854
855            if (ls != CORBA_OBJECT_NIL)
856              {
857                /* we clone (don't dup) the listener, to avoid refcount inc. */
858                notify = g_slist_prepend (notify,
859                                          spi_listener_clone (listener, ev));
860                found = TRUE;
861              }
862          }
863     }
864
865 #ifdef SPI_KEYEVENT_DEBUG
866   if (!found)
867     {
868       g_print ("no match for event\n");
869     }
870 #endif
871
872   is_consumed = FALSE;
873   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
874     {
875       DEControllerListener *listener = l2->data;            
876       Accessibility_DeviceEventListener ls = listener->object;
877
878       CORBA_exception_init (ev);
879       is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, event, ev);
880       if (BONOBO_EX (ev))
881         {
882           is_consumed = FALSE;
883           DBG (2, g_warning ("error notifying listener, removing it\n"));
884           spi_deregister_controller_device_listener (controller, listener,
885                                                      ev);
886           CORBA_exception_free (ev);
887         }
888       
889       spi_listener_clone_free ((DEControllerListener *) l2->data, ev);
890     }
891
892   for (; l2; l2 = l2->next)
893     {
894       DEControllerListener *listener = l2->data;            
895       spi_listener_clone_free (listener, ev);
896       /* clone doesn't have its own ref, so don't use spi_device_listener_free */
897     }
898
899   g_slist_free (notify);
900
901 #ifdef SPI_DEBUG
902   if (is_consumed) g_message ("consumed\n");
903 #endif
904   return is_consumed;
905 }
906
907 static void
908 spi_device_event_controller_forward_mouse_event (SpiDEController *controller,
909                                                  XEvent *xevent)
910 {
911   Accessibility_Event e;
912   Accessibility_DeviceEvent mouse_e;
913   CORBA_Environment ev;
914   gchar event_name[24];
915   gboolean is_consumed = FALSE;
916   gboolean xkb_mod_unlatch_occurred;
917   XButtonEvent *xbutton_event = (XButtonEvent *) xevent;
918
919   int button = xbutton_event->button;
920   
921   unsigned int mouse_button_state = xbutton_event->state;
922
923   switch (button)
924     {
925     case 1:
926             mouse_button_state |= Button1Mask;
927             break;
928     case 2:
929             mouse_button_state |= Button2Mask;
930             break;
931     case 3:
932             mouse_button_state |= Button3Mask;
933             break;
934     case 4:
935             mouse_button_state |= Button4Mask;
936             break;
937     case 5:
938             mouse_button_state |= Button5Mask;
939             break;
940     }
941
942   last_mouse_pos->x = ((XButtonEvent *) xevent)->x_root;
943   last_mouse_pos->y = ((XButtonEvent *) xevent)->y_root;
944
945 #ifdef SPI_DEBUG  
946   fprintf (stderr, "mouse button %d %s (%x)\n",
947            xbutton_event->button, 
948            (xevent->type == ButtonPress) ? "Press" : "Release",
949            mouse_button_state);
950 #endif
951   snprintf (event_name, 22, "mouse:button:%d%c", button,
952             (xevent->type == ButtonPress) ? 'p' : 'r');
953
954   /* TODO: FIXME distinguish between physical and logical buttons */
955   mouse_e.type      = (xevent->type == ButtonPress) ? 
956                       Accessibility_BUTTON_PRESSED_EVENT :
957                       Accessibility_BUTTON_RELEASED_EVENT;
958   mouse_e.id        = button;
959   mouse_e.hw_code   = button;
960   mouse_e.modifiers = (CORBA_unsigned_short) xbutton_event->state;
961   mouse_e.timestamp = (CORBA_unsigned_long) xbutton_event->time;
962   mouse_e.event_string = "";
963   mouse_e.is_text   = CORBA_FALSE;
964   if ((mouse_button_state & mouse_button_mask) != 
965        (mouse_mask_state & mouse_button_mask))
966     { 
967       if ((mouse_mask_state & key_modifier_mask) !=
968           (mouse_button_state & key_modifier_mask))
969         spi_dec_emit_modifier_event (controller, 
970                                      mouse_mask_state, mouse_button_state);
971       mouse_mask_state = mouse_button_state;
972       is_consumed = 
973         spi_controller_notify_mouselisteners (controller, &mouse_e, &ev);
974       e.type = CORBA_string_dup (event_name);
975       e.source = BONOBO_OBJREF (controller->registry->desktop);
976       e.detail1 = last_mouse_pos->x;
977       e.detail2 = last_mouse_pos->y;
978       spi_init_any_nil (&e.any_data);
979       CORBA_exception_init (&ev);
980       
981       Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
982                                           &e,
983                                           &ev);
984     }
985
986   xkb_mod_unlatch_occurred = (xevent->type == ButtonPress ||
987                               xevent->type == ButtonRelease);
988   
989   /* if client wants to consume this event, and XKB latch state was
990    *   unset by this button event, we reset it
991    */
992   if (is_consumed && xkb_mod_unlatch_occurred)
993     spi_dec_set_unlatch_pending (controller, mouse_mask_state);
994   
995   XAllowEvents (spi_get_display (),
996                 (is_consumed) ? SyncPointer : ReplayPointer,
997                 CurrentTime);
998 }
999
1000 static GdkFilterReturn
1001 global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
1002 {
1003   XEvent *xevent = gdk_xevent;
1004   SpiDEController *controller;
1005   DEControllerPrivateData *priv;
1006   Display *display = spi_get_display ();
1007   controller = SPI_DEVICE_EVENT_CONTROLLER (data);
1008   priv = (DEControllerPrivateData *)
1009           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);  
1010
1011   if (xevent->type == KeyPress || xevent->type == KeyRelease)
1012     {
1013       if (controller->xevie_display == NULL)
1014         {
1015           gboolean is_consumed =
1016             spi_device_event_controller_forward_key_event (controller, xevent);
1017
1018           if (is_consumed)
1019             XAllowEvents (spi_get_display (), AsyncKeyboard, CurrentTime);
1020           else
1021             {
1022               wait_for_release_event (event, controller);
1023               XAllowEvents (spi_get_display (), ReplayKeyboard, CurrentTime);
1024             }
1025         }
1026
1027       return GDK_FILTER_CONTINUE;
1028     }
1029   if (xevent->type == ButtonPress || xevent->type == ButtonRelease)
1030     {
1031       spi_device_event_controller_forward_mouse_event (controller, xevent);
1032     }
1033   if (xevent->type == priv->xkb_base_event_code)
1034     {
1035       XkbAnyEvent * xkb_ev = (XkbAnyEvent *) xevent;
1036       /* ugly but probably necessary...*/
1037       XSynchronize (spi_get_display (), TRUE);
1038
1039       if (xkb_ev->xkb_type == XkbStateNotify)
1040         {
1041           XkbStateNotifyEvent *xkb_snev =
1042                   (XkbStateNotifyEvent *) xkb_ev;
1043           /* check the mouse, to catch mouse events grabbed by
1044            * another client; in case we should revert this XKB delatch 
1045            */
1046           if (!priv->pending_xkb_mod_relatch_mask)
1047             {
1048               int x, y;
1049               gboolean moved;
1050               spi_dec_mouse_check (controller, &x, &y, &moved);
1051             }
1052           /* we check again, since the previous call may have 
1053              changed this flag */
1054           if (priv->pending_xkb_mod_relatch_mask)
1055             {
1056               unsigned int feedback_mask;
1057 #ifdef SPI_XKB_DEBUG
1058               fprintf (stderr, "relatching %x\n",
1059                        priv->pending_xkb_mod_relatch_mask);
1060 #endif
1061               /* temporarily turn off the latch bell, if it's on */
1062               XkbGetControls (display,
1063                               XkbAccessXFeedbackMask,
1064                               priv->xkb_desc);
1065               feedback_mask = priv->xkb_desc->ctrls->ax_options;
1066               if (feedback_mask & XkbAX_StickyKeysFBMask)
1067               {
1068                 XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
1069                                                  0, False};      
1070                 priv->xkb_desc->ctrls->ax_options
1071                               &= ~(XkbAX_StickyKeysFBMask);
1072                 XkbChangeControls (display, priv->xkb_desc, &changes);
1073               }
1074               /* TODO: account for lock as well as latch */
1075               XkbLatchModifiers (display,
1076                                  XkbUseCoreKbd,
1077                                  priv->pending_xkb_mod_relatch_mask,
1078                                  priv->pending_xkb_mod_relatch_mask);
1079               if (feedback_mask & XkbAX_StickyKeysFBMask)
1080               { 
1081                 XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
1082                                                  0, False};      
1083                 priv->xkb_desc->ctrls->ax_options = feedback_mask;
1084                 XkbChangeControls (display, priv->xkb_desc, &changes);
1085               }
1086 #ifdef SPI_XKB_DEBUG
1087               fprintf (stderr, "relatched %x\n",
1088                        priv->pending_xkb_mod_relatch_mask);
1089 #endif
1090               priv->pending_xkb_mod_relatch_mask = 0;
1091             }
1092           else
1093             {
1094               priv->xkb_latch_mask = xkb_snev->latched_mods;
1095             }
1096         }
1097         else
1098                DBG (2, g_warning ("XKB event %d\n", xkb_ev->xkb_type));
1099       XSynchronize (spi_get_display (), FALSE);
1100     }
1101   
1102   return GDK_FILTER_CONTINUE;
1103 }
1104
1105 int
1106 _spi_controller_device_error_handler (Display *display, XErrorEvent *error)
1107 {
1108   if (error->error_code == BadAccess) 
1109     {  
1110       g_message ("Could not complete key grab: grab already in use.\n");
1111       spi_error_code = BadAccess;
1112       return 0;
1113     }
1114   else 
1115     {
1116       return (*x_default_error_handler) (display, error);
1117     }
1118 }
1119
1120 static void
1121 spi_controller_register_with_devices (SpiDEController *controller)
1122 {
1123   DEControllerPrivateData *priv = (DEControllerPrivateData *) 
1124           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);     
1125   /* FIXME: should check for extension first! */
1126   XTestGrabControl (spi_get_display (), True);
1127
1128   /* calls to device-specific implementations and routines go here */
1129   /* register with: keyboard hardware code handler */
1130   /* register with: (translated) keystroke handler */
1131
1132   priv->have_xkb = XkbQueryExtension (spi_get_display (),
1133                                       &priv->xkb_major_extension_opcode,
1134                                       &priv->xkb_base_event_code,
1135                                       &priv->xkb_base_error_code, NULL, NULL);
1136   if (priv->have_xkb)
1137     {
1138       priv->xkb_desc = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd);
1139       XkbSelectEvents (spi_get_display (),
1140                        XkbUseCoreKbd,
1141                        XkbStateNotifyMask, XkbStateNotifyMask);     
1142       _numlock_physical_mask = XkbKeysymToModifiers (spi_get_display (), 
1143                                                      XK_Num_Lock);
1144     }   
1145
1146   gdk_window_add_filter (NULL, global_filter_fn, controller);
1147
1148   gdk_window_set_events (gdk_get_default_root_window (),
1149                          GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
1150
1151   x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler);
1152 }
1153
1154 static gboolean
1155 spi_key_set_contains_key (Accessibility_KeySet            *key_set,
1156                           const Accessibility_DeviceEvent *key_event)
1157 {
1158   gint i;
1159   gint len;
1160
1161   if (!key_set)
1162     {
1163       g_print ("null key set!");
1164       return TRUE;
1165     }
1166
1167   len = key_set->_length;
1168   
1169   if (len == 0) /* special case, means "all keys/any key" */
1170     {
1171       g_print ("anykey\n");         
1172       return TRUE;
1173     }
1174
1175   for (i = 0; i < len; ++i)
1176     {
1177 #ifdef SPI_KEYEVENT_DEBUG           
1178       g_print ("key_set[%d] event = %d, code = %d; key_event %d, code %d, string %s\n",
1179                 i,
1180                 (int)key_set->_buffer[i].keysym,
1181                 (int) key_set->_buffer[i].keycode,
1182                 (int) key_event->id,
1183                 (int) key_event->hw_code,
1184                 key_event->event_string); 
1185 #endif
1186       if (key_set->_buffer[i].keysym == (CORBA_long) key_event->id)
1187         {
1188           return TRUE;
1189         }
1190       if (key_set->_buffer[i].keycode == (CORBA_long) key_event->hw_code)
1191         {
1192           return TRUE;
1193         }
1194       if (key_event->event_string && key_event->event_string[0] &&
1195           !strcmp (key_set->_buffer[i].keystring, key_event->event_string))
1196         {
1197           return TRUE;
1198         }
1199     }
1200
1201   return FALSE;
1202 }
1203
1204 static gboolean
1205 spi_eventtype_seq_contains_event (Accessibility_EventTypeSeq      *type_seq,
1206                                   const Accessibility_DeviceEvent *event)
1207 {
1208   gint i;
1209   gint len;
1210
1211
1212   if (!type_seq)
1213     {
1214       g_print ("null type seq!");
1215       return TRUE;
1216     }
1217
1218   len = type_seq->_length;
1219   
1220   if (len == 0) /* special case, means "all events/any event" */
1221     {
1222       return TRUE;
1223     }
1224
1225   for (i = 0; i < len; ++i)
1226     {
1227 #ifdef SPI_DEBUG            
1228       g_print ("type_seq[%d] = %d; event type = %d\n", i,
1229                (int) type_seq->_buffer[i], (int) event->type);
1230 #endif      
1231       if (type_seq->_buffer[i] == (CORBA_long) event->type)
1232         {
1233           return TRUE;
1234         }
1235     }
1236   
1237   return FALSE;
1238 }
1239
1240 static gboolean
1241 spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event,
1242                                 DEControllerKeyListener         *listener,
1243                                 CORBA_boolean                    is_system_global)
1244 {
1245   if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFF)) &&
1246        spi_key_set_contains_key (listener->keys, key_event) &&
1247        spi_eventtype_seq_contains_event (listener->listener.typeseq, key_event) && 
1248       (is_system_global == listener->mode->global))
1249     {
1250       return TRUE;
1251     }
1252   else
1253     {
1254       return FALSE;
1255     }
1256 }
1257
1258 static gboolean
1259 spi_controller_notify_keylisteners (SpiDEController                 *controller,
1260                                     const Accessibility_DeviceEvent *key_event,
1261                                     CORBA_boolean                    is_system_global,
1262                                     CORBA_Environment               *ev)
1263 {
1264   GList   *l;
1265   GSList  *notify = NULL, *l2;
1266   GList  **key_listeners = &controller->key_listeners;
1267   gboolean is_consumed;
1268
1269   if (!key_listeners)
1270     {
1271       return FALSE;
1272     }
1273
1274   for (l = *key_listeners; l; l = l->next)
1275     {
1276        DEControllerKeyListener *key_listener = l->data;
1277
1278        if (spi_key_event_matches_listener (key_event, key_listener, is_system_global))
1279          {
1280            Accessibility_DeviceEventListener ls = key_listener->listener.object;
1281
1282            if (ls != CORBA_OBJECT_NIL)
1283              {
1284                /* we clone (don't dup) the listener, to avoid refcount inc. */
1285                notify = g_slist_prepend (notify,
1286                                          spi_key_listener_clone (key_listener, ev));
1287              }
1288          }
1289     }
1290
1291 #ifdef SPI_KEYEVENT_DEBUG
1292   if (!notify)
1293     {
1294       g_print ("no match for event\n");
1295     }
1296 #endif
1297
1298   is_consumed = FALSE;
1299   for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
1300     {
1301       DEControllerKeyListener *key_listener = l2->data;     
1302       Accessibility_DeviceEventListener ls = key_listener->listener.object;
1303
1304       is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, key_event, ev);
1305
1306       if (BONOBO_EX (ev))
1307         {
1308           is_consumed = FALSE;
1309           spi_deregister_controller_key_listener (controller, key_listener,
1310                                                   ev);
1311           CORBA_exception_free (ev);
1312         }
1313
1314       spi_key_listener_clone_free (key_listener, ev);
1315     }
1316
1317   for (; l2; l2 = l2->next)
1318     {
1319       DEControllerKeyListener *key_listener = l2->data;     
1320       spi_key_listener_clone_free (key_listener, ev);
1321       /* clone doesn't have its own ref, so don't use spi_dec_listener_free */
1322     }
1323
1324   g_slist_free (notify);
1325
1326 #ifdef SPI_DEBUG
1327   if (is_consumed) g_message ("consumed\n");
1328 #endif
1329   return is_consumed;
1330 }
1331
1332 static gboolean
1333 spi_clear_error_state ()
1334 {
1335         gboolean retval = spi_error_code != 0;
1336         spi_error_code = 0;
1337         return retval;
1338 }
1339
1340 static Accessibility_DeviceEvent
1341 spi_keystroke_from_x_key_event (XKeyEvent *x_key_event)
1342 {
1343   Accessibility_DeviceEvent key_event;
1344   KeySym keysym;
1345   const int cbuf_bytes = 20;
1346   char cbuf [cbuf_bytes+1];
1347   int nbytes;
1348
1349   nbytes = XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL);  
1350   key_event.id = (CORBA_long)(keysym);
1351   key_event.hw_code = (CORBA_short) x_key_event->keycode;
1352   if (((XEvent *) x_key_event)->type == KeyPress)
1353     {
1354       key_event.type = Accessibility_KEY_PRESSED_EVENT;
1355     }
1356   else
1357     {
1358       key_event.type = Accessibility_KEY_RELEASED_EVENT;
1359     } 
1360   key_event.modifiers = (CORBA_unsigned_short)(x_key_event->state);
1361   key_event.is_text = CORBA_FALSE;
1362   switch (keysym)
1363     {
1364       case ' ':
1365         key_event.event_string = CORBA_string_dup ("space");
1366         break;
1367       case XK_Tab:
1368         key_event.event_string = CORBA_string_dup ("Tab");
1369         break;
1370       case XK_BackSpace:
1371         key_event.event_string = CORBA_string_dup ("Backspace");
1372         break;
1373       case XK_Return:
1374         key_event.event_string = CORBA_string_dup ("Return");
1375         break;
1376       case XK_Home:
1377         key_event.event_string = CORBA_string_dup ("Home");
1378         break;
1379       case XK_Page_Down:
1380         key_event.event_string = CORBA_string_dup ("Page_Down");
1381         break;
1382       case XK_Page_Up:
1383         key_event.event_string = CORBA_string_dup ("Page_Up");
1384         break;
1385       case XK_F1:
1386         key_event.event_string = CORBA_string_dup ("F1");
1387         break;
1388       case XK_F2:
1389         key_event.event_string = CORBA_string_dup ("F2");
1390         break;
1391       case XK_F3:
1392         key_event.event_string = CORBA_string_dup ("F3");
1393         break;
1394       case XK_F4:
1395         key_event.event_string = CORBA_string_dup ("F4");
1396         break;
1397       case XK_F5:
1398         key_event.event_string = CORBA_string_dup ("F5");
1399         break;
1400       case XK_F6:
1401         key_event.event_string = CORBA_string_dup ("F6");
1402         break;
1403       case XK_F7:
1404         key_event.event_string = CORBA_string_dup ("F7");
1405         break;
1406       case XK_F8:
1407         key_event.event_string = CORBA_string_dup ("F8");
1408         break;
1409       case XK_F9:
1410         key_event.event_string = CORBA_string_dup ("F9");
1411         break;
1412       case XK_F10:
1413         key_event.event_string = CORBA_string_dup ("F10");
1414         break;
1415       case XK_F11:
1416         key_event.event_string = CORBA_string_dup ("F11");
1417         break;
1418       case XK_F12:
1419         key_event.event_string = CORBA_string_dup ("F12");
1420         break;
1421       case XK_End:
1422         key_event.event_string = CORBA_string_dup ("End");
1423         break;
1424       case XK_Escape:
1425         key_event.event_string = CORBA_string_dup ("Escape");
1426         break;
1427       case XK_Up:
1428         key_event.event_string = CORBA_string_dup ("Up");
1429         break;
1430       case XK_Down:
1431         key_event.event_string = CORBA_string_dup ("Down");
1432         break;
1433       case XK_Left:
1434         key_event.event_string = CORBA_string_dup ("Left");
1435         break;
1436       case XK_Right:
1437         key_event.event_string = CORBA_string_dup ("Right");
1438         break;
1439       default:
1440         if (nbytes > 0)
1441           {
1442             gunichar c;
1443             cbuf[nbytes] = '\0'; /* OK since length is cbuf_bytes+1 */
1444             key_event.event_string = CORBA_string_dup (cbuf);
1445             c = g_utf8_get_char_validated (cbuf, nbytes);
1446             if ((c > 0) && g_unichar_isprint (c))
1447               {
1448                 key_event.is_text = CORBA_TRUE; 
1449                 /* incorrect for some composed chars? */
1450               }
1451           }
1452         else
1453           {
1454             key_event.event_string = CORBA_string_dup ("");
1455           }
1456     }
1457
1458   key_event.timestamp = (CORBA_unsigned_long) x_key_event->time;
1459 #ifdef SPI_KEYEVENT_DEBUG
1460   {
1461     char *pressed_str  = "pressed";
1462     char *released_str = "released";
1463     char *state_ptr;
1464
1465     if (key_event.type == Accessibility_KEY_PRESSED_EVENT)
1466       state_ptr = pressed_str;
1467     else
1468       state_ptr = released_str;
1469  
1470     fprintf (stderr,
1471              "Key %lu %s (%c), modifiers %d; string=%s [%x] %s\n",
1472              (unsigned long) keysym,
1473              state_ptr,
1474              keysym ? (int) keysym : '*',
1475              (int) x_key_event->state,
1476              key_event.event_string,
1477              key_event.event_string[0],
1478              (key_event.is_text == CORBA_TRUE) ? "(text)" : "(not text)");
1479   }
1480 #endif
1481 #ifdef SPI_DEBUG
1482   fprintf (stderr, "%s%c\n",
1483      (x_key_event->state & Mod1Mask)?"Alt-":"",
1484      ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))?
1485      g_ascii_toupper (keysym) : g_ascii_tolower (keysym));
1486 #endif /* SPI_DEBUG */
1487   return key_event;     
1488 }
1489
1490 static gboolean
1491 spi_controller_update_key_grabs (SpiDEController           *controller,
1492                                  Accessibility_DeviceEvent *recv)
1493 {
1494   GList *l, *next;
1495   gboolean   update_failed = FALSE;
1496   
1497   g_return_val_if_fail (controller != NULL, FALSE);
1498
1499   /*
1500    * masks known to work with default RH 7.1+:
1501    * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask,
1502    * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask,
1503    * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask,
1504    * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask,
1505    *
1506    * ControlMask grabs are broken, must be in use already
1507    */
1508   for (l = controller->keygrabs_list; l; l = next)
1509     {
1510       gboolean do_remove;
1511       gboolean re_issue_grab;
1512       DEControllerGrabMask *grab_mask = l->data;
1513
1514       next = l->next;
1515
1516       re_issue_grab = recv &&
1517               (recv->modifiers & grab_mask->mod_mask) &&
1518               (grab_mask->key_val == keycode_for_keysym (recv->id, NULL));
1519
1520 #ifdef SPI_DEBUG
1521       fprintf (stderr, "mask=%lx %lx (%c%c) %s\n",
1522                (long int) grab_mask->key_val,
1523                (long int) grab_mask->mod_mask,
1524                grab_mask->pending_add ? '+' : '.',
1525                grab_mask->pending_remove ? '-' : '.',
1526                re_issue_grab ? "re-issue": "");
1527 #endif
1528
1529       do_remove = FALSE;
1530
1531       if (grab_mask->pending_add && grab_mask->pending_remove)
1532         {
1533           do_remove = TRUE;
1534         }
1535       else if (grab_mask->pending_remove)
1536         {
1537 #ifdef SPI_DEBUG
1538       fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask);
1539 #endif
1540           XUngrabKey (spi_get_display (),
1541                       grab_mask->key_val,
1542                       grab_mask->mod_mask,
1543                       gdk_x11_get_default_root_xwindow ());
1544
1545           do_remove = TRUE;
1546         }
1547       else if (grab_mask->pending_add || re_issue_grab)
1548         {
1549
1550 #ifdef SPI_DEBUG
1551           fprintf (stderr, "grab %d with mask %x\n", grab_mask->key_val, grab_mask->mod_mask);
1552 #endif
1553           XGrabKey (spi_get_display (),
1554                     grab_mask->key_val,
1555                     grab_mask->mod_mask,
1556                     gdk_x11_get_default_root_xwindow (),
1557                     True,
1558                     GrabModeSync,
1559                     GrabModeSync);
1560           XSync (spi_get_display (), False);
1561           update_failed = spi_clear_error_state ();
1562           if (update_failed) {
1563                   while (grab_mask->ref_count > 0) --grab_mask->ref_count;
1564                   do_remove = TRUE;
1565           }
1566         }
1567
1568       grab_mask->pending_add = FALSE;
1569       grab_mask->pending_remove = FALSE;
1570
1571       if (do_remove)
1572         {
1573           g_assert (grab_mask->ref_count <= 0);
1574
1575           controller->keygrabs_list = g_list_delete_link (
1576             controller->keygrabs_list, l);
1577
1578           spi_grab_mask_free (grab_mask);
1579         }
1580
1581     } 
1582
1583   return ! update_failed;
1584 }
1585
1586 /*
1587  * Implemented GObject::finalize
1588  */
1589 static void
1590 spi_device_event_controller_object_finalize (GObject *object)
1591 {
1592   SpiDEController *controller;
1593   DEControllerPrivateData *private;
1594   controller = SPI_DEVICE_EVENT_CONTROLLER (object);
1595
1596 #ifdef SPI_DEBUG
1597   fprintf(stderr, "spi_device_event_controller_object_finalize called\n");
1598 #endif
1599   /* disconnect any special listeners, get rid of outstanding keygrabs */
1600   XUngrabKey (spi_get_display (), AnyKey, AnyModifier, DefaultRootWindow (spi_get_display ()));
1601
1602 #ifdef HAVE_XEVIE
1603   if (controller->xevie_display != NULL)
1604     {
1605       XevieEnd(controller->xevie_display);
1606 #ifdef SPI_KEYEVENT_DEBUG
1607       printf("XevieEnd(dpy) finished \n");
1608 #endif
1609     }
1610 #endif
1611
1612   private = g_object_get_data (G_OBJECT (controller), "spi-dec-private");
1613   if (private->xkb_desc)
1614           XkbFreeKeyboard (private->xkb_desc, 0, True);
1615   g_free (private);
1616   spi_device_event_controller_parent_class->finalize (object);
1617 }
1618
1619 /*
1620  * CORBA Accessibility::DEController::registerKeystrokeListener
1621  *     method implementation
1622  */
1623 static CORBA_boolean
1624 impl_register_keystroke_listener (PortableServer_Servant                  servant,
1625                                   const Accessibility_DeviceEventListener l,
1626                                   const Accessibility_KeySet             *keys,
1627                                   const Accessibility_ControllerEventMask mask,
1628                                   const Accessibility_EventTypeSeq       *type,
1629                                   const Accessibility_EventListenerMode  *mode,
1630                                   CORBA_Environment                      *ev)
1631 {
1632   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
1633           bonobo_object_from_servant (servant));
1634   DEControllerKeyListener *dec_listener;
1635 #ifdef SPI_DEBUG
1636   fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n",
1637            (void *) l, (unsigned long) mask);
1638 #endif
1639   dec_listener = spi_dec_key_listener_new (l, keys, mask, type, mode, ev);
1640   return spi_controller_register_device_listener (
1641           controller, (DEControllerListener *) dec_listener, ev);
1642 }
1643
1644
1645 /*
1646  * CORBA Accessibility::DEController::registerDeviceEventListener
1647  *     method implementation
1648  */
1649 static CORBA_boolean
1650 impl_register_device_listener (PortableServer_Servant                  servant,
1651                                const Accessibility_DeviceEventListener l,
1652                                const Accessibility_EventTypeSeq       *event_types,
1653                                CORBA_Environment                      *ev)
1654 {
1655   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
1656           bonobo_object_from_servant (servant));
1657   DEControllerListener *dec_listener;
1658
1659   dec_listener = spi_dec_listener_new (l, event_types, ev);
1660   return spi_controller_register_device_listener (
1661           controller, (DEControllerListener *) dec_listener, ev);
1662 }
1663
1664 typedef struct {
1665         CORBA_Environment       *ev;
1666         DEControllerListener    *listener;
1667 } RemoveListenerClosure;
1668
1669 static SpiReEntrantContinue
1670 remove_listener_cb (GList * const *list,
1671                     gpointer       user_data)
1672 {
1673   DEControllerListener  *listener = (*list)->data;
1674   RemoveListenerClosure *ctx = user_data;
1675
1676   if (CORBA_Object_is_equivalent (ctx->listener->object,
1677                                   listener->object, ctx->ev))
1678     {
1679       spi_re_entrant_list_delete_link (list);
1680       spi_dec_listener_free (listener, ctx->ev);
1681     }
1682
1683   return SPI_RE_ENTRANT_CONTINUE;
1684 }
1685
1686 static SpiReEntrantContinue
1687 copy_key_listener_cb (GList * const *list,
1688                       gpointer       user_data)
1689 {
1690   DEControllerKeyListener  *key_listener = (*list)->data;
1691   RemoveListenerClosure    *ctx = user_data;
1692
1693   if (CORBA_Object_is_equivalent (ctx->listener->object,
1694                                   key_listener->listener.object, ctx->ev))
1695     {
1696       /* TODO: FIXME aggregate keys in case the listener is registered twice */
1697       DEControllerKeyListener *ctx_key_listener = 
1698         (DEControllerKeyListener *) ctx->listener; 
1699       CORBA_free (ctx_key_listener->keys);          
1700       ctx_key_listener->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
1701     }
1702
1703   return SPI_RE_ENTRANT_CONTINUE;
1704 }
1705
1706 static void
1707 spi_deregister_controller_device_listener (SpiDEController            *controller,
1708                                            DEControllerListener *listener,
1709                                            CORBA_Environment          *ev)
1710 {
1711   RemoveListenerClosure  ctx;
1712
1713   ctx.ev = ev;
1714   ctx.listener = listener;
1715
1716   spi_re_entrant_list_foreach (&controller->mouse_listeners,
1717                                remove_listener_cb, &ctx);
1718 }
1719
1720 static void
1721 spi_deregister_controller_key_listener (SpiDEController            *controller,
1722                                         DEControllerKeyListener    *key_listener,
1723                                         CORBA_Environment          *ev)
1724 {
1725   RemoveListenerClosure  ctx;
1726
1727   ctx.ev = ev;
1728   ctx.listener = (DEControllerListener *) key_listener;
1729
1730   /* special case, copy keyset from existing controller list entry */
1731   if (key_listener->keys->_length == 0) 
1732     {
1733       spi_re_entrant_list_foreach (&controller->key_listeners,
1734                                   copy_key_listener_cb, &ctx);
1735     }
1736   
1737   spi_controller_deregister_global_keygrabs (controller, key_listener);
1738
1739   spi_re_entrant_list_foreach (&controller->key_listeners,
1740                                 remove_listener_cb, &ctx);
1741
1742 }
1743
1744 /*
1745  * CORBA Accessibility::DEController::deregisterKeystrokeListener
1746  *     method implementation
1747  */
1748 static void
1749 impl_deregister_keystroke_listener (PortableServer_Servant                  servant,
1750                                     const Accessibility_DeviceEventListener l,
1751                                     const Accessibility_KeySet             *keys,
1752                                     const Accessibility_ControllerEventMask mask,
1753                                     const Accessibility_EventTypeSeq       *type,
1754                                     CORBA_Environment                      *ev)
1755 {
1756   DEControllerKeyListener  *key_listener;
1757   SpiDEController *controller;
1758
1759   controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
1760
1761   key_listener = spi_dec_key_listener_new (l, keys, mask, type, NULL, ev);
1762
1763 #ifdef SPI_DEREGISTER_DEBUG
1764   fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n",
1765            (void *) l, (unsigned long) mask->value);
1766 #endif
1767
1768   spi_deregister_controller_key_listener (controller, key_listener, ev);
1769
1770   spi_dec_listener_free ((DEControllerListener *) key_listener, ev);
1771 }
1772
1773 /*
1774  * CORBA Accessibility::DEController::deregisterDeviceEventListener
1775  *     method implementation
1776  */
1777 static void
1778 impl_deregister_device_listener (PortableServer_Servant                  servant,
1779                                  const Accessibility_DeviceEventListener l,
1780                                  const Accessibility_EventTypeSeq       *event_types,
1781                                  CORBA_Environment                      *ev)
1782 {
1783   SpiDEController *controller;
1784   DEControllerListener *listener = 
1785           spi_dec_listener_new (l, event_types, ev);
1786
1787   controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
1788
1789   spi_deregister_controller_device_listener (controller, listener, ev);
1790
1791   spi_dec_listener_free (listener, ev);
1792 }
1793
1794 static unsigned int dec_xkb_get_slowkeys_delay (SpiDEController *controller)
1795 {
1796   unsigned int retval = 0;
1797   DEControllerPrivateData *priv = (DEControllerPrivateData *)
1798           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
1799 #ifdef HAVE_XKB
1800 #ifdef XKB_HAS_GET_SLOW_KEYS_DELAY      
1801   retval = XkbGetSlowKeysDelay (spi_get_display (),
1802                                 XkbUseCoreKbd, &bounce_delay);
1803 #else
1804   if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
1805     {
1806       Status s = XkbGetControls (spi_get_display (),
1807                                  XkbAllControlsMask, priv->xkb_desc);
1808       if (s == Success)
1809         {
1810          if (priv->xkb_desc->ctrls->enabled_ctrls & XkbSlowKeysMask)
1811                  retval = priv->xkb_desc->ctrls->slow_keys_delay;
1812         }
1813     }
1814 #endif
1815 #endif
1816 #ifdef SPI_XKB_DEBUG
1817         fprintf (stderr, "SlowKeys delay: %d\n", (int) retval);
1818 #endif
1819         return retval;
1820 }
1821
1822 static unsigned int dec_xkb_get_bouncekeys_delay (SpiDEController *controller)
1823 {
1824   unsigned int retval = 0;
1825   DEControllerPrivateData *priv = (DEControllerPrivateData *)
1826           g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
1827 #ifdef HAVE_XKB
1828 #ifdef XKB_HAS_GET_BOUNCE_KEYS_DELAY    
1829   retval = XkbGetBounceKeysDelay (spi_get_display (),
1830                                   XkbUseCoreKbd, &bounce_delay);
1831 #else
1832   if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
1833     {
1834       Status s = XkbGetControls (spi_get_display (),
1835                                  XkbAllControlsMask, priv->xkb_desc);
1836       if (s == Success)
1837         {
1838           if (priv->xkb_desc->ctrls->enabled_ctrls & XkbBounceKeysMask)
1839                   retval = priv->xkb_desc->ctrls->debounce_delay;
1840         }
1841     }
1842 #endif
1843 #endif
1844 #ifdef SPI_XKB_DEBUG
1845   fprintf (stderr, "BounceKeys delay: %d\n", (int) retval);
1846 #endif
1847   return retval;
1848 }
1849
1850 static gboolean
1851 dec_synth_keycode_press (SpiDEController *controller,
1852                          unsigned int keycode)
1853 {
1854         unsigned int time = CurrentTime;
1855         unsigned int bounce_delay;
1856         unsigned int elapsed_msec;
1857         struct timeval tv;
1858         DEControllerPrivateData *priv =
1859                 (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller),
1860                                                                 spi_dec_private_quark);
1861         if (keycode == priv->last_release_keycode)
1862         {
1863                 bounce_delay = dec_xkb_get_bouncekeys_delay (controller); 
1864                 if (bounce_delay)
1865                 {
1866                         gettimeofday (&tv, NULL);
1867                         elapsed_msec =
1868                                 (tv.tv_sec - priv->last_release_time.tv_sec) * 1000
1869                                 + (tv.tv_usec - priv->last_release_time.tv_usec) / 1000;
1870 #ifdef SPI_XKB_DEBUG                    
1871                         fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec,
1872                                  (long) (tv.tv_usec - priv->last_release_time.tv_usec));
1873 #endif
1874 #ifdef THIS_IS_BROKEN
1875                         if (elapsed_msec < bounce_delay)
1876                                 time = bounce_delay - elapsed_msec + 1;
1877 #else
1878                         time = bounce_delay + 10;
1879                         /* fudge for broken XTest */
1880 #endif
1881 #ifdef SPI_XKB_DEBUG                    
1882                         fprintf (stderr, "waiting %d ms\n", time);
1883 #endif
1884                 }
1885         }
1886         XTestFakeKeyEvent (spi_get_display (), keycode, True, time);
1887         priv->last_press_keycode = keycode;
1888         XSync (spi_get_display (), False);
1889         gettimeofday (&priv->last_press_time, NULL);
1890         return TRUE;
1891 }
1892
1893 static gboolean
1894 dec_synth_keycode_release (SpiDEController *controller,
1895                            unsigned int keycode)
1896 {
1897         unsigned int time = CurrentTime;
1898         unsigned int slow_delay;
1899         unsigned int elapsed_msec;
1900         struct timeval tv;
1901         DEControllerPrivateData *priv =
1902                 (DEControllerPrivateData *) g_object_get_qdata (G_OBJECT (controller),
1903                                                                 spi_dec_private_quark);
1904         if (keycode == priv->last_press_keycode)
1905         {
1906                 slow_delay = dec_xkb_get_slowkeys_delay (controller);
1907                 if (slow_delay)
1908                 {
1909                         gettimeofday (&tv, NULL);
1910                         elapsed_msec =
1911                                 (tv.tv_sec - priv->last_press_time.tv_sec) * 1000
1912                                 + (tv.tv_usec - priv->last_press_time.tv_usec) / 1000;
1913 #ifdef SPI_XKB_DEBUG                    
1914                         fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec,
1915                                  (long) (tv.tv_usec - priv->last_press_time.tv_usec));
1916 #endif
1917 #ifdef THIS_IS_BROKEN_DUNNO_WHY
1918                         if (elapsed_msec < slow_delay)
1919                                 time = slow_delay - elapsed_msec + 1;
1920 #else
1921                         time = slow_delay + 10;
1922                         /* our XTest seems broken, we have to add slop as above */
1923 #endif
1924 #ifdef SPI_XKB_DEBUG                    
1925                         fprintf (stderr, "waiting %d ms\n", time);
1926 #endif
1927                 }
1928         }
1929         XTestFakeKeyEvent (spi_get_display (), keycode, False, time);
1930         priv->last_release_keycode = keycode;
1931         XSync (spi_get_display (), False);
1932         gettimeofday (&priv->last_release_time, NULL);
1933         return TRUE;
1934 }
1935
1936 static unsigned
1937 dec_get_modifier_state (SpiDEController *controller)
1938 {
1939         return mouse_mask_state;
1940 }
1941
1942 static gboolean
1943 dec_lock_modifiers (SpiDEController *controller, unsigned modifiers)
1944 {
1945         return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, 
1946                           modifiers, modifiers);
1947 }
1948
1949 static gboolean
1950 dec_unlock_modifiers (SpiDEController *controller, unsigned modifiers)
1951 {
1952         return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, 
1953                           modifiers, 0);
1954 }
1955
1956 static KeySym
1957 dec_keysym_for_unichar (SpiDEController *controller, gunichar unichar)
1958 {
1959         /* TODO: table lookups within a range, for various code pages! */
1960         KeySym keysym = NoSymbol;
1961
1962         if (unichar >= 0x20 && unichar < 0x7f) { /* Basic Latin/ASCII */
1963                 keysym = (KeySym) unichar;
1964         }
1965         else if (unichar >= 0xa0 && unichar <= 0xff) { /* Latin 1 extensions */
1966                 keysym = (KeySym) unichar;
1967         }
1968         else if (unichar >= 0x100 && unichar <= 0x233) { /* unfortunately the mapping gets nasty for Latin-2 and 3... help! */
1969                 keysym = NoSymbol;
1970         }
1971         else if (unichar >= 0x7c1 && unichar <= 0x3a1) { /* let's try Greek anyway... */
1972                 keysym = (KeySym) (0x391 + (unichar - 0x7c1));
1973         }
1974         else if (unichar >= 0x3a3 && unichar <= 0x3a9) { /* let's try Greek anyway... */
1975                 keysym = (KeySym) (0x7d2 + (unichar - 0x3a3));
1976         }
1977         else if (unichar >= 0x3b1 && unichar <= 0x3c1) { /* let's try Greek anyway... */
1978                 keysym = (KeySym) (0x7e1 + (unichar - 0x3b1));
1979         }
1980         else if (unichar == 0x3c2) {
1981                 keysym = (KeySym) 0x7f3; /* XK_Greek_finalsmallsigma; */
1982         }
1983         else if (unichar >= 0x3c3 && unichar <= 0x3c9) { /* let's try Greek anyway... */
1984                 keysym = (KeySym) (0x7f2 + (unichar - 0x3c2));
1985         }       
1986         else if (unichar >= 0x5d0 && unichar <= 0x5ea) { /* Hebrew basics */
1987                 /* probably broken :-) */
1988                 keysym = (KeySym) (0xce0 + (unichar - 0x5d0));
1989         }       
1990         else if (unichar >= 0x30a1 && unichar <= 0x30ab) { /* partial katakana support */
1991                 /* TODO: complete! */
1992                 keysym = (KeySym) (0x4b1 + (unichar - 0x30a1)/2);
1993         }
1994         else if (unichar >= 0x20a0 && unichar <= 0x20ac) { /* currency */
1995                 keysym = (KeySym) unichar; /* how convenient ;-) */
1996         }
1997         return keysym;
1998 }
1999
2000 static gboolean
2001 dec_synth_keysym (SpiDEController *controller, KeySym keysym)
2002 {
2003         KeyCode key_synth_code;
2004         unsigned int modifiers, synth_mods, lock_mods;
2005
2006         key_synth_code = keycode_for_keysym (keysym, &synth_mods);
2007
2008         if ((key_synth_code == 0) || (synth_mods == 0xFF)) return FALSE;
2009
2010         /* TODO: set the modifiers accordingly! */
2011         modifiers = dec_get_modifier_state (controller);
2012         /* side-effect; we may unset mousebutton modifiers here! */
2013
2014         lock_mods = 0;
2015         if (synth_mods != modifiers) {
2016                 lock_mods = synth_mods & ~modifiers;
2017                 dec_lock_modifiers (controller, lock_mods);
2018         }
2019         dec_synth_keycode_press (controller, key_synth_code);
2020         dec_synth_keycode_release (controller, key_synth_code);
2021         if (synth_mods != modifiers) 
2022                 dec_unlock_modifiers (controller, lock_mods);
2023         return TRUE;
2024 }
2025
2026
2027 static gboolean
2028 dec_synth_keystring (SpiDEController *controller, const CORBA_char *keystring)
2029 {
2030         /* probably we need to create and inject an XIM handler eventually. */
2031         /* for now, try to match the string to existing 
2032          * keycode+modifier states. 
2033          */
2034         KeySym *keysyms;
2035         gint maxlen = 0;
2036         gunichar unichar = 0;
2037         gint i = 0;
2038         gboolean retval = TRUE;
2039         const gchar *c;
2040
2041         maxlen = strlen (keystring);
2042         keysyms = g_new0 (KeySym, maxlen);
2043         if (!(keystring && *keystring && g_utf8_validate (keystring, -1, &c))) { 
2044                 retval = FALSE;
2045         } 
2046         else {
2047 #ifdef SPI_DEBUG
2048                 fprintf (stderr, "[keystring synthesis attempted on %s]\n", keystring);
2049 #endif
2050                 while (keystring && (unichar = g_utf8_get_char (keystring))) {
2051                         KeySym keysym;
2052                         char bytes[6];
2053                         gint mbytes;
2054                         
2055                         mbytes = g_unichar_to_utf8 (unichar, bytes);
2056                         bytes[mbytes] = '\0';
2057 #ifdef SPI_DEBUG
2058                         fprintf (stderr, "[unichar %s]", bytes);
2059 #endif
2060                         keysym = dec_keysym_for_unichar (controller, unichar);
2061                         if (keysym == NoSymbol) {
2062 #ifdef SPI_DEBUG
2063                                 fprintf (stderr, "no keysym for %s", bytes);
2064 #endif
2065                                 retval = FALSE;
2066                                 break;
2067                         }
2068                         keysyms[i++] = keysym;
2069                         keystring = g_utf8_next_char (keystring); 
2070                 }
2071                 keysyms[i++] = 0;
2072                 for (i = 0; keysyms[i]; ++i) {
2073                         if (!dec_synth_keysym (controller, keysyms[i])) {
2074 #ifdef SPI_DEBUG
2075                                 fprintf (stderr, "could not synthesize %c\n",
2076                                          (int) keysyms[i]);
2077 #endif
2078                                 retval = FALSE;
2079                                 break;
2080                         }
2081                 }
2082         }
2083         g_free (keysyms);
2084
2085         return retval;
2086 }
2087
2088
2089 /*
2090  * CORBA Accessibility::DEController::registerKeystrokeListener
2091  *     method implementation
2092  */
2093 static void
2094 impl_generate_keyboard_event (PortableServer_Servant           servant,
2095                               const CORBA_long                 keycode,
2096                               const CORBA_char                *keystring,
2097                               const Accessibility_KeySynthType synth_type,
2098                               CORBA_Environment               *ev)
2099 {
2100   SpiDEController *controller =
2101         SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
2102   long key_synth_code;
2103   KeySym keysym;
2104
2105 #ifdef SPI_DEBUG
2106         fprintf (stderr, "synthesizing keystroke %ld, type %d\n",
2107                  (long) keycode, (int) synth_type);
2108 #endif
2109   /* TODO: hide/wrap/remove X dependency */
2110
2111   /*
2112    * TODO: when initializing, query for XTest extension before using,
2113    * and fall back to XSendEvent() if XTest is not available.
2114    */
2115   
2116   gdk_error_trap_push ();
2117   key_synth_code = keycode;
2118
2119   switch (synth_type)
2120     {
2121       case Accessibility_KEY_PRESS:
2122               dec_synth_keycode_press (controller, keycode);
2123               break;
2124       case Accessibility_KEY_PRESSRELEASE:
2125               dec_synth_keycode_press (controller, keycode);
2126       case Accessibility_KEY_RELEASE:
2127               dec_synth_keycode_release (controller, keycode);
2128               break;
2129       case Accessibility_KEY_SYM:
2130 #ifdef SPI_XKB_DEBUG          
2131               fprintf (stderr, "KeySym synthesis\n");
2132 #endif
2133               /* 
2134                * note: we are using long for 'keycode'
2135                * in our arg list; it can contain either
2136                * a keycode or a keysym.
2137                */
2138               dec_synth_keysym (controller, (KeySym) keycode);
2139               break;
2140       case Accessibility_KEY_STRING:
2141               if (!dec_synth_keystring (controller, keystring))
2142                       fprintf (stderr, "Keystring synthesis failure, string=%s\n",
2143                                keystring);
2144               break;
2145     }
2146   if (gdk_error_trap_pop ())
2147     {
2148       DBG (-1, g_warning ("Error emitting keystroke"));
2149     }
2150   if (synth_type == Accessibility_KEY_SYM) {
2151     keysym = keycode;
2152   }
2153   else {
2154     keysym = XkbKeycodeToKeysym (spi_get_display (), keycode, 0, 0);
2155   }
2156   if (XkbKeysymToModifiers (spi_get_display (), keysym) == 0) 
2157     {
2158       spi_dec_clear_unlatch_pending (controller);
2159     }
2160 }
2161
2162 /* Accessibility::DEController::generateMouseEvent */
2163 static void
2164 impl_generate_mouse_event (PortableServer_Servant servant,
2165                            const CORBA_long       x,
2166                            const CORBA_long       y,
2167                            const CORBA_char      *eventName,
2168                            CORBA_Environment     *ev)
2169 {
2170   int button = 0;
2171   gboolean error = FALSE;
2172   Display *display = spi_get_display ();
2173 #ifdef SPI_DEBUG
2174   fprintf (stderr, "generating mouse %s event at %ld, %ld\n",
2175            eventName, (long int) x, (long int) y);
2176 #endif
2177   switch (eventName[0])
2178     {
2179       case 'b':
2180         switch (eventName[1])
2181           {
2182           /* TODO: check number of buttons before parsing */
2183           case '1':
2184                     button = 1;
2185                     break;
2186           case '2':
2187                   button = 2;
2188                   break;
2189           case '3':
2190                   button = 3;
2191                   break;
2192           case '4':
2193                   button = 4;
2194                   break;
2195           case '5':
2196                   button = 5;
2197                   break;
2198           default:
2199                   error = TRUE;
2200           }
2201         if (!error)
2202           {
2203             if (x != -1 && y != -1)
2204               {
2205                 XTestFakeMotionEvent (display, DefaultScreen (display),
2206                                       x, y, 0);
2207               }
2208             XTestFakeButtonEvent (display, button, !(eventName[2] == 'r'), 0);
2209             if (eventName[2] == 'c')
2210               XTestFakeButtonEvent (display, button, FALSE, 1);
2211             else if (eventName[2] == 'd')
2212               {
2213               XTestFakeButtonEvent (display, button, FALSE, 1);
2214               XTestFakeButtonEvent (display, button, TRUE, 2);
2215               XTestFakeButtonEvent (display, button, FALSE, 3);
2216               }
2217           }
2218         break;
2219       case 'r': /* relative motion */ 
2220         XTestFakeRelativeMotionEvent (display, x, y, 0);
2221         break;
2222       case 'a': /* absolute motion */
2223         XTestFakeMotionEvent (display, DefaultScreen (display),
2224                               x, y, 0);
2225         break;
2226     }
2227 }
2228
2229 /* Accessibility::DEController::notifyListenersSync */
2230 static CORBA_boolean
2231 impl_notify_listeners_sync (PortableServer_Servant           servant,
2232                             const Accessibility_DeviceEvent *event,
2233                             CORBA_Environment               *ev)
2234 {
2235   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
2236     bonobo_object_from_servant (servant));
2237 #ifdef SPI_DEBUG
2238   g_print ("notifylistening listeners synchronously: controller %p, event id %d\n",
2239            controller, (int) event->id);
2240 #endif
2241   return spi_controller_notify_keylisteners (controller, event, CORBA_FALSE, ev) ?
2242           CORBA_TRUE : CORBA_FALSE; 
2243 }
2244
2245 /* Accessibility::DEController::notifyListenersAsync */
2246 static void
2247 impl_notify_listeners_async (PortableServer_Servant           servant,
2248                              const Accessibility_DeviceEvent *event,
2249                              CORBA_Environment               *ev)
2250 {
2251   SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
2252     bonobo_object_from_servant (servant));
2253 #ifdef SPI_DEBUG
2254   fprintf (stderr, "notifying listeners asynchronously\n");
2255 #endif
2256   spi_controller_notify_keylisteners (controller, event, CORBA_FALSE, ev); 
2257 }
2258
2259 static void
2260 spi_device_event_controller_class_init (SpiDEControllerClass *klass)
2261 {
2262   GObjectClass * object_class = (GObjectClass *) klass;
2263   POA_Accessibility_DeviceEventController__epv *epv = &klass->epv;
2264
2265   spi_device_event_controller_parent_class = g_type_class_peek_parent (klass);
2266   
2267   object_class->finalize = spi_device_event_controller_object_finalize;
2268         
2269   epv->registerKeystrokeListener   = impl_register_keystroke_listener;
2270   epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener;
2271   epv->registerDeviceEventListener = impl_register_device_listener;
2272   epv->deregisterDeviceEventListener = impl_deregister_device_listener;
2273   epv->generateKeyboardEvent       = impl_generate_keyboard_event;
2274   epv->generateMouseEvent          = impl_generate_mouse_event;
2275   epv->notifyListenersSync         = impl_notify_listeners_sync;
2276   epv->notifyListenersAsync        = impl_notify_listeners_async;
2277
2278   if (!spi_dec_private_quark)
2279           spi_dec_private_quark = g_quark_from_static_string ("spi-dec-private");
2280 }
2281
2282 #ifdef HAVE_XEVIE
2283 Bool isEvent(dpy,event,arg)
2284      Display *dpy;
2285      XEvent *event;
2286      char *arg;
2287 {
2288    return TRUE;
2289 }
2290
2291 gboolean
2292 handle_io (GIOChannel *source,
2293            GIOCondition condition,
2294            gpointer data) 
2295 {
2296   SpiDEController *controller = (SpiDEController *) data;
2297   gboolean is_consumed = FALSE;
2298   XEvent ev;
2299
2300   while (XCheckIfEvent(controller->xevie_display, &ev, isEvent, NULL))
2301     {
2302       if (ev.type == KeyPress || ev.type == KeyRelease)
2303         is_consumed = spi_device_event_controller_forward_key_event (controller, &ev);
2304
2305       if (! is_consumed)
2306         XevieSendEvent(controller->xevie_display, &ev, XEVIE_UNMODIFIED);
2307     }
2308
2309   return TRUE;
2310 }
2311 #endif /* HAVE_XEVIE */
2312
2313 static void
2314 spi_device_event_controller_init (SpiDEController *device_event_controller)
2315 {
2316 #ifdef HAVE_XEVIE
2317   GIOChannel *ioc;
2318   int fd;
2319 #endif /* HAVE_XEVIE */
2320
2321   DEControllerPrivateData *private;     
2322   device_event_controller->key_listeners   = NULL;
2323   device_event_controller->mouse_listeners = NULL;
2324   device_event_controller->keygrabs_list   = NULL;
2325   device_event_controller->xevie_display   = NULL;
2326
2327 #ifdef HAVE_XEVIE
2328   device_event_controller->xevie_display = XOpenDisplay(NULL);
2329
2330   if (XevieStart(device_event_controller->xevie_display) == TRUE)
2331     {
2332 #ifdef SPI_KEYEVENT_DEBUG
2333       fprintf (stderr, "XevieStart() success \n");
2334 #endif
2335       XevieSelectInput(device_event_controller->xevie_display, KeyPressMask | KeyReleaseMask);
2336
2337       fd = ConnectionNumber(device_event_controller->xevie_display);
2338       ioc = g_io_channel_unix_new (fd);
2339       g_io_add_watch (ioc, G_IO_IN | G_IO_HUP, handle_io, device_event_controller);
2340       g_io_channel_unref (ioc);
2341     }
2342   else
2343     {
2344       device_event_controller->xevie_display = NULL;
2345 #ifdef SPI_KEYEVENT_DEBUG
2346       fprintf (stderr, "XevieStart() failed, only one client is allowed to do event int exception\n");
2347 #endif
2348     }
2349 #endif /* HAVE_XEVIE */
2350
2351   private = g_new0 (DEControllerPrivateData, 1);
2352   gettimeofday (&private->last_press_time, NULL);
2353   gettimeofday (&private->last_release_time, NULL);
2354   g_object_set_qdata (G_OBJECT (device_event_controller),
2355                       spi_dec_private_quark,
2356                       private);
2357   spi_controller_register_with_devices (device_event_controller);
2358 }
2359
2360 static gboolean
2361 spi_device_event_controller_forward_key_event (SpiDEController *controller,
2362                                                const XEvent    *event)
2363 {
2364   CORBA_Environment ev;
2365   Accessibility_DeviceEvent key_event;
2366
2367   g_assert (event->type == KeyPress || event->type == KeyRelease);
2368
2369   CORBA_exception_init (&ev);
2370
2371   key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event);
2372
2373   if (controller->xevie_display == NULL)
2374     spi_controller_update_key_grabs (controller, &key_event);
2375
2376   /* relay to listeners, and decide whether to consume it or not */
2377   return spi_controller_notify_keylisteners (controller, &key_event, CORBA_TRUE, &ev);
2378 }
2379
2380 SpiDEController *
2381 spi_device_event_controller_new (SpiRegistry *registry)
2382 {
2383   SpiDEController *retval = g_object_new (
2384     SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL);
2385   
2386   retval->registry = SPI_REGISTRY (bonobo_object_ref (
2387           BONOBO_OBJECT (registry)));
2388
2389   spi_dec_init_mouse_listener (registry);
2390   /* TODO: kill mouse listener on finalize */  
2391   return retval;
2392 }
2393
2394 static gboolean
2395 is_key_released (KeyCode code)
2396 {
2397   char keys[32];
2398   int down;
2399   int i;
2400
2401   XQueryKeymap (spi_get_display (), keys);
2402   down = BIT (keys, code);
2403   return (down == 0);
2404 }
2405
2406 static gboolean
2407 check_release (gpointer data)
2408 {
2409   gboolean released;
2410   Accessibility_DeviceEvent *event = (Accessibility_DeviceEvent *)data;
2411   KeyCode code = event->hw_code;
2412   CORBA_Environment ev;
2413
2414   released = is_key_released (code);
2415
2416   if (released)
2417     {
2418       check_release_handler = 0;
2419       event->type = Accessibility_KEY_RELEASED_EVENT;
2420       ev._major = CORBA_NO_EXCEPTION;
2421       spi_controller_notify_keylisteners (saved_controller, event, CORBA_TRUE, &ev);
2422     }
2423   return (released == 0);
2424 }
2425
2426 static void wait_for_release_event (GdkEvent        *event,
2427                                     SpiDEController *controller)
2428 {
2429   pressed_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event);
2430   saved_controller = controller;
2431   check_release_handler = g_timeout_add (CHECK_RELEASE_DELAY, check_release, &pressed_event);
2432 }
2433
2434 BONOBO_TYPE_FUNC_FULL (SpiDEController,
2435                        Accessibility_DeviceEventController,
2436                        PARENT_TYPE,
2437                        spi_device_event_controller)