Home | History | Annotate | Download | only in keycodes
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
      6 
      7 #include <algorithm>
      8 
      9 #define XK_3270  // for XK_3270_BackTab
     10 #include <X11/XF86keysym.h>
     11 #include <X11/Xlib.h>
     12 #include <X11/Xutil.h>
     13 #include <X11/extensions/XInput2.h>
     14 #include <X11/keysym.h>
     15 
     16 #include "base/basictypes.h"
     17 #include "base/logging.h"
     18 #include "base/strings/stringprintf.h"
     19 #include "base/strings/sys_string_conversions.h"
     20 #include "base/strings/utf_string_conversions.h"
     21 #include "ui/events/keycodes/dom4/keycode_converter.h"
     22 #include "ui/events/x/keysym_to_unicode.h"
     23 
     24 #define VKEY_UNSUPPORTED VKEY_UNKNOWN
     25 
     26 namespace ui {
     27 
     28 namespace {
     29 
     30 // MAP0 - MAP3:
     31 // These are the generated VKEY code maps for all possible Latin keyboard
     32 // layouts in Windows. And the maps are only for special letter keys excluding
     33 // [a-z] & [0-9].
     34 //
     35 // ch0: the keysym without modifier states.
     36 // ch1: the keysym with shift state.
     37 // ch2: the keysym with altgr state.
     38 // sc: the hardware keycode (in Windows, it's called scan code).
     39 // vk: the VKEY code.
     40 //
     41 // MAP0: maps from ch0 to vk.
     42 // MAP1: maps from ch0+sc to vk.
     43 // MAP2: maps from ch0+ch1+sc to vk.
     44 // MAP3: maps from ch0+ch1+ch2+sc to vk.
     45 // MAP0 - MAP3 are all sorted, so that finding VK can be binary search.
     46 //
     47 // Reason for creating these maps is because a hard-coded mapping in
     48 // KeyboardCodeFromXKeysym() doesn't support non-US keyboard layouts.
     49 // e.g. in UK keyboard, the key between Quote and Enter keys has the VKEY code
     50 // VKEY_OEM_5 instead of VKEY_3.
     51 //
     52 // The key symbols which are not [a-zA-Z0-9] and functional/extend keys (e.g.
     53 // TAB, ENTER, BS, Arrow keys, modifier keys, F1-F12, media/app keys, etc.)
     54 // should go through these maps for correct VKEY codes.
     55 //
     56 // Please refer to crbug.com/386066.
     57 //
     58 const struct MAP0 {
     59   KeySym ch0;
     60   uint8 vk;
     61   bool operator()(const MAP0& m1, const MAP0& m2) const {
     62     return m1.ch0 < m2.ch0;
     63   }
     64 } map0[] = {
     65       {0x0025, 0x35},  // XK_percent: VKEY_5
     66       {0x0026, 0x31},  // XK_ampersand: VKEY_1
     67       {0x003C, 0xDC},  // XK_less: VKEY_OEM_5
     68       {0x007B, 0xDE},  // XK_braceleft: VKEY_OEM_7
     69       {0x007C, 0xDC},  // XK_bar: VKEY_OEM_5
     70       {0x007D, 0xBF},  // XK_braceright: VKEY_OEM_2
     71       {0x007E, 0xDC},  // XK_asciitilde: VKEY_OEM_5
     72       {0x00A1, 0xDD},  // XK_exclamdown: VKEY_OEM_6
     73       {0x00AD, 0xC0},  // XK_hyphen: VKEY_OEM_3
     74       {0x00B2, 0xDE},  // XK_twosuperior: VKEY_OEM_7
     75       {0x00B5, 0xDC},  // XK_mu: VKEY_OEM_5
     76       {0x00BB, 0x39},  // XK_guillemotright: VKEY_9
     77       {0x00BD, 0xDC},  // XK_onehalf: VKEY_OEM_5
     78       {0x00BF, 0xDD},  // XK_questiondown: VKEY_OEM_6
     79       {0x00DF, 0xDB},  // XK_ssharp: VKEY_OEM_4
     80       {0x00E5, 0xDD},  // XK_aring: VKEY_OEM_6
     81       {0x00EA, 0x33},  // XK_ecircumflex: VKEY_3
     82       {0x00EB, 0xBA},  // XK_ediaeresis: VKEY_OEM_1
     83       {0x00EC, 0xDD},  // XK_igrave: VKEY_OEM_6
     84       {0x00EE, 0xDD},  // XK_icircumflex: VKEY_OEM_6
     85       {0x00F1, 0xC0},  // XK_ntilde: VKEY_OEM_3
     86       {0x00F2, 0xC0},  // XK_ograve: VKEY_OEM_3
     87       {0x00F5, 0xDB},  // XK_otilde: VKEY_OEM_4
     88       {0x00F7, 0xDD},  // XK_division: VKEY_OEM_6
     89       {0x00FD, 0x37},  // XK_yacute: VKEY_7
     90       {0x00FE, 0xBD},  // XK_thorn: VKEY_OEM_MINUS
     91       {0x01A1, 0xDD},  // XK_ohorn: VKEY_OEM_6
     92       {0x01B0, 0xDB},  // XK_uhorn: VKEY_OEM_4
     93       {0x01B5, 0x32},  // XK_lcaron: VKEY_2
     94       {0x01B6, 0xDD},  // XK_zstroke: VKEY_OEM_6
     95       {0x01BB, 0x35},  // XK_tcaron: VKEY_5
     96       {0x01E6, 0xDE},  // XK_cacute: VKEY_OEM_7
     97       {0x01EC, 0x32},  // XK_ecaron: VKEY_2
     98       {0x01F2, 0xDC},  // XK_ncaron: VKEY_OEM_5
     99       {0x01F5, 0xDB},  // XK_odoubleacute: VKEY_OEM_4
    100       {0x01F8, 0x35},  // XK_rcaron: VKEY_5
    101       {0x01F9, 0xBA},  // XK_uring: VKEY_OEM_1
    102       {0x01FB, 0xDC},  // XK_udoubleacute: VKEY_OEM_5
    103       {0x01FE, 0xDE},  // XK_tcedilla: VKEY_OEM_7
    104       {0x0259, 0xC0},  // XK_schwa: VKEY_OEM_3
    105       {0x02B1, 0xDD},  // XK_hstroke: VKEY_OEM_6
    106       {0x02B9, 0xBA},  // XK_idotless: VKEY_OEM_1
    107       {0x02BB, 0xDD},  // XK_gbreve: VKEY_OEM_6
    108       {0x02E5, 0xC0},  // XK_cabovedot: VKEY_OEM_3
    109       {0x02F5, 0xDB},  // XK_gabovedot: VKEY_OEM_4
    110       {0x03B6, 0xBF},  // XK_lcedilla: VKEY_OEM_2
    111       {0x03BA, 0x57},  // XK_emacron: VKEY_W
    112       {0x03E0, 0xDF},  // XK_amacron: VKEY_OEM_8
    113       {0x03EF, 0xDD},  // XK_imacron: VKEY_OEM_6
    114       {0x03F1, 0xDB},  // XK_ncedilla: VKEY_OEM_4
    115       {0x03F3, 0xDC},  // XK_kcedilla: VKEY_OEM_5
    116 };
    117 
    118 const struct MAP1 {
    119   KeySym ch0;
    120   unsigned sc;
    121   uint8 vk;
    122   bool operator()(const MAP1& m1, const MAP1& m2) const {
    123     if (m1.ch0 == m2.ch0)
    124       return m1.sc < m2.sc;
    125     return m1.ch0 < m2.ch0;
    126   }
    127 } map1[] = {
    128       {0x0021, 0x0A, 0x31},  // XK_exclam+AE01: VKEY_1
    129       {0x0021, 0x11, 0x38},  // XK_exclam+AE08: VKEY_8
    130       {0x0021, 0x3D, 0xDF},  // XK_exclam+AB10: VKEY_OEM_8
    131       {0x0022, 0x0B, 0x32},  // XK_quotedbl+AE02: VKEY_2
    132       {0x0022, 0x0C, 0x33},  // XK_quotedbl+AE03: VKEY_3
    133       {0x0023, 0x31, 0xDE},  // XK_numbersign+TLDE: VKEY_OEM_7
    134       {0x0024, 0x23, 0xBA},  // XK_dollar+AD12: VKEY_OEM_1
    135       {0x0024, 0x33, 0xDF},  // XK_dollar+BKSL: VKEY_OEM_8
    136       {0x0027, 0x0D, 0x34},  // XK_quoteright+AE04: VKEY_4
    137       {0x0027, 0x18, 0xDE},  // XK_quoteright+AD01: VKEY_OEM_7
    138       {0x0027, 0x23, 0xBA},  // XK_quoteright+AD12: VKEY_OEM_1
    139       {0x0027, 0x3D, 0xDE},  // XK_quoteright+AB10: VKEY_OEM_7
    140       {0x0028, 0x0E, 0x35},  // XK_parenleft+AE05: VKEY_5
    141       {0x0028, 0x12, 0x39},  // XK_parenleft+AE09: VKEY_9
    142       {0x0028, 0x33, 0xDC},  // XK_parenleft+BKSL: VKEY_OEM_5
    143       {0x0029, 0x13, 0x30},  // XK_parenright+AE10: VKEY_0
    144       {0x0029, 0x14, 0xDB},  // XK_parenright+AE11: VKEY_OEM_4
    145       {0x0029, 0x23, 0xDD},  // XK_parenright+AD12: VKEY_OEM_6
    146       {0x002A, 0x23, 0xBA},  // XK_asterisk+AD12: VKEY_OEM_1
    147       {0x002A, 0x33, 0xDC},  // XK_asterisk+BKSL: VKEY_OEM_5
    148       {0x002B, 0x0A, 0x31},  // XK_plus+AE01: VKEY_1
    149       {0x002B, 0x15, 0xBB},  // XK_plus+AE12: VKEY_OEM_PLUS
    150       {0x002B, 0x22, 0xBB},  // XK_plus+AD11: VKEY_OEM_PLUS
    151       {0x002B, 0x23, 0xBB},  // XK_plus+AD12: VKEY_OEM_PLUS
    152       {0x002B, 0x2F, 0xBB},  // XK_plus+AC10: VKEY_OEM_PLUS
    153       {0x002B, 0x33, 0xBF},  // XK_plus+BKSL: VKEY_OEM_2
    154       {0x002C, 0x0C, 0x33},  // XK_comma+AE03: VKEY_3
    155       {0x002C, 0x0E, 0x35},  // XK_comma+AE05: VKEY_5
    156       {0x002C, 0x0F, 0x36},  // XK_comma+AE06: VKEY_6
    157       {0x002C, 0x12, 0x39},  // XK_comma+AE09: VKEY_9
    158       {0x002C, 0x19, 0xBC},  // XK_comma+AD02: VKEY_OEM_COMMA
    159       {0x002C, 0x37, 0xBC},  // XK_comma+AB04: VKEY_OEM_COMMA
    160       {0x002C, 0x3A, 0xBC},  // XK_comma+AB07: VKEY_OEM_COMMA
    161       {0x002C, 0x3B, 0xBC},  // XK_comma+AB08: VKEY_OEM_COMMA
    162       {0x002D, 0x0B, 0x32},  // XK_minus+AE02: VKEY_2
    163       {0x002D, 0x0F, 0x36},  // XK_minus+AE06: VKEY_6
    164       {0x002D, 0x14, 0xBD},  // XK_minus+AE11: VKEY_OEM_MINUS
    165       {0x002D, 0x26, 0xBD},  // XK_minus+AC01: VKEY_OEM_MINUS
    166       {0x002D, 0x30, 0xBD},  // XK_minus+AC11: VKEY_OEM_MINUS
    167       {0x002E, 0x10, 0x37},  // XK_period+AE07: VKEY_7
    168       {0x002E, 0x11, 0x38},  // XK_period+AE08: VKEY_8
    169       {0x002E, 0x1A, 0xBE},  // XK_period+AD03: VKEY_OEM_PERIOD
    170       {0x002E, 0x1B, 0xBE},  // XK_period+AD04: VKEY_OEM_PERIOD
    171       {0x002E, 0x20, 0xBE},  // XK_period+AD09: VKEY_OEM_PERIOD
    172       {0x002E, 0x30, 0xDE},  // XK_period+AC11: VKEY_OEM_7
    173       {0x002E, 0x3C, 0xBE},  // XK_period+AB09: VKEY_OEM_PERIOD
    174       {0x002E, 0x3D, 0xBF},  // XK_period+AB10: VKEY_OEM_2
    175       {0x002F, 0x14, 0xDB},  // XK_slash+AE11: VKEY_OEM_4
    176       {0x002F, 0x22, 0xBF},  // XK_slash+AD11: VKEY_OEM_2
    177       {0x002F, 0x31, 0xDE},  // XK_slash+TLDE: VKEY_OEM_7
    178       {0x002F, 0x33, 0xDC},  // XK_slash+BKSL: VKEY_OEM_5
    179       {0x002F, 0x3D, 0xBF},  // XK_slash+AB10: VKEY_OEM_2
    180       {0x003A, 0x0A, 0x31},  // XK_colon+AE01: VKEY_1
    181       {0x003A, 0x0E, 0x35},  // XK_colon+AE05: VKEY_5
    182       {0x003A, 0x0F, 0x36},  // XK_colon+AE06: VKEY_6
    183       {0x003A, 0x3C, 0xBF},  // XK_colon+AB09: VKEY_OEM_2
    184       {0x003B, 0x0D, 0x34},  // XK_semicolon+AE04: VKEY_4
    185       {0x003B, 0x11, 0x38},  // XK_semicolon+AE08: VKEY_8
    186       {0x003B, 0x18, 0xBA},  // XK_semicolon+AD01: VKEY_OEM_1
    187       {0x003B, 0x22, 0xBA},  // XK_semicolon+AD11: VKEY_OEM_1
    188       {0x003B, 0x23, 0xDD},  // XK_semicolon+AD12: VKEY_OEM_6
    189       {0x003B, 0x2F, 0xBA},  // XK_semicolon+AC10: VKEY_OEM_1
    190       {0x003B, 0x31, 0xC0},  // XK_semicolon+TLDE: VKEY_OEM_3
    191       {0x003B, 0x34, 0xBA},  // XK_semicolon+AB01: VKEY_OEM_1
    192       {0x003B, 0x3B, 0xBE},  // XK_semicolon+AB08: VKEY_OEM_PERIOD
    193       {0x003B, 0x3D, 0xBF},  // XK_semicolon+AB10: VKEY_OEM_2
    194       {0x003D, 0x11, 0x38},  // XK_equal+AE08: VKEY_8
    195       {0x003D, 0x15, 0xBB},  // XK_equal+AE12: VKEY_OEM_PLUS
    196       {0x003D, 0x23, 0xBB},  // XK_equal+AD12: VKEY_OEM_PLUS
    197       {0x003F, 0x0B, 0x32},  // XK_question+AE02: VKEY_2
    198       {0x003F, 0x10, 0x37},  // XK_question+AE07: VKEY_7
    199       {0x003F, 0x11, 0x38},  // XK_question+AE08: VKEY_8
    200       {0x003F, 0x14, 0xBB},  // XK_question+AE11: VKEY_OEM_PLUS
    201       {0x0040, 0x23, 0xDD},  // XK_at+AD12: VKEY_OEM_6
    202       {0x0040, 0x31, 0xDE},  // XK_at+TLDE: VKEY_OEM_7
    203       {0x005B, 0x0A, 0xDB},  // XK_bracketleft+AE01: VKEY_OEM_4
    204       {0x005B, 0x14, 0xDB},  // XK_bracketleft+AE11: VKEY_OEM_4
    205       {0x005B, 0x22, 0xDB},  // XK_bracketleft+AD11: VKEY_OEM_4
    206       {0x005B, 0x23, 0xDD},  // XK_bracketleft+AD12: VKEY_OEM_6
    207       {0x005B, 0x30, 0xDE},  // XK_bracketleft+AC11: VKEY_OEM_7
    208       {0x005C, 0x15, 0xDB},  // XK_backslash+AE12: VKEY_OEM_4
    209       {0x005D, 0x0B, 0xDD},  // XK_bracketright+AE02: VKEY_OEM_6
    210       {0x005D, 0x15, 0xDD},  // XK_bracketright+AE12: VKEY_OEM_6
    211       {0x005D, 0x23, 0xDD},  // XK_bracketright+AD12: VKEY_OEM_6
    212       {0x005D, 0x31, 0xC0},  // XK_bracketright+TLDE: VKEY_OEM_3
    213       {0x005D, 0x33, 0xDC},  // XK_bracketright+BKSL: VKEY_OEM_5
    214       {0x005F, 0x11, 0x38},  // XK_underscore+AE08: VKEY_8
    215       {0x005F, 0x14, 0xBD},  // XK_underscore+AE11: VKEY_OEM_MINUS
    216       {0x00A7, 0x0D, 0x34},  // XK_section+AE04: VKEY_4
    217       {0x00A7, 0x0F, 0x36},  // XK_section+AE06: VKEY_6
    218       {0x00A7, 0x30, 0xDE},  // XK_section+AC11: VKEY_OEM_7
    219       {0x00AB, 0x11, 0x38},  // XK_guillemotleft+AE08: VKEY_8
    220       {0x00AB, 0x15, 0xDD},  // XK_guillemotleft+AE12: VKEY_OEM_6
    221       {0x00B0, 0x15, 0xBF},  // XK_degree+AE12: VKEY_OEM_2
    222       {0x00B0, 0x31, 0xDE},  // XK_degree+TLDE: VKEY_OEM_7
    223       {0x00BA, 0x30, 0xDE},  // XK_masculine+AC11: VKEY_OEM_7
    224       {0x00BA, 0x31, 0xDC},  // XK_masculine+TLDE: VKEY_OEM_5
    225       {0x00E0, 0x13, 0x30},  // XK_agrave+AE10: VKEY_0
    226       {0x00E0, 0x33, 0xDC},  // XK_agrave+BKSL: VKEY_OEM_5
    227       {0x00E1, 0x11, 0x38},  // XK_aacute+AE08: VKEY_8
    228       {0x00E1, 0x30, 0xDE},  // XK_aacute+AC11: VKEY_OEM_7
    229       {0x00E2, 0x0B, 0x32},  // XK_acircumflex+AE02: VKEY_2
    230       {0x00E2, 0x33, 0xDC},  // XK_acircumflex+BKSL: VKEY_OEM_5
    231       {0x00E4, 0x23, 0xDD},  // XK_adiaeresis+AD12: VKEY_OEM_6
    232       {0x00E6, 0x2F, 0xC0},  // XK_ae+AC10: VKEY_OEM_3
    233       {0x00E6, 0x30, 0xDE},  // XK_ae+AC11: VKEY_OEM_7
    234       {0x00E7, 0x12, 0x39},  // XK_ccedilla+AE09: VKEY_9
    235       {0x00E7, 0x22, 0xDB},  // XK_ccedilla+AD11: VKEY_OEM_4
    236       {0x00E7, 0x23, 0xDD},  // XK_ccedilla+AD12: VKEY_OEM_6
    237       {0x00E7, 0x30, 0xDE},  // XK_ccedilla+AC11: VKEY_OEM_7
    238       {0x00E7, 0x33, 0xBF},  // XK_ccedilla+BKSL: VKEY_OEM_2
    239       {0x00E7, 0x3B, 0xBC},  // XK_ccedilla+AB08: VKEY_OEM_COMMA
    240       {0x00E8, 0x10, 0x37},  // XK_egrave+AE07: VKEY_7
    241       {0x00E8, 0x22, 0xBA},  // XK_egrave+AD11: VKEY_OEM_1
    242       {0x00E8, 0x30, 0xC0},  // XK_egrave+AC11: VKEY_OEM_3
    243       {0x00E9, 0x0B, 0x32},  // XK_eacute+AE02: VKEY_2
    244       {0x00E9, 0x13, 0x30},  // XK_eacute+AE10: VKEY_0
    245       {0x00E9, 0x3D, 0xBF},  // XK_eacute+AB10: VKEY_OEM_2
    246       {0x00ED, 0x12, 0x39},  // XK_iacute+AE09: VKEY_9
    247       {0x00ED, 0x31, 0x30},  // XK_iacute+TLDE: VKEY_0
    248       {0x00F0, 0x22, 0xDD},  // XK_eth+AD11: VKEY_OEM_6
    249       {0x00F0, 0x23, 0xBA},  // XK_eth+AD12: VKEY_OEM_1
    250       {0x00F3, 0x15, 0xBB},  // XK_oacute+AE12: VKEY_OEM_PLUS
    251       {0x00F3, 0x33, 0xDC},  // XK_oacute+BKSL: VKEY_OEM_5
    252       {0x00F4, 0x0D, 0x34},  // XK_ocircumflex+AE04: VKEY_4
    253       {0x00F4, 0x2F, 0xBA},  // XK_ocircumflex+AC10: VKEY_OEM_1
    254       {0x00F6, 0x13, 0xC0},  // XK_odiaeresis+AE10: VKEY_OEM_3
    255       {0x00F6, 0x14, 0xBB},  // XK_odiaeresis+AE11: VKEY_OEM_PLUS
    256       {0x00F6, 0x22, 0xDB},  // XK_odiaeresis+AD11: VKEY_OEM_4
    257       {0x00F8, 0x2F, 0xC0},  // XK_oslash+AC10: VKEY_OEM_3
    258       {0x00F8, 0x30, 0xDE},  // XK_oslash+AC11: VKEY_OEM_7
    259       {0x00F9, 0x30, 0xC0},  // XK_ugrave+AC11: VKEY_OEM_3
    260       {0x00F9, 0x33, 0xBF},  // XK_ugrave+BKSL: VKEY_OEM_2
    261       {0x00FA, 0x22, 0xDB},  // XK_uacute+AD11: VKEY_OEM_4
    262       {0x00FA, 0x23, 0xDD},  // XK_uacute+AD12: VKEY_OEM_6
    263       {0x00FC, 0x19, 0x57},  // XK_udiaeresis+AD02: VKEY_W
    264       {0x01B1, 0x0A, 0x31},  // XK_aogonek+AE01: VKEY_1
    265       {0x01B1, 0x18, 0x51},  // XK_aogonek+AD01: VKEY_Q
    266       {0x01B1, 0x30, 0xDE},  // XK_aogonek+AC11: VKEY_OEM_7
    267       {0x01B3, 0x2F, 0xBA},  // XK_lstroke+AC10: VKEY_OEM_1
    268       {0x01B3, 0x33, 0xBF},  // XK_lstroke+BKSL: VKEY_OEM_2
    269       {0x01B9, 0x0C, 0x33},  // XK_scaron+AE03: VKEY_3
    270       {0x01B9, 0x0F, 0x36},  // XK_scaron+AE06: VKEY_6
    271       {0x01B9, 0x22, 0xDB},  // XK_scaron+AD11: VKEY_OEM_4
    272       {0x01B9, 0x26, 0xBA},  // XK_scaron+AC01: VKEY_OEM_1
    273       {0x01B9, 0x29, 0x46},  // XK_scaron+AC04: VKEY_F
    274       {0x01B9, 0x3C, 0xBE},  // XK_scaron+AB09: VKEY_OEM_PERIOD
    275       {0x01BA, 0x2F, 0xBA},  // XK_scedilla+AC10: VKEY_OEM_1
    276       {0x01BA, 0x3C, 0xBE},  // XK_scedilla+AB09: VKEY_OEM_PERIOD
    277       {0x01BE, 0x0F, 0x36},  // XK_zcaron+AE06: VKEY_6
    278       {0x01BE, 0x15, 0xBB},  // XK_zcaron+AE12: VKEY_OEM_PLUS
    279       {0x01BE, 0x19, 0x57},  // XK_zcaron+AD02: VKEY_W
    280       {0x01BE, 0x22, 0x59},  // XK_zcaron+AD11: VKEY_Y
    281       {0x01BE, 0x33, 0xDC},  // XK_zcaron+BKSL: VKEY_OEM_5
    282       {0x01BF, 0x22, 0xDB},  // XK_zabovedot+AD11: VKEY_OEM_4
    283       {0x01BF, 0x33, 0xDC},  // XK_zabovedot+BKSL: VKEY_OEM_5
    284       {0x01E3, 0x0A, 0x31},  // XK_abreve+AE01: VKEY_1
    285       {0x01E3, 0x22, 0xDB},  // XK_abreve+AD11: VKEY_OEM_4
    286       {0x01E8, 0x0B, 0x32},  // XK_ccaron+AE02: VKEY_2
    287       {0x01E8, 0x0D, 0x34},  // XK_ccaron+AE04: VKEY_4
    288       {0x01E8, 0x21, 0x58},  // XK_ccaron+AD10: VKEY_X
    289       {0x01E8, 0x2F, 0xBA},  // XK_ccaron+AC10: VKEY_OEM_1
    290       {0x01E8, 0x3B, 0xBC},  // XK_ccaron+AB08: VKEY_OEM_COMMA
    291       {0x01EA, 0x0C, 0x33},  // XK_eogonek+AE03: VKEY_3
    292       {0x01F0, 0x13, 0x30},  // XK_dstroke+AE10: VKEY_0
    293       {0x01F0, 0x23, 0xDD},  // XK_dstroke+AD12: VKEY_OEM_6
    294       {0x03E7, 0x0E, 0x35},  // XK_iogonek+AE05: VKEY_5
    295       {0x03EC, 0x0D, 0x34},  // XK_eabovedot+AE04: VKEY_4
    296       {0x03EC, 0x30, 0xDE},  // XK_eabovedot+AC11: VKEY_OEM_7
    297       {0x03F9, 0x10, 0x37},  // XK_uogonek+AE07: VKEY_7
    298       {0x03FE, 0x11, 0x38},  // XK_umacron+AE08: VKEY_8
    299       {0x03FE, 0x18, 0x51},  // XK_umacron+AD01: VKEY_Q
    300       {0x03FE, 0x35, 0x58},  // XK_umacron+AB02: VKEY_X
    301 };
    302 
    303 const struct MAP2 {
    304   KeySym ch0;
    305   unsigned sc;
    306   KeySym ch1;
    307   uint8 vk;
    308   bool operator()(const MAP2& m1, const MAP2& m2) const {
    309     if (m1.ch0 == m2.ch0 && m1.sc == m2.sc)
    310       return m1.ch1 < m2.ch1;
    311     if (m1.ch0 == m2.ch0)
    312       return m1.sc < m2.sc;
    313     return m1.ch0 < m2.ch0;
    314   }
    315 } map2[] = {
    316       {0x0023, 0x33, 0x0027,
    317        0xBF},  // XK_numbersign+BKSL+XK_quoteright: VKEY_OEM_2
    318       {0x0027, 0x30, 0x0022,
    319        0xDE},  // XK_quoteright+AC11+XK_quotedbl: VKEY_OEM_7
    320       {0x0027, 0x31, 0x0022,
    321        0xC0},  // XK_quoteright+TLDE+XK_quotedbl: VKEY_OEM_3
    322       {0x0027, 0x31, 0x00B7,
    323        0xDC},  // XK_quoteright+TLDE+XK_periodcentered: VKEY_OEM_5
    324       {0x0027, 0x33, 0x0000, 0xDC},  // XK_quoteright+BKSL+NoSymbol: VKEY_OEM_5
    325       {0x002D, 0x3D, 0x003D, 0xBD},  // XK_minus+AB10+XK_equal: VKEY_OEM_MINUS
    326       {0x002F, 0x0C, 0x0033, 0x33},  // XK_slash+AE03+XK_3: VKEY_3
    327       {0x002F, 0x0C, 0x003F, 0xBF},  // XK_slash+AE03+XK_question: VKEY_OEM_2
    328       {0x002F, 0x13, 0x0030, 0x30},  // XK_slash+AE10+XK_0: VKEY_0
    329       {0x002F, 0x13, 0x003F, 0xBF},  // XK_slash+AE10+XK_question: VKEY_OEM_2
    330       {0x003D, 0x3D, 0x0025, 0xDF},  // XK_equal+AB10+XK_percent: VKEY_OEM_8
    331       {0x003D, 0x3D, 0x002B, 0xBB},  // XK_equal+AB10+XK_plus: VKEY_OEM_PLUS
    332       {0x005C, 0x33, 0x002F, 0xDE},  // XK_backslash+BKSL+XK_slash: VKEY_OEM_7
    333       {0x005C, 0x33, 0x007C, 0xDC},  // XK_backslash+BKSL+XK_bar: VKEY_OEM_5
    334       {0x0060, 0x31, 0x0000, 0xC0},  // XK_quoteleft+TLDE+NoSymbol: VKEY_OEM_3
    335       {0x0060, 0x31, 0x00AC, 0xDF},  // XK_quoteleft+TLDE+XK_notsign: VKEY_OEM_8
    336       {0x00A7, 0x31, 0x00B0, 0xBF},  // XK_section+TLDE+XK_degree: VKEY_OEM_2
    337       {0x00A7, 0x31, 0x00BD, 0xDC},  // XK_section+TLDE+XK_onehalf: VKEY_OEM_5
    338       {0x00E0, 0x30, 0x00B0, 0xDE},  // XK_agrave+AC11+XK_degree: VKEY_OEM_7
    339       {0x00E0, 0x30, 0x00E4, 0xDC},  // XK_agrave+AC11+XK_adiaeresis: VKEY_OEM_5
    340       {0x00E4, 0x30, 0x00E0, 0xDC},  // XK_adiaeresis+AC11+XK_agrave: VKEY_OEM_5
    341       {0x00E9, 0x2F, 0x00C9, 0xBA},  // XK_eacute+AC10+XK_Eacute: VKEY_OEM_1
    342       {0x00E9, 0x2F, 0x00F6, 0xDE},  // XK_eacute+AC10+XK_odiaeresis: VKEY_OEM_7
    343       {0x00F6, 0x2F, 0x00E9, 0xDE},  // XK_odiaeresis+AC10+XK_eacute: VKEY_OEM_7
    344       {0x00FC, 0x22, 0x00E8, 0xBA},  // XK_udiaeresis+AD11+XK_egrave: VKEY_OEM_1
    345 };
    346 
    347 const struct MAP3 {
    348   KeySym ch0;
    349   unsigned sc;
    350   KeySym ch1;
    351   KeySym ch2;
    352   uint8 vk;
    353   bool operator()(const MAP3& m1, const MAP3& m2) const {
    354     if (m1.ch0 == m2.ch0 && m1.sc == m2.sc && m1.ch1 == m2.ch1)
    355       return m1.ch2 < m2.ch2;
    356     if (m1.ch0 == m2.ch0 && m1.sc == m2.sc)
    357       return m1.ch1 < m2.ch1;
    358     if (m1.ch0 == m2.ch0)
    359       return m1.sc < m2.sc;
    360     return m1.ch0 < m2.ch0;
    361   }
    362 } map3[] = {
    363       {0x0023, 0x33, 0x007E, 0x0000,
    364        0xDE},  // XK_numbersign+BKSL+XK_asciitilde+NoSymbol: VKEY_OEM_7
    365       {0x0027, 0x14, 0x003F, 0x0000,
    366        0xDB},  // XK_quoteright+AE11+XK_question+NoSymbol: VKEY_OEM_4
    367       {0x0027, 0x14, 0x003F, 0x00DD,
    368        0xDB},  // XK_quoteright+AE11+XK_question+XK_Yacute: VKEY_OEM_4
    369       {0x0027, 0x15, 0x002A, 0x0000,
    370        0xBB},  // XK_quoteright+AE12+XK_asterisk+NoSymbol: VKEY_OEM_PLUS
    371       {0x0027, 0x30, 0x0040, 0x0000,
    372        0xC0},  // XK_quoteright+AC11+XK_at+NoSymbol: VKEY_OEM_3
    373       {0x0027, 0x33, 0x002A, 0x0000,
    374        0xBF},  // XK_quoteright+BKSL+XK_asterisk+NoSymbol: VKEY_OEM_2
    375       {0x0027, 0x33, 0x002A, 0x00BD,
    376        0xDC},  // XK_quoteright+BKSL+XK_asterisk+XK_onehalf: VKEY_OEM_5
    377       {0x0027, 0x33, 0x002A, 0x01A3,
    378        0xBF},  // XK_quoteright+BKSL+XK_asterisk+XK_Lstroke: VKEY_OEM_2
    379       {0x0027, 0x34, 0x0022, 0x0000,
    380        0x5A},  // XK_quoteright+AB01+XK_quotedbl+NoSymbol: VKEY_Z
    381       {0x0027, 0x34, 0x0022, 0x01D8,
    382        0xDE},  // XK_quoteright+AB01+XK_quotedbl+XK_Rcaron: VKEY_OEM_7
    383       {0x002B, 0x14, 0x003F, 0x0000,
    384        0xBB},  // XK_plus+AE11+XK_question+NoSymbol: VKEY_OEM_PLUS
    385       {0x002B, 0x14, 0x003F, 0x005C,
    386        0xBD},  // XK_plus+AE11+XK_question+XK_backslash: VKEY_OEM_MINUS
    387       {0x002B, 0x14, 0x003F, 0x01F5,
    388        0xBB},  // XK_plus+AE11+XK_question+XK_odoubleacute: VKEY_OEM_PLUS
    389       {0x002D, 0x15, 0x005F, 0x0000,
    390        0xBD},  // XK_minus+AE12+XK_underscore+NoSymbol: VKEY_OEM_MINUS
    391       {0x002D, 0x15, 0x005F, 0x03B3,
    392        0xDB},  // XK_minus+AE12+XK_underscore+XK_rcedilla: VKEY_OEM_4
    393       {0x002D, 0x3D, 0x005F, 0x0000,
    394        0xBD},  // XK_minus+AB10+XK_underscore+NoSymbol: VKEY_OEM_MINUS
    395       {0x002D, 0x3D, 0x005F, 0x002A,
    396        0xBD},  // XK_minus+AB10+XK_underscore+XK_asterisk: VKEY_OEM_MINUS
    397       {0x002D, 0x3D, 0x005F, 0x002F,
    398        0xBF},  // XK_minus+AB10+XK_underscore+XK_slash: VKEY_OEM_2
    399       {0x002D, 0x3D, 0x005F, 0x006E,
    400        0xBD},  // XK_minus+AB10+XK_underscore+XK_n: VKEY_OEM_MINUS
    401       {0x003D, 0x14, 0x0025, 0x0000,
    402        0xBB},  // XK_equal+AE11+XK_percent+NoSymbol: VKEY_OEM_PLUS
    403       {0x003D, 0x14, 0x0025, 0x002D,
    404        0xBD},  // XK_equal+AE11+XK_percent+XK_minus: VKEY_OEM_MINUS
    405       {0x005C, 0x31, 0x007C, 0x0031,
    406        0xDC},  // XK_backslash+TLDE+XK_bar+XK_1: VKEY_OEM_5
    407       {0x005C, 0x31, 0x007C, 0x03D1,
    408        0xC0},  // XK_backslash+TLDE+XK_bar+XK_Ncedilla: VKEY_OEM_3
    409       {0x0060, 0x31, 0x007E, 0x0000,
    410        0xC0},  // XK_quoteleft+TLDE+XK_asciitilde+NoSymbol: VKEY_OEM_3
    411       {0x0060, 0x31, 0x007E, 0x0031,
    412        0xC0},  // XK_quoteleft+TLDE+XK_asciitilde+XK_1: VKEY_OEM_3
    413       {0x0060, 0x31, 0x007E, 0x003B,
    414        0xC0},  // XK_quoteleft+TLDE+XK_asciitilde+XK_semicolon: VKEY_OEM_3
    415       {0x0060, 0x31, 0x007E, 0x0060,
    416        0xC0},  // XK_quoteleft+TLDE+XK_asciitilde+XK_quoteleft: VKEY_OEM_3
    417       {0x0060, 0x31, 0x007E, 0x00BF,
    418        0xC0},  // XK_quoteleft+TLDE+XK_asciitilde+XK_questiondown: VKEY_OEM_3
    419       {0x0060, 0x31, 0x007E, 0x01F5,
    420        0xC0},  // XK_quoteleft+TLDE+XK_asciitilde+XK_odoubleacute: VKEY_OEM_3
    421       {0x00E4, 0x30, 0x00C4, 0x0000,
    422        0xDE},  // XK_adiaeresis+AC11+XK_Adiaeresis+NoSymbol: VKEY_OEM_7
    423       {0x00E4, 0x30, 0x00C4, 0x01A6,
    424        0xDE},  // XK_adiaeresis+AC11+XK_Adiaeresis+XK_Sacute: VKEY_OEM_7
    425       {0x00E4, 0x30, 0x00C4, 0x01F8,
    426        0xDE},  // XK_adiaeresis+AC11+XK_Adiaeresis+XK_rcaron: VKEY_OEM_7
    427       {0x00E7, 0x2F, 0x00C7, 0x0000,
    428        0xBA},  // XK_ccedilla+AC10+XK_Ccedilla+NoSymbol: VKEY_OEM_1
    429       {0x00E7, 0x2F, 0x00C7, 0x00DE,
    430        0xC0},  // XK_ccedilla+AC10+XK_Ccedilla+XK_Thorn: VKEY_OEM_3
    431       {0x00F6, 0x2F, 0x00D6, 0x0000,
    432        0xC0},  // XK_odiaeresis+AC10+XK_Odiaeresis+NoSymbol: VKEY_OEM_3
    433       {0x00F6, 0x2F, 0x00D6, 0x01DE,
    434        0xC0},  // XK_odiaeresis+AC10+XK_Odiaeresis+XK_Tcedilla: VKEY_OEM_3
    435       {0x00FC, 0x14, 0x00DC, 0x0000,
    436        0xBF},  // XK_udiaeresis+AE11+XK_Udiaeresis+NoSymbol: VKEY_OEM_2
    437       {0x00FC, 0x22, 0x00DC, 0x0000,
    438        0xBA},  // XK_udiaeresis+AD11+XK_Udiaeresis+NoSymbol: VKEY_OEM_1
    439       {0x00FC, 0x22, 0x00DC, 0x01A3,
    440        0xC0},  // XK_udiaeresis+AD11+XK_Udiaeresis+XK_Lstroke: VKEY_OEM_3
    441       {0x01EA, 0x3D, 0x01CA, 0x0000,
    442        0xBD},  // XK_eogonek+AB10+XK_Eogonek+NoSymbol: VKEY_OEM_MINUS
    443       {0x01EA, 0x3D, 0x01CA, 0x006E,
    444        0xBF},  // XK_eogonek+AB10+XK_Eogonek+XK_n: VKEY_OEM_2
    445       {0x03E7, 0x22, 0x03C7, 0x0000,
    446        0xDB},  // XK_iogonek+AD11+XK_Iogonek+NoSymbol: VKEY_OEM_4
    447       {0x03F9, 0x2F, 0x03D9, 0x0000,
    448        0xC0},  // XK_uogonek+AC10+XK_Uogonek+NoSymbol: VKEY_OEM_3
    449       {0x03F9, 0x2F, 0x03D9, 0x01DE,
    450        0xBA},  // XK_uogonek+AC10+XK_Uogonek+XK_Tcedilla: VKEY_OEM_1
    451 };
    452 
    453 template <class T_MAP>
    454 KeyboardCode FindVK(const T_MAP& key, const T_MAP* map, size_t size) {
    455   T_MAP comp = {0};
    456   const T_MAP* p = std::lower_bound(map, map + size, key, comp);
    457   if (p != map + size && !comp(*p, key) && !comp(key, *p))
    458     return static_cast<KeyboardCode>(p->vk);
    459   return VKEY_UNKNOWN;
    460 }
    461 
    462 }  // namespace
    463 
    464 // Get an ui::KeyboardCode from an X keyevent
    465 KeyboardCode KeyboardCodeFromXKeyEvent(const XEvent* xev) {
    466   // Gets correct VKEY code from XEvent is performed as the following steps:
    467   // 1. Gets the keysym without modifier states.
    468   // 2. For [a-z] & [0-9] cases, returns the VKEY code accordingly.
    469   // 3. Find keysym in map0.
    470   // 4. If not found, fallback to find keysym + hardware_code in map1.
    471   // 5. If not found, fallback to find keysym + keysym_shift + hardware_code
    472   //    in map2.
    473   // 6. If not found, fallback to find keysym + keysym_shift + keysym_altgr +
    474   //    hardware_code in map3.
    475   // 7. If not found, fallback to find in KeyboardCodeFromXKeysym(), which
    476   //    mainly for non-letter keys.
    477   // 8. If not found, fallback to find with the hardware code in US layout.
    478 
    479   KeySym keysym = NoSymbol;
    480   XEvent xkeyevent = {0};
    481   if (xev->type == GenericEvent) {
    482     // Convert the XI2 key event into a core key event so that we can
    483     // continue to use XLookupString() until crbug.com/367732 is complete.
    484     InitXKeyEventFromXIDeviceEvent(*xev, &xkeyevent);
    485   } else {
    486     xkeyevent.xkey = xev->xkey;
    487   }
    488   XKeyEvent* xkey = &xkeyevent.xkey;
    489   xkey->state &= (~0xFF | Mod2Mask);  // Clears the xkey's state except numlock.
    490   // XLookupKeysym does not take into consideration the state of the lock/shift
    491   // etc. keys. So it is necessary to use XLookupString instead.
    492   XLookupString(xkey, NULL, 0, &keysym, NULL);
    493 
    494   // [a-z] cases.
    495   if (keysym >= XK_a && keysym <= XK_z)
    496     return static_cast<KeyboardCode>(VKEY_A + keysym - XK_a);
    497 
    498   // [0-9] cases.
    499   if (keysym >= XK_0 && keysym <= XK_9)
    500     return static_cast<KeyboardCode>(VKEY_0 + keysym - XK_0);
    501 
    502   KeyboardCode keycode = VKEY_UNKNOWN;
    503 
    504   if (!IsKeypadKey(keysym) && !IsPrivateKeypadKey(keysym) &&
    505       !IsCursorKey(keysym) && !IsPFKey(keysym) && !IsFunctionKey(keysym) &&
    506       !IsModifierKey(keysym)) {
    507     MAP0 key0 = {keysym & 0xFFFF, 0};
    508     keycode = FindVK(key0, map0, arraysize(map0));
    509     if (keycode != VKEY_UNKNOWN)
    510       return keycode;
    511 
    512     MAP1 key1 = {keysym & 0xFFFF, xkey->keycode, 0};
    513     keycode = FindVK(key1, map1, arraysize(map1));
    514     if (keycode != VKEY_UNKNOWN)
    515       return keycode;
    516 
    517     KeySym keysym_shift = NoSymbol;
    518     xkey->state |= ShiftMask;
    519     XLookupString(xkey, NULL, 0, &keysym_shift, NULL);
    520     MAP2 key2 = {keysym & 0xFFFF, xkey->keycode, keysym_shift & 0xFFFF, 0};
    521     keycode = FindVK(key2, map2, arraysize(map2));
    522     if (keycode != VKEY_UNKNOWN)
    523       return keycode;
    524 
    525     KeySym keysym_altgr = NoSymbol;
    526     xkey->state &= ~ShiftMask;
    527     xkey->state |= Mod1Mask;
    528     XLookupString(xkey, NULL, 0, &keysym_altgr, NULL);
    529     MAP3 key3 = {keysym & 0xFFFF, xkey->keycode, keysym_shift & 0xFFFF,
    530                  keysym_altgr & 0xFFFF, 0};
    531     keycode = FindVK(key3, map3, arraysize(map3));
    532     if (keycode != VKEY_UNKNOWN)
    533       return keycode;
    534 
    535     // On Linux some keys has AltGr char but not on Windows.
    536     // So if cannot find VKEY with (ch0+sc+ch1+ch2) in map3, tries to fallback
    537     // to just find VKEY with (ch0+sc+ch1). This is the best we could do.
    538     MAP3 key4 = {keysym & 0xFFFF, xkey->keycode, keysym_shift & 0xFFFF, 0xFFFF,
    539                  0};
    540     const MAP3* p =
    541         std::lower_bound(map3, map3 + arraysize(map3), key4, MAP3());
    542     if (p != map3 + arraysize(map3) && p->ch0 == key4.ch0 && p->sc == key4.sc &&
    543         p->ch1 == key4.ch1)
    544       return static_cast<KeyboardCode>(p->vk);
    545   }
    546 
    547   keycode = KeyboardCodeFromXKeysym(keysym);
    548   if (keycode == VKEY_UNKNOWN && !IsModifierKey(keysym)) {
    549     // Modifier keys should not fall back to the hardware-keycode-based US
    550     // layout.  See crbug.com/402320
    551     keycode = DefaultKeyboardCodeFromHardwareKeycode(xkey->keycode);
    552   }
    553 
    554   return keycode;
    555 }
    556 
    557 KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) {
    558   // TODO(sad): Have |keysym| go through the X map list?
    559 
    560   switch (keysym) {
    561     case XK_BackSpace:
    562       return VKEY_BACK;
    563     case XK_Delete:
    564     case XK_KP_Delete:
    565       return VKEY_DELETE;
    566     case XK_Tab:
    567     case XK_KP_Tab:
    568     case XK_ISO_Left_Tab:
    569     case XK_3270_BackTab:
    570       return VKEY_TAB;
    571     case XK_Linefeed:
    572     case XK_Return:
    573     case XK_KP_Enter:
    574     case XK_ISO_Enter:
    575       return VKEY_RETURN;
    576     case XK_Clear:
    577     case XK_KP_Begin:  // NumPad 5 without Num Lock, for crosbug.com/29169.
    578       return VKEY_CLEAR;
    579     case XK_KP_Space:
    580     case XK_space:
    581       return VKEY_SPACE;
    582     case XK_Home:
    583     case XK_KP_Home:
    584       return VKEY_HOME;
    585     case XK_End:
    586     case XK_KP_End:
    587       return VKEY_END;
    588     case XK_Page_Up:
    589     case XK_KP_Page_Up:  // aka XK_KP_Prior
    590       return VKEY_PRIOR;
    591     case XK_Page_Down:
    592     case XK_KP_Page_Down:  // aka XK_KP_Next
    593       return VKEY_NEXT;
    594     case XK_Left:
    595     case XK_KP_Left:
    596       return VKEY_LEFT;
    597     case XK_Right:
    598     case XK_KP_Right:
    599       return VKEY_RIGHT;
    600     case XK_Down:
    601     case XK_KP_Down:
    602       return VKEY_DOWN;
    603     case XK_Up:
    604     case XK_KP_Up:
    605       return VKEY_UP;
    606     case XK_Escape:
    607       return VKEY_ESCAPE;
    608     case XK_Kana_Lock:
    609     case XK_Kana_Shift:
    610       return VKEY_KANA;
    611     case XK_Hangul:
    612       return VKEY_HANGUL;
    613     case XK_Hangul_Hanja:
    614       return VKEY_HANJA;
    615     case XK_Kanji:
    616       return VKEY_KANJI;
    617     case XK_Henkan:
    618       return VKEY_CONVERT;
    619     case XK_Muhenkan:
    620       return VKEY_NONCONVERT;
    621     case XK_Zenkaku_Hankaku:
    622       return VKEY_DBE_DBCSCHAR;
    623 
    624     case XK_KP_0:
    625     case XK_KP_1:
    626     case XK_KP_2:
    627     case XK_KP_3:
    628     case XK_KP_4:
    629     case XK_KP_5:
    630     case XK_KP_6:
    631     case XK_KP_7:
    632     case XK_KP_8:
    633     case XK_KP_9:
    634       return static_cast<KeyboardCode>(VKEY_NUMPAD0 + (keysym - XK_KP_0));
    635 
    636     case XK_multiply:
    637     case XK_KP_Multiply:
    638       return VKEY_MULTIPLY;
    639     case XK_KP_Add:
    640       return VKEY_ADD;
    641     case XK_KP_Separator:
    642       return VKEY_SEPARATOR;
    643     case XK_KP_Subtract:
    644       return VKEY_SUBTRACT;
    645     case XK_KP_Decimal:
    646       return VKEY_DECIMAL;
    647     case XK_KP_Divide:
    648       return VKEY_DIVIDE;
    649     case XK_KP_Equal:
    650     case XK_equal:
    651     case XK_plus:
    652       return VKEY_OEM_PLUS;
    653     case XK_comma:
    654     case XK_less:
    655       return VKEY_OEM_COMMA;
    656     case XK_minus:
    657     case XK_underscore:
    658       return VKEY_OEM_MINUS;
    659     case XK_greater:
    660     case XK_period:
    661       return VKEY_OEM_PERIOD;
    662     case XK_colon:
    663     case XK_semicolon:
    664       return VKEY_OEM_1;
    665     case XK_question:
    666     case XK_slash:
    667       return VKEY_OEM_2;
    668     case XK_asciitilde:
    669     case XK_quoteleft:
    670       return VKEY_OEM_3;
    671     case XK_bracketleft:
    672     case XK_braceleft:
    673       return VKEY_OEM_4;
    674     case XK_backslash:
    675     case XK_bar:
    676       return VKEY_OEM_5;
    677     case XK_bracketright:
    678     case XK_braceright:
    679       return VKEY_OEM_6;
    680     case XK_quoteright:
    681     case XK_quotedbl:
    682       return VKEY_OEM_7;
    683     case XK_ISO_Level5_Shift:
    684       return VKEY_OEM_8;
    685     case XK_Shift_L:
    686     case XK_Shift_R:
    687       return VKEY_SHIFT;
    688     case XK_Control_L:
    689     case XK_Control_R:
    690       return VKEY_CONTROL;
    691     case XK_Meta_L:
    692     case XK_Meta_R:
    693     case XK_Alt_L:
    694     case XK_Alt_R:
    695       return VKEY_MENU;
    696     case XK_ISO_Level3_Shift:
    697     case XK_Mode_switch:
    698       return VKEY_ALTGR;
    699     case XK_Multi_key:
    700       return VKEY_COMPOSE;
    701     case XK_Pause:
    702       return VKEY_PAUSE;
    703     case XK_Caps_Lock:
    704       return VKEY_CAPITAL;
    705     case XK_Num_Lock:
    706       return VKEY_NUMLOCK;
    707     case XK_Scroll_Lock:
    708       return VKEY_SCROLL;
    709     case XK_Select:
    710       return VKEY_SELECT;
    711     case XK_Print:
    712       return VKEY_PRINT;
    713     case XK_Execute:
    714       return VKEY_EXECUTE;
    715     case XK_Insert:
    716     case XK_KP_Insert:
    717       return VKEY_INSERT;
    718     case XK_Help:
    719       return VKEY_HELP;
    720     case XK_Super_L:
    721       return VKEY_LWIN;
    722     case XK_Super_R:
    723       return VKEY_RWIN;
    724     case XK_Menu:
    725       return VKEY_APPS;
    726     case XK_F1:
    727     case XK_F2:
    728     case XK_F3:
    729     case XK_F4:
    730     case XK_F5:
    731     case XK_F6:
    732     case XK_F7:
    733     case XK_F8:
    734     case XK_F9:
    735     case XK_F10:
    736     case XK_F11:
    737     case XK_F12:
    738     case XK_F13:
    739     case XK_F14:
    740     case XK_F15:
    741     case XK_F16:
    742     case XK_F17:
    743     case XK_F18:
    744     case XK_F19:
    745     case XK_F20:
    746     case XK_F21:
    747     case XK_F22:
    748     case XK_F23:
    749     case XK_F24:
    750       return static_cast<KeyboardCode>(VKEY_F1 + (keysym - XK_F1));
    751     case XK_KP_F1:
    752     case XK_KP_F2:
    753     case XK_KP_F3:
    754     case XK_KP_F4:
    755       return static_cast<KeyboardCode>(VKEY_F1 + (keysym - XK_KP_F1));
    756 
    757     case XK_guillemotleft:
    758     case XK_guillemotright:
    759     case XK_degree:
    760     // In the case of canadian multilingual keyboard layout, VKEY_OEM_102 is
    761     // assigned to ugrave key.
    762     case XK_ugrave:
    763     case XK_Ugrave:
    764     case XK_brokenbar:
    765       return VKEY_OEM_102;  // international backslash key in 102 keyboard.
    766 
    767     // When evdev is in use, /usr/share/X11/xkb/symbols/inet maps F13-18 keys
    768     // to the special XF86XK symbols to support Microsoft Ergonomic keyboards:
    769     // https://bugs.freedesktop.org/show_bug.cgi?id=5783
    770     // In Chrome, we map these X key symbols back to F13-18 since we don't have
    771     // VKEYs for these XF86XK symbols.
    772     case XF86XK_Tools:
    773       return VKEY_F13;
    774     case XF86XK_Launch5:
    775       return VKEY_F14;
    776     case XF86XK_Launch6:
    777       return VKEY_F15;
    778     case XF86XK_Launch7:
    779       return VKEY_F16;
    780     case XF86XK_Launch8:
    781       return VKEY_F17;
    782     case XF86XK_Launch9:
    783       return VKEY_F18;
    784 
    785     // For supporting multimedia buttons on a USB keyboard.
    786     case XF86XK_Back:
    787       return VKEY_BROWSER_BACK;
    788     case XF86XK_Forward:
    789       return VKEY_BROWSER_FORWARD;
    790     case XF86XK_Reload:
    791       return VKEY_BROWSER_REFRESH;
    792     case XF86XK_Stop:
    793       return VKEY_BROWSER_STOP;
    794     case XF86XK_Search:
    795       return VKEY_BROWSER_SEARCH;
    796     case XF86XK_Favorites:
    797       return VKEY_BROWSER_FAVORITES;
    798     case XF86XK_HomePage:
    799       return VKEY_BROWSER_HOME;
    800     case XF86XK_AudioMute:
    801       return VKEY_VOLUME_MUTE;
    802     case XF86XK_AudioLowerVolume:
    803       return VKEY_VOLUME_DOWN;
    804     case XF86XK_AudioRaiseVolume:
    805       return VKEY_VOLUME_UP;
    806     case XF86XK_AudioNext:
    807       return VKEY_MEDIA_NEXT_TRACK;
    808     case XF86XK_AudioPrev:
    809       return VKEY_MEDIA_PREV_TRACK;
    810     case XF86XK_AudioStop:
    811       return VKEY_MEDIA_STOP;
    812     case XF86XK_AudioPlay:
    813       return VKEY_MEDIA_PLAY_PAUSE;
    814     case XF86XK_Mail:
    815       return VKEY_MEDIA_LAUNCH_MAIL;
    816     case XF86XK_LaunchA:  // F3 on an Apple keyboard.
    817       return VKEY_MEDIA_LAUNCH_APP1;
    818     case XF86XK_LaunchB:  // F4 on an Apple keyboard.
    819     case XF86XK_Calculator:
    820       return VKEY_MEDIA_LAUNCH_APP2;
    821     case XF86XK_WLAN:
    822       return VKEY_WLAN;
    823     case XF86XK_PowerOff:
    824       return VKEY_POWER;
    825     case XF86XK_Sleep:
    826       return VKEY_SLEEP;
    827     case XF86XK_MonBrightnessDown:
    828       return VKEY_BRIGHTNESS_DOWN;
    829     case XF86XK_MonBrightnessUp:
    830       return VKEY_BRIGHTNESS_UP;
    831     case XF86XK_KbdBrightnessDown:
    832       return VKEY_KBD_BRIGHTNESS_DOWN;
    833     case XF86XK_KbdBrightnessUp:
    834       return VKEY_KBD_BRIGHTNESS_UP;
    835 
    836     // TODO(sad): some keycodes are still missing.
    837   }
    838   DLOG(WARNING) << "Unknown keysym: " << base::StringPrintf("0x%x", keysym);
    839   return VKEY_UNKNOWN;
    840 }
    841 
    842 const char* CodeFromXEvent(const XEvent* xev) {
    843   int keycode = (xev->type == GenericEvent)
    844                     ? static_cast<XIDeviceEvent*>(xev->xcookie.data)->detail
    845                     : xev->xkey.keycode;
    846   return ui::KeycodeConverter::NativeKeycodeToCode(keycode);
    847 }
    848 
    849 uint16 GetCharacterFromXEvent(const XEvent* xev) {
    850   XEvent xkeyevent = {0};
    851   const XKeyEvent* xkey = NULL;
    852   if (xev->type == GenericEvent) {
    853     // Convert the XI2 key event into a core key event so that we can
    854     // continue to use XLookupString() until crbug.com/367732 is complete.
    855     InitXKeyEventFromXIDeviceEvent(*xev, &xkeyevent);
    856     xkey = &xkeyevent.xkey;
    857   } else {
    858     xkey = &xev->xkey;
    859   }
    860   KeySym keysym = XK_VoidSymbol;
    861   XLookupString(const_cast<XKeyEvent*>(xkey), NULL, 0, &keysym, NULL);
    862   return GetUnicodeCharacterFromXKeySym(keysym);
    863 }
    864 
    865 KeyboardCode DefaultKeyboardCodeFromHardwareKeycode(
    866     unsigned int hardware_code) {
    867   // This function assumes that X11 is using evdev-based keycodes.
    868   static const KeyboardCode kHardwareKeycodeMap[] = {
    869       // Please refer to below links for the table content:
    870       // http://www.w3.org/TR/DOM-Level-3-Events-code/#keyboard-101
    871       // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode
    872       // http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
    873       VKEY_UNKNOWN,       // 0x00:
    874       VKEY_UNKNOWN,       // 0x01:
    875       VKEY_UNKNOWN,       // 0x02:
    876       VKEY_UNKNOWN,       // 0x03:
    877       VKEY_UNKNOWN,       // 0x04:
    878       VKEY_UNKNOWN,       // 0x05:
    879       VKEY_UNKNOWN,       // 0x06:
    880       VKEY_UNKNOWN,       // XKB   evdev (XKB - 8)      X KeySym
    881       VKEY_UNKNOWN,       // ===   ===============      ======
    882       VKEY_ESCAPE,        // 0x09: KEY_ESC              Escape
    883       VKEY_1,             // 0x0A: KEY_1                1
    884       VKEY_2,             // 0x0B: KEY_2                2
    885       VKEY_3,             // 0x0C: KEY_3                3
    886       VKEY_4,             // 0x0D: KEY_4                4
    887       VKEY_5,             // 0x0E: KEY_5                5
    888       VKEY_6,             // 0x0F: KEY_6                6
    889       VKEY_7,             // 0x10: KEY_7                7
    890       VKEY_8,             // 0x11: KEY_8                8
    891       VKEY_9,             // 0x12: KEY_9                9
    892       VKEY_0,             // 0x13: KEY_0                0
    893       VKEY_OEM_MINUS,     // 0x14: KEY_MINUS            minus
    894       VKEY_OEM_PLUS,      // 0x15: KEY_EQUAL            equal
    895       VKEY_BACK,          // 0x16: KEY_BACKSPACE        BackSpace
    896       VKEY_TAB,           // 0x17: KEY_TAB              Tab
    897       VKEY_Q,             // 0x18: KEY_Q                q
    898       VKEY_W,             // 0x19: KEY_W                w
    899       VKEY_E,             // 0x1A: KEY_E                e
    900       VKEY_R,             // 0x1B: KEY_R                r
    901       VKEY_T,             // 0x1C: KEY_T                t
    902       VKEY_Y,             // 0x1D: KEY_Y                y
    903       VKEY_U,             // 0x1E: KEY_U                u
    904       VKEY_I,             // 0x1F: KEY_I                i
    905       VKEY_O,             // 0x20: KEY_O                o
    906       VKEY_P,             // 0x21: KEY_P                p
    907       VKEY_OEM_4,         // 0x22: KEY_LEFTBRACE        bracketleft
    908       VKEY_OEM_6,         // 0x23: KEY_RIGHTBRACE       bracketright
    909       VKEY_RETURN,        // 0x24: KEY_ENTER            Return
    910       VKEY_LCONTROL,      // 0x25: KEY_LEFTCTRL         Control_L
    911       VKEY_A,             // 0x26: KEY_A                a
    912       VKEY_S,             // 0x27: KEY_S                s
    913       VKEY_D,             // 0x28: KEY_D                d
    914       VKEY_F,             // 0x29: KEY_F                f
    915       VKEY_G,             // 0x2A: KEY_G                g
    916       VKEY_H,             // 0x2B: KEY_H                h
    917       VKEY_J,             // 0x2C: KEY_J                j
    918       VKEY_K,             // 0x2D: KEY_K                k
    919       VKEY_L,             // 0x2E: KEY_L                l
    920       VKEY_OEM_1,         // 0x2F: KEY_SEMICOLON        semicolon
    921       VKEY_OEM_7,         // 0x30: KEY_APOSTROPHE       apostrophe
    922       VKEY_OEM_3,         // 0x31: KEY_GRAVE            grave
    923       VKEY_LSHIFT,        // 0x32: KEY_LEFTSHIFT        Shift_L
    924       VKEY_OEM_5,         // 0x33: KEY_BACKSLASH        backslash
    925       VKEY_Z,             // 0x34: KEY_Z                z
    926       VKEY_X,             // 0x35: KEY_X                x
    927       VKEY_C,             // 0x36: KEY_C                c
    928       VKEY_V,             // 0x37: KEY_V                v
    929       VKEY_B,             // 0x38: KEY_B                b
    930       VKEY_N,             // 0x39: KEY_N                n
    931       VKEY_M,             // 0x3A: KEY_M                m
    932       VKEY_OEM_COMMA,     // 0x3B: KEY_COMMA            comma
    933       VKEY_OEM_PERIOD,    // 0x3C: KEY_DOT              period
    934       VKEY_OEM_2,         // 0x3D: KEY_SLASH            slash
    935       VKEY_RSHIFT,        // 0x3E: KEY_RIGHTSHIFT       Shift_R
    936       VKEY_MULTIPLY,      // 0x3F: KEY_KPASTERISK       KP_Multiply
    937       VKEY_LMENU,         // 0x40: KEY_LEFTALT          Alt_L
    938       VKEY_SPACE,         // 0x41: KEY_SPACE            space
    939       VKEY_CAPITAL,       // 0x42: KEY_CAPSLOCK         Caps_Lock
    940       VKEY_F1,            // 0x43: KEY_F1               F1
    941       VKEY_F2,            // 0x44: KEY_F2               F2
    942       VKEY_F3,            // 0x45: KEY_F3               F3
    943       VKEY_F4,            // 0x46: KEY_F4               F4
    944       VKEY_F5,            // 0x47: KEY_F5               F5
    945       VKEY_F6,            // 0x48: KEY_F6               F6
    946       VKEY_F7,            // 0x49: KEY_F7               F7
    947       VKEY_F8,            // 0x4A: KEY_F8               F8
    948       VKEY_F9,            // 0x4B: KEY_F9               F9
    949       VKEY_F10,           // 0x4C: KEY_F10              F10
    950       VKEY_NUMLOCK,       // 0x4D: KEY_NUMLOCK          Num_Lock
    951       VKEY_SCROLL,        // 0x4E: KEY_SCROLLLOCK       Scroll_Lock
    952       VKEY_NUMPAD7,       // 0x4F: KEY_KP7              KP_7
    953       VKEY_NUMPAD8,       // 0x50: KEY_KP8              KP_8
    954       VKEY_NUMPAD9,       // 0x51: KEY_KP9              KP_9
    955       VKEY_SUBTRACT,      // 0x52: KEY_KPMINUS          KP_Subtract
    956       VKEY_NUMPAD4,       // 0x53: KEY_KP4              KP_4
    957       VKEY_NUMPAD5,       // 0x54: KEY_KP5              KP_5
    958       VKEY_NUMPAD6,       // 0x55: KEY_KP6              KP_6
    959       VKEY_ADD,           // 0x56: KEY_KPPLUS           KP_Add
    960       VKEY_NUMPAD1,       // 0x57: KEY_KP1              KP_1
    961       VKEY_NUMPAD2,       // 0x58: KEY_KP2              KP_2
    962       VKEY_NUMPAD3,       // 0x59: KEY_KP3              KP_3
    963       VKEY_NUMPAD0,       // 0x5A: KEY_KP0              KP_0
    964       VKEY_DECIMAL,       // 0x5B: KEY_KPDOT            KP_Decimal
    965       VKEY_UNKNOWN,       // 0x5C:
    966       VKEY_DBE_DBCSCHAR,  // 0x5D: KEY_ZENKAKUHANKAKU   Zenkaku_Hankaku
    967       VKEY_OEM_5,         // 0x5E: KEY_102ND            backslash
    968       VKEY_F11,           // 0x5F: KEY_F11              F11
    969       VKEY_F12,           // 0x60: KEY_F12              F12
    970       VKEY_OEM_102,       // 0x61: KEY_RO               Romaji
    971       VKEY_UNSUPPORTED,   // 0x62: KEY_KATAKANA         Katakana
    972       VKEY_UNSUPPORTED,   // 0x63: KEY_HIRAGANA         Hiragana
    973       VKEY_CONVERT,       // 0x64: KEY_HENKAN           Henkan
    974       VKEY_UNSUPPORTED,   // 0x65: KEY_KATAKANAHIRAGANA Hiragana_Katakana
    975       VKEY_NONCONVERT,    // 0x66: KEY_MUHENKAN         Muhenkan
    976       VKEY_SEPARATOR,     // 0x67: KEY_KPJPCOMMA        KP_Separator
    977       VKEY_RETURN,        // 0x68: KEY_KPENTER          KP_Enter
    978       VKEY_RCONTROL,      // 0x69: KEY_RIGHTCTRL        Control_R
    979       VKEY_DIVIDE,        // 0x6A: KEY_KPSLASH          KP_Divide
    980       VKEY_PRINT,         // 0x6B: KEY_SYSRQ            Print
    981       VKEY_RMENU,         // 0x6C: KEY_RIGHTALT         Alt_R
    982       VKEY_RETURN,        // 0x6D: KEY_LINEFEED         Linefeed
    983       VKEY_HOME,          // 0x6E: KEY_HOME             Home
    984       VKEY_UP,            // 0x6F: KEY_UP               Up
    985       VKEY_PRIOR,         // 0x70: KEY_PAGEUP           Page_Up
    986       VKEY_LEFT,          // 0x71: KEY_LEFT             Left
    987       VKEY_RIGHT,         // 0x72: KEY_RIGHT            Right
    988       VKEY_END,           // 0x73: KEY_END              End
    989       VKEY_DOWN,          // 0x74: KEY_DOWN             Down
    990       VKEY_NEXT,          // 0x75: KEY_PAGEDOWN         Page_Down
    991       VKEY_INSERT,        // 0x76: KEY_INSERT           Insert
    992       VKEY_DELETE,        // 0x77: KEY_DELETE           Delete
    993       VKEY_UNSUPPORTED,   // 0x78: KEY_MACRO
    994       VKEY_VOLUME_MUTE,   // 0x79: KEY_MUTE             XF86AudioMute
    995       VKEY_VOLUME_DOWN,   // 0x7A: KEY_VOLUMEDOWN       XF86AudioLowerVolume
    996       VKEY_VOLUME_UP,     // 0x7B: KEY_VOLUMEUP         XF86AudioRaiseVolume
    997       VKEY_POWER,         // 0x7C: KEY_POWER            XF86PowerOff
    998       VKEY_OEM_PLUS,      // 0x7D: KEY_KPEQUAL          KP_Equal
    999       VKEY_UNSUPPORTED,   // 0x7E: KEY_KPPLUSMINUS      plusminus
   1000       VKEY_PAUSE,         // 0x7F: KEY_PAUSE            Pause
   1001       VKEY_MEDIA_LAUNCH_APP1,  // 0x80: KEY_SCALE            XF86LaunchA
   1002       VKEY_DECIMAL,            // 0x81: KEY_KPCOMMA          KP_Decimal
   1003       VKEY_HANGUL,             // 0x82: KEY_HANGUEL          Hangul
   1004       VKEY_HANJA,              // 0x83: KEY_HANJA            Hangul_Hanja
   1005       VKEY_OEM_5,              // 0x84: KEY_YEN              yen
   1006       VKEY_LWIN,               // 0x85: KEY_LEFTMETA         Super_L
   1007       VKEY_RWIN,               // 0x86: KEY_RIGHTMETA        Super_R
   1008       VKEY_COMPOSE,            // 0x87: KEY_COMPOSE          Menu
   1009   };
   1010 
   1011   if (hardware_code >= arraysize(kHardwareKeycodeMap)) {
   1012     // Additional keycodes used by the Chrome OS top row special function keys.
   1013     switch (hardware_code) {
   1014       case 0xA6:  // KEY_BACK
   1015         return VKEY_BACK;
   1016       case 0xA7:  // KEY_FORWARD
   1017         return VKEY_BROWSER_FORWARD;
   1018       case 0xB5:  // KEY_REFRESH
   1019         return VKEY_BROWSER_REFRESH;
   1020       case 0xD4:  // KEY_DASHBOARD
   1021         return VKEY_MEDIA_LAUNCH_APP2;
   1022       case 0xE8:  // KEY_BRIGHTNESSDOWN
   1023         return VKEY_BRIGHTNESS_DOWN;
   1024       case 0xE9:  // KEY_BRIGHTNESSUP
   1025         return VKEY_BRIGHTNESS_UP;
   1026     }
   1027     return VKEY_UNKNOWN;
   1028   }
   1029   return kHardwareKeycodeMap[hardware_code];
   1030 }
   1031 
   1032 // TODO(jcampan): this method might be incomplete.
   1033 int XKeysymForWindowsKeyCode(KeyboardCode keycode, bool shift) {
   1034   switch (keycode) {
   1035     case VKEY_NUMPAD0:
   1036       return XK_KP_0;
   1037     case VKEY_NUMPAD1:
   1038       return XK_KP_1;
   1039     case VKEY_NUMPAD2:
   1040       return XK_KP_2;
   1041     case VKEY_NUMPAD3:
   1042       return XK_KP_3;
   1043     case VKEY_NUMPAD4:
   1044       return XK_KP_4;
   1045     case VKEY_NUMPAD5:
   1046       return XK_KP_5;
   1047     case VKEY_NUMPAD6:
   1048       return XK_KP_6;
   1049     case VKEY_NUMPAD7:
   1050       return XK_KP_7;
   1051     case VKEY_NUMPAD8:
   1052       return XK_KP_8;
   1053     case VKEY_NUMPAD9:
   1054       return XK_KP_9;
   1055     case VKEY_MULTIPLY:
   1056       return XK_KP_Multiply;
   1057     case VKEY_ADD:
   1058       return XK_KP_Add;
   1059     case VKEY_SUBTRACT:
   1060       return XK_KP_Subtract;
   1061     case VKEY_DECIMAL:
   1062       return XK_KP_Decimal;
   1063     case VKEY_DIVIDE:
   1064       return XK_KP_Divide;
   1065 
   1066     case VKEY_BACK:
   1067       return XK_BackSpace;
   1068     case VKEY_TAB:
   1069       return shift ? XK_ISO_Left_Tab : XK_Tab;
   1070     case VKEY_CLEAR:
   1071       return XK_Clear;
   1072     case VKEY_RETURN:
   1073       return XK_Return;
   1074     case VKEY_SHIFT:
   1075       return XK_Shift_L;
   1076     case VKEY_CONTROL:
   1077       return XK_Control_L;
   1078     case VKEY_MENU:
   1079       return XK_Alt_L;
   1080     case VKEY_APPS:
   1081       return XK_Menu;
   1082     case VKEY_ALTGR:
   1083       return XK_ISO_Level3_Shift;
   1084     case VKEY_COMPOSE:
   1085       return XK_Multi_key;
   1086 
   1087     case VKEY_PAUSE:
   1088       return XK_Pause;
   1089     case VKEY_CAPITAL:
   1090       return XK_Caps_Lock;
   1091     case VKEY_KANA:
   1092       return XK_Kana_Lock;
   1093     case VKEY_HANJA:
   1094       return XK_Hangul_Hanja;
   1095     case VKEY_CONVERT:
   1096       return XK_Henkan;
   1097     case VKEY_NONCONVERT:
   1098       return XK_Muhenkan;
   1099     case VKEY_DBE_SBCSCHAR:
   1100       return XK_Zenkaku_Hankaku;
   1101     case VKEY_DBE_DBCSCHAR:
   1102       return XK_Zenkaku_Hankaku;
   1103     case VKEY_ESCAPE:
   1104       return XK_Escape;
   1105     case VKEY_SPACE:
   1106       return XK_space;
   1107     case VKEY_PRIOR:
   1108       return XK_Page_Up;
   1109     case VKEY_NEXT:
   1110       return XK_Page_Down;
   1111     case VKEY_END:
   1112       return XK_End;
   1113     case VKEY_HOME:
   1114       return XK_Home;
   1115     case VKEY_LEFT:
   1116       return XK_Left;
   1117     case VKEY_UP:
   1118       return XK_Up;
   1119     case VKEY_RIGHT:
   1120       return XK_Right;
   1121     case VKEY_DOWN:
   1122       return XK_Down;
   1123     case VKEY_SELECT:
   1124       return XK_Select;
   1125     case VKEY_PRINT:
   1126       return XK_Print;
   1127     case VKEY_EXECUTE:
   1128       return XK_Execute;
   1129     case VKEY_INSERT:
   1130       return XK_Insert;
   1131     case VKEY_DELETE:
   1132       return XK_Delete;
   1133     case VKEY_HELP:
   1134       return XK_Help;
   1135     case VKEY_0:
   1136       return shift ? XK_parenright : XK_0;
   1137     case VKEY_1:
   1138       return shift ? XK_exclam : XK_1;
   1139     case VKEY_2:
   1140       return shift ? XK_at : XK_2;
   1141     case VKEY_3:
   1142       return shift ? XK_numbersign : XK_3;
   1143     case VKEY_4:
   1144       return shift ? XK_dollar : XK_4;
   1145     case VKEY_5:
   1146       return shift ? XK_percent : XK_5;
   1147     case VKEY_6:
   1148       return shift ? XK_asciicircum : XK_6;
   1149     case VKEY_7:
   1150       return shift ? XK_ampersand : XK_7;
   1151     case VKEY_8:
   1152       return shift ? XK_asterisk : XK_8;
   1153     case VKEY_9:
   1154       return shift ? XK_parenleft : XK_9;
   1155 
   1156     case VKEY_A:
   1157     case VKEY_B:
   1158     case VKEY_C:
   1159     case VKEY_D:
   1160     case VKEY_E:
   1161     case VKEY_F:
   1162     case VKEY_G:
   1163     case VKEY_H:
   1164     case VKEY_I:
   1165     case VKEY_J:
   1166     case VKEY_K:
   1167     case VKEY_L:
   1168     case VKEY_M:
   1169     case VKEY_N:
   1170     case VKEY_O:
   1171     case VKEY_P:
   1172     case VKEY_Q:
   1173     case VKEY_R:
   1174     case VKEY_S:
   1175     case VKEY_T:
   1176     case VKEY_U:
   1177     case VKEY_V:
   1178     case VKEY_W:
   1179     case VKEY_X:
   1180     case VKEY_Y:
   1181     case VKEY_Z:
   1182       return (shift ? XK_A : XK_a) + (keycode - VKEY_A);
   1183 
   1184     case VKEY_LWIN:
   1185       return XK_Super_L;
   1186     case VKEY_RWIN:
   1187       return XK_Super_R;
   1188 
   1189     case VKEY_NUMLOCK:
   1190       return XK_Num_Lock;
   1191 
   1192     case VKEY_SCROLL:
   1193       return XK_Scroll_Lock;
   1194 
   1195     case VKEY_OEM_1:
   1196       return shift ? XK_colon : XK_semicolon;
   1197     case VKEY_OEM_PLUS:
   1198       return shift ? XK_plus : XK_equal;
   1199     case VKEY_OEM_COMMA:
   1200       return shift ? XK_less : XK_comma;
   1201     case VKEY_OEM_MINUS:
   1202       return shift ? XK_underscore : XK_minus;
   1203     case VKEY_OEM_PERIOD:
   1204       return shift ? XK_greater : XK_period;
   1205     case VKEY_OEM_2:
   1206       return shift ? XK_question : XK_slash;
   1207     case VKEY_OEM_3:
   1208       return shift ? XK_asciitilde : XK_quoteleft;
   1209     case VKEY_OEM_4:
   1210       return shift ? XK_braceleft : XK_bracketleft;
   1211     case VKEY_OEM_5:
   1212       return shift ? XK_bar : XK_backslash;
   1213     case VKEY_OEM_6:
   1214       return shift ? XK_braceright : XK_bracketright;
   1215     case VKEY_OEM_7:
   1216       return shift ? XK_quotedbl : XK_quoteright;
   1217     case VKEY_OEM_8:
   1218       return XK_ISO_Level5_Shift;
   1219     case VKEY_OEM_102:
   1220       return shift ? XK_guillemotleft : XK_guillemotright;
   1221 
   1222     case VKEY_F1:
   1223     case VKEY_F2:
   1224     case VKEY_F3:
   1225     case VKEY_F4:
   1226     case VKEY_F5:
   1227     case VKEY_F6:
   1228     case VKEY_F7:
   1229     case VKEY_F8:
   1230     case VKEY_F9:
   1231     case VKEY_F10:
   1232     case VKEY_F11:
   1233     case VKEY_F12:
   1234     case VKEY_F13:
   1235     case VKEY_F14:
   1236     case VKEY_F15:
   1237     case VKEY_F16:
   1238     case VKEY_F17:
   1239     case VKEY_F18:
   1240     case VKEY_F19:
   1241     case VKEY_F20:
   1242     case VKEY_F21:
   1243     case VKEY_F22:
   1244     case VKEY_F23:
   1245     case VKEY_F24:
   1246       return XK_F1 + (keycode - VKEY_F1);
   1247 
   1248     case VKEY_BROWSER_BACK:
   1249       return XF86XK_Back;
   1250     case VKEY_BROWSER_FORWARD:
   1251       return XF86XK_Forward;
   1252     case VKEY_BROWSER_REFRESH:
   1253       return XF86XK_Reload;
   1254     case VKEY_BROWSER_STOP:
   1255       return XF86XK_Stop;
   1256     case VKEY_BROWSER_SEARCH:
   1257       return XF86XK_Search;
   1258     case VKEY_BROWSER_FAVORITES:
   1259       return XF86XK_Favorites;
   1260     case VKEY_BROWSER_HOME:
   1261       return XF86XK_HomePage;
   1262     case VKEY_VOLUME_MUTE:
   1263       return XF86XK_AudioMute;
   1264     case VKEY_VOLUME_DOWN:
   1265       return XF86XK_AudioLowerVolume;
   1266     case VKEY_VOLUME_UP:
   1267       return XF86XK_AudioRaiseVolume;
   1268     case VKEY_MEDIA_NEXT_TRACK:
   1269       return XF86XK_AudioNext;
   1270     case VKEY_MEDIA_PREV_TRACK:
   1271       return XF86XK_AudioPrev;
   1272     case VKEY_MEDIA_STOP:
   1273       return XF86XK_AudioStop;
   1274     case VKEY_MEDIA_PLAY_PAUSE:
   1275       return XF86XK_AudioPlay;
   1276     case VKEY_MEDIA_LAUNCH_MAIL:
   1277       return XF86XK_Mail;
   1278     case VKEY_MEDIA_LAUNCH_APP1:
   1279       return XF86XK_LaunchA;
   1280     case VKEY_MEDIA_LAUNCH_APP2:
   1281       return XF86XK_LaunchB;
   1282     case VKEY_WLAN:
   1283       return XF86XK_WLAN;
   1284     case VKEY_POWER:
   1285       return XF86XK_PowerOff;
   1286     case VKEY_BRIGHTNESS_DOWN:
   1287       return XF86XK_MonBrightnessDown;
   1288     case VKEY_BRIGHTNESS_UP:
   1289       return XF86XK_MonBrightnessUp;
   1290     case VKEY_KBD_BRIGHTNESS_DOWN:
   1291       return XF86XK_KbdBrightnessDown;
   1292     case VKEY_KBD_BRIGHTNESS_UP:
   1293       return XF86XK_KbdBrightnessUp;
   1294 
   1295     default:
   1296       LOG(WARNING) << "Unknown keycode:" << keycode;
   1297       return 0;
   1298     }
   1299 }
   1300 
   1301 void InitXKeyEventFromXIDeviceEvent(const XEvent& src, XEvent* xkeyevent) {
   1302   DCHECK(src.type == GenericEvent);
   1303   XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(src.xcookie.data);
   1304   switch (xievent->evtype) {
   1305     case XI_KeyPress:
   1306       xkeyevent->type = KeyPress;
   1307       break;
   1308     case XI_KeyRelease:
   1309       xkeyevent->type = KeyRelease;
   1310       break;
   1311     default:
   1312       NOTREACHED();
   1313   }
   1314   xkeyevent->xkey.serial = xievent->serial;
   1315   xkeyevent->xkey.send_event = xievent->send_event;
   1316   xkeyevent->xkey.display = xievent->display;
   1317   xkeyevent->xkey.window = xievent->event;
   1318   xkeyevent->xkey.root = xievent->root;
   1319   xkeyevent->xkey.subwindow = xievent->child;
   1320   xkeyevent->xkey.time = xievent->time;
   1321   xkeyevent->xkey.x = xievent->event_x;
   1322   xkeyevent->xkey.y = xievent->event_y;
   1323   xkeyevent->xkey.x_root = xievent->root_x;
   1324   xkeyevent->xkey.y_root = xievent->root_y;
   1325   xkeyevent->xkey.state = xievent->mods.effective;
   1326   xkeyevent->xkey.keycode = xievent->detail;
   1327   xkeyevent->xkey.same_screen = 1;
   1328 }
   1329 
   1330 unsigned int XKeyCodeForWindowsKeyCode(ui::KeyboardCode key_code,
   1331                                        int flags,
   1332                                        XDisplay* display) {
   1333   // SHIFT state is ignored in the call to XKeysymForWindowsKeyCode() here
   1334   // because we map the XKeysym back to a keycode, i.e. a physical key position.
   1335   // Using a SHIFT-modified XKeysym would sometimes yield X keycodes that,
   1336   // while technically valid, may be surprising in that they do not match
   1337   // the keycode of the original press, and conflict with assumptions in
   1338   // other code.
   1339   //
   1340   // For example, in a US layout, Shift-9 has the interpretation XK_parenleft,
   1341   // but the keycode KEY_9 alone does not map to XK_parenleft; instead,
   1342   // XKeysymToKeycode() returns KEY_KPLEFTPAREN (keypad left parenthesis)
   1343   // which does map to XK_parenleft -- notwithstanding that keyboards with
   1344   // dedicated number pad parenthesis keys are currently uncommon.
   1345   //
   1346   // Similarly, Shift-Comma has the interpretation XK_less, but KEY_COMMA
   1347   // alone does not map to XK_less; XKeysymToKeycode() returns KEY_102ND
   1348   // (the '<>' key between Shift and Z on 105-key keyboards) which does.
   1349   //
   1350   // crbug.com/386066 and crbug.com/390263 are examples of problems
   1351   // associated with this.
   1352   //
   1353   return XKeysymToKeycode(display, XKeysymForWindowsKeyCode(key_code, false));
   1354 }
   1355 
   1356 }  // namespace ui
   1357