diff options
Diffstat (limited to 'chromium/ui/events/keycodes/keyboard_code_conversion_x.cc')
-rw-r--r-- | chromium/ui/events/keycodes/keyboard_code_conversion_x.cc | 899 |
1 files changed, 682 insertions, 217 deletions
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc index 821f8c47013..4f277ecff27 100644 --- a/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc +++ b/chromium/ui/events/keycodes/keyboard_code_conversion_x.cc @@ -4,6 +4,8 @@ #include "ui/events/keycodes/keyboard_code_conversion_x.h" +#include <algorithm> + #define XK_3270 // for XK_3270_BackTab #include <X11/keysym.h> #include <X11/Xlib.h> @@ -13,23 +15,529 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "ui/events/keycodes/dom4/keycode_converter.h" +#define VKEY_UNSUPPORTED VKEY_UNKNOWN + namespace ui { +namespace { + +// MAP0 - MAP3: +// These are the generated VKEY code maps for all possible Latin keyboard +// layouts in Windows. And the maps are only for special letter keys excluding +// [a-z] & [0-9]. +// +// ch0: the keysym without modifier states. +// ch1: the keysym with shift state. +// ch2: the keysym with altgr state. +// sc: the hardware keycode (in Windows, it's called scan code). +// vk: the VKEY code. +// +// MAP0: maps from ch0 to vk. +// MAP1: maps from ch0+sc to vk. +// MAP2: maps from ch0+ch1+sc to vk. +// MAP3: maps from ch0+ch1+ch2+sc to vk. +// MAP0 - MAP3 are all sorted, so that finding VK can be binary search. +// +// Reason for creating these maps is because a hard-coded mapping in +// KeyboardCodeFromXKeysym() doesn't support non-US keyboard layouts. +// e.g. in UK keyboard, the key between Quote and Enter keys has the VKEY code +// VKEY_OEM_5 instead of VKEY_3. +// +// The key symbols which are not [a-zA-Z0-9] and functional/extend keys (e.g. +// TAB, ENTER, BS, Arrow keys, modifier keys, F1-F12, media/app keys, etc.) +// should go through these maps for correct VKEY codes. +// +// Please refer to crbug.com/386066. +// +const struct MAP0 { + KeySym ch0; + uint8 vk; + bool operator()(const MAP0& m1, const MAP0& m2) const { + return m1.ch0 < m2.ch0; + } +} map0[] = { + {0x0025, 0x35}, // XK_percent: VKEY_5 + {0x0026, 0x31}, // XK_ampersand: VKEY_1 + {0x003C, 0xDC}, // XK_less: VKEY_OEM_5 + {0x007B, 0xDE}, // XK_braceleft: VKEY_OEM_7 + {0x007C, 0xDC}, // XK_bar: VKEY_OEM_5 + {0x007D, 0xBF}, // XK_braceright: VKEY_OEM_2 + {0x007E, 0xDC}, // XK_asciitilde: VKEY_OEM_5 + {0x00A1, 0xDD}, // XK_exclamdown: VKEY_OEM_6 + {0x00AD, 0xC0}, // XK_hyphen: VKEY_OEM_3 + {0x00B2, 0xDE}, // XK_twosuperior: VKEY_OEM_7 + {0x00B5, 0xDC}, // XK_mu: VKEY_OEM_5 + {0x00BB, 0x39}, // XK_guillemotright: VKEY_9 + {0x00BD, 0xDC}, // XK_onehalf: VKEY_OEM_5 + {0x00BF, 0xDD}, // XK_questiondown: VKEY_OEM_6 + {0x00DF, 0xDB}, // XK_ssharp: VKEY_OEM_4 + {0x00E5, 0xDD}, // XK_aring: VKEY_OEM_6 + {0x00EA, 0x33}, // XK_ecircumflex: VKEY_3 + {0x00EB, 0xBA}, // XK_ediaeresis: VKEY_OEM_1 + {0x00EC, 0xDD}, // XK_igrave: VKEY_OEM_6 + {0x00EE, 0xDD}, // XK_icircumflex: VKEY_OEM_6 + {0x00F1, 0xC0}, // XK_ntilde: VKEY_OEM_3 + {0x00F2, 0xC0}, // XK_ograve: VKEY_OEM_3 + {0x00F5, 0xDB}, // XK_otilde: VKEY_OEM_4 + {0x00F7, 0xDD}, // XK_division: VKEY_OEM_6 + {0x00FD, 0x37}, // XK_yacute: VKEY_7 + {0x00FE, 0xBD}, // XK_thorn: VKEY_OEM_MINUS + {0x01A1, 0xDD}, // XK_ohorn: VKEY_OEM_6 + {0x01B0, 0xDB}, // XK_uhorn: VKEY_OEM_4 + {0x01B5, 0x32}, // XK_lcaron: VKEY_2 + {0x01B6, 0xDD}, // XK_zstroke: VKEY_OEM_6 + {0x01BB, 0x35}, // XK_tcaron: VKEY_5 + {0x01E6, 0xDE}, // XK_cacute: VKEY_OEM_7 + {0x01EC, 0x32}, // XK_ecaron: VKEY_2 + {0x01F2, 0xDC}, // XK_ncaron: VKEY_OEM_5 + {0x01F5, 0xDB}, // XK_odoubleacute: VKEY_OEM_4 + {0x01F8, 0x35}, // XK_rcaron: VKEY_5 + {0x01F9, 0xBA}, // XK_uring: VKEY_OEM_1 + {0x01FB, 0xDC}, // XK_udoubleacute: VKEY_OEM_5 + {0x01FE, 0xDE}, // XK_tcedilla: VKEY_OEM_7 + {0x0259, 0xC0}, // XK_schwa: VKEY_OEM_3 + {0x02B1, 0xDD}, // XK_hstroke: VKEY_OEM_6 + {0x02B9, 0xBA}, // XK_idotless: VKEY_OEM_1 + {0x02BB, 0xDD}, // XK_gbreve: VKEY_OEM_6 + {0x02E5, 0xC0}, // XK_cabovedot: VKEY_OEM_3 + {0x02F5, 0xDB}, // XK_gabovedot: VKEY_OEM_4 + {0x03B6, 0xBF}, // XK_lcedilla: VKEY_OEM_2 + {0x03BA, 0x57}, // XK_emacron: VKEY_W + {0x03E0, 0xDF}, // XK_amacron: VKEY_OEM_8 + {0x03EF, 0xDD}, // XK_imacron: VKEY_OEM_6 + {0x03F1, 0xDB}, // XK_ncedilla: VKEY_OEM_4 + {0x03F3, 0xDC}, // XK_kcedilla: VKEY_OEM_5 +}; + +const struct MAP1 { + KeySym ch0; + unsigned sc; + uint8 vk; + bool operator()(const MAP1& m1, const MAP1& m2) const { + if (m1.ch0 == m2.ch0) + return m1.sc < m2.sc; + return m1.ch0 < m2.ch0; + } +} map1[] = { + {0x0021, 0x0A, 0x31}, // XK_exclam+AE01: VKEY_1 + {0x0021, 0x11, 0x38}, // XK_exclam+AE08: VKEY_8 + {0x0021, 0x3D, 0xDF}, // XK_exclam+AB10: VKEY_OEM_8 + {0x0022, 0x0B, 0x32}, // XK_quotedbl+AE02: VKEY_2 + {0x0022, 0x0C, 0x33}, // XK_quotedbl+AE03: VKEY_3 + {0x0023, 0x31, 0xDE}, // XK_numbersign+TLDE: VKEY_OEM_7 + {0x0024, 0x23, 0xBA}, // XK_dollar+AD12: VKEY_OEM_1 + {0x0024, 0x33, 0xDF}, // XK_dollar+BKSL: VKEY_OEM_8 + {0x0027, 0x0D, 0x34}, // XK_quoteright+AE04: VKEY_4 + {0x0027, 0x18, 0xDE}, // XK_quoteright+AD01: VKEY_OEM_7 + {0x0027, 0x23, 0xBA}, // XK_quoteright+AD12: VKEY_OEM_1 + {0x0027, 0x3D, 0xDE}, // XK_quoteright+AB10: VKEY_OEM_7 + {0x0028, 0x0E, 0x35}, // XK_parenleft+AE05: VKEY_5 + {0x0028, 0x12, 0x39}, // XK_parenleft+AE09: VKEY_9 + {0x0028, 0x33, 0xDC}, // XK_parenleft+BKSL: VKEY_OEM_5 + {0x0029, 0x13, 0x30}, // XK_parenright+AE10: VKEY_0 + {0x0029, 0x14, 0xDB}, // XK_parenright+AE11: VKEY_OEM_4 + {0x0029, 0x23, 0xDD}, // XK_parenright+AD12: VKEY_OEM_6 + {0x002A, 0x23, 0xBA}, // XK_asterisk+AD12: VKEY_OEM_1 + {0x002A, 0x33, 0xDC}, // XK_asterisk+BKSL: VKEY_OEM_5 + {0x002B, 0x0A, 0x31}, // XK_plus+AE01: VKEY_1 + {0x002B, 0x15, 0xBB}, // XK_plus+AE12: VKEY_OEM_PLUS + {0x002B, 0x22, 0xBB}, // XK_plus+AD11: VKEY_OEM_PLUS + {0x002B, 0x23, 0xBB}, // XK_plus+AD12: VKEY_OEM_PLUS + {0x002B, 0x2F, 0xBB}, // XK_plus+AC10: VKEY_OEM_PLUS + {0x002B, 0x33, 0xBF}, // XK_plus+BKSL: VKEY_OEM_2 + {0x002C, 0x0C, 0x33}, // XK_comma+AE03: VKEY_3 + {0x002C, 0x0E, 0x35}, // XK_comma+AE05: VKEY_5 + {0x002C, 0x0F, 0x36}, // XK_comma+AE06: VKEY_6 + {0x002C, 0x12, 0x39}, // XK_comma+AE09: VKEY_9 + {0x002C, 0x19, 0xBC}, // XK_comma+AD02: VKEY_OEM_COMMA + {0x002C, 0x37, 0xBC}, // XK_comma+AB04: VKEY_OEM_COMMA + {0x002C, 0x3A, 0xBC}, // XK_comma+AB07: VKEY_OEM_COMMA + {0x002C, 0x3B, 0xBC}, // XK_comma+AB08: VKEY_OEM_COMMA + {0x002D, 0x0B, 0x32}, // XK_minus+AE02: VKEY_2 + {0x002D, 0x0F, 0x36}, // XK_minus+AE06: VKEY_6 + {0x002D, 0x14, 0xBD}, // XK_minus+AE11: VKEY_OEM_MINUS + {0x002D, 0x26, 0xBD}, // XK_minus+AC01: VKEY_OEM_MINUS + {0x002D, 0x30, 0xBD}, // XK_minus+AC11: VKEY_OEM_MINUS + {0x002E, 0x10, 0x37}, // XK_period+AE07: VKEY_7 + {0x002E, 0x11, 0x38}, // XK_period+AE08: VKEY_8 + {0x002E, 0x1A, 0xBE}, // XK_period+AD03: VKEY_OEM_PERIOD + {0x002E, 0x1B, 0xBE}, // XK_period+AD04: VKEY_OEM_PERIOD + {0x002E, 0x20, 0xBE}, // XK_period+AD09: VKEY_OEM_PERIOD + {0x002E, 0x30, 0xDE}, // XK_period+AC11: VKEY_OEM_7 + {0x002E, 0x3C, 0xBE}, // XK_period+AB09: VKEY_OEM_PERIOD + {0x002E, 0x3D, 0xBF}, // XK_period+AB10: VKEY_OEM_2 + {0x002F, 0x14, 0xDB}, // XK_slash+AE11: VKEY_OEM_4 + {0x002F, 0x22, 0xBF}, // XK_slash+AD11: VKEY_OEM_2 + {0x002F, 0x31, 0xDE}, // XK_slash+TLDE: VKEY_OEM_7 + {0x002F, 0x33, 0xDC}, // XK_slash+BKSL: VKEY_OEM_5 + {0x002F, 0x3D, 0xBF}, // XK_slash+AB10: VKEY_OEM_2 + {0x003A, 0x0A, 0x31}, // XK_colon+AE01: VKEY_1 + {0x003A, 0x0E, 0x35}, // XK_colon+AE05: VKEY_5 + {0x003A, 0x0F, 0x36}, // XK_colon+AE06: VKEY_6 + {0x003A, 0x3C, 0xBF}, // XK_colon+AB09: VKEY_OEM_2 + {0x003B, 0x0D, 0x34}, // XK_semicolon+AE04: VKEY_4 + {0x003B, 0x11, 0x38}, // XK_semicolon+AE08: VKEY_8 + {0x003B, 0x18, 0xBA}, // XK_semicolon+AD01: VKEY_OEM_1 + {0x003B, 0x22, 0xBA}, // XK_semicolon+AD11: VKEY_OEM_1 + {0x003B, 0x23, 0xDD}, // XK_semicolon+AD12: VKEY_OEM_6 + {0x003B, 0x2F, 0xBA}, // XK_semicolon+AC10: VKEY_OEM_1 + {0x003B, 0x31, 0xC0}, // XK_semicolon+TLDE: VKEY_OEM_3 + {0x003B, 0x34, 0xBA}, // XK_semicolon+AB01: VKEY_OEM_1 + {0x003B, 0x3B, 0xBE}, // XK_semicolon+AB08: VKEY_OEM_PERIOD + {0x003B, 0x3D, 0xBF}, // XK_semicolon+AB10: VKEY_OEM_2 + {0x003D, 0x11, 0x38}, // XK_equal+AE08: VKEY_8 + {0x003D, 0x15, 0xBB}, // XK_equal+AE12: VKEY_OEM_PLUS + {0x003D, 0x23, 0xBB}, // XK_equal+AD12: VKEY_OEM_PLUS + {0x003F, 0x0B, 0x32}, // XK_question+AE02: VKEY_2 + {0x003F, 0x10, 0x37}, // XK_question+AE07: VKEY_7 + {0x003F, 0x11, 0x38}, // XK_question+AE08: VKEY_8 + {0x003F, 0x14, 0xBB}, // XK_question+AE11: VKEY_OEM_PLUS + {0x0040, 0x23, 0xDD}, // XK_at+AD12: VKEY_OEM_6 + {0x0040, 0x31, 0xDE}, // XK_at+TLDE: VKEY_OEM_7 + {0x005B, 0x0A, 0xDB}, // XK_bracketleft+AE01: VKEY_OEM_4 + {0x005B, 0x14, 0xDB}, // XK_bracketleft+AE11: VKEY_OEM_4 + {0x005B, 0x22, 0xDB}, // XK_bracketleft+AD11: VKEY_OEM_4 + {0x005B, 0x23, 0xDD}, // XK_bracketleft+AD12: VKEY_OEM_6 + {0x005B, 0x30, 0xDE}, // XK_bracketleft+AC11: VKEY_OEM_7 + {0x005C, 0x15, 0xDB}, // XK_backslash+AE12: VKEY_OEM_4 + {0x005D, 0x0B, 0xDD}, // XK_bracketright+AE02: VKEY_OEM_6 + {0x005D, 0x15, 0xDD}, // XK_bracketright+AE12: VKEY_OEM_6 + {0x005D, 0x23, 0xDD}, // XK_bracketright+AD12: VKEY_OEM_6 + {0x005D, 0x31, 0xC0}, // XK_bracketright+TLDE: VKEY_OEM_3 + {0x005D, 0x33, 0xDC}, // XK_bracketright+BKSL: VKEY_OEM_5 + {0x005F, 0x11, 0x38}, // XK_underscore+AE08: VKEY_8 + {0x005F, 0x14, 0xBD}, // XK_underscore+AE11: VKEY_OEM_MINUS + {0x00A7, 0x0D, 0x34}, // XK_section+AE04: VKEY_4 + {0x00A7, 0x0F, 0x36}, // XK_section+AE06: VKEY_6 + {0x00A7, 0x30, 0xDE}, // XK_section+AC11: VKEY_OEM_7 + {0x00AB, 0x11, 0x38}, // XK_guillemotleft+AE08: VKEY_8 + {0x00AB, 0x15, 0xDD}, // XK_guillemotleft+AE12: VKEY_OEM_6 + {0x00B0, 0x15, 0xBF}, // XK_degree+AE12: VKEY_OEM_2 + {0x00B0, 0x31, 0xDE}, // XK_degree+TLDE: VKEY_OEM_7 + {0x00BA, 0x30, 0xDE}, // XK_masculine+AC11: VKEY_OEM_7 + {0x00BA, 0x31, 0xDC}, // XK_masculine+TLDE: VKEY_OEM_5 + {0x00E0, 0x13, 0x30}, // XK_agrave+AE10: VKEY_0 + {0x00E0, 0x33, 0xDC}, // XK_agrave+BKSL: VKEY_OEM_5 + {0x00E1, 0x11, 0x38}, // XK_aacute+AE08: VKEY_8 + {0x00E1, 0x30, 0xDE}, // XK_aacute+AC11: VKEY_OEM_7 + {0x00E2, 0x0B, 0x32}, // XK_acircumflex+AE02: VKEY_2 + {0x00E2, 0x33, 0xDC}, // XK_acircumflex+BKSL: VKEY_OEM_5 + {0x00E4, 0x23, 0xDD}, // XK_adiaeresis+AD12: VKEY_OEM_6 + {0x00E6, 0x2F, 0xC0}, // XK_ae+AC10: VKEY_OEM_3 + {0x00E6, 0x30, 0xDE}, // XK_ae+AC11: VKEY_OEM_7 + {0x00E7, 0x12, 0x39}, // XK_ccedilla+AE09: VKEY_9 + {0x00E7, 0x22, 0xDB}, // XK_ccedilla+AD11: VKEY_OEM_4 + {0x00E7, 0x23, 0xDD}, // XK_ccedilla+AD12: VKEY_OEM_6 + {0x00E7, 0x30, 0xDE}, // XK_ccedilla+AC11: VKEY_OEM_7 + {0x00E7, 0x33, 0xBF}, // XK_ccedilla+BKSL: VKEY_OEM_2 + {0x00E7, 0x3B, 0xBC}, // XK_ccedilla+AB08: VKEY_OEM_COMMA + {0x00E8, 0x10, 0x37}, // XK_egrave+AE07: VKEY_7 + {0x00E8, 0x22, 0xBA}, // XK_egrave+AD11: VKEY_OEM_1 + {0x00E8, 0x30, 0xC0}, // XK_egrave+AC11: VKEY_OEM_3 + {0x00E9, 0x0B, 0x32}, // XK_eacute+AE02: VKEY_2 + {0x00E9, 0x13, 0x30}, // XK_eacute+AE10: VKEY_0 + {0x00E9, 0x3D, 0xBF}, // XK_eacute+AB10: VKEY_OEM_2 + {0x00ED, 0x12, 0x39}, // XK_iacute+AE09: VKEY_9 + {0x00ED, 0x31, 0x30}, // XK_iacute+TLDE: VKEY_0 + {0x00F0, 0x22, 0xDD}, // XK_eth+AD11: VKEY_OEM_6 + {0x00F0, 0x23, 0xBA}, // XK_eth+AD12: VKEY_OEM_1 + {0x00F3, 0x15, 0xBB}, // XK_oacute+AE12: VKEY_OEM_PLUS + {0x00F3, 0x33, 0xDC}, // XK_oacute+BKSL: VKEY_OEM_5 + {0x00F4, 0x0D, 0x34}, // XK_ocircumflex+AE04: VKEY_4 + {0x00F4, 0x2F, 0xBA}, // XK_ocircumflex+AC10: VKEY_OEM_1 + {0x00F6, 0x13, 0xC0}, // XK_odiaeresis+AE10: VKEY_OEM_3 + {0x00F6, 0x14, 0xBB}, // XK_odiaeresis+AE11: VKEY_OEM_PLUS + {0x00F6, 0x22, 0xDB}, // XK_odiaeresis+AD11: VKEY_OEM_4 + {0x00F8, 0x2F, 0xC0}, // XK_oslash+AC10: VKEY_OEM_3 + {0x00F8, 0x30, 0xDE}, // XK_oslash+AC11: VKEY_OEM_7 + {0x00F9, 0x30, 0xC0}, // XK_ugrave+AC11: VKEY_OEM_3 + {0x00F9, 0x33, 0xBF}, // XK_ugrave+BKSL: VKEY_OEM_2 + {0x00FA, 0x22, 0xDB}, // XK_uacute+AD11: VKEY_OEM_4 + {0x00FA, 0x23, 0xDD}, // XK_uacute+AD12: VKEY_OEM_6 + {0x00FC, 0x19, 0x57}, // XK_udiaeresis+AD02: VKEY_W + {0x01B1, 0x0A, 0x31}, // XK_aogonek+AE01: VKEY_1 + {0x01B1, 0x18, 0x51}, // XK_aogonek+AD01: VKEY_Q + {0x01B1, 0x30, 0xDE}, // XK_aogonek+AC11: VKEY_OEM_7 + {0x01B3, 0x2F, 0xBA}, // XK_lstroke+AC10: VKEY_OEM_1 + {0x01B3, 0x33, 0xBF}, // XK_lstroke+BKSL: VKEY_OEM_2 + {0x01B9, 0x0C, 0x33}, // XK_scaron+AE03: VKEY_3 + {0x01B9, 0x0F, 0x36}, // XK_scaron+AE06: VKEY_6 + {0x01B9, 0x22, 0xDB}, // XK_scaron+AD11: VKEY_OEM_4 + {0x01B9, 0x26, 0xBA}, // XK_scaron+AC01: VKEY_OEM_1 + {0x01B9, 0x29, 0x46}, // XK_scaron+AC04: VKEY_F + {0x01B9, 0x3C, 0xBE}, // XK_scaron+AB09: VKEY_OEM_PERIOD + {0x01BA, 0x2F, 0xBA}, // XK_scedilla+AC10: VKEY_OEM_1 + {0x01BA, 0x3C, 0xBE}, // XK_scedilla+AB09: VKEY_OEM_PERIOD + {0x01BE, 0x0F, 0x36}, // XK_zcaron+AE06: VKEY_6 + {0x01BE, 0x15, 0xBB}, // XK_zcaron+AE12: VKEY_OEM_PLUS + {0x01BE, 0x19, 0x57}, // XK_zcaron+AD02: VKEY_W + {0x01BE, 0x22, 0x59}, // XK_zcaron+AD11: VKEY_Y + {0x01BE, 0x33, 0xDC}, // XK_zcaron+BKSL: VKEY_OEM_5 + {0x01BF, 0x22, 0xDB}, // XK_zabovedot+AD11: VKEY_OEM_4 + {0x01BF, 0x33, 0xDC}, // XK_zabovedot+BKSL: VKEY_OEM_5 + {0x01E3, 0x0A, 0x31}, // XK_abreve+AE01: VKEY_1 + {0x01E3, 0x22, 0xDB}, // XK_abreve+AD11: VKEY_OEM_4 + {0x01E8, 0x0B, 0x32}, // XK_ccaron+AE02: VKEY_2 + {0x01E8, 0x0D, 0x34}, // XK_ccaron+AE04: VKEY_4 + {0x01E8, 0x21, 0x58}, // XK_ccaron+AD10: VKEY_X + {0x01E8, 0x2F, 0xBA}, // XK_ccaron+AC10: VKEY_OEM_1 + {0x01E8, 0x3B, 0xBC}, // XK_ccaron+AB08: VKEY_OEM_COMMA + {0x01EA, 0x0C, 0x33}, // XK_eogonek+AE03: VKEY_3 + {0x01F0, 0x13, 0x30}, // XK_dstroke+AE10: VKEY_0 + {0x01F0, 0x23, 0xDD}, // XK_dstroke+AD12: VKEY_OEM_6 + {0x03E7, 0x0E, 0x35}, // XK_iogonek+AE05: VKEY_5 + {0x03EC, 0x0D, 0x34}, // XK_eabovedot+AE04: VKEY_4 + {0x03EC, 0x30, 0xDE}, // XK_eabovedot+AC11: VKEY_OEM_7 + {0x03F9, 0x10, 0x37}, // XK_uogonek+AE07: VKEY_7 + {0x03FE, 0x11, 0x38}, // XK_umacron+AE08: VKEY_8 + {0x03FE, 0x18, 0x51}, // XK_umacron+AD01: VKEY_Q + {0x03FE, 0x35, 0x58}, // XK_umacron+AB02: VKEY_X +}; + +const struct MAP2 { + KeySym ch0; + unsigned sc; + KeySym ch1; + uint8 vk; + bool operator()(const MAP2& m1, const MAP2& m2) const { + if (m1.ch0 == m2.ch0 && m1.sc == m2.sc) + return m1.ch1 < m2.ch1; + if (m1.ch0 == m2.ch0) + return m1.sc < m2.sc; + return m1.ch0 < m2.ch0; + } +} map2[] = { + {0x0023, 0x33, 0x0027, + 0xBF}, // XK_numbersign+BKSL+XK_quoteright: VKEY_OEM_2 + {0x0027, 0x30, 0x0022, + 0xDE}, // XK_quoteright+AC11+XK_quotedbl: VKEY_OEM_7 + {0x0027, 0x31, 0x0022, + 0xC0}, // XK_quoteright+TLDE+XK_quotedbl: VKEY_OEM_3 + {0x0027, 0x31, 0x00B7, + 0xDC}, // XK_quoteright+TLDE+XK_periodcentered: VKEY_OEM_5 + {0x0027, 0x33, 0x0000, 0xDC}, // XK_quoteright+BKSL+NoSymbol: VKEY_OEM_5 + {0x002D, 0x3D, 0x003D, 0xBD}, // XK_minus+AB10+XK_equal: VKEY_OEM_MINUS + {0x002F, 0x0C, 0x0033, 0x33}, // XK_slash+AE03+XK_3: VKEY_3 + {0x002F, 0x0C, 0x003F, 0xBF}, // XK_slash+AE03+XK_question: VKEY_OEM_2 + {0x002F, 0x13, 0x0030, 0x30}, // XK_slash+AE10+XK_0: VKEY_0 + {0x002F, 0x13, 0x003F, 0xBF}, // XK_slash+AE10+XK_question: VKEY_OEM_2 + {0x003D, 0x3D, 0x0025, 0xDF}, // XK_equal+AB10+XK_percent: VKEY_OEM_8 + {0x003D, 0x3D, 0x002B, 0xBB}, // XK_equal+AB10+XK_plus: VKEY_OEM_PLUS + {0x005C, 0x33, 0x002F, 0xDE}, // XK_backslash+BKSL+XK_slash: VKEY_OEM_7 + {0x005C, 0x33, 0x007C, 0xDC}, // XK_backslash+BKSL+XK_bar: VKEY_OEM_5 + {0x0060, 0x31, 0x0000, 0xC0}, // XK_quoteleft+TLDE+NoSymbol: VKEY_OEM_3 + {0x0060, 0x31, 0x00AC, 0xDF}, // XK_quoteleft+TLDE+XK_notsign: VKEY_OEM_8 + {0x00A7, 0x31, 0x00B0, 0xBF}, // XK_section+TLDE+XK_degree: VKEY_OEM_2 + {0x00A7, 0x31, 0x00BD, 0xDC}, // XK_section+TLDE+XK_onehalf: VKEY_OEM_5 + {0x00E0, 0x30, 0x00B0, 0xDE}, // XK_agrave+AC11+XK_degree: VKEY_OEM_7 + {0x00E0, 0x30, 0x00E4, 0xDC}, // XK_agrave+AC11+XK_adiaeresis: VKEY_OEM_5 + {0x00E4, 0x30, 0x00E0, 0xDC}, // XK_adiaeresis+AC11+XK_agrave: VKEY_OEM_5 + {0x00E9, 0x2F, 0x00C9, 0xBA}, // XK_eacute+AC10+XK_Eacute: VKEY_OEM_1 + {0x00E9, 0x2F, 0x00F6, 0xDE}, // XK_eacute+AC10+XK_odiaeresis: VKEY_OEM_7 + {0x00F6, 0x2F, 0x00E9, 0xDE}, // XK_odiaeresis+AC10+XK_eacute: VKEY_OEM_7 + {0x00FC, 0x22, 0x00E8, 0xBA}, // XK_udiaeresis+AD11+XK_egrave: VKEY_OEM_1 +}; + +const struct MAP3 { + KeySym ch0; + unsigned sc; + KeySym ch1; + KeySym ch2; + uint8 vk; + bool operator()(const MAP3& m1, const MAP3& m2) const { + if (m1.ch0 == m2.ch0 && m1.sc == m2.sc && m1.ch1 == m2.ch1) + return m1.ch2 < m2.ch2; + if (m1.ch0 == m2.ch0 && m1.sc == m2.sc) + return m1.ch1 < m2.ch1; + if (m1.ch0 == m2.ch0) + return m1.sc < m2.sc; + return m1.ch0 < m2.ch0; + } +} map3[] = { + {0x0023, 0x33, 0x007E, 0x0000, + 0xDE}, // XK_numbersign+BKSL+XK_asciitilde+NoSymbol: VKEY_OEM_7 + {0x0027, 0x14, 0x003F, 0x0000, + 0xDB}, // XK_quoteright+AE11+XK_question+NoSymbol: VKEY_OEM_4 + {0x0027, 0x14, 0x003F, 0x00DD, + 0xDB}, // XK_quoteright+AE11+XK_question+XK_Yacute: VKEY_OEM_4 + {0x0027, 0x15, 0x002A, 0x0000, + 0xBB}, // XK_quoteright+AE12+XK_asterisk+NoSymbol: VKEY_OEM_PLUS + {0x0027, 0x30, 0x0040, 0x0000, + 0xC0}, // XK_quoteright+AC11+XK_at+NoSymbol: VKEY_OEM_3 + {0x0027, 0x33, 0x002A, 0x0000, + 0xBF}, // XK_quoteright+BKSL+XK_asterisk+NoSymbol: VKEY_OEM_2 + {0x0027, 0x33, 0x002A, 0x00BD, + 0xDC}, // XK_quoteright+BKSL+XK_asterisk+XK_onehalf: VKEY_OEM_5 + {0x0027, 0x33, 0x002A, 0x01A3, + 0xBF}, // XK_quoteright+BKSL+XK_asterisk+XK_Lstroke: VKEY_OEM_2 + {0x0027, 0x34, 0x0022, 0x0000, + 0x5A}, // XK_quoteright+AB01+XK_quotedbl+NoSymbol: VKEY_Z + {0x0027, 0x34, 0x0022, 0x01D8, + 0xDE}, // XK_quoteright+AB01+XK_quotedbl+XK_Rcaron: VKEY_OEM_7 + {0x002B, 0x14, 0x003F, 0x0000, + 0xBB}, // XK_plus+AE11+XK_question+NoSymbol: VKEY_OEM_PLUS + {0x002B, 0x14, 0x003F, 0x005C, + 0xBD}, // XK_plus+AE11+XK_question+XK_backslash: VKEY_OEM_MINUS + {0x002B, 0x14, 0x003F, 0x01F5, + 0xBB}, // XK_plus+AE11+XK_question+XK_odoubleacute: VKEY_OEM_PLUS + {0x002D, 0x15, 0x005F, 0x0000, + 0xBD}, // XK_minus+AE12+XK_underscore+NoSymbol: VKEY_OEM_MINUS + {0x002D, 0x15, 0x005F, 0x03B3, + 0xDB}, // XK_minus+AE12+XK_underscore+XK_rcedilla: VKEY_OEM_4 + {0x002D, 0x3D, 0x005F, 0x0000, + 0xBD}, // XK_minus+AB10+XK_underscore+NoSymbol: VKEY_OEM_MINUS + {0x002D, 0x3D, 0x005F, 0x002A, + 0xBD}, // XK_minus+AB10+XK_underscore+XK_asterisk: VKEY_OEM_MINUS + {0x002D, 0x3D, 0x005F, 0x002F, + 0xBF}, // XK_minus+AB10+XK_underscore+XK_slash: VKEY_OEM_2 + {0x002D, 0x3D, 0x005F, 0x006E, + 0xBD}, // XK_minus+AB10+XK_underscore+XK_n: VKEY_OEM_MINUS + {0x003D, 0x14, 0x0025, 0x0000, + 0xBB}, // XK_equal+AE11+XK_percent+NoSymbol: VKEY_OEM_PLUS + {0x003D, 0x14, 0x0025, 0x002D, + 0xBD}, // XK_equal+AE11+XK_percent+XK_minus: VKEY_OEM_MINUS + {0x005C, 0x31, 0x007C, 0x0031, + 0xDC}, // XK_backslash+TLDE+XK_bar+XK_1: VKEY_OEM_5 + {0x005C, 0x31, 0x007C, 0x03D1, + 0xC0}, // XK_backslash+TLDE+XK_bar+XK_Ncedilla: VKEY_OEM_3 + {0x0060, 0x31, 0x007E, 0x0000, + 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+NoSymbol: VKEY_OEM_3 + {0x0060, 0x31, 0x007E, 0x0031, + 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_1: VKEY_OEM_3 + {0x0060, 0x31, 0x007E, 0x003B, + 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_semicolon: VKEY_OEM_3 + {0x0060, 0x31, 0x007E, 0x0060, + 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_quoteleft: VKEY_OEM_3 + {0x0060, 0x31, 0x007E, 0x00BF, + 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_questiondown: VKEY_OEM_3 + {0x0060, 0x31, 0x007E, 0x01F5, + 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_odoubleacute: VKEY_OEM_3 + {0x00E4, 0x30, 0x00C4, 0x0000, + 0xDE}, // XK_adiaeresis+AC11+XK_Adiaeresis+NoSymbol: VKEY_OEM_7 + {0x00E4, 0x30, 0x00C4, 0x01A6, + 0xDE}, // XK_adiaeresis+AC11+XK_Adiaeresis+XK_Sacute: VKEY_OEM_7 + {0x00E4, 0x30, 0x00C4, 0x01F8, + 0xDE}, // XK_adiaeresis+AC11+XK_Adiaeresis+XK_rcaron: VKEY_OEM_7 + {0x00E7, 0x2F, 0x00C7, 0x0000, + 0xBA}, // XK_ccedilla+AC10+XK_Ccedilla+NoSymbol: VKEY_OEM_1 + {0x00E7, 0x2F, 0x00C7, 0x00DE, + 0xC0}, // XK_ccedilla+AC10+XK_Ccedilla+XK_Thorn: VKEY_OEM_3 + {0x00F6, 0x2F, 0x00D6, 0x0000, + 0xC0}, // XK_odiaeresis+AC10+XK_Odiaeresis+NoSymbol: VKEY_OEM_3 + {0x00F6, 0x2F, 0x00D6, 0x01DE, + 0xC0}, // XK_odiaeresis+AC10+XK_Odiaeresis+XK_Tcedilla: VKEY_OEM_3 + {0x00FC, 0x14, 0x00DC, 0x0000, + 0xBF}, // XK_udiaeresis+AE11+XK_Udiaeresis+NoSymbol: VKEY_OEM_2 + {0x00FC, 0x22, 0x00DC, 0x0000, + 0xBA}, // XK_udiaeresis+AD11+XK_Udiaeresis+NoSymbol: VKEY_OEM_1 + {0x00FC, 0x22, 0x00DC, 0x01A3, + 0xC0}, // XK_udiaeresis+AD11+XK_Udiaeresis+XK_Lstroke: VKEY_OEM_3 + {0x01EA, 0x3D, 0x01CA, 0x0000, + 0xBD}, // XK_eogonek+AB10+XK_Eogonek+NoSymbol: VKEY_OEM_MINUS + {0x01EA, 0x3D, 0x01CA, 0x006E, + 0xBF}, // XK_eogonek+AB10+XK_Eogonek+XK_n: VKEY_OEM_2 + {0x03E7, 0x22, 0x03C7, 0x0000, + 0xDB}, // XK_iogonek+AD11+XK_Iogonek+NoSymbol: VKEY_OEM_4 + {0x03F9, 0x2F, 0x03D9, 0x0000, + 0xC0}, // XK_uogonek+AC10+XK_Uogonek+NoSymbol: VKEY_OEM_3 + {0x03F9, 0x2F, 0x03D9, 0x01DE, + 0xBA}, // XK_uogonek+AC10+XK_Uogonek+XK_Tcedilla: VKEY_OEM_1 +}; + +template <class T_MAP> +KeyboardCode FindVK(const T_MAP& key, const T_MAP* map, size_t size) { + T_MAP comp = {0}; + const T_MAP* p = std::lower_bound(map, map + size, key, comp); + if (p != map + size && !comp(*p, key) && !comp(key, *p)) + return static_cast<KeyboardCode>(p->vk); + return VKEY_UNKNOWN; +} + +} // namespace + // Get an ui::KeyboardCode from an X keyevent KeyboardCode KeyboardCodeFromXKeyEvent(XEvent* xev) { + // Gets correct VKEY code from XEvent is performed as the following steps: + // 1. Gets the keysym without modifier states. + // 2. For [a-z] & [0-9] cases, returns the VKEY code accordingly. + // 3. Find keysym in map0. + // 4. If not found, fallback to find keysym + hardware_code in map1. + // 5. If not found, fallback to find keysym + keysym_shift + hardware_code + // in map2. + // 6. If not found, fallback to find keysym + keysym_shift + keysym_altgr + + // hardware_code in map3. + // 7. If not found, fallback to find in KeyboardCodeFromXKeysym(), which + // mainly for non-letter keys. + // 8. If not found, fallback to find with the hardware code in US layout. + + KeySym keysym = NoSymbol; + XKeyEvent xkey = xev->xkey; + xkey.state &= (~0xFF | Mod2Mask); // Clears the xkey's state except numlock. // XLookupKeysym does not take into consideration the state of the lock/shift // etc. keys. So it is necessary to use XLookupString instead. - KeySym keysym; - XLookupString(&xev->xkey, NULL, 0, &keysym, NULL); - KeyboardCode keycode = KeyboardCodeFromXKeysym(keysym); - if (keycode == VKEY_UNKNOWN) { - keysym = DefaultXKeysymFromHardwareKeycode(xev->xkey.keycode); - keycode = KeyboardCodeFromXKeysym(keysym); + XLookupString(&xkey, NULL, 0, &keysym, NULL); + + // [a-z] cases. + if (keysym >= XK_a && keysym <= XK_z) + return static_cast<KeyboardCode>(VKEY_A + keysym - XK_a); + + // [0-9] cases. + if (keysym >= XK_0 && keysym <= XK_9) + return static_cast<KeyboardCode>(VKEY_0 + keysym - XK_0); + + KeyboardCode keycode = VKEY_UNKNOWN; + + if (!IsKeypadKey(keysym) && !IsPrivateKeypadKey(keysym) && + !IsCursorKey(keysym) && !IsPFKey(keysym) && !IsFunctionKey(keysym) && + !IsModifierKey(keysym)) { + MAP0 key0 = {keysym & 0xFFFF, 0}; + keycode = FindVK(key0, map0, arraysize(map0)); + if (keycode != VKEY_UNKNOWN) + return keycode; + + MAP1 key1 = {keysym & 0xFFFF, xkey.keycode, 0}; + keycode = FindVK(key1, map1, arraysize(map1)); + if (keycode != VKEY_UNKNOWN) + return keycode; + + KeySym keysym_shift = NoSymbol; + xkey.state |= ShiftMask; + XLookupString(&xkey, NULL, 0, &keysym_shift, NULL); + MAP2 key2 = {keysym & 0xFFFF, xkey.keycode, keysym_shift & 0xFFFF, 0}; + keycode = FindVK(key2, map2, arraysize(map2)); + if (keycode != VKEY_UNKNOWN) + return keycode; + + KeySym keysym_altgr = NoSymbol; + xkey.state &= ~ShiftMask; + xkey.state |= Mod1Mask; + XLookupString(&xkey, NULL, 0, &keysym_altgr, NULL); + MAP3 key3 = {keysym & 0xFFFF, xkey.keycode, keysym_shift & 0xFFFF, + keysym_altgr & 0xFFFF, 0}; + keycode = FindVK(key3, map3, arraysize(map3)); + if (keycode != VKEY_UNKNOWN) + return keycode; + + // On Linux some keys has AltGr char but not on Windows. + // So if cannot find VKEY with (ch0+sc+ch1+ch2) in map3, tries to fallback + // to just find VKEY with (ch0+sc+ch1). This is the best we could do. + MAP3 key4 = {keysym & 0xFFFF, xkey.keycode, keysym_shift & 0xFFFF, 0xFFFF, + 0}; + const MAP3* p = + std::lower_bound(map3, map3 + arraysize(map3), key4, MAP3()); + if (p != map3 + arraysize(map3) && p->ch0 == key4.ch0 && p->sc == key4.sc && + p->ch1 == key4.ch1) + return static_cast<KeyboardCode>(p->vk); } + keycode = KeyboardCodeFromXKeysym(keysym); + if (keycode == VKEY_UNKNOWN) + keycode = DefaultKeyboardCodeFromHardwareKeycode(xkey.keycode); + return keycode; } @@ -99,117 +607,6 @@ KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { return VKEY_NONCONVERT; case XK_Zenkaku_Hankaku: return VKEY_DBE_DBCSCHAR; - case XK_A: - case XK_a: - return VKEY_A; - case XK_B: - case XK_b: - return VKEY_B; - case XK_C: - case XK_c: - return VKEY_C; - case XK_D: - case XK_d: - return VKEY_D; - case XK_E: - case XK_e: - return VKEY_E; - case XK_F: - case XK_f: - return VKEY_F; - case XK_G: - case XK_g: - return VKEY_G; - case XK_H: - case XK_h: - return VKEY_H; - case XK_I: - case XK_i: - return VKEY_I; - case XK_J: - case XK_j: - return VKEY_J; - case XK_K: - case XK_k: - return VKEY_K; - case XK_L: - case XK_l: - return VKEY_L; - case XK_M: - case XK_m: - return VKEY_M; - case XK_N: - case XK_n: - return VKEY_N; - case XK_O: - case XK_o: - return VKEY_O; - case XK_P: - case XK_p: - return VKEY_P; - case XK_Q: - case XK_q: - return VKEY_Q; - case XK_R: - case XK_r: - return VKEY_R; - case XK_S: - case XK_s: - return VKEY_S; - case XK_T: - case XK_t: - return VKEY_T; - case XK_U: - case XK_u: - return VKEY_U; - case XK_V: - case XK_v: - return VKEY_V; - case XK_W: - case XK_w: - return VKEY_W; - case XK_X: - case XK_x: - return VKEY_X; - case XK_Y: - case XK_y: - return VKEY_Y; - case XK_Z: - case XK_z: - return VKEY_Z; - - case XK_0: - case XK_1: - case XK_2: - case XK_3: - case XK_4: - case XK_5: - case XK_6: - case XK_7: - case XK_8: - case XK_9: - return static_cast<KeyboardCode>(VKEY_0 + (keysym - XK_0)); - - case XK_parenright: - return VKEY_0; - case XK_exclam: - return VKEY_1; - case XK_at: - return VKEY_2; - case XK_numbersign: - return VKEY_3; - case XK_dollar: - return VKEY_4; - case XK_percent: - return VKEY_5; - case XK_asciicircum: - return VKEY_6; - case XK_ampersand: - return VKEY_7; - case XK_asterisk: - return VKEY_8; - case XK_parenleft: - return VKEY_9; case XK_KP_0: case XK_KP_1: @@ -371,20 +768,6 @@ KeyboardCode KeyboardCodeFromXKeysym(unsigned int keysym) { case XF86XK_Launch9: return VKEY_F18; -#if defined(TOOLKIT_GTK) - case XF86XK_Refresh: - case XF86XK_History: - case XF86XK_OpenURL: - case XF86XK_AddFavorite: - case XF86XK_Go: - case XF86XK_ZoomIn: - case XF86XK_ZoomOut: - // ui::AcceleratorGtk tries to convert the XF86XK_ keysyms on Chrome - // startup. It's safe to return VKEY_UNKNOWN here since ui::AcceleratorGtk - // also checks a Gdk keysym. http://crbug.com/109843 - return VKEY_UNKNOWN; -#endif - // For supporting multimedia buttons on a USB keyboard. case XF86XK_Back: return VKEY_BROWSER_BACK; @@ -450,96 +833,178 @@ uint16 GetCharacterFromXEvent(XEvent* xev) { int bytes_written = XLookupString(&xev->xkey, buf, 6, NULL, NULL); DCHECK_LE(bytes_written, 6); - base::string16 result; - return (bytes_written > 0 && UTF8ToUTF16(buf, bytes_written, &result) && - result.length() == 1) ? result[0] : 0; + if (bytes_written <= 0) + return 0; + const base::string16& result = base::WideToUTF16( + base::SysNativeMBToWide(base::StringPiece(buf, bytes_written))); + return result.length() == 1 ? result[0] : 0; } -unsigned int DefaultXKeysymFromHardwareKeycode(unsigned int hardware_code) { - static const unsigned int kHardwareKeycodeMap[] = { - 0, // 0x00: - 0, // 0x01: - 0, // 0x02: - 0, // 0x03: - 0, // 0x04: - 0, // 0x05: - 0, // 0x06: - 0, // 0x07: - 0, // 0x08: - XK_Escape, // 0x09: XK_Escape - XK_1, // 0x0A: XK_1 - XK_2, // 0x0B: XK_2 - XK_3, // 0x0C: XK_3 - XK_4, // 0x0D: XK_4 - XK_5, // 0x0E: XK_5 - XK_6, // 0x0F: XK_6 - XK_7, // 0x10: XK_7 - XK_8, // 0x11: XK_8 - XK_9, // 0x12: XK_9 - XK_0, // 0x13: XK_0 - XK_minus, // 0x14: XK_minus - XK_equal, // 0x15: XK_equal - XK_BackSpace, // 0x16: XK_BackSpace - XK_Tab, // 0x17: XK_Tab - XK_q, // 0x18: XK_q - XK_w, // 0x19: XK_w - XK_e, // 0x1A: XK_e - XK_r, // 0x1B: XK_r - XK_t, // 0x1C: XK_t - XK_y, // 0x1D: XK_y - XK_u, // 0x1E: XK_u - XK_i, // 0x1F: XK_i - XK_o, // 0x20: XK_o - XK_p, // 0x21: XK_p - XK_bracketleft, // 0x22: XK_bracketleft - XK_bracketright, // 0x23: XK_bracketright - XK_Return, // 0x24: XK_Return - XK_Control_L, // 0x25: XK_Control_L - XK_a, // 0x26: XK_a - XK_s, // 0x27: XK_s - XK_d, // 0x28: XK_d - XK_f, // 0x29: XK_f - XK_g, // 0x2A: XK_g - XK_h, // 0x2B: XK_h - XK_j, // 0x2C: XK_j - XK_k, // 0x2D: XK_k - XK_l, // 0x2E: XK_l - XK_semicolon, // 0x2F: XK_semicolon - XK_apostrophe, // 0x30: XK_apostrophe - XK_grave, // 0x31: XK_grave - XK_Shift_L, // 0x32: XK_Shift_L - XK_backslash, // 0x33: XK_backslash - XK_z, // 0x34: XK_z - XK_x, // 0x35: XK_x - XK_c, // 0x36: XK_c - XK_v, // 0x37: XK_v - XK_b, // 0x38: XK_b - XK_n, // 0x39: XK_n - XK_m, // 0x3A: XK_m - XK_comma, // 0x3B: XK_comma - XK_period, // 0x3C: XK_period - XK_slash, // 0x3D: XK_slash - XK_Shift_R, // 0x3E: XK_Shift_R - 0, // 0x3F: XK_KP_Multiply - XK_Alt_L, // 0x40: XK_Alt_L - XK_space, // 0x41: XK_space - XK_Caps_Lock, // 0x42: XK_Caps_Lock - XK_F1, // 0x43: XK_F1 - XK_F2, // 0x44: XK_F2 - XK_F3, // 0x45: XK_F3 - XK_F4, // 0x46: XK_F4 - XK_F5, // 0x47: XK_F5 - XK_F6, // 0x48: XK_F6 - XK_F7, // 0x49: XK_F7 - XK_F8, // 0x4A: XK_F8 - XK_F9, // 0x4B: XK_F9 - XK_F10, // 0x4C: XK_F10 - XK_Num_Lock, // 0x4D: XK_Num_Lock - XK_Scroll_Lock, // 0x4E: XK_Scroll_Lock +KeyboardCode DefaultKeyboardCodeFromHardwareKeycode( + unsigned int hardware_code) { + // This function assumes that X11 is using evdev-based keycodes. + static const KeyboardCode kHardwareKeycodeMap[] = { + // Please refer to below links for the table content: + // http://www.w3.org/TR/DOM-Level-3-Events-code/#keyboard-101 + // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode + // http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf + VKEY_UNKNOWN, // 0x00: + VKEY_UNKNOWN, // 0x01: + VKEY_UNKNOWN, // 0x02: + VKEY_UNKNOWN, // 0x03: + VKEY_UNKNOWN, // 0x04: + VKEY_UNKNOWN, // 0x05: + VKEY_UNKNOWN, // 0x06: + VKEY_UNKNOWN, // XKB evdev (XKB - 8) X KeySym + VKEY_UNKNOWN, // === =============== ====== + VKEY_ESCAPE, // 0x09: KEY_ESC Escape + VKEY_1, // 0x0A: KEY_1 1 + VKEY_2, // 0x0B: KEY_2 2 + VKEY_3, // 0x0C: KEY_3 3 + VKEY_4, // 0x0D: KEY_4 4 + VKEY_5, // 0x0E: KEY_5 5 + VKEY_6, // 0x0F: KEY_6 6 + VKEY_7, // 0x10: KEY_7 7 + VKEY_8, // 0x11: KEY_8 8 + VKEY_9, // 0x12: KEY_9 9 + VKEY_0, // 0x13: KEY_0 0 + VKEY_OEM_MINUS, // 0x14: KEY_MINUS minus + VKEY_OEM_PLUS, // 0x15: KEY_EQUAL equal + VKEY_BACK, // 0x16: KEY_BACKSPACE BackSpace + VKEY_TAB, // 0x17: KEY_TAB Tab + VKEY_Q, // 0x18: KEY_Q q + VKEY_W, // 0x19: KEY_W w + VKEY_E, // 0x1A: KEY_E e + VKEY_R, // 0x1B: KEY_R r + VKEY_T, // 0x1C: KEY_T t + VKEY_Y, // 0x1D: KEY_Y y + VKEY_U, // 0x1E: KEY_U u + VKEY_I, // 0x1F: KEY_I i + VKEY_O, // 0x20: KEY_O o + VKEY_P, // 0x21: KEY_P p + VKEY_OEM_4, // 0x22: KEY_LEFTBRACE bracketleft + VKEY_OEM_6, // 0x23: KEY_RIGHTBRACE bracketright + VKEY_RETURN, // 0x24: KEY_ENTER Return + VKEY_LCONTROL, // 0x25: KEY_LEFTCTRL Control_L + VKEY_A, // 0x26: KEY_A a + VKEY_S, // 0x27: KEY_S s + VKEY_D, // 0x28: KEY_D d + VKEY_F, // 0x29: KEY_F f + VKEY_G, // 0x2A: KEY_G g + VKEY_H, // 0x2B: KEY_H h + VKEY_J, // 0x2C: KEY_J j + VKEY_K, // 0x2D: KEY_K k + VKEY_L, // 0x2E: KEY_L l + VKEY_OEM_1, // 0x2F: KEY_SEMICOLON semicolon + VKEY_OEM_7, // 0x30: KEY_APOSTROPHE apostrophe + VKEY_OEM_3, // 0x31: KEY_GRAVE grave + VKEY_LSHIFT, // 0x32: KEY_LEFTSHIFT Shift_L + VKEY_OEM_5, // 0x33: KEY_BACKSLASH backslash + VKEY_Z, // 0x34: KEY_Z z + VKEY_X, // 0x35: KEY_X x + VKEY_C, // 0x36: KEY_C c + VKEY_V, // 0x37: KEY_V v + VKEY_B, // 0x38: KEY_B b + VKEY_N, // 0x39: KEY_N n + VKEY_M, // 0x3A: KEY_M m + VKEY_OEM_COMMA, // 0x3B: KEY_COMMA comma + VKEY_OEM_PERIOD, // 0x3C: KEY_DOT period + VKEY_OEM_2, // 0x3D: KEY_SLASH slash + VKEY_RSHIFT, // 0x3E: KEY_RIGHTSHIFT Shift_R + VKEY_MULTIPLY, // 0x3F: KEY_KPASTERISK KP_Multiply + VKEY_LMENU, // 0x40: KEY_LEFTALT Alt_L + VKEY_SPACE, // 0x41: KEY_SPACE space + VKEY_CAPITAL, // 0x42: KEY_CAPSLOCK Caps_Lock + VKEY_F1, // 0x43: KEY_F1 F1 + VKEY_F2, // 0x44: KEY_F2 F2 + VKEY_F3, // 0x45: KEY_F3 F3 + VKEY_F4, // 0x46: KEY_F4 F4 + VKEY_F5, // 0x47: KEY_F5 F5 + VKEY_F6, // 0x48: KEY_F6 F6 + VKEY_F7, // 0x49: KEY_F7 F7 + VKEY_F8, // 0x4A: KEY_F8 F8 + VKEY_F9, // 0x4B: KEY_F9 F9 + VKEY_F10, // 0x4C: KEY_F10 F10 + VKEY_NUMLOCK, // 0x4D: KEY_NUMLOCK Num_Lock + VKEY_SCROLL, // 0x4E: KEY_SCROLLLOCK Scroll_Lock + VKEY_NUMPAD7, // 0x4F: KEY_KP7 KP_7 + VKEY_NUMPAD8, // 0x50: KEY_KP8 KP_8 + VKEY_NUMPAD9, // 0x51: KEY_KP9 KP_9 + VKEY_SUBTRACT, // 0x52: KEY_KPMINUS KP_Subtract + VKEY_NUMPAD4, // 0x53: KEY_KP4 KP_4 + VKEY_NUMPAD5, // 0x54: KEY_KP5 KP_5 + VKEY_NUMPAD6, // 0x55: KEY_KP6 KP_6 + VKEY_ADD, // 0x56: KEY_KPPLUS KP_Add + VKEY_NUMPAD1, // 0x57: KEY_KP1 KP_1 + VKEY_NUMPAD2, // 0x58: KEY_KP2 KP_2 + VKEY_NUMPAD3, // 0x59: KEY_KP3 KP_3 + VKEY_NUMPAD0, // 0x5A: KEY_KP0 KP_0 + VKEY_DECIMAL, // 0x5B: KEY_KPDOT KP_Decimal + VKEY_UNKNOWN, // 0x5C: + VKEY_DBE_DBCSCHAR, // 0x5D: KEY_ZENKAKUHANKAKU Zenkaku_Hankaku + VKEY_OEM_5, // 0x5E: KEY_102ND backslash + VKEY_F11, // 0x5F: KEY_F11 F11 + VKEY_F12, // 0x60: KEY_F12 F12 + VKEY_OEM_102, // 0x61: KEY_RO Romaji + VKEY_UNSUPPORTED, // 0x62: KEY_KATAKANA Katakana + VKEY_UNSUPPORTED, // 0x63: KEY_HIRAGANA Hiragana + VKEY_CONVERT, // 0x64: KEY_HENKAN Henkan + VKEY_UNSUPPORTED, // 0x65: KEY_KATAKANAHIRAGANA Hiragana_Katakana + VKEY_NONCONVERT, // 0x66: KEY_MUHENKAN Muhenkan + VKEY_SEPARATOR, // 0x67: KEY_KPJPCOMMA KP_Separator + VKEY_RETURN, // 0x68: KEY_KPENTER KP_Enter + VKEY_RCONTROL, // 0x69: KEY_RIGHTCTRL Control_R + VKEY_DIVIDE, // 0x6A: KEY_KPSLASH KP_Divide + VKEY_PRINT, // 0x6B: KEY_SYSRQ Print + VKEY_RMENU, // 0x6C: KEY_RIGHTALT Alt_R + VKEY_RETURN, // 0x6D: KEY_LINEFEED Linefeed + VKEY_HOME, // 0x6E: KEY_HOME Home + VKEY_UP, // 0x6F: KEY_UP Up + VKEY_PRIOR, // 0x70: KEY_PAGEUP Page_Up + VKEY_LEFT, // 0x71: KEY_LEFT Left + VKEY_RIGHT, // 0x72: KEY_RIGHT Right + VKEY_END, // 0x73: KEY_END End + VKEY_DOWN, // 0x74: KEY_DOWN Down + VKEY_NEXT, // 0x75: KEY_PAGEDOWN Page_Down + VKEY_INSERT, // 0x76: KEY_INSERT Insert + VKEY_DELETE, // 0x77: KEY_DELETE Delete + VKEY_UNSUPPORTED, // 0x78: KEY_MACRO + VKEY_VOLUME_MUTE, // 0x79: KEY_MUTE XF86AudioMute + VKEY_VOLUME_DOWN, // 0x7A: KEY_VOLUMEDOWN XF86AudioLowerVolume + VKEY_VOLUME_UP, // 0x7B: KEY_VOLUMEUP XF86AudioRaiseVolume + VKEY_POWER, // 0x7C: KEY_POWER XF86PowerOff + VKEY_OEM_PLUS, // 0x7D: KEY_KPEQUAL KP_Equal + VKEY_UNSUPPORTED, // 0x7E: KEY_KPPLUSMINUS plusminus + VKEY_PAUSE, // 0x7F: KEY_PAUSE Pause + VKEY_MEDIA_LAUNCH_APP1, // 0x80: KEY_SCALE XF86LaunchA + VKEY_DECIMAL, // 0x81: KEY_KPCOMMA KP_Decimal + VKEY_HANGUL, // 0x82: KEY_HANGUEL Hangul + VKEY_HANJA, // 0x83: KEY_HANJA Hangul_Hanja + VKEY_OEM_5, // 0x84: KEY_YEN yen + VKEY_LWIN, // 0x85: KEY_LEFTMETA Super_L + VKEY_RWIN, // 0x86: KEY_RIGHTMETA Super_R + VKEY_COMPOSE, // 0x87: KEY_COMPOSE Menu }; - return hardware_code < arraysize(kHardwareKeycodeMap) ? - kHardwareKeycodeMap[hardware_code] : 0; + if (hardware_code >= arraysize(kHardwareKeycodeMap)) { + // Additional keycodes used by the Chrome OS top row special function keys. + switch (hardware_code) { + case 0xA6: // KEY_BACK + return VKEY_BACK; + case 0xA7: // KEY_FORWARD + return VKEY_BROWSER_FORWARD; + case 0xB5: // KEY_REFRESH + return VKEY_BROWSER_REFRESH; + case 0xD4: // KEY_DASHBOARD + return VKEY_MEDIA_LAUNCH_APP2; + case 0xE8: // KEY_BRIGHTNESSDOWN + return VKEY_BRIGHTNESS_DOWN; + case 0xE9: // KEY_BRIGHTNESSUP + return VKEY_BRIGHTNESS_UP; + } + return VKEY_UNKNOWN; + } + return kHardwareKeycodeMap[hardware_code]; } // TODO(jcampan): this method might be incomplete. |