• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
operator ()ui::__anon80b8e3d40111::MAP061   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;
operator ()ui::__anon80b8e3d40111::MAP1122   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;
operator ()ui::__anon80b8e3d40111::MAP2308   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;
operator ()ui::__anon80b8e3d40111::MAP3353   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>
FindVK(const T_MAP & key,const T_MAP * map,size_t size)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
KeyboardCodeFromXKeyEvent(const XEvent * xev)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 
KeyboardCodeFromXKeysym(unsigned int keysym)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 
CodeFromXEvent(const XEvent * xev)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 
GetCharacterFromXEvent(const XEvent * xev)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 
DefaultKeyboardCodeFromHardwareKeycode(unsigned int hardware_code)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.
XKeysymForWindowsKeyCode(KeyboardCode keycode,bool shift)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 
InitXKeyEventFromXIDeviceEvent(const XEvent & src,XEvent * xkeyevent)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 
XKeyCodeForWindowsKeyCode(ui::KeyboardCode key_code,int flags,XDisplay * display)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