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.
5 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
9 #define XK_3270 // for XK_3270_BackTab
10 #include <X11/XF86keysym.h>
12 #include <X11/Xutil.h>
13 #include <X11/extensions/XInput2.h>
14 #include <X11/keysym.h>
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/dom/keycode_converter.h"
22 #include "ui/events/keycodes/keyboard_code_conversion_xkb.h"
23 #include "ui/events/x/keysym_to_unicode.h"
25 #define VKEY_UNSUPPORTED VKEY_UNKNOWN
32 // These are the generated VKEY code maps for all possible Latin keyboard
33 // layouts in Windows. And the maps are only for special letter keys excluding
36 // ch0: the keysym without modifier states.
37 // ch1: the keysym with shift state.
38 // ch2: the keysym with altgr state.
39 // sc: the hardware keycode (in Windows, it's called scan code).
42 // MAP0: maps from ch0 to vk.
43 // MAP1: maps from ch0+sc to vk.
44 // MAP2: maps from ch0+ch1+sc to vk.
45 // MAP3: maps from ch0+ch1+ch2+sc to vk.
46 // MAP0 - MAP3 are all sorted, so that finding VK can be binary search.
48 // Reason for creating these maps is because a hard-coded mapping in
49 // KeyboardCodeFromXKeysym() doesn't support non-US keyboard layouts.
50 // e.g. in UK keyboard, the key between Quote and Enter keys has the VKEY code
51 // VKEY_OEM_5 instead of VKEY_3.
53 // The key symbols which are not [a-zA-Z0-9] and functional/extend keys (e.g.
54 // TAB, ENTER, BS, Arrow keys, modifier keys, F1-F12, media/app keys, etc.)
55 // should go through these maps for correct VKEY codes.
57 // Please refer to crbug.com/386066.
62 bool operator()(const MAP0
& m1
, const MAP0
& m2
) const {
63 return m1
.ch0
< m2
.ch0
;
66 {0x0025, 0x35}, // XK_percent: VKEY_5
67 {0x0026, 0x31}, // XK_ampersand: VKEY_1
68 {0x003C, 0xDC}, // XK_less: VKEY_OEM_5
69 {0x007B, 0xDE}, // XK_braceleft: VKEY_OEM_7
70 {0x007C, 0xDC}, // XK_bar: VKEY_OEM_5
71 {0x007D, 0xBF}, // XK_braceright: VKEY_OEM_2
72 {0x007E, 0xDC}, // XK_asciitilde: VKEY_OEM_5
73 {0x00A1, 0xDD}, // XK_exclamdown: VKEY_OEM_6
74 {0x00AD, 0xC0}, // XK_hyphen: VKEY_OEM_3
75 {0x00B2, 0xDE}, // XK_twosuperior: VKEY_OEM_7
76 {0x00B5, 0xDC}, // XK_mu: VKEY_OEM_5
77 {0x00BB, 0x39}, // XK_guillemotright: VKEY_9
78 {0x00BD, 0xDC}, // XK_onehalf: VKEY_OEM_5
79 {0x00BF, 0xDD}, // XK_questiondown: VKEY_OEM_6
80 {0x00DF, 0xDB}, // XK_ssharp: VKEY_OEM_4
81 {0x00E5, 0xDD}, // XK_aring: VKEY_OEM_6
82 {0x00EA, 0x33}, // XK_ecircumflex: VKEY_3
83 {0x00EB, 0xBA}, // XK_ediaeresis: VKEY_OEM_1
84 {0x00EC, 0xDD}, // XK_igrave: VKEY_OEM_6
85 {0x00EE, 0xDD}, // XK_icircumflex: VKEY_OEM_6
86 {0x00F1, 0xC0}, // XK_ntilde: VKEY_OEM_3
87 {0x00F2, 0xC0}, // XK_ograve: VKEY_OEM_3
88 {0x00F5, 0xDB}, // XK_otilde: VKEY_OEM_4
89 {0x00F7, 0xDD}, // XK_division: VKEY_OEM_6
90 {0x00FD, 0x37}, // XK_yacute: VKEY_7
91 {0x00FE, 0xBD}, // XK_thorn: VKEY_OEM_MINUS
92 {0x01A1, 0xDD}, // XK_ohorn: VKEY_OEM_6
93 {0x01B0, 0xDB}, // XK_uhorn: VKEY_OEM_4
94 {0x01B5, 0x32}, // XK_lcaron: VKEY_2
95 {0x01B6, 0xDD}, // XK_zstroke: VKEY_OEM_6
96 {0x01BB, 0x35}, // XK_tcaron: VKEY_5
97 {0x01E6, 0xDE}, // XK_cacute: VKEY_OEM_7
98 {0x01EC, 0x32}, // XK_ecaron: VKEY_2
99 {0x01F2, 0xDC}, // XK_ncaron: VKEY_OEM_5
100 {0x01F5, 0xDB}, // XK_odoubleacute: VKEY_OEM_4
101 {0x01F8, 0x35}, // XK_rcaron: VKEY_5
102 {0x01F9, 0xBA}, // XK_uring: VKEY_OEM_1
103 {0x01FB, 0xDC}, // XK_udoubleacute: VKEY_OEM_5
104 {0x01FE, 0xDE}, // XK_tcedilla: VKEY_OEM_7
105 {0x0259, 0xC0}, // XK_schwa: VKEY_OEM_3
106 {0x02B1, 0xDD}, // XK_hstroke: VKEY_OEM_6
107 {0x02B9, 0xBA}, // XK_idotless: VKEY_OEM_1
108 {0x02BB, 0xDD}, // XK_gbreve: VKEY_OEM_6
109 {0x02E5, 0xC0}, // XK_cabovedot: VKEY_OEM_3
110 {0x02F5, 0xDB}, // XK_gabovedot: VKEY_OEM_4
111 {0x03B6, 0xBF}, // XK_lcedilla: VKEY_OEM_2
112 {0x03BA, 0x57}, // XK_emacron: VKEY_W
113 {0x03E0, 0xDF}, // XK_amacron: VKEY_OEM_8
114 {0x03EF, 0xDD}, // XK_imacron: VKEY_OEM_6
115 {0x03F1, 0xDB}, // XK_ncedilla: VKEY_OEM_4
116 {0x03F3, 0xDC}, // XK_kcedilla: VKEY_OEM_5
123 bool operator()(const MAP1
& m1
, const MAP1
& m2
) const {
124 if (m1
.ch0
== m2
.ch0
)
125 return m1
.sc
< m2
.sc
;
126 return m1
.ch0
< m2
.ch0
;
129 {0x0021, 0x0A, 0x31}, // XK_exclam+AE01: VKEY_1
130 {0x0021, 0x11, 0x38}, // XK_exclam+AE08: VKEY_8
131 {0x0021, 0x3D, 0xDF}, // XK_exclam+AB10: VKEY_OEM_8
132 {0x0022, 0x0B, 0x32}, // XK_quotedbl+AE02: VKEY_2
133 {0x0022, 0x0C, 0x33}, // XK_quotedbl+AE03: VKEY_3
134 {0x0023, 0x31, 0xDE}, // XK_numbersign+TLDE: VKEY_OEM_7
135 {0x0024, 0x23, 0xBA}, // XK_dollar+AD12: VKEY_OEM_1
136 {0x0024, 0x33, 0xDF}, // XK_dollar+BKSL: VKEY_OEM_8
137 {0x0027, 0x0D, 0x34}, // XK_quoteright+AE04: VKEY_4
138 {0x0027, 0x18, 0xDE}, // XK_quoteright+AD01: VKEY_OEM_7
139 {0x0027, 0x23, 0xBA}, // XK_quoteright+AD12: VKEY_OEM_1
140 {0x0027, 0x3D, 0xDE}, // XK_quoteright+AB10: VKEY_OEM_7
141 {0x0028, 0x0E, 0x35}, // XK_parenleft+AE05: VKEY_5
142 {0x0028, 0x12, 0x39}, // XK_parenleft+AE09: VKEY_9
143 {0x0028, 0x33, 0xDC}, // XK_parenleft+BKSL: VKEY_OEM_5
144 {0x0029, 0x13, 0x30}, // XK_parenright+AE10: VKEY_0
145 {0x0029, 0x14, 0xDB}, // XK_parenright+AE11: VKEY_OEM_4
146 {0x0029, 0x23, 0xDD}, // XK_parenright+AD12: VKEY_OEM_6
147 {0x002A, 0x23, 0xBA}, // XK_asterisk+AD12: VKEY_OEM_1
148 {0x002A, 0x33, 0xDC}, // XK_asterisk+BKSL: VKEY_OEM_5
149 {0x002B, 0x0A, 0x31}, // XK_plus+AE01: VKEY_1
150 {0x002B, 0x15, 0xBB}, // XK_plus+AE12: VKEY_OEM_PLUS
151 {0x002B, 0x22, 0xBB}, // XK_plus+AD11: VKEY_OEM_PLUS
152 {0x002B, 0x23, 0xBB}, // XK_plus+AD12: VKEY_OEM_PLUS
153 {0x002B, 0x2F, 0xBB}, // XK_plus+AC10: VKEY_OEM_PLUS
154 {0x002B, 0x33, 0xBF}, // XK_plus+BKSL: VKEY_OEM_2
155 {0x002C, 0x0C, 0x33}, // XK_comma+AE03: VKEY_3
156 {0x002C, 0x0E, 0x35}, // XK_comma+AE05: VKEY_5
157 {0x002C, 0x0F, 0x36}, // XK_comma+AE06: VKEY_6
158 {0x002C, 0x12, 0x39}, // XK_comma+AE09: VKEY_9
159 {0x002C, 0x19, 0xBC}, // XK_comma+AD02: VKEY_OEM_COMMA
160 {0x002C, 0x37, 0xBC}, // XK_comma+AB04: VKEY_OEM_COMMA
161 {0x002C, 0x3A, 0xBC}, // XK_comma+AB07: VKEY_OEM_COMMA
162 {0x002C, 0x3B, 0xBC}, // XK_comma+AB08: VKEY_OEM_COMMA
163 {0x002D, 0x0B, 0x32}, // XK_minus+AE02: VKEY_2
164 {0x002D, 0x0F, 0x36}, // XK_minus+AE06: VKEY_6
165 {0x002D, 0x14, 0xBD}, // XK_minus+AE11: VKEY_OEM_MINUS
166 {0x002D, 0x26, 0xBD}, // XK_minus+AC01: VKEY_OEM_MINUS
167 {0x002D, 0x30, 0xBD}, // XK_minus+AC11: VKEY_OEM_MINUS
168 {0x002E, 0x10, 0x37}, // XK_period+AE07: VKEY_7
169 {0x002E, 0x11, 0x38}, // XK_period+AE08: VKEY_8
170 {0x002E, 0x1A, 0xBE}, // XK_period+AD03: VKEY_OEM_PERIOD
171 {0x002E, 0x1B, 0xBE}, // XK_period+AD04: VKEY_OEM_PERIOD
172 {0x002E, 0x20, 0xBE}, // XK_period+AD09: VKEY_OEM_PERIOD
173 {0x002E, 0x30, 0xDE}, // XK_period+AC11: VKEY_OEM_7
174 {0x002E, 0x3C, 0xBE}, // XK_period+AB09: VKEY_OEM_PERIOD
175 {0x002E, 0x3D, 0xBF}, // XK_period+AB10: VKEY_OEM_2
176 {0x002F, 0x14, 0xDB}, // XK_slash+AE11: VKEY_OEM_4
177 {0x002F, 0x22, 0xBF}, // XK_slash+AD11: VKEY_OEM_2
178 {0x002F, 0x31, 0xDE}, // XK_slash+TLDE: VKEY_OEM_7
179 {0x002F, 0x33, 0xDC}, // XK_slash+BKSL: VKEY_OEM_5
180 {0x002F, 0x3D, 0xBF}, // XK_slash+AB10: VKEY_OEM_2
181 {0x003A, 0x0A, 0x31}, // XK_colon+AE01: VKEY_1
182 {0x003A, 0x0E, 0x35}, // XK_colon+AE05: VKEY_5
183 {0x003A, 0x0F, 0x36}, // XK_colon+AE06: VKEY_6
184 {0x003A, 0x3C, 0xBF}, // XK_colon+AB09: VKEY_OEM_2
185 {0x003B, 0x0D, 0x34}, // XK_semicolon+AE04: VKEY_4
186 {0x003B, 0x11, 0x38}, // XK_semicolon+AE08: VKEY_8
187 {0x003B, 0x18, 0xBA}, // XK_semicolon+AD01: VKEY_OEM_1
188 {0x003B, 0x22, 0xBA}, // XK_semicolon+AD11: VKEY_OEM_1
189 {0x003B, 0x23, 0xDD}, // XK_semicolon+AD12: VKEY_OEM_6
190 {0x003B, 0x2F, 0xBA}, // XK_semicolon+AC10: VKEY_OEM_1
191 {0x003B, 0x31, 0xC0}, // XK_semicolon+TLDE: VKEY_OEM_3
192 {0x003B, 0x34, 0xBA}, // XK_semicolon+AB01: VKEY_OEM_1
193 {0x003B, 0x3B, 0xBE}, // XK_semicolon+AB08: VKEY_OEM_PERIOD
194 {0x003B, 0x3D, 0xBF}, // XK_semicolon+AB10: VKEY_OEM_2
195 {0x003D, 0x11, 0x38}, // XK_equal+AE08: VKEY_8
196 {0x003D, 0x15, 0xBB}, // XK_equal+AE12: VKEY_OEM_PLUS
197 {0x003D, 0x23, 0xBB}, // XK_equal+AD12: VKEY_OEM_PLUS
198 {0x003F, 0x0B, 0x32}, // XK_question+AE02: VKEY_2
199 {0x003F, 0x10, 0x37}, // XK_question+AE07: VKEY_7
200 {0x003F, 0x11, 0x38}, // XK_question+AE08: VKEY_8
201 {0x003F, 0x14, 0xBB}, // XK_question+AE11: VKEY_OEM_PLUS
202 {0x0040, 0x23, 0xDD}, // XK_at+AD12: VKEY_OEM_6
203 {0x0040, 0x31, 0xDE}, // XK_at+TLDE: VKEY_OEM_7
204 {0x005B, 0x0A, 0xDB}, // XK_bracketleft+AE01: VKEY_OEM_4
205 {0x005B, 0x14, 0xDB}, // XK_bracketleft+AE11: VKEY_OEM_4
206 {0x005B, 0x22, 0xDB}, // XK_bracketleft+AD11: VKEY_OEM_4
207 {0x005B, 0x23, 0xDD}, // XK_bracketleft+AD12: VKEY_OEM_6
208 {0x005B, 0x30, 0xDE}, // XK_bracketleft+AC11: VKEY_OEM_7
209 {0x005C, 0x15, 0xDB}, // XK_backslash+AE12: VKEY_OEM_4
210 {0x005D, 0x0B, 0xDD}, // XK_bracketright+AE02: VKEY_OEM_6
211 {0x005D, 0x15, 0xDD}, // XK_bracketright+AE12: VKEY_OEM_6
212 {0x005D, 0x23, 0xDD}, // XK_bracketright+AD12: VKEY_OEM_6
213 {0x005D, 0x31, 0xC0}, // XK_bracketright+TLDE: VKEY_OEM_3
214 {0x005D, 0x33, 0xDC}, // XK_bracketright+BKSL: VKEY_OEM_5
215 {0x005F, 0x11, 0x38}, // XK_underscore+AE08: VKEY_8
216 {0x005F, 0x14, 0xBD}, // XK_underscore+AE11: VKEY_OEM_MINUS
217 {0x00A7, 0x0D, 0x34}, // XK_section+AE04: VKEY_4
218 {0x00A7, 0x0F, 0x36}, // XK_section+AE06: VKEY_6
219 {0x00A7, 0x30, 0xDE}, // XK_section+AC11: VKEY_OEM_7
220 {0x00AB, 0x11, 0x38}, // XK_guillemotleft+AE08: VKEY_8
221 {0x00AB, 0x15, 0xDD}, // XK_guillemotleft+AE12: VKEY_OEM_6
222 {0x00B0, 0x15, 0xBF}, // XK_degree+AE12: VKEY_OEM_2
223 {0x00B0, 0x31, 0xDE}, // XK_degree+TLDE: VKEY_OEM_7
224 {0x00BA, 0x30, 0xDE}, // XK_masculine+AC11: VKEY_OEM_7
225 {0x00BA, 0x31, 0xDC}, // XK_masculine+TLDE: VKEY_OEM_5
226 {0x00E0, 0x13, 0x30}, // XK_agrave+AE10: VKEY_0
227 {0x00E0, 0x33, 0xDC}, // XK_agrave+BKSL: VKEY_OEM_5
228 {0x00E1, 0x11, 0x38}, // XK_aacute+AE08: VKEY_8
229 {0x00E1, 0x30, 0xDE}, // XK_aacute+AC11: VKEY_OEM_7
230 {0x00E2, 0x0B, 0x32}, // XK_acircumflex+AE02: VKEY_2
231 {0x00E2, 0x33, 0xDC}, // XK_acircumflex+BKSL: VKEY_OEM_5
232 {0x00E4, 0x23, 0xDD}, // XK_adiaeresis+AD12: VKEY_OEM_6
233 {0x00E6, 0x2F, 0xC0}, // XK_ae+AC10: VKEY_OEM_3
234 {0x00E6, 0x30, 0xDE}, // XK_ae+AC11: VKEY_OEM_7
235 {0x00E7, 0x12, 0x39}, // XK_ccedilla+AE09: VKEY_9
236 {0x00E7, 0x22, 0xDB}, // XK_ccedilla+AD11: VKEY_OEM_4
237 {0x00E7, 0x23, 0xDD}, // XK_ccedilla+AD12: VKEY_OEM_6
238 {0x00E7, 0x30, 0xDE}, // XK_ccedilla+AC11: VKEY_OEM_7
239 {0x00E7, 0x33, 0xBF}, // XK_ccedilla+BKSL: VKEY_OEM_2
240 {0x00E7, 0x3B, 0xBC}, // XK_ccedilla+AB08: VKEY_OEM_COMMA
241 {0x00E8, 0x10, 0x37}, // XK_egrave+AE07: VKEY_7
242 {0x00E8, 0x22, 0xBA}, // XK_egrave+AD11: VKEY_OEM_1
243 {0x00E8, 0x30, 0xC0}, // XK_egrave+AC11: VKEY_OEM_3
244 {0x00E9, 0x0B, 0x32}, // XK_eacute+AE02: VKEY_2
245 {0x00E9, 0x13, 0x30}, // XK_eacute+AE10: VKEY_0
246 {0x00E9, 0x3D, 0xBF}, // XK_eacute+AB10: VKEY_OEM_2
247 {0x00ED, 0x12, 0x39}, // XK_iacute+AE09: VKEY_9
248 {0x00ED, 0x31, 0x30}, // XK_iacute+TLDE: VKEY_0
249 {0x00F0, 0x22, 0xDD}, // XK_eth+AD11: VKEY_OEM_6
250 {0x00F0, 0x23, 0xBA}, // XK_eth+AD12: VKEY_OEM_1
251 {0x00F3, 0x15, 0xBB}, // XK_oacute+AE12: VKEY_OEM_PLUS
252 {0x00F3, 0x33, 0xDC}, // XK_oacute+BKSL: VKEY_OEM_5
253 {0x00F4, 0x0D, 0x34}, // XK_ocircumflex+AE04: VKEY_4
254 {0x00F4, 0x2F, 0xBA}, // XK_ocircumflex+AC10: VKEY_OEM_1
255 {0x00F6, 0x13, 0xC0}, // XK_odiaeresis+AE10: VKEY_OEM_3
256 {0x00F6, 0x14, 0xBB}, // XK_odiaeresis+AE11: VKEY_OEM_PLUS
257 {0x00F6, 0x22, 0xDB}, // XK_odiaeresis+AD11: VKEY_OEM_4
258 {0x00F8, 0x2F, 0xC0}, // XK_oslash+AC10: VKEY_OEM_3
259 {0x00F8, 0x30, 0xDE}, // XK_oslash+AC11: VKEY_OEM_7
260 {0x00F9, 0x30, 0xC0}, // XK_ugrave+AC11: VKEY_OEM_3
261 {0x00F9, 0x33, 0xBF}, // XK_ugrave+BKSL: VKEY_OEM_2
262 {0x00FA, 0x22, 0xDB}, // XK_uacute+AD11: VKEY_OEM_4
263 {0x00FA, 0x23, 0xDD}, // XK_uacute+AD12: VKEY_OEM_6
264 {0x00FC, 0x19, 0x57}, // XK_udiaeresis+AD02: VKEY_W
265 {0x01B1, 0x0A, 0x31}, // XK_aogonek+AE01: VKEY_1
266 {0x01B1, 0x18, 0x51}, // XK_aogonek+AD01: VKEY_Q
267 {0x01B1, 0x30, 0xDE}, // XK_aogonek+AC11: VKEY_OEM_7
268 {0x01B3, 0x2F, 0xBA}, // XK_lstroke+AC10: VKEY_OEM_1
269 {0x01B3, 0x33, 0xBF}, // XK_lstroke+BKSL: VKEY_OEM_2
270 {0x01B9, 0x0C, 0x33}, // XK_scaron+AE03: VKEY_3
271 {0x01B9, 0x0F, 0x36}, // XK_scaron+AE06: VKEY_6
272 {0x01B9, 0x22, 0xDB}, // XK_scaron+AD11: VKEY_OEM_4
273 {0x01B9, 0x26, 0xBA}, // XK_scaron+AC01: VKEY_OEM_1
274 {0x01B9, 0x29, 0x46}, // XK_scaron+AC04: VKEY_F
275 {0x01B9, 0x3C, 0xBE}, // XK_scaron+AB09: VKEY_OEM_PERIOD
276 {0x01BA, 0x2F, 0xBA}, // XK_scedilla+AC10: VKEY_OEM_1
277 {0x01BA, 0x3C, 0xBE}, // XK_scedilla+AB09: VKEY_OEM_PERIOD
278 {0x01BE, 0x0F, 0x36}, // XK_zcaron+AE06: VKEY_6
279 {0x01BE, 0x15, 0xBB}, // XK_zcaron+AE12: VKEY_OEM_PLUS
280 {0x01BE, 0x19, 0x57}, // XK_zcaron+AD02: VKEY_W
281 {0x01BE, 0x22, 0x59}, // XK_zcaron+AD11: VKEY_Y
282 {0x01BE, 0x33, 0xDC}, // XK_zcaron+BKSL: VKEY_OEM_5
283 {0x01BF, 0x22, 0xDB}, // XK_zabovedot+AD11: VKEY_OEM_4
284 {0x01BF, 0x33, 0xDC}, // XK_zabovedot+BKSL: VKEY_OEM_5
285 {0x01E3, 0x0A, 0x31}, // XK_abreve+AE01: VKEY_1
286 {0x01E3, 0x22, 0xDB}, // XK_abreve+AD11: VKEY_OEM_4
287 {0x01E8, 0x0B, 0x32}, // XK_ccaron+AE02: VKEY_2
288 {0x01E8, 0x0D, 0x34}, // XK_ccaron+AE04: VKEY_4
289 {0x01E8, 0x21, 0x58}, // XK_ccaron+AD10: VKEY_X
290 {0x01E8, 0x2F, 0xBA}, // XK_ccaron+AC10: VKEY_OEM_1
291 {0x01E8, 0x3B, 0xBC}, // XK_ccaron+AB08: VKEY_OEM_COMMA
292 {0x01EA, 0x0C, 0x33}, // XK_eogonek+AE03: VKEY_3
293 {0x01F0, 0x13, 0x30}, // XK_dstroke+AE10: VKEY_0
294 {0x01F0, 0x23, 0xDD}, // XK_dstroke+AD12: VKEY_OEM_6
295 {0x03E7, 0x0E, 0x35}, // XK_iogonek+AE05: VKEY_5
296 {0x03EC, 0x0D, 0x34}, // XK_eabovedot+AE04: VKEY_4
297 {0x03EC, 0x30, 0xDE}, // XK_eabovedot+AC11: VKEY_OEM_7
298 {0x03F9, 0x10, 0x37}, // XK_uogonek+AE07: VKEY_7
299 {0x03FE, 0x11, 0x38}, // XK_umacron+AE08: VKEY_8
300 {0x03FE, 0x18, 0x51}, // XK_umacron+AD01: VKEY_Q
301 {0x03FE, 0x35, 0x58}, // XK_umacron+AB02: VKEY_X
309 bool operator()(const MAP2
& m1
, const MAP2
& m2
) const {
310 if (m1
.ch0
== m2
.ch0
&& m1
.sc
== m2
.sc
)
311 return m1
.ch1
< m2
.ch1
;
312 if (m1
.ch0
== m2
.ch0
)
313 return m1
.sc
< m2
.sc
;
314 return m1
.ch0
< m2
.ch0
;
317 {0x0023, 0x33, 0x0027,
318 0xBF}, // XK_numbersign+BKSL+XK_quoteright: VKEY_OEM_2
319 {0x0027, 0x30, 0x0022,
320 0xDE}, // XK_quoteright+AC11+XK_quotedbl: VKEY_OEM_7
321 {0x0027, 0x31, 0x0022,
322 0xC0}, // XK_quoteright+TLDE+XK_quotedbl: VKEY_OEM_3
323 {0x0027, 0x31, 0x00B7,
324 0xDC}, // XK_quoteright+TLDE+XK_periodcentered: VKEY_OEM_5
325 {0x0027, 0x33, 0x0000, 0xDC}, // XK_quoteright+BKSL+NoSymbol: VKEY_OEM_5
326 {0x002D, 0x3D, 0x003D, 0xBD}, // XK_minus+AB10+XK_equal: VKEY_OEM_MINUS
327 {0x002F, 0x0C, 0x0033, 0x33}, // XK_slash+AE03+XK_3: VKEY_3
328 {0x002F, 0x0C, 0x003F, 0xBF}, // XK_slash+AE03+XK_question: VKEY_OEM_2
329 {0x002F, 0x13, 0x0030, 0x30}, // XK_slash+AE10+XK_0: VKEY_0
330 {0x002F, 0x13, 0x003F, 0xBF}, // XK_slash+AE10+XK_question: VKEY_OEM_2
331 {0x003D, 0x3D, 0x0025, 0xDF}, // XK_equal+AB10+XK_percent: VKEY_OEM_8
332 {0x003D, 0x3D, 0x002B, 0xBB}, // XK_equal+AB10+XK_plus: VKEY_OEM_PLUS
333 {0x005C, 0x33, 0x002F, 0xDE}, // XK_backslash+BKSL+XK_slash: VKEY_OEM_7
334 {0x005C, 0x33, 0x007C, 0xDC}, // XK_backslash+BKSL+XK_bar: VKEY_OEM_5
335 {0x0060, 0x31, 0x0000, 0xC0}, // XK_quoteleft+TLDE+NoSymbol: VKEY_OEM_3
336 {0x0060, 0x31, 0x00AC, 0xDF}, // XK_quoteleft+TLDE+XK_notsign: VKEY_OEM_8
337 {0x00A7, 0x31, 0x00B0, 0xBF}, // XK_section+TLDE+XK_degree: VKEY_OEM_2
338 {0x00A7, 0x31, 0x00BD, 0xDC}, // XK_section+TLDE+XK_onehalf: VKEY_OEM_5
339 {0x00E0, 0x30, 0x00B0, 0xDE}, // XK_agrave+AC11+XK_degree: VKEY_OEM_7
340 {0x00E0, 0x30, 0x00E4, 0xDC}, // XK_agrave+AC11+XK_adiaeresis: VKEY_OEM_5
341 {0x00E4, 0x30, 0x00E0, 0xDC}, // XK_adiaeresis+AC11+XK_agrave: VKEY_OEM_5
342 {0x00E9, 0x2F, 0x00C9, 0xBA}, // XK_eacute+AC10+XK_Eacute: VKEY_OEM_1
343 {0x00E9, 0x2F, 0x00F6, 0xDE}, // XK_eacute+AC10+XK_odiaeresis: VKEY_OEM_7
344 {0x00F6, 0x2F, 0x00E9, 0xDE}, // XK_odiaeresis+AC10+XK_eacute: VKEY_OEM_7
345 {0x00FC, 0x22, 0x00E8, 0xBA}, // XK_udiaeresis+AD11+XK_egrave: VKEY_OEM_1
354 bool operator()(const MAP3
& m1
, const MAP3
& m2
) const {
355 if (m1
.ch0
== m2
.ch0
&& m1
.sc
== m2
.sc
&& m1
.ch1
== m2
.ch1
)
356 return m1
.ch2
< m2
.ch2
;
357 if (m1
.ch0
== m2
.ch0
&& m1
.sc
== m2
.sc
)
358 return m1
.ch1
< m2
.ch1
;
359 if (m1
.ch0
== m2
.ch0
)
360 return m1
.sc
< m2
.sc
;
361 return m1
.ch0
< m2
.ch0
;
364 {0x0023, 0x33, 0x007E, 0x0000,
365 0xDE}, // XK_numbersign+BKSL+XK_asciitilde+NoSymbol: VKEY_OEM_7
366 {0x0027, 0x14, 0x003F, 0x0000,
367 0xDB}, // XK_quoteright+AE11+XK_question+NoSymbol: VKEY_OEM_4
368 {0x0027, 0x14, 0x003F, 0x00DD,
369 0xDB}, // XK_quoteright+AE11+XK_question+XK_Yacute: VKEY_OEM_4
370 {0x0027, 0x15, 0x002A, 0x0000,
371 0xBB}, // XK_quoteright+AE12+XK_asterisk+NoSymbol: VKEY_OEM_PLUS
372 {0x0027, 0x30, 0x0040, 0x0000,
373 0xC0}, // XK_quoteright+AC11+XK_at+NoSymbol: VKEY_OEM_3
374 {0x0027, 0x33, 0x002A, 0x0000,
375 0xBF}, // XK_quoteright+BKSL+XK_asterisk+NoSymbol: VKEY_OEM_2
376 {0x0027, 0x33, 0x002A, 0x00BD,
377 0xDC}, // XK_quoteright+BKSL+XK_asterisk+XK_onehalf: VKEY_OEM_5
378 {0x0027, 0x33, 0x002A, 0x01A3,
379 0xBF}, // XK_quoteright+BKSL+XK_asterisk+XK_Lstroke: VKEY_OEM_2
380 {0x0027, 0x34, 0x0022, 0x0000,
381 0x5A}, // XK_quoteright+AB01+XK_quotedbl+NoSymbol: VKEY_Z
382 {0x0027, 0x34, 0x0022, 0x01D8,
383 0xDE}, // XK_quoteright+AB01+XK_quotedbl+XK_Rcaron: VKEY_OEM_7
384 {0x002B, 0x14, 0x003F, 0x0000,
385 0xBB}, // XK_plus+AE11+XK_question+NoSymbol: VKEY_OEM_PLUS
386 {0x002B, 0x14, 0x003F, 0x005C,
387 0xBD}, // XK_plus+AE11+XK_question+XK_backslash: VKEY_OEM_MINUS
388 {0x002B, 0x14, 0x003F, 0x01F5,
389 0xBB}, // XK_plus+AE11+XK_question+XK_odoubleacute: VKEY_OEM_PLUS
390 {0x002D, 0x15, 0x005F, 0x0000,
391 0xBD}, // XK_minus+AE12+XK_underscore+NoSymbol: VKEY_OEM_MINUS
392 {0x002D, 0x15, 0x005F, 0x03B3,
393 0xDB}, // XK_minus+AE12+XK_underscore+XK_rcedilla: VKEY_OEM_4
394 {0x002D, 0x3D, 0x005F, 0x0000,
395 0xBD}, // XK_minus+AB10+XK_underscore+NoSymbol: VKEY_OEM_MINUS
396 {0x002D, 0x3D, 0x005F, 0x002A,
397 0xBD}, // XK_minus+AB10+XK_underscore+XK_asterisk: VKEY_OEM_MINUS
398 {0x002D, 0x3D, 0x005F, 0x002F,
399 0xBF}, // XK_minus+AB10+XK_underscore+XK_slash: VKEY_OEM_2
400 {0x002D, 0x3D, 0x005F, 0x006E,
401 0xBD}, // XK_minus+AB10+XK_underscore+XK_n: VKEY_OEM_MINUS
402 {0x003D, 0x14, 0x0025, 0x0000,
403 0xBB}, // XK_equal+AE11+XK_percent+NoSymbol: VKEY_OEM_PLUS
404 {0x003D, 0x14, 0x0025, 0x002D,
405 0xBD}, // XK_equal+AE11+XK_percent+XK_minus: VKEY_OEM_MINUS
406 {0x005C, 0x31, 0x007C, 0x0031,
407 0xDC}, // XK_backslash+TLDE+XK_bar+XK_1: VKEY_OEM_5
408 {0x005C, 0x31, 0x007C, 0x03D1,
409 0xC0}, // XK_backslash+TLDE+XK_bar+XK_Ncedilla: VKEY_OEM_3
410 {0x0060, 0x31, 0x007E, 0x0000,
411 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+NoSymbol: VKEY_OEM_3
412 {0x0060, 0x31, 0x007E, 0x0031,
413 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_1: VKEY_OEM_3
414 {0x0060, 0x31, 0x007E, 0x003B,
415 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_semicolon: VKEY_OEM_3
416 {0x0060, 0x31, 0x007E, 0x0060,
417 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_quoteleft: VKEY_OEM_3
418 {0x0060, 0x31, 0x007E, 0x00BF,
419 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_questiondown: VKEY_OEM_3
420 {0x0060, 0x31, 0x007E, 0x01F5,
421 0xC0}, // XK_quoteleft+TLDE+XK_asciitilde+XK_odoubleacute: VKEY_OEM_3
422 {0x00E4, 0x30, 0x00C4, 0x0000,
423 0xDE}, // XK_adiaeresis+AC11+XK_Adiaeresis+NoSymbol: VKEY_OEM_7
424 {0x00E4, 0x30, 0x00C4, 0x01A6,
425 0xDE}, // XK_adiaeresis+AC11+XK_Adiaeresis+XK_Sacute: VKEY_OEM_7
426 {0x00E4, 0x30, 0x00C4, 0x01F8,
427 0xDE}, // XK_adiaeresis+AC11+XK_Adiaeresis+XK_rcaron: VKEY_OEM_7
428 {0x00E7, 0x2F, 0x00C7, 0x0000,
429 0xBA}, // XK_ccedilla+AC10+XK_Ccedilla+NoSymbol: VKEY_OEM_1
430 {0x00E7, 0x2F, 0x00C7, 0x00DE,
431 0xC0}, // XK_ccedilla+AC10+XK_Ccedilla+XK_Thorn: VKEY_OEM_3
432 {0x00F6, 0x2F, 0x00D6, 0x0000,
433 0xC0}, // XK_odiaeresis+AC10+XK_Odiaeresis+NoSymbol: VKEY_OEM_3
434 {0x00F6, 0x2F, 0x00D6, 0x01DE,
435 0xC0}, // XK_odiaeresis+AC10+XK_Odiaeresis+XK_Tcedilla: VKEY_OEM_3
436 {0x00FC, 0x14, 0x00DC, 0x0000,
437 0xBF}, // XK_udiaeresis+AE11+XK_Udiaeresis+NoSymbol: VKEY_OEM_2
438 {0x00FC, 0x22, 0x00DC, 0x0000,
439 0xBA}, // XK_udiaeresis+AD11+XK_Udiaeresis+NoSymbol: VKEY_OEM_1
440 {0x00FC, 0x22, 0x00DC, 0x01A3,
441 0xC0}, // XK_udiaeresis+AD11+XK_Udiaeresis+XK_Lstroke: VKEY_OEM_3
442 {0x01EA, 0x3D, 0x01CA, 0x0000,
443 0xBD}, // XK_eogonek+AB10+XK_Eogonek+NoSymbol: VKEY_OEM_MINUS
444 {0x01EA, 0x3D, 0x01CA, 0x006E,
445 0xBF}, // XK_eogonek+AB10+XK_Eogonek+XK_n: VKEY_OEM_2
446 {0x03E7, 0x22, 0x03C7, 0x0000,
447 0xDB}, // XK_iogonek+AD11+XK_Iogonek+NoSymbol: VKEY_OEM_4
448 {0x03F9, 0x2F, 0x03D9, 0x0000,
449 0xC0}, // XK_uogonek+AC10+XK_Uogonek+NoSymbol: VKEY_OEM_3
450 {0x03F9, 0x2F, 0x03D9, 0x01DE,
451 0xBA}, // XK_uogonek+AC10+XK_Uogonek+XK_Tcedilla: VKEY_OEM_1
454 template <class T_MAP
>
455 KeyboardCode
FindVK(const T_MAP
& key
, const T_MAP
* map
, size_t size
) {
457 const T_MAP
* p
= std::lower_bound(map
, map
+ size
, key
, comp
);
458 if (p
!= map
+ size
&& !comp(*p
, key
) && !comp(key
, *p
))
459 return static_cast<KeyboardCode
>(p
->vk
);
463 // Check for TTY function keys or space key which should always be mapped
464 // based on KeySym, and never fall back to MAP0~MAP3, since some layouts
465 // generate them by applying the Control/AltGr modifier to some other key.
466 // e.g. in de(neo), AltGr+V generates XK_Enter.
467 bool IsTtyFunctionOrSpaceKey(KeySym keysym
) {
482 for (size_t i
= 0; i
< arraysize(keysyms
); ++i
) {
483 if (keysyms
[i
] == keysym
)
491 // Get an ui::KeyboardCode from an X keyevent
492 KeyboardCode
KeyboardCodeFromXKeyEvent(const XEvent
* xev
) {
493 // Gets correct VKEY code from XEvent is performed as the following steps:
494 // 1. Gets the keysym without modifier states.
495 // 2. For [a-z] & [0-9] cases, returns the VKEY code accordingly.
496 // 3. Find keysym in map0.
497 // 4. If not found, fallback to find keysym + hardware_code in map1.
498 // 5. If not found, fallback to find keysym + keysym_shift + hardware_code
500 // 6. If not found, fallback to find keysym + keysym_shift + keysym_altgr +
501 // hardware_code in map3.
502 // 7. If not found, fallback to find in KeyboardCodeFromXKeysym(), which
503 // mainly for non-letter keys.
504 // 8. If not found, fallback to find with the hardware code in US layout.
506 KeySym keysym
= NoSymbol
;
507 XEvent xkeyevent
= {0};
508 if (xev
->type
== GenericEvent
) {
509 // Convert the XI2 key event into a core key event so that we can
510 // continue to use XLookupString() until crbug.com/367732 is complete.
511 InitXKeyEventFromXIDeviceEvent(*xev
, &xkeyevent
);
513 xkeyevent
.xkey
= xev
->xkey
;
515 KeyboardCode keycode
= VKEY_UNKNOWN
;
516 XKeyEvent
* xkey
= &xkeyevent
.xkey
;
517 // XLookupKeysym does not take into consideration the state of the lock/shift
518 // etc. keys. So it is necessary to use XLookupString instead.
519 XLookupString(xkey
, NULL
, 0, &keysym
, NULL
);
520 if (IsKeypadKey(keysym
) || IsPrivateKeypadKey(keysym
) ||
521 IsCursorKey(keysym
) || IsPFKey(keysym
) || IsFunctionKey(keysym
) ||
522 IsModifierKey(keysym
) || IsTtyFunctionOrSpaceKey(keysym
)) {
523 return KeyboardCodeFromXKeysym(keysym
);
526 // If |xkey| has modifiers set, other than NumLock, then determine the
527 // un-modified KeySym and use that to map, so that e.g. Ctrl+D correctly
529 if (xkey
->state
& 0xFF & ~Mod2Mask
) {
530 xkey
->state
&= (~0xFF | Mod2Mask
);
531 XLookupString(xkey
, NULL
, 0, &keysym
, NULL
);
535 if (keysym
>= XK_a
&& keysym
<= XK_z
)
536 return static_cast<KeyboardCode
>(VKEY_A
+ keysym
- XK_a
);
539 if (keysym
>= XK_0
&& keysym
<= XK_9
)
540 return static_cast<KeyboardCode
>(VKEY_0
+ keysym
- XK_0
);
542 if (!IsKeypadKey(keysym
) && !IsPrivateKeypadKey(keysym
) &&
543 !IsCursorKey(keysym
) && !IsPFKey(keysym
) && !IsFunctionKey(keysym
) &&
544 !IsModifierKey(keysym
)) {
545 MAP0 key0
= {keysym
& 0xFFFF, 0};
546 keycode
= FindVK(key0
, map0
, arraysize(map0
));
547 if (keycode
!= VKEY_UNKNOWN
)
550 MAP1 key1
= {keysym
& 0xFFFF, xkey
->keycode
, 0};
551 keycode
= FindVK(key1
, map1
, arraysize(map1
));
552 if (keycode
!= VKEY_UNKNOWN
)
555 KeySym keysym_shift
= NoSymbol
;
556 xkey
->state
|= ShiftMask
;
557 XLookupString(xkey
, NULL
, 0, &keysym_shift
, NULL
);
558 MAP2 key2
= {keysym
& 0xFFFF, xkey
->keycode
, keysym_shift
& 0xFFFF, 0};
559 keycode
= FindVK(key2
, map2
, arraysize(map2
));
560 if (keycode
!= VKEY_UNKNOWN
)
563 KeySym keysym_altgr
= NoSymbol
;
564 xkey
->state
&= ~ShiftMask
;
565 xkey
->state
|= Mod1Mask
;
566 XLookupString(xkey
, NULL
, 0, &keysym_altgr
, NULL
);
567 MAP3 key3
= {keysym
& 0xFFFF, xkey
->keycode
, keysym_shift
& 0xFFFF,
568 keysym_altgr
& 0xFFFF, 0};
569 keycode
= FindVK(key3
, map3
, arraysize(map3
));
570 if (keycode
!= VKEY_UNKNOWN
)
573 // On Linux some keys has AltGr char but not on Windows.
574 // So if cannot find VKEY with (ch0+sc+ch1+ch2) in map3, tries to fallback
575 // to just find VKEY with (ch0+sc+ch1). This is the best we could do.
576 MAP3 key4
= {keysym
& 0xFFFF, xkey
->keycode
, keysym_shift
& 0xFFFF, 0,
579 std::lower_bound(map3
, map3
+ arraysize(map3
), key4
, MAP3());
580 if (p
!= map3
+ arraysize(map3
) && p
->ch0
== key4
.ch0
&& p
->sc
== key4
.sc
&&
582 return static_cast<KeyboardCode
>(p
->vk
);
585 keycode
= KeyboardCodeFromXKeysym(keysym
);
586 if (keycode
== VKEY_UNKNOWN
&& !IsModifierKey(keysym
)) {
587 // Modifier keys should not fall back to the hardware-keycode-based US
588 // layout. See crbug.com/402320
589 keycode
= DefaultKeyboardCodeFromHardwareKeycode(xkey
->keycode
);
595 KeyboardCode
KeyboardCodeFromXKeysym(unsigned int keysym
) {
596 // TODO(sad): Have |keysym| go through the X map list?
606 case XK_ISO_Left_Tab
:
607 case XK_3270_BackTab
:
615 case XK_KP_Begin
: // NumPad 5 without Num Lock, for crosbug.com/29169.
627 case XK_KP_Page_Up
: // aka XK_KP_Prior
630 case XK_KP_Page_Down
: // aka XK_KP_Next
651 case XK_Hangul_Hanja
:
658 return VKEY_NONCONVERT
;
659 case XK_Zenkaku_Hankaku
:
660 return VKEY_DBE_DBCSCHAR
;
672 return static_cast<KeyboardCode
>(VKEY_NUMPAD0
+ (keysym
- XK_KP_0
));
676 return VKEY_MULTIPLY
;
679 case XK_KP_Separator
:
680 return VKEY_SEPARATOR
;
682 return VKEY_SUBTRACT
;
690 return VKEY_OEM_PLUS
;
693 return VKEY_OEM_COMMA
;
696 return VKEY_OEM_MINUS
;
699 return VKEY_OEM_PERIOD
;
715 case XK_bracketright
:
721 case XK_ISO_Level5_Shift
:
734 case XK_ISO_Level3_Shift
:
788 return static_cast<KeyboardCode
>(VKEY_F1
+ (keysym
- XK_F1
));
793 return static_cast<KeyboardCode
>(VKEY_F1
+ (keysym
- XK_KP_F1
));
795 case XK_guillemotleft
:
796 case XK_guillemotright
:
798 // In the case of canadian multilingual keyboard layout, VKEY_OEM_102 is
799 // assigned to ugrave key.
803 return VKEY_OEM_102
; // international backslash key in 102 keyboard.
805 // When evdev is in use, /usr/share/X11/xkb/symbols/inet maps F13-18 keys
806 // to the special XF86XK symbols to support Microsoft Ergonomic keyboards:
807 // https://bugs.freedesktop.org/show_bug.cgi?id=5783
808 // In Chrome, we map these X key symbols back to F13-18 since we don't have
809 // VKEYs for these XF86XK symbols.
823 // For supporting multimedia buttons on a USB keyboard.
825 return VKEY_BROWSER_BACK
;
827 return VKEY_BROWSER_FORWARD
;
829 return VKEY_BROWSER_REFRESH
;
831 return VKEY_BROWSER_STOP
;
833 return VKEY_BROWSER_SEARCH
;
834 case XF86XK_Favorites
:
835 return VKEY_BROWSER_FAVORITES
;
836 case XF86XK_HomePage
:
837 return VKEY_BROWSER_HOME
;
838 case XF86XK_AudioMute
:
839 return VKEY_VOLUME_MUTE
;
840 case XF86XK_AudioLowerVolume
:
841 return VKEY_VOLUME_DOWN
;
842 case XF86XK_AudioRaiseVolume
:
843 return VKEY_VOLUME_UP
;
844 case XF86XK_AudioNext
:
845 return VKEY_MEDIA_NEXT_TRACK
;
846 case XF86XK_AudioPrev
:
847 return VKEY_MEDIA_PREV_TRACK
;
848 case XF86XK_AudioStop
:
849 return VKEY_MEDIA_STOP
;
850 case XF86XK_AudioPlay
:
851 return VKEY_MEDIA_PLAY_PAUSE
;
853 return VKEY_MEDIA_LAUNCH_MAIL
;
854 case XF86XK_LaunchA
: // F3 on an Apple keyboard.
855 return VKEY_MEDIA_LAUNCH_APP1
;
856 case XF86XK_LaunchB
: // F4 on an Apple keyboard.
857 case XF86XK_Calculator
:
858 return VKEY_MEDIA_LAUNCH_APP2
;
861 case XF86XK_PowerOff
:
865 case XF86XK_MonBrightnessDown
:
866 return VKEY_BRIGHTNESS_DOWN
;
867 case XF86XK_MonBrightnessUp
:
868 return VKEY_BRIGHTNESS_UP
;
869 case XF86XK_KbdBrightnessDown
:
870 return VKEY_KBD_BRIGHTNESS_DOWN
;
871 case XF86XK_KbdBrightnessUp
:
872 return VKEY_KBD_BRIGHTNESS_UP
;
874 // TODO(sad): some keycodes are still missing.
876 DVLOG(1) << "Unknown keysym: " << base::StringPrintf("0x%x", keysym
);
880 DomCode
CodeFromXEvent(const XEvent
* xev
) {
881 int keycode
= (xev
->type
== GenericEvent
)
882 ? static_cast<XIDeviceEvent
*>(xev
->xcookie
.data
)->detail
884 return ui::KeycodeConverter::NativeKeycodeToDomCode(keycode
);
887 uint16
GetCharacterFromXEvent(const XEvent
* xev
) {
888 XEvent xkeyevent
= {0};
889 const XKeyEvent
* xkey
= NULL
;
890 if (xev
->type
== GenericEvent
) {
891 // Convert the XI2 key event into a core key event so that we can
892 // continue to use XLookupString() until crbug.com/367732 is complete.
893 InitXKeyEventFromXIDeviceEvent(*xev
, &xkeyevent
);
894 xkey
= &xkeyevent
.xkey
;
898 KeySym keysym
= XK_VoidSymbol
;
899 XLookupString(const_cast<XKeyEvent
*>(xkey
), NULL
, 0, &keysym
, NULL
);
900 return GetUnicodeCharacterFromXKeySym(keysym
);
903 void GetMeaningFromXEvent(const XEvent
* xev
, DomKey
* key
, base::char16
* ch
) {
904 XEvent xkeyevent
= {0};
905 const XKeyEvent
* xkey
= NULL
;
906 if (xev
->type
== GenericEvent
) {
907 // Convert the XI2 key event into a core key event so that we can
908 // continue to use XLookupString() until crbug.com/367732 is complete.
909 InitXKeyEventFromXIDeviceEvent(*xev
, &xkeyevent
);
910 xkey
= &xkeyevent
.xkey
;
914 KeySym keysym
= XK_VoidSymbol
;
915 XLookupString(const_cast<XKeyEvent
*>(xkey
), NULL
, 0, &keysym
, NULL
);
916 *ch
= GetUnicodeCharacterFromXKeySym(keysym
);
917 *key
= XKeySymToDomKey(keysym
, *ch
);
920 KeyboardCode
DefaultKeyboardCodeFromHardwareKeycode(
921 unsigned int hardware_code
) {
922 // This function assumes that X11 is using evdev-based keycodes.
923 static const KeyboardCode kHardwareKeycodeMap
[] = {
924 // Please refer to below links for the table content:
925 // http://www.w3.org/TR/DOM-Level-3-Events-code/#keyboard-101
926 // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode
927 // http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
928 VKEY_UNKNOWN
, // 0x00:
929 VKEY_UNKNOWN
, // 0x01:
930 VKEY_UNKNOWN
, // 0x02:
931 VKEY_UNKNOWN
, // 0x03:
932 VKEY_UNKNOWN
, // 0x04:
933 VKEY_UNKNOWN
, // 0x05:
934 VKEY_UNKNOWN
, // 0x06:
935 VKEY_UNKNOWN
, // XKB evdev (XKB - 8) X KeySym
936 VKEY_UNKNOWN
, // === =============== ======
937 VKEY_ESCAPE
, // 0x09: KEY_ESC Escape
938 VKEY_1
, // 0x0A: KEY_1 1
939 VKEY_2
, // 0x0B: KEY_2 2
940 VKEY_3
, // 0x0C: KEY_3 3
941 VKEY_4
, // 0x0D: KEY_4 4
942 VKEY_5
, // 0x0E: KEY_5 5
943 VKEY_6
, // 0x0F: KEY_6 6
944 VKEY_7
, // 0x10: KEY_7 7
945 VKEY_8
, // 0x11: KEY_8 8
946 VKEY_9
, // 0x12: KEY_9 9
947 VKEY_0
, // 0x13: KEY_0 0
948 VKEY_OEM_MINUS
, // 0x14: KEY_MINUS minus
949 VKEY_OEM_PLUS
, // 0x15: KEY_EQUAL equal
950 VKEY_BACK
, // 0x16: KEY_BACKSPACE BackSpace
951 VKEY_TAB
, // 0x17: KEY_TAB Tab
952 VKEY_Q
, // 0x18: KEY_Q q
953 VKEY_W
, // 0x19: KEY_W w
954 VKEY_E
, // 0x1A: KEY_E e
955 VKEY_R
, // 0x1B: KEY_R r
956 VKEY_T
, // 0x1C: KEY_T t
957 VKEY_Y
, // 0x1D: KEY_Y y
958 VKEY_U
, // 0x1E: KEY_U u
959 VKEY_I
, // 0x1F: KEY_I i
960 VKEY_O
, // 0x20: KEY_O o
961 VKEY_P
, // 0x21: KEY_P p
962 VKEY_OEM_4
, // 0x22: KEY_LEFTBRACE bracketleft
963 VKEY_OEM_6
, // 0x23: KEY_RIGHTBRACE bracketright
964 VKEY_RETURN
, // 0x24: KEY_ENTER Return
965 VKEY_LCONTROL
, // 0x25: KEY_LEFTCTRL Control_L
966 VKEY_A
, // 0x26: KEY_A a
967 VKEY_S
, // 0x27: KEY_S s
968 VKEY_D
, // 0x28: KEY_D d
969 VKEY_F
, // 0x29: KEY_F f
970 VKEY_G
, // 0x2A: KEY_G g
971 VKEY_H
, // 0x2B: KEY_H h
972 VKEY_J
, // 0x2C: KEY_J j
973 VKEY_K
, // 0x2D: KEY_K k
974 VKEY_L
, // 0x2E: KEY_L l
975 VKEY_OEM_1
, // 0x2F: KEY_SEMICOLON semicolon
976 VKEY_OEM_7
, // 0x30: KEY_APOSTROPHE apostrophe
977 VKEY_OEM_3
, // 0x31: KEY_GRAVE grave
978 VKEY_LSHIFT
, // 0x32: KEY_LEFTSHIFT Shift_L
979 VKEY_OEM_5
, // 0x33: KEY_BACKSLASH backslash
980 VKEY_Z
, // 0x34: KEY_Z z
981 VKEY_X
, // 0x35: KEY_X x
982 VKEY_C
, // 0x36: KEY_C c
983 VKEY_V
, // 0x37: KEY_V v
984 VKEY_B
, // 0x38: KEY_B b
985 VKEY_N
, // 0x39: KEY_N n
986 VKEY_M
, // 0x3A: KEY_M m
987 VKEY_OEM_COMMA
, // 0x3B: KEY_COMMA comma
988 VKEY_OEM_PERIOD
, // 0x3C: KEY_DOT period
989 VKEY_OEM_2
, // 0x3D: KEY_SLASH slash
990 VKEY_RSHIFT
, // 0x3E: KEY_RIGHTSHIFT Shift_R
991 VKEY_MULTIPLY
, // 0x3F: KEY_KPASTERISK KP_Multiply
992 VKEY_LMENU
, // 0x40: KEY_LEFTALT Alt_L
993 VKEY_SPACE
, // 0x41: KEY_SPACE space
994 VKEY_CAPITAL
, // 0x42: KEY_CAPSLOCK Caps_Lock
995 VKEY_F1
, // 0x43: KEY_F1 F1
996 VKEY_F2
, // 0x44: KEY_F2 F2
997 VKEY_F3
, // 0x45: KEY_F3 F3
998 VKEY_F4
, // 0x46: KEY_F4 F4
999 VKEY_F5
, // 0x47: KEY_F5 F5
1000 VKEY_F6
, // 0x48: KEY_F6 F6
1001 VKEY_F7
, // 0x49: KEY_F7 F7
1002 VKEY_F8
, // 0x4A: KEY_F8 F8
1003 VKEY_F9
, // 0x4B: KEY_F9 F9
1004 VKEY_F10
, // 0x4C: KEY_F10 F10
1005 VKEY_NUMLOCK
, // 0x4D: KEY_NUMLOCK Num_Lock
1006 VKEY_SCROLL
, // 0x4E: KEY_SCROLLLOCK Scroll_Lock
1007 VKEY_NUMPAD7
, // 0x4F: KEY_KP7 KP_7
1008 VKEY_NUMPAD8
, // 0x50: KEY_KP8 KP_8
1009 VKEY_NUMPAD9
, // 0x51: KEY_KP9 KP_9
1010 VKEY_SUBTRACT
, // 0x52: KEY_KPMINUS KP_Subtract
1011 VKEY_NUMPAD4
, // 0x53: KEY_KP4 KP_4
1012 VKEY_NUMPAD5
, // 0x54: KEY_KP5 KP_5
1013 VKEY_NUMPAD6
, // 0x55: KEY_KP6 KP_6
1014 VKEY_ADD
, // 0x56: KEY_KPPLUS KP_Add
1015 VKEY_NUMPAD1
, // 0x57: KEY_KP1 KP_1
1016 VKEY_NUMPAD2
, // 0x58: KEY_KP2 KP_2
1017 VKEY_NUMPAD3
, // 0x59: KEY_KP3 KP_3
1018 VKEY_NUMPAD0
, // 0x5A: KEY_KP0 KP_0
1019 VKEY_DECIMAL
, // 0x5B: KEY_KPDOT KP_Decimal
1020 VKEY_UNKNOWN
, // 0x5C:
1021 VKEY_DBE_DBCSCHAR
, // 0x5D: KEY_ZENKAKUHANKAKU Zenkaku_Hankaku
1022 VKEY_OEM_5
, // 0x5E: KEY_102ND backslash
1023 VKEY_F11
, // 0x5F: KEY_F11 F11
1024 VKEY_F12
, // 0x60: KEY_F12 F12
1025 VKEY_OEM_102
, // 0x61: KEY_RO Romaji
1026 VKEY_UNSUPPORTED
, // 0x62: KEY_KATAKANA Katakana
1027 VKEY_UNSUPPORTED
, // 0x63: KEY_HIRAGANA Hiragana
1028 VKEY_CONVERT
, // 0x64: KEY_HENKAN Henkan
1029 VKEY_UNSUPPORTED
, // 0x65: KEY_KATAKANAHIRAGANA Hiragana_Katakana
1030 VKEY_NONCONVERT
, // 0x66: KEY_MUHENKAN Muhenkan
1031 VKEY_SEPARATOR
, // 0x67: KEY_KPJPCOMMA KP_Separator
1032 VKEY_RETURN
, // 0x68: KEY_KPENTER KP_Enter
1033 VKEY_RCONTROL
, // 0x69: KEY_RIGHTCTRL Control_R
1034 VKEY_DIVIDE
, // 0x6A: KEY_KPSLASH KP_Divide
1035 VKEY_PRINT
, // 0x6B: KEY_SYSRQ Print
1036 VKEY_RMENU
, // 0x6C: KEY_RIGHTALT Alt_R
1037 VKEY_RETURN
, // 0x6D: KEY_LINEFEED Linefeed
1038 VKEY_HOME
, // 0x6E: KEY_HOME Home
1039 VKEY_UP
, // 0x6F: KEY_UP Up
1040 VKEY_PRIOR
, // 0x70: KEY_PAGEUP Page_Up
1041 VKEY_LEFT
, // 0x71: KEY_LEFT Left
1042 VKEY_RIGHT
, // 0x72: KEY_RIGHT Right
1043 VKEY_END
, // 0x73: KEY_END End
1044 VKEY_DOWN
, // 0x74: KEY_DOWN Down
1045 VKEY_NEXT
, // 0x75: KEY_PAGEDOWN Page_Down
1046 VKEY_INSERT
, // 0x76: KEY_INSERT Insert
1047 VKEY_DELETE
, // 0x77: KEY_DELETE Delete
1048 VKEY_UNSUPPORTED
, // 0x78: KEY_MACRO
1049 VKEY_VOLUME_MUTE
, // 0x79: KEY_MUTE XF86AudioMute
1050 VKEY_VOLUME_DOWN
, // 0x7A: KEY_VOLUMEDOWN XF86AudioLowerVolume
1051 VKEY_VOLUME_UP
, // 0x7B: KEY_VOLUMEUP XF86AudioRaiseVolume
1052 VKEY_POWER
, // 0x7C: KEY_POWER XF86PowerOff
1053 VKEY_OEM_PLUS
, // 0x7D: KEY_KPEQUAL KP_Equal
1054 VKEY_UNSUPPORTED
, // 0x7E: KEY_KPPLUSMINUS plusminus
1055 VKEY_PAUSE
, // 0x7F: KEY_PAUSE Pause
1056 VKEY_MEDIA_LAUNCH_APP1
, // 0x80: KEY_SCALE XF86LaunchA
1057 VKEY_DECIMAL
, // 0x81: KEY_KPCOMMA KP_Decimal
1058 VKEY_HANGUL
, // 0x82: KEY_HANGUEL Hangul
1059 VKEY_HANJA
, // 0x83: KEY_HANJA Hangul_Hanja
1060 VKEY_OEM_5
, // 0x84: KEY_YEN yen
1061 VKEY_LWIN
, // 0x85: KEY_LEFTMETA Super_L
1062 VKEY_RWIN
, // 0x86: KEY_RIGHTMETA Super_R
1063 VKEY_COMPOSE
, // 0x87: KEY_COMPOSE Menu
1066 if (hardware_code
>= arraysize(kHardwareKeycodeMap
)) {
1067 // Additional keycodes used by the Chrome OS top row special function keys.
1068 switch (hardware_code
) {
1069 case 0xA6: // KEY_BACK
1071 case 0xA7: // KEY_FORWARD
1072 return VKEY_BROWSER_FORWARD
;
1073 case 0xB5: // KEY_REFRESH
1074 return VKEY_BROWSER_REFRESH
;
1075 case 0xD4: // KEY_DASHBOARD
1076 return VKEY_MEDIA_LAUNCH_APP2
;
1077 case 0xE8: // KEY_BRIGHTNESSDOWN
1078 return VKEY_BRIGHTNESS_DOWN
;
1079 case 0xE9: // KEY_BRIGHTNESSUP
1080 return VKEY_BRIGHTNESS_UP
;
1082 return VKEY_UNKNOWN
;
1084 return kHardwareKeycodeMap
[hardware_code
];
1087 // TODO(jcampan): this method might be incomplete.
1088 int XKeysymForWindowsKeyCode(KeyboardCode keycode
, bool shift
) {
1111 return XK_KP_Multiply
;
1115 return XK_KP_Subtract
;
1117 return XK_KP_Decimal
;
1119 return XK_KP_Divide
;
1122 return XK_BackSpace
;
1124 return shift
? XK_ISO_Left_Tab
: XK_Tab
;
1132 return XK_Control_L
;
1138 return XK_ISO_Level3_Shift
;
1140 return XK_Multi_key
;
1145 return XK_Caps_Lock
;
1147 return XK_Kana_Lock
;
1149 return XK_Hangul_Hanja
;
1152 case VKEY_NONCONVERT
:
1154 case VKEY_DBE_SBCSCHAR
:
1155 return XK_Zenkaku_Hankaku
;
1156 case VKEY_DBE_DBCSCHAR
:
1157 return XK_Zenkaku_Hankaku
;
1165 return XK_Page_Down
;
1191 return shift
? XK_parenright
: XK_0
;
1193 return shift
? XK_exclam
: XK_1
;
1195 return shift
? XK_at
: XK_2
;
1197 return shift
? XK_numbersign
: XK_3
;
1199 return shift
? XK_dollar
: XK_4
;
1201 return shift
? XK_percent
: XK_5
;
1203 return shift
? XK_asciicircum
: XK_6
;
1205 return shift
? XK_ampersand
: XK_7
;
1207 return shift
? XK_asterisk
: XK_8
;
1209 return shift
? XK_parenleft
: XK_9
;
1237 return (shift
? XK_A
: XK_a
) + (keycode
- VKEY_A
);
1248 return XK_Scroll_Lock
;
1251 return shift
? XK_colon
: XK_semicolon
;
1253 return shift
? XK_plus
: XK_equal
;
1254 case VKEY_OEM_COMMA
:
1255 return shift
? XK_less
: XK_comma
;
1256 case VKEY_OEM_MINUS
:
1257 return shift
? XK_underscore
: XK_minus
;
1258 case VKEY_OEM_PERIOD
:
1259 return shift
? XK_greater
: XK_period
;
1261 return shift
? XK_question
: XK_slash
;
1263 return shift
? XK_asciitilde
: XK_quoteleft
;
1265 return shift
? XK_braceleft
: XK_bracketleft
;
1267 return shift
? XK_bar
: XK_backslash
;
1269 return shift
? XK_braceright
: XK_bracketright
;
1271 return shift
? XK_quotedbl
: XK_quoteright
;
1273 return XK_ISO_Level5_Shift
;
1275 return shift
? XK_guillemotleft
: XK_guillemotright
;
1301 return XK_F1
+ (keycode
- VKEY_F1
);
1303 case VKEY_BROWSER_BACK
:
1305 case VKEY_BROWSER_FORWARD
:
1306 return XF86XK_Forward
;
1307 case VKEY_BROWSER_REFRESH
:
1308 return XF86XK_Reload
;
1309 case VKEY_BROWSER_STOP
:
1311 case VKEY_BROWSER_SEARCH
:
1312 return XF86XK_Search
;
1313 case VKEY_BROWSER_FAVORITES
:
1314 return XF86XK_Favorites
;
1315 case VKEY_BROWSER_HOME
:
1316 return XF86XK_HomePage
;
1317 case VKEY_VOLUME_MUTE
:
1318 return XF86XK_AudioMute
;
1319 case VKEY_VOLUME_DOWN
:
1320 return XF86XK_AudioLowerVolume
;
1321 case VKEY_VOLUME_UP
:
1322 return XF86XK_AudioRaiseVolume
;
1323 case VKEY_MEDIA_NEXT_TRACK
:
1324 return XF86XK_AudioNext
;
1325 case VKEY_MEDIA_PREV_TRACK
:
1326 return XF86XK_AudioPrev
;
1327 case VKEY_MEDIA_STOP
:
1328 return XF86XK_AudioStop
;
1329 case VKEY_MEDIA_PLAY_PAUSE
:
1330 return XF86XK_AudioPlay
;
1331 case VKEY_MEDIA_LAUNCH_MAIL
:
1333 case VKEY_MEDIA_LAUNCH_APP1
:
1334 return XF86XK_LaunchA
;
1335 case VKEY_MEDIA_LAUNCH_APP2
:
1336 return XF86XK_LaunchB
;
1340 return XF86XK_PowerOff
;
1341 case VKEY_BRIGHTNESS_DOWN
:
1342 return XF86XK_MonBrightnessDown
;
1343 case VKEY_BRIGHTNESS_UP
:
1344 return XF86XK_MonBrightnessUp
;
1345 case VKEY_KBD_BRIGHTNESS_DOWN
:
1346 return XF86XK_KbdBrightnessDown
;
1347 case VKEY_KBD_BRIGHTNESS_UP
:
1348 return XF86XK_KbdBrightnessUp
;
1351 LOG(WARNING
) << "Unknown keycode:" << keycode
;
1356 void InitXKeyEventFromXIDeviceEvent(const XEvent
& src
, XEvent
* xkeyevent
) {
1357 DCHECK(src
.type
== GenericEvent
);
1358 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(src
.xcookie
.data
);
1359 switch (xievent
->evtype
) {
1361 xkeyevent
->type
= KeyPress
;
1364 xkeyevent
->type
= KeyRelease
;
1369 xkeyevent
->xkey
.serial
= xievent
->serial
;
1370 xkeyevent
->xkey
.send_event
= xievent
->send_event
;
1371 xkeyevent
->xkey
.display
= xievent
->display
;
1372 xkeyevent
->xkey
.window
= xievent
->event
;
1373 xkeyevent
->xkey
.root
= xievent
->root
;
1374 xkeyevent
->xkey
.subwindow
= xievent
->child
;
1375 xkeyevent
->xkey
.time
= xievent
->time
;
1376 xkeyevent
->xkey
.x
= xievent
->event_x
;
1377 xkeyevent
->xkey
.y
= xievent
->event_y
;
1378 xkeyevent
->xkey
.x_root
= xievent
->root_x
;
1379 xkeyevent
->xkey
.y_root
= xievent
->root_y
;
1380 xkeyevent
->xkey
.state
= xievent
->mods
.effective
;
1381 xkeyevent
->xkey
.keycode
= xievent
->detail
;
1382 xkeyevent
->xkey
.same_screen
= 1;
1385 unsigned int XKeyCodeForWindowsKeyCode(ui::KeyboardCode key_code
,
1387 XDisplay
* display
) {
1388 // SHIFT state is ignored in the call to XKeysymForWindowsKeyCode() here
1389 // because we map the XKeysym back to a keycode, i.e. a physical key position.
1390 // Using a SHIFT-modified XKeysym would sometimes yield X keycodes that,
1391 // while technically valid, may be surprising in that they do not match
1392 // the keycode of the original press, and conflict with assumptions in
1395 // For example, in a US layout, Shift-9 has the interpretation XK_parenleft,
1396 // but the keycode KEY_9 alone does not map to XK_parenleft; instead,
1397 // XKeysymToKeycode() returns KEY_KPLEFTPAREN (keypad left parenthesis)
1398 // which does map to XK_parenleft -- notwithstanding that keyboards with
1399 // dedicated number pad parenthesis keys are currently uncommon.
1401 // Similarly, Shift-Comma has the interpretation XK_less, but KEY_COMMA
1402 // alone does not map to XK_less; XKeysymToKeycode() returns KEY_102ND
1403 // (the '<>' key between Shift and Z on 105-key keyboards) which does.
1405 // crbug.com/386066 and crbug.com/390263 are examples of problems
1406 // associated with this.
1408 return XKeysymToKeycode(display
, XKeysymForWindowsKeyCode(key_code
, false));