0x0000041d = Swedish keyboard layout

scan code 0x1a corresponds to virtual key code VK_OEM_4

Using a set of maps exported from the XKB database, a map of keycodes to virtual key codes would be loaded. 0x0000041d would be sent either automatically from auto-detection of keyboard layout or from user specified settings, in order to specify a Swedish keyboard layout. When the user would press the key that is _consistently_ called VK_OEM_4, rdesktop would send scan code 0x1a, and the server would then interpret 0x1a as being aring according to the Swedish keyboard layout.


Look in keyboard.h, you should find a map of keyboard layout IDs to their names:

keyboardLayout keyboardLayouts[] =
{
    { 0x00000401, "Arabic (101)" },
    { 0x00000402, "Bulgarian" },
    { 0x00000404, "Chinese (Traditional) - US Keyboard" },
    { 0x00000405, "Czech" },
    { 0x00000406, "Danish" },
    { 0x00000407, "German" },
    { 0x00000408, "Greek" },

....

    { 0x00001009, "Canadian French" },
    { 0x0000100C, "Swiss French" },
    { 0x0000141A, "Bosnian" },
    { 0x00001809, "Irish" },
    { 0x0000201A, "Bosnian Cyrillic" }
};


Take a closer look at the map from virtual key code to scan code:

virtualKey virtualKeyboard[256] =
{
    { 0x00, "" },
    { 0x00, "VK_LBUTTON" },
    { 0x00, "VK_RBUTTON" },
    { 0x00, "VK_CANCEL" },
    { 0x00, "VK_MBUTTON" },
    { 0x00, "VK_XBUTTON1" },
    { 0x00, "VK_XBUTTON2" },

...

    { 0x1A, "VK_OEM_4" },
    { 0x2B, "VK_OEM_5" },
    { 0x1B, "VK_OEM_6" },
    { 0x28, "VK_OEM_7" },
    { 0x1D, "VK_OEM_8" },

...

(I'm truncating the maps because they are quite big, look at the source code for the complete one)


Look in xkb.pl, the big hash table that maps XKB keynames to virtual key codes:

my %sym2virt = (
    "AE00" => "VK_TILDE",
    "AE01" => "VK_KEY_1",
        "AE02" => "VK_KEY_2",
        "AE03" => "VK_KEY_3",
        "AE04" => "VK_KEY_4",
        "AE05" => "VK_KEY_5",
        "AE06" => "VK_KEY_6",

...

        "AD06" => "VK_KEY_Y",
        "AD07" => "VK_KEY_U",
        "AD08" => "VK_KEY_I",
        "AD09" => "VK_KEY_O",
        "AD10" => "VK_KEY_P",
        "AD11" => "VK_OEM_4",
        "AD12" => "VK_OEM_6",

...


Now, download xkeyboard-config 1.5 and take a look at what the XKB database looks like in its original form:

xkb_keycodes "pc_common" {
    // "Function" keys
    <FK01>    = 9;
    <FK02>    = 15;
    <FK03>    = 23;
    <FK04>    = 31;
    <FK05>    = 39;

...

    // "Alphanumeric" keys
    <AE01>    = 22;
    <AE02>    = 30;
    <AE03>    = 38;
    <AE04>    = 37;
    <AE05>    = 46;
    <AE06>    = 54;
    <AE07>    = 61;
    <AE08>    = 62;

...


And now, take a look at what it looks like in the keycode->virtual key code format as exported by my perl script:

keyboard "pc_common"
{
    VK_F1        <9>
    VK_F2        <15>
    VK_F3        <23>
    VK_F4        <31>
    VK_F5        <39>
    VK_F6        <47>
    VK_F7        <55>
    VK_F8        <63>
    VK_F9        <71>

...

    VK_OEM_4    <84>
    VK_OEM_6    <91>
    VK_CAPITAL    <20>
    VK_KEY_A    <28>
    VK_KEY_S    <27>
    VK_KEY_D    <35>
    VK_KEY_F    <43>
    VK_KEY_G    <52>

...

Now, take a look at xkbkeymap.c for the function loadKeyboard(char* kbd)

The function will load a keycode->virtual keycode map from the exported maps. When loaded, the name of the virtual key code is taken, and then its corresponding virtual key code (the number) is found by looking in the array shown earlier (virtualKey virtualKeyboard[256]...). The map that is used at run time is an array of 256 unsigned chars. The index in the array corresponds to the keycode, and the value at the index is the resulting virtual key code. When the user presses a key, my code will simply look for the value at the index corresponding to the keycode of the last keystroke, and will use that value as an index in virtualKey virtualKeyboard[256] to get the corresponding scan code instantly.

On Mon, May 18, 2009 at 3:29 AM, Peter Åstrand <astrand@cendio.se> wrote:
On Mon, 18 May 2009, Marc-André Moreau wrote:

Sure, but that doesn't mean that they are usable.


     keycodes alone are unreliable as they are
     hardware dependent, but that was the whole point of using the XKB *database* to map them a
     consistent naming system
     (XKB key names / virtual key codes).

Perhaps an example helps. In a typical Xvnc session, you have have a layout that includes this mapping:

$ xmodmap -pke | grep aring
keycode 255 = aring

To get a "aring" in the remove RDP session, one needs to send a keyboard layout code of 0x0000041d, and then the scancode 0x1a.

Now tell me: How do you know that the keycode 255 should be translated to scancode 0x1a, by using the XKB database?


Rgds, ---
Peter Åstrand           ThinLinc Chief Developer
Cendio AB               http://www.cendio.com
Wallenbergs gata 4
583 30 Linköping        Phone: +46-13-21 46 00