Index: src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h
===================================================================
--- src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/include/VBoxGlobal.h	(working copy)
@@ -39,6 +39,7 @@
 
 #ifdef Q_WS_X11
 # include <sys/wait.h>
+# include "XKeyboard.h"
 #endif
 
 class QAction;
@@ -1001,4 +1002,8 @@
     bool     mInverted;
 };
 
+#ifdef Q_WS_X11
+void initMappedX11Keyboard();
+#endif
+
 #endif /* __VBoxGlobal_h__ */
Index: src/VBox/Frontends/VirtualBox/include/XKeyboard.h
===================================================================
--- src/VBox/Frontends/VirtualBox/include/XKeyboard.h	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/include/XKeyboard.h	(working copy)
@@ -24,7 +24,7 @@
 #define __XKeyboard_h__
 
 // initialize the X keyboard subsystem
-bool initXKeyboard(Display *dpy);
+bool initXKeyboard(Display *dpy, int (*scancodes)[2]);
 // our custom keyboard handler
 unsigned handleXKeyEvent(XEvent *event);
 // returns the number of keysyms per keycode (only valid after initXKeyboard())
Index: src/VBox/Frontends/VirtualBox/include/VBoxGlobalSettings.h
===================================================================
--- src/VBox/Frontends/VirtualBox/include/VBoxGlobalSettings.h	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/include/VBoxGlobalSettings.h	(working copy)
@@ -46,6 +46,7 @@
     QString guiFeatures;
     QString languageId;
     QString maxGuestRes;
+    QString remapScancodes;
     bool trayIconEnabled;
     bool dockPreviewEnabled;
 
@@ -62,6 +63,7 @@
     Q_PROPERTY (QString guiFeatures READ guiFeatures WRITE setGuiFeatures)
     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,6 +108,13 @@
         mData()->maxGuestRes = aMaxGuestRes;
     }
 
+    QString remapScancodes() const { return data()->remapScancodes; }
+    void setRemapScancodes (const QString &aRemapScancodes)
+    {
+        mData()->remapScancodes = aRemapScancodes;
+    }
+
+
     bool trayIconEnabled() const { return data()->trayIconEnabled; }
     void setTrayIconEnabled (bool enabled)
     {
Index: src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.cpp	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.cpp	(working copy)
@@ -59,6 +59,7 @@
     guiFeatures = QString::null;
     languageId  = QString::null;
     maxGuestRes = "auto";
+    remapScancodes = QString::null;
     trayIconEnabled = false;
     dockPreviewEnabled = true;
 }
@@ -70,6 +71,7 @@
     guiFeatures = that.guiFeatures;
     languageId  = that.languageId;
     maxGuestRes = that.maxGuestRes;
+    remapScancodes = that.remapScancodes;
     trayIconEnabled = that.trayIconEnabled;
     dockPreviewEnabled = that.dockPreviewEnabled;
 }
@@ -86,6 +88,7 @@
          guiFeatures == that.guiFeatures &&
          languageId  == that.languageId &&
          maxGuestRes == that.maxGuestRes &&
+         remapScancodes == that.remapScancodes &&
          trayIconEnabled == that.trayIconEnabled
          && dockPreviewEnabled == that.dockPreviewEnabled
         );
@@ -114,6 +117,7 @@
     { "GUI/Customizations",                        "guiFeatures",        "\\S+", true },
     { "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
     { VBoxDefs::GUI_RealtimeDockIconUpdateEnabled, "dockPreviewEnabled", "true|false", true }
Index: src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp	(working copy)
@@ -810,7 +810,7 @@
 
 #ifdef Q_WS_X11
     /* initialize the X keyboard subsystem */
-    initXKeyboard (QX11Info::display());
+    initMappedX11Keyboard();
 #endif
 
     ::memset (mPressedKeys, 0, sizeof (mPressedKeys));
Index: src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp	(working copy)
@@ -4941,3 +4941,36 @@
     mAction->setText (text);
 }
 
+#ifdef Q_WS_X11
+/** 
+ * 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() {
+    int (*scancodes)[2] = NULL;
+    int (*scancodesTail)[2] = NULL;
+    QString remapScancodes = vboxGlobal().settings().publicProperty ("GUI/RemapScancodes");
+
+    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 (QX11Info::display(),scancodes);
+
+    if(scancodes) delete scancodes;
+}
+#endif
Index: src/VBox/Frontends/VirtualBox/src/X11/XKeyboard-new.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/X11/XKeyboard-new.cpp	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/src/X11/XKeyboard-new.cpp	(working copy)
@@ -186,9 +186,9 @@
  * X server, find the PC layout which is closest to it and remember the
  * mappings.
  */
-bool initXKeyboard(Display *dpy)
+bool initXKeyboard(Display *dpy, int (*remapScancodes)[2])
 {
-    X11DRV_InitKeyboard(dpy, &gfByLayoutOK, &gfByTypeOK);
+    X11DRV_InitKeyboard(dpy, &gfByLayoutOK, &gfByTypeOK, remapScancodes);
     /* It will almost always work to some extent */
     return true;
 }
@@ -202,14 +202,21 @@
         dumpLayout(dpy);
     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"
                 "work correctly in the guest.  If you would like to help us improve\n"
                 "the product, please submit a bug report, giving us information\n"
                 "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"));
+    }
 }
 
 /*
Index: src/VBox/Frontends/VirtualBox/src/X11/keyboard.h
===================================================================
--- src/VBox/Frontends/VirtualBox/src/X11/keyboard.h	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/src/X11/keyboard.h	(working copy)
@@ -43,10 +43,12 @@
 # define CCALL
 #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
 
Index: src/VBox/Frontends/VirtualBox/src/X11/keyboard-new.c
===================================================================
--- src/VBox/Frontends/VirtualBox/src/X11/keyboard-new.c	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/src/X11/keyboard-new.c	(working copy)
@@ -54,18 +54,13 @@
 #include <stdlib.h>
 #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;
 /** Whether to output verbose debugging information to standard output */
@@ -125,12 +120,8 @@
             scan = 0x138;
     }
     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;
 }
 
@@ -439,9 +430,8 @@
             && (XKeysymToKeycode(display, XK_F8)        == main_keyboard_type_list[i].f8)
            )
             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;
 }
 
@@ -463,17 +453,38 @@
  * @warning not re-entrant
  * @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
+ * @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)
+unsigned X11DRV_InitKeyboard(Display *display, unsigned *byLayoutOK, unsigned *byTypeOK, int (*remapScancodes)[2])
 {
-    unsigned byLayout = X11DRV_InitKeyboardByLayout(display);
-    unsigned byType   = X11DRV_InitKeyboardByType(display);
+    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: src/VBox/Frontends/VirtualBox/src/QIHotKeyEdit.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/QIHotKeyEdit.cpp	(revision 20699)
+++ src/VBox/Frontends/VirtualBox/src/QIHotKeyEdit.cpp	(working copy)
@@ -22,6 +22,7 @@
 
 #include "QIHotKeyEdit.h"
 #include "VBoxDefs.h"
+#include "VBoxGlobal.h"
 
 /* Qt includes */
 #include <QApplication>
@@ -118,7 +119,7 @@
 {
 #ifdef Q_WS_X11
     /* Initialize the X keyboard subsystem */
-    initXKeyboard (QX11Info::display());
+    initMappedX11Keyboard();
 #endif
 
     clear();
