diff --git a/hw/rdp/rdp.h b/hw/rdp/rdp.h
index 3e62a9c..aaf6ab6 100644
--- a/hw/rdp/rdp.h
+++ b/hw/rdp/rdp.h
@@ -58,6 +58,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "dpmsproc.h"
 #include <X11/extensions/XIproto.h>
 #include "XIstubs.h"
+#include "exevents.h"
+#ifdef XKB
+#include "xkbsrv.h"
+#endif
 
 /* Per-screen (framebuffer) structure.  There is only one of these, since we
    don't allow the X server to have multiple screens. */
@@ -93,6 +97,28 @@ typedef struct
 
 typedef rdpScreenInfo* rdpScreenInfoPtr;
 
+typedef enum
+{
+    RDP_INPUT_LAYOUT_NONE = 0,
+    RDP_INPUT_LAYOUT_EN_US = 1,
+    RDP_INPUT_LAYOUT_EN_UK,
+    RDP_INPUT_LAYOUT_FRANCE,
+    RDP_INPUT_LAYOUT_GERMAN,
+    RDP_INPUT_LAYOUT_ITALY,
+    RDP_INPUT_LAYOUT_PORTUGUESE,
+    RDP_INPUT_LAYOUT_SWEDISH,
+    RDP_INPUT_LAYOUT_CZECH,
+    RDP_INPUT_LAYOUT_RUSSIAN,
+} rdpInputLayout;
+
+typedef struct
+{
+    rdpInputLayout layout;
+    const char *layout_name;
+} rdpInputInfo;
+
+typedef rdpInputInfo* rdpInputInfoPtr;
+
 typedef struct
 {
   GCFuncs* funcs;
@@ -102,6 +128,8 @@ typedef struct
 typedef rdpGCRec* rdpGCPtr;
 
 /* rdpmisc.c */
+rdpInputLayout
+rdpStr2Layout(const char *lyo);
 void
 rdpLog(char *format, ...);
 int
@@ -212,6 +240,8 @@ void
 rdpSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
 void
 PtrAddEvent(int buttonMask, int x, int y);
+int
+KbdLockedStateSync(int lockstate);
 void
 KbdAddEvent(int down, int param1, int param2, int param3, int param4);
 
diff --git a/hw/rdp/rdpinput.c b/hw/rdp/rdpinput.c
index ba43185..acf5bd5 100644
--- a/hw/rdp/rdpinput.c
+++ b/hw/rdp/rdpinput.c
@@ -22,7 +22,16 @@ keyboard and mouse stuff
 */
 
 #include "rdp.h"
+#ifdef XKB
+#include "xkbstr.h"
+#include "xkbsrv.h"
+#endif
 
+rdpInputInfo rdpInput =
+{
+    .layout = RDP_INPUT_LAYOUT_EN_US,
+    .layout_name = "us"
+};
 static DeviceIntPtr kbdDevice;
 static int g_old_button_mask = 0;
 static int g_caps_lock = 0;
@@ -306,6 +315,17 @@ rdpKeybdProc(DeviceIntPtr pDevice, int onoff)
   {
     case DEVICE_INIT:
       KbdDeviceInit(pDevice, &keySyms, modMap);
+#ifdef XKB
+      if (!noXkbExtension) {
+        XkbComponentNamesRec names;
+        bzero (&names, sizeof (names));
+        XkbSetRulesDflts ("base", "pc105", rdpInput.layout_name, NULL, NULL);
+        XkbInitKeyboardDeviceStruct(pDevice, &names, &keySyms, modMap,
+                                    (BellProcPtr) rdpSendBell,
+                                    (KbdCtrlProcPtr)NoopDDA);
+        ErrorF("Set keyboard layout to %s\n", rdpInput.layout_name);
+      } else
+#endif
       InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
                                (BellProcPtr)rdpSendBell,
                                (KbdCtrlProcPtr)NoopDDA);
@@ -634,6 +654,34 @@ PtrAddEvent(int buttonMask, int x, int y)
   g_old_button_mask = buttonMask;
 }
 
+#ifdef XKB
+int
+KbdLockedStateSync(int lockstate)
+{
+
+    /* num lock 69*/
+    if (lockstate & 2) {
+        XkbSyncLockedMods(kbdDevice,77,TRUE);
+    }
+    else {
+        XkbSyncLockedMods(kbdDevice,77,FALSE);
+    }
+    /* scroll lock 70*/
+    if (lockstate & 1) {
+        XkbSyncLockedMods(kbdDevice,78,TRUE);
+    } else {
+        XkbSyncLockedMods(kbdDevice,78,FALSE);
+    }
+    /* caps lock 58*/
+    if (lockstate & 4) {
+        XkbSyncLockedMods(kbdDevice,66,TRUE);
+    } else {
+        XkbSyncLockedMods(kbdDevice,66,FALSE);
+    }
+
+    return 0;
+}
+#endif
 /******************************************************************************/
 void
 KbdAddEvent(int down, int param1, int param2, int param3, int param4)
@@ -644,97 +692,97 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
   switch (param3)
   {
     case 1: /* esc */
-      ch = 67;
+      ch = 9;
       break;
     case 2: /* 1 or ! */
-      ch = 18;
+      ch = 10;
       break;
     case 3: /* 2 or @ */
-      ch = 19;
+      ch = 11;
       break;
     case 4: /* 3 or # */
-      ch = 20;
+      ch = 12;
       break;
     case 5: /* 4 or $ */
-      ch = 21;
+      ch = 13;
       break;
     case 6: /* 5 or % */
-      ch = 22;
+      ch = 14;
       break;
     case 7: /* 6 or ^ */
-      ch = 23;
+      ch = 15;
       break;
     case 8: /* 7 or & */
-      ch = 24;
+      ch = 16;
       break;
     case 9: /* 8 or * */
-      ch = 25;
+      ch = 17;
       break;
     case 10: /* 9 or ( */
-      ch = 26;
+      ch = 18;
       break;
     case 11: /* 0 or ) */
-      ch = 17;
+      ch = 19;
       break;
     case 12: /* - or _ */
-      ch = 27;
+      ch = 20;
       break;
     case 13: /* = or + */
-      ch = 28;
+      ch = 21;
       break;
     case 14: /* backspace */
-      ch = 64;
+      ch = 22;
       break;
     case 15: /* tab */
-      ch = 66;
+      ch = 23;
       break;
     case 16: /* q */
-      ch = 54;
+      ch = 24;
       break;
     case 17: /* w */
-      ch = 60;
+      ch = 25;
       break;
     case 18: /* e */
-      ch = 42;
+      ch = 26;
       break;
     case 19: /* r */
-      ch = 55;
+      ch = 27;
       break;
     case 20: /* t */
-      ch = 57;
+      ch = 28;
       break;
     case 21: /* y */
-      ch = 62;
+      ch = 29;
       break;
     case 22: /* u */
-      ch = 58;
+      ch = 30;
       break;
     case 23: /* i */
-      ch = 46;
+      ch = 31;
       break;
     case 24: /* o */
-      ch = 52;
+      ch = 32;
       break;
     case 25: /* p */
-      ch = 53;
+      ch = 33;
       break;
     case 26: /* [ or { */
-      ch = 29;
+      ch = 34;
       break;
     case 27: /* ] or } */
-      ch = 30;
+      ch = 35;
       break;
     case 28: /* enter */
-      ch = 65;
+      ch = 36;
       break;
     case 29: /* left and right control */
       if (param4 & 0x100) /* rdp ext flag */
       {
-        ch = 9;
+        ch = 109;
       }
       else
       {
-        ch = 8;
+        ch = 37;
       }
       break;
     case 30: /* a */
@@ -743,295 +791,298 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4)
       ch = 38;
       break;
     case 31: /* s */
-      ch = 56;
+      ch = 39;
       break;
     case 32: /* d */
-      ch = 41;
+      ch = 40;
       break;
     case 33: /* f */
-      ch = 43;
+      ch = 41;
       break;
     case 34: /* g */
-      ch = 44;
+      ch = 42;
       break;
     case 35: /* h */
-      ch = 45;
+      ch = 43;
       break;
     case 36: /* j */
-      ch = 47;
+      ch = 44;
       break;
     case 37: /* k */
-      ch = 48;
+      ch = 45;
       break;
     case 38: /* l */
-      ch = 49;
+      ch = 46;
       break;
     case 39: /* : or ; */
-      ch = 31;
+      ch = 47;
       break;
     case 40: /* ' or " */
-      ch = 32;
+      ch = 48;
       break;
     case 41: /* ` or ~ */
-      ch = 33;
+      ch = 49;
       break;
     case 42: /* left shift */
-      ch = 10;
+      ch = 50;
       break;
     case 43: /* \ or | */
-      ch = 37;
+      ch = 51;
       break;
     case 44: /* z */
-      ch = 63;
+      ch = 52;
       break;
     case 45: /* x */
-      ch = 61;
+      ch = 53;
       break;
     case 46: /* c */
-      ch = 40;
+      ch = 54;
       break;
     case 47: /* v */
-      ch = 59;
+      ch = 55;
       break;
     case 48: /* b */
-      ch = 39;
+      ch = 56;
       break;
     case 49: /* n */
-      ch = 51;
+      ch = 57;
       break;
     case 50: /* m */
-      ch = 50;
+      ch = 58;
       break;
     case 51: /* , or < */
-      ch = 34;
+      ch = 59;
       break;
     case 52: /* . or > */
-      ch = 35;
+      ch = 60;
       break;
     case 53: /* / or ? */
-      ch = 36;
+      ch = 61;
       break;
     case 54: /* right shift */
-      ch = 11;
+      ch = 62;
       break;
     case 55: /* * on keypad or print screen if ext */
       if (param4 & 0x100) /* rdp ext flag */
       {
-        ch = 90;
+         ch = 111;  /* Print */
       }
       else
       {
-        ch = 89;
+         ch = 63;
       }
       break;
     case 56: /* left and right alt */
       if (param4 & 0x100) /* rdp ext flag */
       {
-        ch = 15; /* right alt */
+        ch = 113; /* right alt */
       }
       else
       {
-        ch = 14; /* left alt */
+        ch = 64; /* left alt */
       }
       break;
     case 57: /* space */
-      ch = 16;
+      ch = 65;
       break;
     case 58: /* caps lock */
-      ch = 91;
+      ch = 66;
       g_caps_lock = down;
       break;
     case 59: /* F1 */
-      ch = 77;
+      ch = 67;
       break;
     case 60: /* F2 */
-      ch = 78;
+      ch = 68;
       break;
     case 61: /* F3 */
-      ch = 79;
+      ch = 69;
       break;
     case 62: /* F4 */
-      ch = 80;
+      ch = 70;
       break;
     case 63: /* F5 */
-      ch = 81;
+      ch = 71;
       break;
     case 64: /* F6 */
-      ch = 82;
+      ch = 72;
       break;
     case 65: /* F7 */
-      ch = 83;
+      ch = 73;
       break;
     case 66: /* F8 */
-      ch = 84;
+      ch = 74;
       break;
     case 67: /* F9 */
-      ch = 85;
+      ch = 75;
       break;
     case 68: /* F10 */
-      ch = 86;
+      ch = 76;
       break;
     case 69: /* Num lock */
-      ch = 92;
+      ch = 77;
       break;
     case 70: /* Scroll lock */
-      ch = 93;
+      ch = 78;
       break;
     case 71: /* 7 or home */
       if (param2 == 0xffff) /* ascii 7 */
       {
-        ch = 95; /* keypad 7 */
+        ch = 79; /* keypad 7 */
       }
       else if (param4 & 0x100)
       {
-        ch = 69; /* non keypad home */
+        ch = 97; /* non keypad home */
       }
       else
       {
-        ch = 94; /* keypad home */
+        ch = 79; /* keypad home */
       }
       break;
     case 72: /* 8 or up arrow */
       if (param2 == 0xffff) /* ascii 8 */
       {
-        ch = 97; /* keypad 8 */
+        ch = 80; /* keypad 8 */
       }
       else if (param4 & 0x100)
       {
-        ch = 73; /* non keypad up */
+        ch = 98; /* non keypad up */
       }
       else
       {
-        ch = 96; /* keypad up */
+        ch = 80; /* keypad up */
       }
       break;
     case 73: /* 9 or page up */
       if (param2 == 0xffff) /* ascii 9 */
       {
-        ch = 99; /* keypad 9 */
+        ch = 81; /* keypad 9 */
       }
       else if (param4 & 0x100)
       {
-        ch = 71; /* non keypad page up */
+        ch = 99; /* non keypad page up */
       }
       else
       {
-        ch = 98; /* keypad page up */
+        ch = 81; /* keypad page up */
       }
       break;
     case 74: /* minus on keypad */
-      ch = 100;
+      ch = 82;
       break;
     case 75: /* 4 or left arrow */
       if (param2 == 0xffff) /* ascii 4 */
       {
-        ch = 102; /* keypad 4 */
+        ch = 83; /* keypad 4 */
       }
       else if (param4 & 0x100)
       {
-        ch = 75; /* non keypad left */
+        ch = 100; /* non keypad left */
       }
       else
       {
-        ch = 101; /* keypad left */
+        ch = 83; /* keypad left */
       }
       break;
     case 76: /* 5 on keypad */
-      ch = 103;
+      ch = 84;
       break;
     case 77: /* 6 or right arrow */
       if (param2 == 0xffff) /* ascii 6 */
       {
-        ch = 105; /* keypad 6 */
+        ch = 85; /* keypad 6 */
       }
       else if (param4 & 0x100)
       {
-        ch = 76; /* non keypad right */
+        ch = 102; /* non keypad right */
       }
       else
       {
-        ch = 104; /* keypad right */
+        ch = 85; /* keypad right */
       }
       break;
     case 78: /* plus on keypad */
-      ch = 106;
+      ch = 86;
       break;
     case 79: /* 1 or end */
       if (param2 == 0xffff) /* ascii 1 */
       {
-        ch = 108; /* keypad 1 */
+        ch = 87; /* keypad 1 */
       }
       else if (param4 & 0x100)
       {
-        ch = 70; /* non keypad end */
+        ch = 103; /* non keypad end */
       }
       else
       {
-        ch = 107; /* keypad end */
+        ch = 87; /* keypad end */
       }
       break;
     case 80: /* 2 or down arrow */
       if (param2 == 0xffff) /* ascii 2 */
       {
-        ch = 110; /* keypad 2 */
+        ch = 88; /* keypad 2 */
       }
       else if (param4 & 0x100)
       {
-        ch = 74; /* non keypad down arrow */
+        ch = 104; /* non keypad down arrow */
       }
       else
       {
-        ch = 109; /* keypad down arrow */
+        ch = 88; /* keypad down arrow */
       }
       break;
     case 81: /* 3 or page down */
       if (param2 == 0xffff) /* ascii 3 */
       {
-        ch = 112; /* keypad 3 */
+        ch = 89; /* keypad 3 */
       }
       else if (param4 & 0x100)
       {
-        ch = 72; /* non keypad page down */
+        ch = 105; /* non keypad page down */
       }
       else
       {
-        ch = 111; /* keypad page down */
+        ch = 89; /* keypad page down */
       }
       break;
     case 82: /* 0 or insert */
       if (param2 == 0xffff) /* ascii 0 */
       {
-        ch = 114; /* keypad 0 */
+        ch = 90; /* keypad 0 */
       }
       else if (param4 & 0x100)
       {
-        ch = 115; /* non keypad insert */
+        ch = 106; /* non keypad insert */
       }
       else
       {
-        ch = 113; /* keypad insert */
+        ch = 90; /* keypad insert */
       }
       break;
     case 83: /* . or delete */
       if (param2 == 0xffff) /* ascii . */
       {
-        ch = 117; /* keypad . */
+        ch = 91; /* keypad . */
       }
       else if (param4 & 0x100)
       {
-        ch = 68; /* non keypad delete */
+        ch = 107; /* non keypad delete */
       }
       else
       {
-        ch = 116; /* keypad delete */
+        ch = 91; /* keypad delete */
       }
       break;
     case 87: /* F11 */
-      ch = 87;
+      ch = 95;
       break;
     case 88: /* F12 */
-      ch = 88;
+      ch = 96;
       break;
+   default:
+      ErrorF ("Unknow key %d\n", ch);
+      return;
   }
   if (ch > 0)
   {
diff --git a/hw/rdp/rdpmain.c b/hw/rdp/rdpmain.c
index 9ea1c19..95b42c2 100644
--- a/hw/rdp/rdpmain.c
+++ b/hw/rdp/rdpmain.c
@@ -23,6 +23,8 @@ Sets up the  functions
 */
 
 #include "rdp.h"
+#include "os.h"
+
 
 rdpScreenInfo g_rdpScreen; /* the one screen */
 ScreenPtr g_pScreen = 0;
@@ -30,6 +32,7 @@ DevPrivateKey g_rdpGCPrivateKey = &g_rdpGCPrivateKey;
 int g_rdpGCIndex = -1;
 int g_firstTime = 1;
 EventList *rdpEvents = NULL;
+extern rdpInputInfo rdpInput;
 
 /* set all these at once, use function set_bpp */
 /* only allow 8 and 16 bpp for not, adding 32 later */
@@ -377,6 +380,31 @@ ddxProcessArgument(int argc, char** argv, int i)
     }
     return 2;
   }
+  if (strcmp (argv[i], "-rdplayout") == 0)
+  {
+      rdpInputLayout layout;
+      if (i + 1 >= argc)
+      {
+          UseMsg();
+      }
+      layout = rdpStr2Layout(argv[i + 1]);
+      if (layout == RDP_INPUT_LAYOUT_NONE)
+      {
+          ErrorF ("Layout %s is not supported. Use us as default\n", argv[i + 1]);
+          rdpInput.layout_name = "us";
+          rdpInput.layout = RDP_INPUT_LAYOUT_EN_US;
+          rdpLog ("use default us\n");
+      }
+      else {
+          rdpInput.layout_name = strdup (argv[i + 1]);
+          rdpInput.layout = layout;
+          ErrorF ("Layout %s is used\n", rdpInput.layout_name);
+          char tmpbuf[256];
+          sprintf (tmpbuf, "use layout %s from commandline\n", rdpInput.layout_name);
+          rdpLog (tmpbuf);
+      }
+      return 2;
+  }
   return 0;
 }
 
@@ -430,14 +458,22 @@ InitInput(int argc, char** argv)
   DeviceIntPtr k;
 
   /* use rdp device control functions for the virtual core devices */
-  inputInfo.keyboard->deviceProc = rdpKeybdProc;
-  inputInfo.pointer->deviceProc  = rdpMouseProc;
+  //  inputInfo.keyboard->deviceProc = rdpKeybdProc;
+  //  inputInfo.pointer->deviceProc  = rdpMouseProc;
 
   k = AddInputDevice(serverClient, rdpKeybdProc, 1);
   p = AddInputDevice(serverClient, rdpMouseProc, 1);
+
   GetEventList(&rdpEvents);
-  RegisterKeyboardDevice(k);
-  RegisterPointerDevice(p);
+
+  RegisterOtherDevice(k);
+  RegisterOtherDevice(p);
+#ifdef XKB
+  if (!noXkbExtension) {
+    XkbSetExtension (k, ProcessKeyboardEvent);
+    XkbSetExtension (k, ProcessPointerEvent);
+  }
+#endif 
   mieqInit();
 /*
   mieqCheckForInput[0] = checkForInput[0];
@@ -496,6 +532,7 @@ ddxUseMsg(void)
   ErrorF("X11rdp specific options\n");
   ErrorF("-geometry WxH          set framebuffer width & height\n");
   ErrorF("-depth D               set framebuffer depth\n");
+  ErrorF("-rdplayout layout      set the remote keyboard layout\n");
   ErrorF("\n");
   exit(1);
 }
diff --git a/hw/rdp/rdpmisc.c b/hw/rdp/rdpmisc.c
index 3078003..24764e0 100644
--- a/hw/rdp/rdpmisc.c
+++ b/hw/rdp/rdpmisc.c
@@ -25,6 +25,51 @@ the rest
 
 /******************************************************************************/
 /* print a time-stamped message to the log file (stderr). */
+
+rdpInputLayout
+rdpStr2Layout(const char *layout_name)
+{
+    rdpInputLayout layout = RDP_INPUT_LAYOUT_NONE;
+
+    if (!strcmp (layout_name, "us"))
+    {
+        layout = RDP_INPUT_LAYOUT_EN_US;
+    }
+    else if (!strcmp (layout_name, "uk"))
+    {
+        layout = RDP_INPUT_LAYOUT_EN_UK;
+    }
+    else if (!strcmp (layout_name, "fr"))
+    {
+        layout = RDP_INPUT_LAYOUT_FRANCE;
+    }
+    else if (!strcmp (layout_name, "de"))
+    {
+        layout = RDP_INPUT_LAYOUT_GERMAN;
+    }
+    else if (!strcmp (layout_name, "it"))
+    {
+        layout = RDP_INPUT_LAYOUT_ITALY;
+    }
+    else if (!strcmp (layout_name, "pt"))
+    {
+        layout = RDP_INPUT_LAYOUT_PORTUGUESE;
+    }
+    else if (!strcmp (layout_name, "sv"))
+    {
+        layout = RDP_INPUT_LAYOUT_SWEDISH;
+    }
+    else if (!strcmp (layout_name, "cs"))
+    {
+        layout = RDP_INPUT_LAYOUT_CZECH;
+    }
+    else if (!strcmp (layout_name, "su"))
+    {
+        layout = RDP_INPUT_LAYOUT_RUSSIAN;
+    }
+    return layout;
+}
+
 void
 rdpLog(char *format, ...)
 {
diff --git a/hw/rdp/rdpup.c b/hw/rdp/rdpup.c
index 9b5b996..7b3d845 100644
--- a/hw/rdp/rdpup.c
+++ b/hw/rdp/rdpup.c
@@ -275,6 +275,7 @@ param4 %d\n", msg, param1, param2, param3, param4);*/
         break;
       case 17: /* from RDP_INPUT_SYNCHRONIZE */
 #if 0
+        KbdLockedStateSync (param1);
         /* scroll lock */
         if (param1 & 1)
         {
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 5254051..f8bbb87 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -734,6 +734,10 @@ extern void XkbProcessKeyboardEvent(
     int 			/* count */
 );
 
+extern int XkbSyncLockedMods(DeviceIntPtr dev,
+                              CARD8 key,
+                              Bool on);
+
 extern void XkbHandleActions(
     DeviceIntPtr		/* dev */,
     DeviceIntPtr		/* kbd */,
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 8a26825..3828245 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1132,6 +1132,44 @@ register int	i,send;
     return send;
 }
 
+int
+XkbSyncLockedMods(DeviceIntPtr dev,CARD8 key,Bool on)
+{
+    XkbAction act;
+    XkbSrvInfoPtr xkbi;
+    KeyClassPtr keyc;
+    XkbStateRec oldState;
+    unsigned char locked_mods;
+    unsigned char base_mods;
+
+    keyc = dev->key;
+    xkbi = keyc->xkbInfo;
+    act = XkbGetKeyAction (xkbi, &xkbi->state, key);
+    //check act
+    oldState = xkbi->state;
+    locked_mods = xkbi->state.locked_mods;
+    base_mods = xkbi->state.base_mods;
+    if (on){
+        locked_mods |= act.mods.mask;
+        base_mods |= act.mods.mask;
+    }
+    else{
+        locked_mods &= act.mods.mask;
+        base_mods &= act.mods.mask;
+    }
+    if (locked_mods == xkbi->state.locked_mods) {
+        return 1;
+    }
+    xkbi->state.locked_mods = locked_mods;
+    xkbi->state.base_mods = base_mods;
+
+    xkbi->prev_state = oldState;
+    XkbComputeDerivedState(xkbi); /* ?? make sure of this */
+    keyc->prev_state = keyc->state;
+    keyc->state = XkbStateFieldFromRec(&xkbi->state);
+    return 0;
+}
+
 void
 XkbHandleActions(DeviceIntPtr dev,DeviceIntPtr kbd,xEvent *xE,int count)
 {
