VirtualBox

Ignore:
Timestamp:
Jun 27, 2008 11:58:47 AM (16 years ago)
Author:
vboxsync
Message:

FE/Qt3 and 4: added a second algorithm for detecting host keyboard layout

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r9209 r9991  
    129129        src/linux/keyboard-list.h \
    130130        src/linux/keyboard-tables.h \
     131        src/linux/keyboard-types.h \
    131132        src/linux/Makefile
    132133VBoxKeyboard_LIBS     = X11
  • trunk/src/VBox/Frontends/VirtualBox/src/linux/XKeyboard-new.cpp

    r8155 r9991  
    2424
    2525#include <X11/Xlib.h>
     26#include <X11/keysym.h>
    2627#include <XKeyboard.h>
    2728#include <VBox/log.h>
    2829#include "keyboard.h"
    2930
    30 static bool gInitStatus = false;
     31static unsigned gfByLayoutOK = 1;
     32static unsigned gfByTypeOK = 1;
    3133
    3234/**
     
    7779/**
    7880 * DEBUG function
    79  * Dump the keyboard layout to the release log.  The result will only make
    80  * sense if the user is using an X.org or XFree86 server locally.
     81 * Dump the keyboard layout to the release log.
    8182 */
    8283static void dumpLayout(Display *display)
    8384{
    84     LogRel(("Your keyboard layout does not appear to fully supported by VirtualBox.  "
    85             "If you would like to help us improve the product, please submit a "
    86             "bug report and attach this logfile.  Please note that the following "
    87             "table will only be valid if you are using an X.org or XFree86 server "
    88             "locally.\n\nThe correct table for your layout is:\n"));
    89     LogRel(("\""));
    90     printKey(display, 49);
    91     for (int i = 10; i <= 21; ++i)
    92     {
    93         LogRel(("\",\""));
    94         printKey(display, i);
     85    LogRel(("Your keyboard layout does not appear to fully supported by\n"
     86            "VirtualBox. If you would like to help us improve the product,\n"
     87            "please submit a bug report and attach this logfile.\n\n"
     88            "The correct table for your layout is:\n"));
     89    /* First, build up a table of scan-to-key code mappings */
     90    unsigned scanToKeycode[512] = { 0 };
     91    int minKey, maxKey;
     92    XDisplayKeycodes(display, &minKey, &maxKey);
     93    for (int i = minKey; i < maxKey; ++i)
     94        scanToKeycode[X11DRV_KeyEvent(i)] = i;
     95    LogRel(("\""));
     96    printKey(display, scanToKeycode[0x29]); /* `~ */
     97    for (int i = 2; i <= 0xd; ++i) /* 1! - =+ */
     98    {
     99        LogRel(("\",\""));
     100        printKey(display, scanToKeycode[i]);
    95101    }
    96102    LogRel(("\",\n"));
    97103    LogRel(("\""));
    98     printKey(display, 24);
    99     for (int i = 25; i <= 35; ++i)
    100     {
    101         LogRel(("\",\""));
    102         printKey(display, i);
     104    printKey(display, scanToKeycode[0x10]); /* qQ */
     105    for (int i = 0x11; i <= 0x1b; ++i) /* wW - ]} */
     106    {
     107        LogRel(("\",\""));
     108        printKey(display, scanToKeycode[i]);
    103109    }
    104110    LogRel(("\",\n"));
    105111    LogRel(("\""));
    106     printKey(display, 38);
    107     for (int i = 39; i <= 48; ++i)
    108     {
    109         LogRel(("\",\""));
    110         printKey(display, i);
    111     }
    112     LogRel(("\",\""));
    113     printKey(display, 51);
     112    printKey(display, scanToKeycode[0x1e]); /* aA */
     113    for (int i = 0x1f; i <= 0x28; ++i) /* sS - '" */
     114    {
     115        LogRel(("\",\""));
     116        printKey(display, scanToKeycode[i]);
     117    }
     118    LogRel(("\",\""));
     119    printKey(display, scanToKeycode[0x2b]); /* \| */
    114120    LogRel(("\",\n"));
    115121    LogRel(("\""));
    116     printKey(display, 52);
    117     for (int i = 53; i <= 61; ++i)
    118     {
    119         LogRel(("\",\""));
    120         printKey(display, i);
    121     }
    122     LogRel(("\",\""));
    123     printKey(display, 94); /* The 102nd key */
    124     LogRel(("\",\""));
    125     printKey(display, 211); /* The Brazilian key */
    126     LogRel(("\",\""));
    127     printKey(display, 133); /* The Yen key */
     122    printKey(display, scanToKeycode[0x2c]); /* zZ */
     123    for (int i = 0x2d; i <= 0x35; ++i) /* xX - /? */
     124    {
     125        LogRel(("\",\""));
     126        printKey(display, scanToKeycode[i]);
     127    }
     128    LogRel(("\",\""));
     129    printKey(display, scanToKeycode[0x56]); /* The 102nd key */
     130    LogRel(("\",\""));
     131    printKey(display, scanToKeycode[0x73]); /* The Brazilian key */
     132    LogRel(("\",\""));
     133    printKey(display, scanToKeycode[0x7d]); /* The Yen key */
    128134    LogRel(("\"\n\n"));
     135}
     136
     137/**
     138 * DEBUG function
     139 * Dump the keyboard type tables to the release log.
     140 */
     141static void dumpType(Display *display)
     142{
     143    LogRel(("Your keyboard type does not appear to be known to VirtualBox. If\n"
     144            "you would like to help us improve the product, please submit a bug\n"
     145            "report, attach this logfile and provide information about what type\n"
     146            "of keyboard you have and whether you are using a remote X server or\n"
     147            "something similar.\n\n"
     148            "The tables for your keyboard are:\n"));
     149    for (unsigned i = 0; i < 256; ++i)
     150    {
     151        LogRel(("0x%x", X11DRV_KeyEvent(i)));
     152        if (i < 255)
     153            LogRel((", "));
     154        if (15 == (i % 16))
     155            LogRel(("\n"));
     156    }
     157    LogRel(("and\n"));
     158    LogRel(("NULL, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x,\n0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
     159            XKeysymToKeycode(display, XK_Control_L),
     160            XKeysymToKeycode(display, XK_Shift_L),
     161            XKeysymToKeycode(display, XK_Caps_Lock),
     162            XKeysymToKeycode(display, XK_Tab),
     163            XKeysymToKeycode(display, XK_Escape),
     164            XKeysymToKeycode(display, XK_Return),
     165            XKeysymToKeycode(display, XK_Up),
     166            XKeysymToKeycode(display, XK_Down),
     167            XKeysymToKeycode(display, XK_Left),
     168            XKeysymToKeycode(display, XK_Right),
     169            XKeysymToKeycode(display, XK_F1),
     170            XKeysymToKeycode(display, XK_F2),
     171            XKeysymToKeycode(display, XK_F3),
     172            XKeysymToKeycode(display, XK_F4),
     173            XKeysymToKeycode(display, XK_F5),
     174            XKeysymToKeycode(display, XK_F6),
     175            XKeysymToKeycode(display, XK_F7),
     176            XKeysymToKeycode(display, XK_F8)));
    129177}
    130178
     
    140188bool initXKeyboard(Display *dpy)
    141189{
    142     if (0 != X11DRV_InitKeyboard(dpy))
    143     {
    144         /* The layout found was optimal. */
    145         gInitStatus = true;
    146     }
     190    X11DRV_InitKeyboard(dpy, &gfByLayoutOK, &gfByTypeOK);
     191    /* It will almost always work to some extent */
    147192    return true;
    148193}
     
    153198void doXKeyboardLogging(Display *dpy)
    154199{
    155     if (!gInitStatus)
    156     {
     200    if ((gfByLayoutOK != 1) && (1 == gfByTypeOK))
    157201        dumpLayout(dpy);
    158     }
     202    if ((1 == gfByLayoutOK) && (gfByTypeOK != 1))
     203        dumpType(dpy);
     204    if ((gfByLayoutOK != 1) && (gfByTypeOK != 1))
     205        LogRel(("Failed to recognize the keyboard mapping or to guess it based on\n"
     206                "the keyboard layout.  It is very likely that some keys will not\n"
     207                "work correctly in the guest.  If you would like to help us improve\n"
     208                "the product, please submit a bug report, giving us information\n"
     209                "about your keyboard type, its layout and other relevant\n"
     210                "information such as whether you are using a remote X server or\n"
     211                "something similar.\n"));
    159212}
    160213
  • trunk/src/VBox/Frontends/VirtualBox/src/linux/keyboard-new.c

    r8916 r9991  
    4646#include <stdio.h>
    4747
     48/**
     49 * Array containing the current mapping of keycodes to scan codes, detected
     50 * using the keyboard layout algorithm in X11DRV_InitKeyboardByLayout.
     51 */
    4852static unsigned keyc2scan[256];
     53/**
     54 * Whether a keyboard was detected with a well-known keycode to scan code
     55 * mapping.
     56 */
     57static unsigned use_builtin_table = 0;
     58/** The index of the well-known keycode to scan code mapping in our table. */
     59static unsigned builtin_table_number;
     60/** Whether to output basic debugging information to standard output */
    4961static int log_kb_1 = 0;
     62/** Whether to output verbose debugging information to standard output */
    5063static int log_kb_2 = 0;
    5164
     65/** Output basic debugging information if wished */
    5266#define LOG_KB_1(a) \
    5367do { \
     
    5771} while (0)
    5872
     73/** Output verbose debugging information if wished */
    5974#define LOG_KB_2(a) \
    6075do { \
     
    6479} while (0)
    6580
    66 /* Keyboard layout tables for guessing the current keyboard layout. */
     81/** Keyboard layout tables for guessing the current keyboard layout. */
    6782#include "keyboard-tables.h"
    6883
     84/** Tables of keycode to scan code mappings for well-known keyboard types. */
     85#include "keyboard-types.h"
     86
    6987/**
    70   * Translate a keycode in a key event to a scan code, using the lookup
    71   * table which we constructed earlier.
     88  * Translate a keycode in a key event to a scan code, using the lookup table
     89  * which we constructed earlier or a well-known mapping from our mapping
     90  * table.
    7291  *
    73   * @returns the scan code number
     92  * @returns the scan code number, with 0x100 added for extended scan codes
    7493  * @param code the X11 key code to be looked up
    7594  */
     
    7796unsigned X11DRV_KeyEvent(KeyCode code)
    7897{
    79     return keyc2scan[code];
     98    unsigned key;
     99    if (use_builtin_table != 0)
     100        key = main_keyboard_type_scans[builtin_table_number][code];
     101    else
     102        key = keyc2scan[code];
     103    return key;
    80104}
    81105
    82 /**********************************************************************
    83  *              X11DRV_KEYBOARD_DetectLayout
    84  *
    85  * Called from X11DRV_InitKeyboard
    86  *  This routine walks through the defined keyboard layouts and selects
    87  *  whichever matches most closely.
     106/**
     107 * Called from X11DRV_InitKeyboardByLayout
     108 *  See the comments for that function for a description what this function
     109 *  does.
    88110 *
    89111 * @returns an index into the table of keyboard layouts, or 0 if absolutely
     
    214236
    215237/**
    216  * Initialise the X11 keyboard driver.  In practice, this means building
    217  * up an internal table to map X11 keycodes to their equivalent PC scan
    218  * codes.
     238 * Initialise the X11 keyboard driver by building up a table to convert X11
     239 * keycodes to scan codes using a heuristic based on comparing the current
     240 * keyboard map to known international keyboard layouts.
     241 * The basic idea is to examine each key in the current layout to see which
     242 * characters it produces in its normal and its "shifted" state, and to look
     243 * for known keyboard layouts which it could belong to.  We then guess the
     244 * current layout based on the number of matches we find.
     245 * One difficulty with this approach is so-called Dvorak layouts, which are
     246 * identical to non-Dvorak layouts, but with the keys in a different order.
     247 * To deal with this, we compare the different candidate layouts to see in
     248 * which one the X11 keycodes would be most sequential and hope that they
     249 * really are layed out more or less sequentially.
     250 *
     251 * The actual detection of the current layout is done in the sub-function
     252 * X11DRV_KEYBOARD_DetectLayout.  Once we have determined the layout, since we
     253 * know which PC scan code corresponds to each key in the layout, we can use
     254 * this information to associate the scan code with an X11 keycode, which is
     255 * what the rest of this function does.
    219256 *
    220257 * @warning not re-entrant
     
    223260 * @param   display a pointer to the X11 display
    224261 */
    225 int X11DRV_InitKeyboard(Display *display)
     262static unsigned
     263X11DRV_InitKeyboardByLayout(Display *display)
    226264{
    227265    KeySym keysym;
     
    332370    return 1;
    333371}
     372
     373static unsigned
     374X11DRV_InitKeyboardByType(Display *display)
     375{
     376    unsigned i = 0, found = 0;
     377   
     378    for (; (main_keyboard_type_list[i].comment != NULL) && (0 == found); ++i)
     379        if (   (XKeysymToKeycode(display, XK_Control_L) == main_keyboard_type_list[i].lctrl)
     380            && (XKeysymToKeycode(display, XK_Shift_L)   == main_keyboard_type_list[i].lshift)
     381            && (XKeysymToKeycode(display, XK_Caps_Lock) == main_keyboard_type_list[i].capslock)
     382            && (XKeysymToKeycode(display, XK_Tab)       == main_keyboard_type_list[i].tab)
     383            && (XKeysymToKeycode(display, XK_Escape)    == main_keyboard_type_list[i].esc)
     384            && (XKeysymToKeycode(display, XK_Return)    == main_keyboard_type_list[i].enter)
     385            && (XKeysymToKeycode(display, XK_Up)        == main_keyboard_type_list[i].up)
     386            && (XKeysymToKeycode(display, XK_Down)      == main_keyboard_type_list[i].down)
     387            && (XKeysymToKeycode(display, XK_Left)      == main_keyboard_type_list[i].left)
     388            && (XKeysymToKeycode(display, XK_Right)     == main_keyboard_type_list[i].right)
     389            && (XKeysymToKeycode(display, XK_F1)        == main_keyboard_type_list[i].f1)
     390            && (XKeysymToKeycode(display, XK_F2)        == main_keyboard_type_list[i].f2)
     391            && (XKeysymToKeycode(display, XK_F3)        == main_keyboard_type_list[i].f3)
     392            && (XKeysymToKeycode(display, XK_F4)        == main_keyboard_type_list[i].f4)
     393            && (XKeysymToKeycode(display, XK_F5)        == main_keyboard_type_list[i].f5)
     394            && (XKeysymToKeycode(display, XK_F6)        == main_keyboard_type_list[i].f6)
     395            && (XKeysymToKeycode(display, XK_F7)        == main_keyboard_type_list[i].f7)
     396            && (XKeysymToKeycode(display, XK_F8)        == main_keyboard_type_list[i].f8)
     397           )
     398            found = 1;
     399    use_builtin_table = found;
     400    if (found != 0)
     401        builtin_table_number = i - 1;
     402    return found;
     403}
     404
     405/**
     406 * Initialise the X11 keyboard driver by finding which X11 keycodes correspond
     407 * to which PC scan codes.  If the keyboard being used is not a PC keyboard,
     408 * the X11 keycodes will be mapped to the scan codes which the equivalent keys
     409 * on a PC keyboard would use.
     410 *
     411 * We use two algorithms to try to determine the mapping.  See the comments
     412 * attached to the two algorithm functions (X11DRV_InitKeyboardByLayout and
     413 * X11DRV_InitKeyboardByType) for descriptions of the algorithms used.  Both
     414 * functions tell us on return whether they think that they have correctly
     415 * determined the mapping.  If both functions claim to have determined the
     416 * mapping correctly, we prefer the second (ByType).  However, if neither does
     417 * then we prefer the first (ByLayout), as it produces a fuzzy result which is
     418 * still likely to be partially correct.
     419 *
     420 * @warning not re-entrant
     421 * @returns 1 if the layout found was optimal, 0 if it was not.  This is
     422 *          for diagnostic purposes
     423 * @param   display     a pointer to the X11 display
     424 * @param   byLayoutOK  diagnostic - set to one if detection by layout
     425 *                      succeeded, and to 0 otherwise
     426 * @param   byTypeOK    diagnostic - set to one if detection by type
     427 *                      succeeded, and to 0 otherwise
     428 */
     429unsigned X11DRV_InitKeyboard(Display *display, unsigned *byLayoutOK, unsigned *byTypeOK)
     430{
     431    unsigned byLayout = X11DRV_InitKeyboardByLayout(display);
     432    unsigned byType   = X11DRV_InitKeyboardByType(display);
     433    *byLayoutOK = byLayout;
     434    *byTypeOK   = byType;
     435    return (byLayout || byType) ? 1 : 0;
     436}
  • trunk/src/VBox/Frontends/VirtualBox/src/linux/keyboard.h

    r8214 r9991  
    3535#endif
    3636#ifdef VBOX_HAVE_VISIBILITY_HIDDEN
    37 extern CCALL __attribute__((visibility("default"))) int X11DRV_InitKeyboard(Display *dpy);
     37extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK);
    3838extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_KeyEvent(KeyCode code);
    3939#else
    40 extern CCALL int X11DRV_InitKeyboard(Display *dpy);
     40extern CCALL unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK);
    4141extern CCALL unsigned X11DRV_KeyEvent(KeyCode code);
    4242#endif
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette