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