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