/src/mpv/input/keycodes.c
Line | Count | Source |
1 | | /* |
2 | | * This file is part of mpv. |
3 | | * |
4 | | * mpv is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Lesser General Public |
6 | | * License as published by the Free Software Foundation; either |
7 | | * version 2.1 of the License, or (at your option) any later version. |
8 | | * |
9 | | * mpv is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | * GNU Lesser General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Lesser General Public |
15 | | * License along with mpv. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | #include <limits.h> |
19 | | #include <stddef.h> |
20 | | #include <string.h> |
21 | | |
22 | | #include "misc/bstr.h" |
23 | | #include "common/common.h" |
24 | | #include "common/msg.h" |
25 | | |
26 | | #include "keycodes.h" |
27 | | |
28 | | struct key_name { |
29 | | int key; |
30 | | char *name; |
31 | | }; |
32 | | |
33 | | /// The names of the keys as used in input.conf |
34 | | /// If you add some new keys, you also need to add them here |
35 | | |
36 | | static const struct key_name key_names[] = { |
37 | | { ' ', "SPACE" }, |
38 | | { '#', "SHARP" }, |
39 | | { 0x3000, "IDEOGRAPHIC_SPACE" }, |
40 | | { MP_KEY_ENTER, "ENTER" }, |
41 | | { MP_KEY_TAB, "TAB" }, |
42 | | { MP_KEY_BACKSPACE, "BS" }, |
43 | | { MP_KEY_DELETE, "DEL" }, |
44 | | { MP_KEY_INSERT, "INS" }, |
45 | | { MP_KEY_HOME, "HOME" }, |
46 | | { MP_KEY_END, "END" }, |
47 | | { MP_KEY_PAGE_UP, "PGUP" }, |
48 | | { MP_KEY_PAGE_DOWN, "PGDWN" }, |
49 | | { MP_KEY_ESC, "ESC" }, |
50 | | { MP_KEY_PRINT, "PRINT" }, |
51 | | { MP_KEY_RIGHT, "RIGHT" }, |
52 | | { MP_KEY_LEFT, "LEFT" }, |
53 | | { MP_KEY_DOWN, "DOWN" }, |
54 | | { MP_KEY_UP, "UP" }, |
55 | | { MP_KEY_F+1, "F1" }, |
56 | | { MP_KEY_F+2, "F2" }, |
57 | | { MP_KEY_F+3, "F3" }, |
58 | | { MP_KEY_F+4, "F4" }, |
59 | | { MP_KEY_F+5, "F5" }, |
60 | | { MP_KEY_F+6, "F6" }, |
61 | | { MP_KEY_F+7, "F7" }, |
62 | | { MP_KEY_F+8, "F8" }, |
63 | | { MP_KEY_F+9, "F9" }, |
64 | | { MP_KEY_F+10, "F10" }, |
65 | | { MP_KEY_F+11, "F11" }, |
66 | | { MP_KEY_F+12, "F12" }, |
67 | | { MP_KEY_F+13, "F13" }, |
68 | | { MP_KEY_F+14, "F14" }, |
69 | | { MP_KEY_F+15, "F15" }, |
70 | | { MP_KEY_F+16, "F16" }, |
71 | | { MP_KEY_F+17, "F17" }, |
72 | | { MP_KEY_F+18, "F18" }, |
73 | | { MP_KEY_F+19, "F19" }, |
74 | | { MP_KEY_F+20, "F20" }, |
75 | | { MP_KEY_F+21, "F21" }, |
76 | | { MP_KEY_F+22, "F22" }, |
77 | | { MP_KEY_F+23, "F23" }, |
78 | | { MP_KEY_F+24, "F24" }, |
79 | | { MP_KEY_KP0, "KP0" }, |
80 | | { MP_KEY_KP1, "KP1" }, |
81 | | { MP_KEY_KP2, "KP2" }, |
82 | | { MP_KEY_KP3, "KP3" }, |
83 | | { MP_KEY_KP4, "KP4" }, |
84 | | { MP_KEY_KP5, "KP5" }, |
85 | | { MP_KEY_KP6, "KP6" }, |
86 | | { MP_KEY_KP7, "KP7" }, |
87 | | { MP_KEY_KP8, "KP8" }, |
88 | | { MP_KEY_KP9, "KP9" }, |
89 | | { MP_KEY_KPDEL, "KP_DEL" }, |
90 | | { MP_KEY_KPDEC, "KP_DEC" }, |
91 | | { MP_KEY_KPINS, "KP_INS" }, |
92 | | { MP_KEY_KPHOME, "KP_HOME" }, |
93 | | { MP_KEY_KPEND, "KP_END" }, |
94 | | { MP_KEY_KPPGUP, "KP_PGUP" }, |
95 | | { MP_KEY_KPPGDOWN, "KP_PGDWN" }, |
96 | | { MP_KEY_KPRIGHT, "KP_RIGHT" }, |
97 | | { MP_KEY_KPBEGIN, "KP_BEGIN" }, |
98 | | { MP_KEY_KPLEFT, "KP_LEFT" }, |
99 | | { MP_KEY_KPDOWN, "KP_DOWN" }, |
100 | | { MP_KEY_KPUP, "KP_UP" }, |
101 | | { MP_KEY_KPENTER, "KP_ENTER" }, |
102 | | { MP_KEY_KPADD, "KP_ADD" }, |
103 | | { MP_KEY_KPSUBTRACT, "KP_SUBTRACT" }, |
104 | | { MP_KEY_KPMULTIPLY, "KP_MULTIPLY" }, |
105 | | { MP_KEY_KPDIVIDE, "KP_DIVIDE" }, |
106 | | { MP_MBTN_LEFT, "MBTN_LEFT" }, |
107 | | { MP_MBTN_MID, "MBTN_MID" }, |
108 | | { MP_MBTN_RIGHT, "MBTN_RIGHT" }, |
109 | | { MP_WHEEL_UP, "WHEEL_UP" }, |
110 | | { MP_WHEEL_DOWN, "WHEEL_DOWN" }, |
111 | | { MP_WHEEL_LEFT, "WHEEL_LEFT" }, |
112 | | { MP_WHEEL_RIGHT, "WHEEL_RIGHT" }, |
113 | | { MP_MBTN_BACK, "MBTN_BACK" }, |
114 | | { MP_MBTN_FORWARD, "MBTN_FORWARD" }, |
115 | | { MP_MBTN9, "MBTN9" }, |
116 | | { MP_MBTN10, "MBTN10" }, |
117 | | { MP_MBTN11, "MBTN11" }, |
118 | | { MP_MBTN12, "MBTN12" }, |
119 | | { MP_MBTN13, "MBTN13" }, |
120 | | { MP_MBTN14, "MBTN14" }, |
121 | | { MP_MBTN15, "MBTN15" }, |
122 | | { MP_MBTN16, "MBTN16" }, |
123 | | { MP_MBTN17, "MBTN17" }, |
124 | | { MP_MBTN18, "MBTN18" }, |
125 | | { MP_MBTN19, "MBTN19" }, |
126 | | { MP_MBTN_LEFT_DBL, "MBTN_LEFT_DBL" }, |
127 | | { MP_MBTN_MID_DBL, "MBTN_MID_DBL" }, |
128 | | { MP_MBTN_RIGHT_DBL, "MBTN_RIGHT_DBL" }, |
129 | | |
130 | | { MP_KEY_TABLET_TOOL_TIP, "TABLET_TOOL_TIP" }, |
131 | | { MP_KEY_TABLET_TOOL_STYLUS_BTN1, "TABLET_TOOL_STYLUS_BTN1" }, |
132 | | { MP_KEY_TABLET_TOOL_STYLUS_BTN2, "TABLET_TOOL_STYLUS_BTN2" }, |
133 | | { MP_KEY_TABLET_TOOL_STYLUS_BTN3, "TABLET_TOOL_STYLUS_BTN3" }, |
134 | | |
135 | | { MP_KEY_GAMEPAD_ACTION_DOWN, "GAMEPAD_ACTION_DOWN" }, |
136 | | { MP_KEY_GAMEPAD_ACTION_RIGHT, "GAMEPAD_ACTION_RIGHT" }, |
137 | | { MP_KEY_GAMEPAD_ACTION_LEFT, "GAMEPAD_ACTION_LEFT" }, |
138 | | { MP_KEY_GAMEPAD_ACTION_UP, "GAMEPAD_ACTION_UP" }, |
139 | | { MP_KEY_GAMEPAD_BACK, "GAMEPAD_BACK" }, |
140 | | { MP_KEY_GAMEPAD_MENU, "GAMEPAD_MENU" }, |
141 | | { MP_KEY_GAMEPAD_START, "GAMEPAD_START" }, |
142 | | { MP_KEY_GAMEPAD_LEFT_SHOULDER, "GAMEPAD_LEFT_SHOULDER" }, |
143 | | { MP_KEY_GAMEPAD_RIGHT_SHOULDER, "GAMEPAD_RIGHT_SHOULDER" }, |
144 | | { MP_KEY_GAMEPAD_LEFT_TRIGGER, "GAMEPAD_LEFT_TRIGGER" }, |
145 | | { MP_KEY_GAMEPAD_RIGHT_TRIGGER, "GAMEPAD_RIGHT_TRIGGER" }, |
146 | | { MP_KEY_GAMEPAD_LEFT_STICK, "GAMEPAD_LEFT_STICK" }, |
147 | | { MP_KEY_GAMEPAD_RIGHT_STICK, "GAMEPAD_RIGHT_STICK" }, |
148 | | { MP_KEY_GAMEPAD_DPAD_UP, "GAMEPAD_DPAD_UP" }, |
149 | | { MP_KEY_GAMEPAD_DPAD_DOWN, "GAMEPAD_DPAD_DOWN" }, |
150 | | { MP_KEY_GAMEPAD_DPAD_LEFT, "GAMEPAD_DPAD_LEFT" }, |
151 | | { MP_KEY_GAMEPAD_DPAD_RIGHT, "GAMEPAD_DPAD_RIGHT" }, |
152 | | { MP_KEY_GAMEPAD_LEFT_STICK_UP, "GAMEPAD_LEFT_STICK_UP" }, |
153 | | { MP_KEY_GAMEPAD_LEFT_STICK_DOWN, "GAMEPAD_LEFT_STICK_DOWN" }, |
154 | | { MP_KEY_GAMEPAD_LEFT_STICK_LEFT, "GAMEPAD_LEFT_STICK_LEFT" }, |
155 | | { MP_KEY_GAMEPAD_LEFT_STICK_RIGHT, "GAMEPAD_LEFT_STICK_RIGHT" }, |
156 | | { MP_KEY_GAMEPAD_RIGHT_STICK_UP, "GAMEPAD_RIGHT_STICK_UP" }, |
157 | | { MP_KEY_GAMEPAD_RIGHT_STICK_DOWN, "GAMEPAD_RIGHT_STICK_DOWN" }, |
158 | | { MP_KEY_GAMEPAD_RIGHT_STICK_LEFT, "GAMEPAD_RIGHT_STICK_LEFT" }, |
159 | | { MP_KEY_GAMEPAD_RIGHT_STICK_RIGHT, "GAMEPAD_RIGHT_STICK_RIGHT" }, |
160 | | |
161 | | { MP_KEY_POWER, "POWER" }, |
162 | | { MP_KEY_MENU, "MENU" }, |
163 | | { MP_KEY_PLAY, "PLAY" }, |
164 | | { MP_KEY_PAUSE, "PAUSE" }, |
165 | | { MP_KEY_PLAYPAUSE, "PLAYPAUSE" }, |
166 | | { MP_KEY_STOP, "STOP" }, |
167 | | { MP_KEY_FORWARD, "FORWARD" }, |
168 | | { MP_KEY_REWIND, "REWIND" }, |
169 | | { MP_KEY_NEXT, "NEXT" }, |
170 | | { MP_KEY_PREV, "PREV" }, |
171 | | { MP_KEY_VOLUME_UP, "VOLUME_UP" }, |
172 | | { MP_KEY_VOLUME_DOWN, "VOLUME_DOWN" }, |
173 | | { MP_KEY_MUTE, "MUTE" }, |
174 | | { MP_KEY_HOMEPAGE, "HOMEPAGE" }, |
175 | | { MP_KEY_WWW, "WWW" }, |
176 | | { MP_KEY_MAIL, "MAIL" }, |
177 | | { MP_KEY_FAVORITES, "FAVORITES" }, |
178 | | { MP_KEY_SEARCH, "SEARCH" }, |
179 | | { MP_KEY_SLEEP, "SLEEP" }, |
180 | | { MP_KEY_CANCEL, "CANCEL" }, |
181 | | { MP_KEY_RECORD, "RECORD" }, |
182 | | { MP_KEY_CHANNEL_UP, "CHANNEL_UP" }, |
183 | | { MP_KEY_CHANNEL_DOWN,"CHANNEL_DOWN" }, |
184 | | { MP_KEY_PLAYONLY, "PLAYONLY" }, |
185 | | { MP_KEY_PAUSEONLY, "PAUSEONLY" }, |
186 | | { MP_KEY_GO_BACK, "GO_BACK" }, |
187 | | { MP_KEY_GO_FORWARD, "GO_FORWARD" }, |
188 | | { MP_KEY_TOOLS, "TOOLS" }, |
189 | | { MP_KEY_ZOOMIN, "ZOOMIN" }, |
190 | | { MP_KEY_ZOOMOUT, "ZOOMOUT" }, |
191 | | |
192 | | // These are kept for backward compatibility |
193 | | { MP_KEY_PAUSE, "XF86_PAUSE" }, |
194 | | { MP_KEY_STOP, "XF86_STOP" }, |
195 | | { MP_KEY_PREV, "XF86_PREV" }, |
196 | | { MP_KEY_NEXT, "XF86_NEXT" }, |
197 | | |
198 | | // Deprecated numeric aliases for the mouse buttons |
199 | | { MP_MBTN_LEFT, "MOUSE_BTN0" }, |
200 | | { MP_MBTN_MID, "MOUSE_BTN1" }, |
201 | | { MP_MBTN_RIGHT, "MOUSE_BTN2" }, |
202 | | { MP_WHEEL_UP, "MOUSE_BTN3" }, |
203 | | { MP_WHEEL_DOWN, "MOUSE_BTN4" }, |
204 | | { MP_WHEEL_LEFT, "MOUSE_BTN5" }, |
205 | | { MP_WHEEL_RIGHT, "MOUSE_BTN6" }, |
206 | | { MP_MBTN_BACK, "MOUSE_BTN7" }, |
207 | | { MP_MBTN_FORWARD, "MOUSE_BTN8" }, |
208 | | { MP_MBTN9, "MOUSE_BTN9" }, |
209 | | { MP_MBTN10, "MOUSE_BTN10" }, |
210 | | { MP_MBTN11, "MOUSE_BTN11" }, |
211 | | { MP_MBTN12, "MOUSE_BTN12" }, |
212 | | { MP_MBTN13, "MOUSE_BTN13" }, |
213 | | { MP_MBTN14, "MOUSE_BTN14" }, |
214 | | { MP_MBTN15, "MOUSE_BTN15" }, |
215 | | { MP_MBTN16, "MOUSE_BTN16" }, |
216 | | { MP_MBTN17, "MOUSE_BTN17" }, |
217 | | { MP_MBTN18, "MOUSE_BTN18" }, |
218 | | { MP_MBTN19, "MOUSE_BTN19" }, |
219 | | { MP_MBTN_LEFT_DBL, "MOUSE_BTN0_DBL" }, |
220 | | { MP_MBTN_MID_DBL, "MOUSE_BTN1_DBL" }, |
221 | | { MP_MBTN_RIGHT_DBL, "MOUSE_BTN2_DBL" }, |
222 | | { MP_WHEEL_UP, "AXIS_UP" }, |
223 | | { MP_WHEEL_DOWN, "AXIS_DOWN" }, |
224 | | { MP_WHEEL_LEFT, "AXIS_LEFT" }, |
225 | | { MP_WHEEL_RIGHT, "AXIS_RIGHT" }, |
226 | | |
227 | | { MP_KEY_CLOSE_WIN, "CLOSE_WIN" }, |
228 | | { MP_KEY_MOUSE_MOVE, "MOUSE_MOVE" }, |
229 | | { MP_KEY_MOUSE_LEAVE, "MOUSE_LEAVE" }, |
230 | | { MP_KEY_MOUSE_ENTER, "MOUSE_ENTER" }, |
231 | | |
232 | | { MP_KEY_UNMAPPED, "UNMAPPED" }, |
233 | | { MP_KEY_ANY_UNICODE, "ANY_UNICODE" }, |
234 | | |
235 | | { 0, NULL } |
236 | | }; |
237 | | |
238 | | static const struct key_name modifier_names[] = { |
239 | | { MP_KEY_MODIFIER_SHIFT, "Shift" }, |
240 | | { MP_KEY_MODIFIER_CTRL, "Ctrl" }, |
241 | | { MP_KEY_MODIFIER_ALT, "Alt" }, |
242 | | { MP_KEY_MODIFIER_META, "Meta" }, |
243 | | { 0 } |
244 | | }; |
245 | | |
246 | | int mp_input_get_key_from_name(const char *name) |
247 | 25.9M | { |
248 | 25.9M | int modifiers = 0; |
249 | 25.9M | const char *p; |
250 | 34.1M | while ((p = strchr(name, '+'))) { |
251 | 18.1M | for (const struct key_name *m = modifier_names; m->name; m++) |
252 | 17.8M | if (!bstrcasecmp(bstr0(m->name), |
253 | 17.8M | (struct bstr){(char *)name, p - name})) { |
254 | 8.16M | modifiers |= m->key; |
255 | 8.16M | goto found; |
256 | 8.16M | } |
257 | 255k | if (!strcmp(name, "+")) |
258 | 253k | return '+' + modifiers; |
259 | 2.07k | return -1; |
260 | 8.16M | found: |
261 | 8.16M | name = p + 1; |
262 | 8.16M | } |
263 | | |
264 | 25.6M | struct bstr bname = bstr0(name); |
265 | | |
266 | 25.6M | struct bstr rest; |
267 | 25.6M | int code = bstr_decode_utf8(bname, &rest); |
268 | 25.6M | if (code >= 0 && rest.len == 0) |
269 | 13.1M | return mp_normalize_keycode(code + modifiers); |
270 | | |
271 | 12.5M | if (bstr_startswith0(bname, "0x")) { |
272 | 3.54k | char *end; |
273 | 3.54k | long long val = strtoll(name, &end, 16); |
274 | 3.54k | if (name == end || val > INT_MAX || val < INT_MIN) |
275 | 486 | return -1; |
276 | 3.06k | long long keycode = val + modifiers; |
277 | 3.06k | if (keycode > INT_MAX || keycode < INT_MIN) |
278 | 194 | return -1; |
279 | 2.86k | return mp_normalize_keycode(keycode); |
280 | 3.06k | } |
281 | | |
282 | 726M | for (int i = 0; key_names[i].name != NULL; i++) { |
283 | 726M | if (strcasecmp(key_names[i].name, name) == 0) |
284 | 12.4M | return mp_normalize_keycode(key_names[i].key + modifiers); |
285 | 726M | } |
286 | | |
287 | 13.5k | return -1; |
288 | 12.5M | } |
289 | | |
290 | | static void mp_input_append_key_name(bstr *buf, int key) |
291 | 25.9M | { |
292 | 129M | for (int i = 0; modifier_names[i].name; i++) { |
293 | 103M | if (modifier_names[i].key & key) { |
294 | 8.17M | bstr_xappend_asprintf(NULL, buf, "%s+", modifier_names[i].name); |
295 | 8.17M | key -= modifier_names[i].key; |
296 | 8.17M | } |
297 | 103M | } |
298 | 3.26G | for (int i = 0; key_names[i].name != NULL; i++) { |
299 | 3.24G | if (key_names[i].key == key) { |
300 | 12.5M | bstr_xappend_asprintf(NULL, buf, "%s", key_names[i].name); |
301 | 12.5M | return; |
302 | 12.5M | } |
303 | 3.24G | } |
304 | | |
305 | 13.4M | if (MP_KEY_IS_UNICODE(key)) { |
306 | 13.4M | mp_append_utf8_bstr(NULL, buf, key); |
307 | 13.4M | return; |
308 | 13.4M | } |
309 | | |
310 | | // Print the hex key code |
311 | 26.6k | bstr_xappend_asprintf(NULL, buf, "0x%x", key); |
312 | 26.6k | } |
313 | | |
314 | | char *mp_input_get_key_name(int key) |
315 | 0 | { |
316 | 0 | bstr dst = {0}; |
317 | 0 | mp_input_append_key_name(&dst, key); |
318 | 0 | return dst.start; |
319 | 0 | } |
320 | | |
321 | | char *mp_input_get_key_combo_name(const int *keys, int max) |
322 | 24.0M | { |
323 | 24.0M | bstr dst = {0}; |
324 | 25.9M | while (max > 0) { |
325 | 25.9M | mp_input_append_key_name(&dst, *keys); |
326 | 25.9M | if (--max && *++keys) |
327 | 1.87M | bstr_xappend(NULL, &dst, bstr0("-")); |
328 | 24.0M | else |
329 | 24.0M | break; |
330 | 25.9M | } |
331 | 24.0M | return dst.start; |
332 | 24.0M | } |
333 | | |
334 | | int mp_input_get_keys_from_string(char *name, int max_num_keys, |
335 | | int *out_num_keys, int *keys) |
336 | 24.0M | { |
337 | 24.0M | char *end, *ptr; |
338 | 24.0M | int n = 0; |
339 | | |
340 | 24.0M | ptr = name; |
341 | 24.0M | n = 0; |
342 | 25.9M | for (end = strchr(ptr, '-'); ; end = strchr(ptr, '-')) { |
343 | 25.9M | if (end && end[1] != '\0') { |
344 | 1.87M | if (*ptr == '-' && end[1] == '-') |
345 | 15.9k | end = &end[1]; |
346 | 1.87M | end[0] = '\0'; |
347 | 1.87M | } |
348 | 25.9M | keys[n] = mp_input_get_key_from_name(ptr); |
349 | 25.9M | if (keys[n] < 0) |
350 | 16.3k | return 0; |
351 | 25.9M | n++; |
352 | 25.9M | if (end && end[1] != '\0' && n < max_num_keys) |
353 | 1.87M | ptr = &end[1]; |
354 | 24.0M | else |
355 | 24.0M | break; |
356 | 25.9M | } |
357 | 24.0M | *out_num_keys = n; |
358 | 24.0M | return 1; |
359 | 24.0M | } |
360 | | |
361 | | void mp_print_key_list(struct mp_log *out) |
362 | 343 | { |
363 | 343 | mp_info(out, "\n"); |
364 | 64.8k | for (int i = 0; key_names[i].name != NULL; i++) |
365 | 64.4k | mp_info(out, "%s\n", key_names[i].name); |
366 | 343 | } |
367 | | |
368 | | char **mp_get_key_list(void) |
369 | 97 | { |
370 | 97 | char **list = NULL; |
371 | 97 | int num = 0; |
372 | 18.3k | for (int i = 0; key_names[i].name != NULL; i++) |
373 | 18.2k | MP_TARRAY_APPEND(NULL, list, num, talloc_strdup(NULL, key_names[i].name)); |
374 | 97 | MP_TARRAY_APPEND(NULL, list, num, NULL); |
375 | 97 | return list; |
376 | 97 | } |
377 | | |
378 | | int mp_normalize_keycode(int keycode) |
379 | 25.6M | { |
380 | 25.6M | if (keycode <= 0) |
381 | 408 | return keycode; |
382 | 25.6M | int code = keycode & ~MP_KEY_MODIFIER_MASK; |
383 | 25.6M | int mod = keycode & MP_KEY_MODIFIER_MASK; |
384 | | /* On normal keyboards shift changes the character code of non-special |
385 | | * keys, so don't count the modifier separately for those. In other words |
386 | | * we want to have "a" and "A" instead of "a" and "Shift+A"; but a separate |
387 | | * shift modifier is still kept for special keys like arrow keys. */ |
388 | 25.6M | if (code >= 32 && code < MP_KEY_BASE) { |
389 | | /* Still try to support ASCII case-modifications properly. For example, |
390 | | * we want to change "Shift+a" to "A", not "a". Doing this for unicode |
391 | | * in general would require huge lookup tables, or a libc with proper |
392 | | * unicode support, so we don't do that. */ |
393 | 13.3M | if (code >= 'a' && code <= 'z' && (mod & MP_KEY_MODIFIER_SHIFT)) |
394 | 1.70k | code &= 0x5F; |
395 | 13.3M | mod &= ~MP_KEY_MODIFIER_SHIFT; |
396 | 13.3M | } |
397 | 25.6M | return code | mod; |
398 | 25.6M | } |