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