Index: trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobalSettings.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobalSettings.h	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/include/VBoxGlobalSettings.h	(revision 21711)
@@ -47,4 +47,5 @@
     QString languageId;
     QString maxGuestRes;
+    QString remapScancodes;
     bool trayIconEnabled;
     bool dockPreviewEnabled;
@@ -63,4 +64,5 @@
     Q_PROPERTY (QString languageId READ languageId WRITE setLanguageId)
     Q_PROPERTY (QString maxGuestRes READ maxGuestRes WRITE setMaxGuestRes)
+    Q_PROPERTY (QString remapScancodes READ remapScancodes WRITE setRemapScancodes)
     Q_PROPERTY (bool trayIconEnabled READ trayIconEnabled WRITE setTrayIconEnabled)
     Q_PROPERTY (bool dockPreviewEnabled READ dockPreviewEnabled WRITE setDockPreviewEnabled)
@@ -106,4 +108,11 @@
         mData()->maxGuestRes = aMaxGuestRes;
     }
+
+    QString remapScancodes() const { return data()->remapScancodes; }
+    void setRemapScancodes (const QString &aRemapScancodes)
+    {
+        mData()->remapScancodes = aRemapScancodes;
+    }
+
 
     bool trayIconEnabled() const { return data()->trayIconEnabled; }
Index: trunk/src/VBox/Frontends/VirtualBox/include/XKeyboard.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/include/XKeyboard.h	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/include/XKeyboard.h	(revision 21711)
@@ -24,6 +24,8 @@
 #define __XKeyboard_h__
 
+#include <QString>
+
 // initialize the X keyboard subsystem
-bool initXKeyboard(Display *dpy);
+void initMappedX11Keyboard(Display *pDisplay, QString remapScancodes);
 // our custom keyboard handler
 unsigned handleXKeyEvent(XEvent *event);
Index: trunk/src/VBox/Frontends/VirtualBox/src/QIHotKeyEdit.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/QIHotKeyEdit.cpp	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/src/QIHotKeyEdit.cpp	(revision 21711)
@@ -23,4 +23,5 @@
 #include "QIHotKeyEdit.h"
 #include "VBoxDefs.h"
+#include "VBoxGlobal.h"
 
 /* Qt includes */
@@ -119,5 +120,6 @@
 #ifdef Q_WS_X11
     /* Initialize the X keyboard subsystem */
-    initXKeyboard (QX11Info::display());
+    initMappedX11Keyboard(QX11Info::display(),
+            vboxGlobal().settings().publicProperty ("GUI/RemapScancodes"));
 #endif
 
Index: trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp	(revision 21711)
@@ -797,5 +797,6 @@
 #ifdef Q_WS_X11
     /* initialize the X keyboard subsystem */
-    initXKeyboard (QX11Info::display());
+    initMappedX11Keyboard(QX11Info::display(),
+            vboxGlobal().settings().publicProperty ("GUI/RemapScancodes"));
 #endif
 
Index: trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.cpp	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.cpp	(revision 21711)
@@ -60,4 +60,5 @@
     languageId  = QString::null;
     maxGuestRes = "auto";
+    remapScancodes = QString::null;
     trayIconEnabled = false;
     dockPreviewEnabled = true;
@@ -71,4 +72,5 @@
     languageId  = that.languageId;
     maxGuestRes = that.maxGuestRes;
+    remapScancodes = that.remapScancodes;
     trayIconEnabled = that.trayIconEnabled;
     dockPreviewEnabled = that.dockPreviewEnabled;
@@ -87,4 +89,5 @@
          languageId  == that.languageId &&
          maxGuestRes == that.maxGuestRes &&
+         remapScancodes == that.remapScancodes &&
          trayIconEnabled == that.trayIconEnabled
          && dockPreviewEnabled == that.dockPreviewEnabled
@@ -115,4 +118,5 @@
     { "GUI/LanguageID",                            "languageId",         gVBoxLangIDRegExp, true },
     { "GUI/MaxGuestResolution",                    "maxGuestRes",        "\\d*[1-9]\\d*,\\d*[1-9]\\d*|any|auto", true },
+    { "GUI/RemapScancodes",                        "remapScancodes",     "(\\d+=\\d+,)*\\d+=\\d+", true },
     { "GUI/TrayIcon/Enabled",                      "trayIconEnabled",    "true|false", true },
 #ifdef Q_WS_MAC
Index: trunk/src/VBox/Frontends/VirtualBox/src/X11/XKeyboard-new.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/X11/XKeyboard-new.cpp	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/src/X11/XKeyboard-new.cpp	(revision 21711)
@@ -23,4 +23,6 @@
 #define LOG_GROUP LOG_GROUP_GUI
 
+#include <QString>
+#include <QStringList>
 #include <X11/Xlib.h>
 #include <X11/keysym.h>
@@ -187,7 +189,7 @@
  * mappings.
  */
-bool initXKeyboard(Display *dpy)
-{
-    X11DRV_InitKeyboard(dpy, &gfByLayoutOK, &gfByTypeOK);
+bool initXKeyboard(Display *dpy, int (*remapScancodes)[2])
+{
+    X11DRV_InitKeyboard(dpy, &gfByLayoutOK, &gfByTypeOK, remapScancodes);
     /* It will almost always work to some extent */
     return true;
@@ -203,5 +205,5 @@
     if ((1 == gfByLayoutOK) && (gfByTypeOK != 1))
         dumpType(dpy);
-    if ((gfByLayoutOK != 1) && (gfByTypeOK != 1))
+    if ((gfByLayoutOK != 1) && (gfByTypeOK != 1)) {
         LogRel(("Failed to recognize the keyboard mapping or to guess it based on\n"
                 "the keyboard layout.  It is very likely that some keys will not\n"
@@ -210,5 +212,12 @@
                 "about your keyboard type, its layout and other relevant\n"
                 "information such as whether you are using a remote X server or\n"
-                "something similar.\n"));
+                "something similar. \n"));
+	unsigned *keyc2scan=X11DRV_getKeyc2scan();
+
+	LogRel(("The keycode-to-scancode table is: %d=%d",0,keyc2scan[0]));
+	for(int i=1; i<256; i++)
+	    LogRel((",%d=%d",i,keyc2scan[i]));
+	LogRel(("\n"));
+    }
 }
 
@@ -234,2 +243,34 @@
     return 8;
 }
+
+/** 
+ * Initialize X11 keyboard including the remapping specified in the
+ * global property GUI/RemapScancodes. This property is a string of
+ * comma-seperated x=y pairs, where x is the X11 keycode and y is the
+ * keyboard scancode that is emitted when the key attached to the X11
+ * keycode is pressed.
+ */
+void initMappedX11Keyboard(Display *pDisplay, QString remapScancodes)
+{
+    int (*scancodes)[2] = NULL;
+    int (*scancodesTail)[2] = NULL;
+
+    if(remapScancodes != QString::null) {
+	QStringList tuples = remapScancodes.split(",", QString::SkipEmptyParts);
+	scancodes = scancodesTail = new int [tuples.size()+1][2];
+	for (int i = 0; i < tuples.size(); ++i) {
+	    QStringList keyc2scan = tuples.at(i).split("=");
+	    (*scancodesTail)[0] = keyc2scan.at(0).toUInt();
+	    (*scancodesTail)[1] = keyc2scan.at(1).toUInt();
+	    /* Do not advance on (ignore) identity mappings as this is
+	       the stop signal to initXKeyboard and friends */
+	    if((*scancodesTail)[0] != (*scancodesTail)[1]) 
+		scancodesTail++;
+	}
+	(*scancodesTail)[0] = (*scancodesTail)[1] = 0;
+    } 
+    /* initialize the X keyboard subsystem */
+    initXKeyboard (pDisplay ,scancodes);
+
+    if(scancodes) delete scancodes;
+}
Index: trunk/src/VBox/Frontends/VirtualBox/src/X11/keyboard-new.c
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/X11/keyboard-new.c	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/src/X11/keyboard-new.c	(revision 21711)
@@ -55,16 +55,11 @@
 #include <stdio.h>
 
+#define KEYC2SCAN_SIZE 256
+
 /** 
  * Array containing the current mapping of keycodes to scan codes, detected
  * using the keyboard layout algorithm in X11DRV_InitKeyboardByLayout.
  */
-static unsigned keyc2scan[256];
-/** 
- * Whether a keyboard was detected with a well-known keycode to scan code
- * mapping.
- */
-static unsigned use_builtin_table = 0;
-/** The index of the well-known keycode to scan code mapping in our table. */
-static unsigned builtin_table_number;
+static unsigned keyc2scan[KEYC2SCAN_SIZE];
 /** Whether to output basic debugging information to standard output */
 static int log_kb_1 = 0;
@@ -126,10 +121,6 @@
     }
     if (keysym != 0 && scan == 0)
-    {
-        if (use_builtin_table != 0)
-            scan = main_keyboard_type_scans[builtin_table_number][code];
-        else
             scan = keyc2scan[code];
-    }
+
     return scan;
 }
@@ -440,7 +431,6 @@
            )
             found = 1;
-    use_builtin_table = found;
     if (found != 0)
-        builtin_table_number = i - 1;
+	memcpy(keyc2scan, main_keyboard_type_scans[i - 1], KEYC2SCAN_SIZE);
     return found;
 }
@@ -464,16 +454,37 @@
  * @returns 1 if the layout found was optimal, 0 if it was not.  This is
  *          for diagnostic purposes
- * @param   display     a pointer to the X11 display
- * @param   byLayoutOK  diagnostic - set to one if detection by layout
- *                      succeeded, and to 0 otherwise
- * @param   byTypeOK    diagnostic - set to one if detection by type
- *                      succeeded, and to 0 otherwise
- */
-unsigned X11DRV_InitKeyboard(Display *display, unsigned *byLayoutOK, unsigned *byTypeOK)
-{
-    unsigned byLayout = X11DRV_InitKeyboardByLayout(display);
-    unsigned byType   = X11DRV_InitKeyboardByType(display);
+ * @param   display          a pointer to the X11 display
+ * @param   byLayoutOK       diagnostic - set to one if detection by layout
+ *                           succeeded, and to 0 otherwise
+ * @param   byTypeOK         diagnostic - set to one if detection by type
+ *                           succeeded, and to 0 otherwise
+ * @param   remapScancode    array of tuples that remap the keycode (first
+ *                           part) to a scancode (second part)
+ */
+unsigned X11DRV_InitKeyboard(Display *display, unsigned *byLayoutOK, unsigned *byTypeOK, int (*remapScancodes)[2])
+{
+    unsigned byLayout; 
+    unsigned byType; 
+
+    byLayout = X11DRV_InitKeyboardByLayout(display);
     *byLayoutOK = byLayout;
-    *byTypeOK   = byType;
+
+    byType = X11DRV_InitKeyboardByType(display);
+    *byTypeOK = byType;
+
+    /* Remap keycodes after initialization. Remapping stops after an
+       identity mapping is seen */
+    if(remapScancodes != NULL)
+	for(; (*remapScancodes)[0] != (*remapScancodes)[1]; remapScancodes++) 
+	    keyc2scan[(*remapScancodes)[0]] = (*remapScancodes)[1];
+
     return (byLayout || byType) ? 1 : 0;
 }
+
+/**
+ * Returns the keycode to scancode array
+ */
+unsigned *X11DRV_getKeyc2scan()
+{
+    return keyc2scan;
+}
Index: trunk/src/VBox/Frontends/VirtualBox/src/X11/keyboard.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/X11/keyboard.h	(revision 21655)
+++ trunk/src/VBox/Frontends/VirtualBox/src/X11/keyboard.h	(revision 21711)
@@ -44,8 +44,10 @@
 #endif
 #ifdef VBOX_HAVE_VISIBILITY_HIDDEN
-extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK);
+extern CCALL __attribute__((visibility("default"))) unsigned *X11DRV_getKeyc2scan();
+extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK, int (*remapScancodes)[2]);
 extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_KeyEvent(Display *dpy, KeyCode code);
 #else
-extern CCALL unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK);
+extern CCALL unsigned *X11DRV_getKeyc2scan();
+extern CCALL unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK, int (*remapScancodes)[2]);
 extern CCALL unsigned X11DRV_KeyEvent(Display *dpy, KeyCode code);
 #endif
