--- deviceeventcontroller.c.orig	2008-02-02 12:16:45.000000000 -0500
+++ deviceeventcontroller.c	2008-02-02 12:17:33.000000000 -0500
@@ -79,12 +79,13 @@
   Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask;
 static unsigned int key_modifier_mask =
   Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | LockMask | ControlMask | SPI_KEYMASK_NUMLOCK;
 static unsigned int _numlock_physical_mask = Mod2Mask; /* a guess, will be reset */
 
 static GQuark spi_dec_private_quark = 0;
+static XModifierKeymap* xmkeymap = NULL;
 
 static int (*x_default_error_handler) (Display *display, XErrorEvent *error_event);
 
 typedef enum {
   SPI_DEVICE_TYPE_KBD,
   SPI_DEVICE_TYPE_MOUSE,
@@ -1116,12 +1117,15 @@
   DEControllerPrivateData *priv;
   Display *display = spi_get_display ();
   controller = SPI_DEVICE_EVENT_CONTROLLER (data);
   priv = (DEControllerPrivateData *)
 	  g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);  
 
+  if (xevent->type == MappingNotify)
+    xmkeymap = NULL;
+
   if (xevent->type == KeyPress || xevent->type == KeyRelease)
     {
       if (controller->xevie_display == NULL)
         {
           gboolean is_consumed;
 
@@ -2127,21 +2131,43 @@
 	return mouse_mask_state;
 }
 
 static gboolean
 dec_lock_modifiers (SpiDEController *controller, unsigned modifiers)
 {
-	return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, 
-			  modifiers, modifiers);
+    DEControllerPrivateData *priv = (DEControllerPrivateData *) 
+    g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);	 
+    
+    if (priv->have_xkb) {
+        return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, 
+                                  modifiers, modifiers);
+    } else {
+	int mod_index;
+	for (mod_index=0;mod_index<8;mod_index++)
+	    if (modifiers & (1<<mod_index))
+	        dec_synth_keycode_press(controller, xmkeymap->modifiermap[mod_index]);
+	return TRUE;
+    }
 }
 
 static gboolean
 dec_unlock_modifiers (SpiDEController *controller, unsigned modifiers)
 {
-	return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, 
-			  modifiers, 0);
+    DEControllerPrivateData *priv = (DEControllerPrivateData *) 
+    g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);	 
+    
+    if (priv->have_xkb) {
+        return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, 
+                                  modifiers, 0);
+    } else {
+	int mod_index;
+	for (mod_index=0;mod_index<8;mod_index++)
+	    if (modifiers & (1<<mod_index))
+	        dec_synth_keycode_release(controller, xmkeymap->modifiermap[mod_index]);
+	return TRUE;
+    }
 }
 
 static KeySym
 dec_keysym_for_unichar (SpiDEController *controller, gunichar unichar)
 {
 	return ucs2keysym ((long) unichar);
@@ -2265,12 +2291,19 @@
    * TODO: when initializing, query for XTest extension before using,
    * and fall back to XSendEvent() if XTest is not available.
    */
   
   gdk_error_trap_push ();
 
+  DEControllerPrivateData *priv = (DEControllerPrivateData *) 
+      g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
+
+  if (!priv->have_xkb && xmkeymap==NULL) {
+    xmkeymap = XGetModifierMapping(spi_get_display ());
+  }
+
   switch (synth_type)
     {
       case Accessibility_KEY_PRESS:
 	      dec_synth_keycode_press (controller, keycode);
 	      break;
       case Accessibility_KEY_PRESSRELEASE:
