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