ddraw/tests: Rewrite LimitTest().
[wine.git] / dlls / wineandroid.drv / keyboard.c
blob3d459cd3c0a409427c02533b96c2793dd944c756
1 /*
2 * Keyboard related functions
4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
7 * Copyright 1998 Morten Welinder
8 * Copyright 1998 Ulrich Weigand
9 * Copyright 1999 Ove Kåven
10 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
11 * Copyright 2013 Alexandre Julliard
12 * Copyright 2015 Josh DuBois for CodeWeavers Inc.
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
32 #include "config.h"
34 #include "android.h"
35 #include "wine/unicode.h"
36 #include "wine/server.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
40 WINE_DECLARE_DEBUG_CHANNEL(key);
42 static const UINT keycode_to_vkey[] =
44 0, /* AKEYCODE_UNKNOWN */
45 0, /* AKEYCODE_SOFT_LEFT */
46 0, /* AKEYCODE_SOFT_RIGHT */
47 0, /* AKEYCODE_HOME */
48 0, /* AKEYCODE_BACK */
49 0, /* AKEYCODE_CALL */
50 0, /* AKEYCODE_ENDCALL */
51 '0', /* AKEYCODE_0 */
52 '1', /* AKEYCODE_1 */
53 '2', /* AKEYCODE_2 */
54 '3', /* AKEYCODE_3 */
55 '4', /* AKEYCODE_4 */
56 '5', /* AKEYCODE_5 */
57 '6', /* AKEYCODE_6 */
58 '7', /* AKEYCODE_7 */
59 '8', /* AKEYCODE_8 */
60 '9', /* AKEYCODE_9 */
61 0, /* AKEYCODE_STAR */
62 0, /* AKEYCODE_POUND */
63 VK_UP, /* AKEYCODE_DPAD_UP */
64 VK_DOWN, /* AKEYCODE_DPAD_DOWN */
65 VK_LEFT, /* AKEYCODE_DPAD_LEFT */
66 VK_RIGHT, /* AKEYCODE_DPAD_RIGHT */
67 0, /* AKEYCODE_DPAD_CENTER */
68 0, /* AKEYCODE_VOLUME_UP */
69 0, /* AKEYCODE_VOLUME_DOWN */
70 0, /* AKEYCODE_POWER */
71 0, /* AKEYCODE_CAMERA */
72 0, /* AKEYCODE_CLEAR */
73 'A', /* AKEYCODE_A */
74 'B', /* AKEYCODE_B */
75 'C', /* AKEYCODE_C */
76 'D', /* AKEYCODE_D */
77 'E', /* AKEYCODE_E */
78 'F', /* AKEYCODE_F */
79 'G', /* AKEYCODE_G */
80 'H', /* AKEYCODE_H */
81 'I', /* AKEYCODE_I */
82 'J', /* AKEYCODE_J */
83 'K', /* AKEYCODE_K */
84 'L', /* AKEYCODE_L */
85 'M', /* AKEYCODE_M */
86 'N', /* AKEYCODE_N */
87 'O', /* AKEYCODE_O */
88 'P', /* AKEYCODE_P */
89 'Q', /* AKEYCODE_Q */
90 'R', /* AKEYCODE_R */
91 'S', /* AKEYCODE_S */
92 'T', /* AKEYCODE_T */
93 'U', /* AKEYCODE_U */
94 'V', /* AKEYCODE_V */
95 'W', /* AKEYCODE_W */
96 'X', /* AKEYCODE_X */
97 'Y', /* AKEYCODE_Y */
98 'Z', /* AKEYCODE_Z */
99 VK_OEM_COMMA, /* AKEYCODE_COMMA */
100 VK_OEM_PERIOD, /* AKEYCODE_PERIOD */
101 VK_LMENU, /* AKEYCODE_ALT_LEFT */
102 VK_RMENU, /* AKEYCODE_ALT_RIGHT */
103 VK_LSHIFT, /* AKEYCODE_SHIFT_LEFT */
104 VK_RSHIFT, /* AKEYCODE_SHIFT_RIGHT */
105 VK_TAB, /* AKEYCODE_TAB */
106 VK_SPACE, /* AKEYCODE_SPACE */
107 0, /* AKEYCODE_SYM */
108 0, /* AKEYCODE_EXPLORER */
109 0, /* AKEYCODE_ENVELOPE */
110 VK_RETURN, /* AKEYCODE_ENTER */
111 VK_BACK, /* AKEYCODE_DEL */
112 VK_OEM_3, /* AKEYCODE_GRAVE */
113 VK_OEM_MINUS, /* AKEYCODE_MINUS */
114 VK_OEM_PLUS, /* AKEYCODE_EQUALS */
115 VK_OEM_4, /* AKEYCODE_LEFT_BRACKET */
116 VK_OEM_6, /* AKEYCODE_RIGHT_BRACKET */
117 VK_OEM_5, /* AKEYCODE_BACKSLASH */
118 VK_OEM_1, /* AKEYCODE_SEMICOLON */
119 VK_OEM_7, /* AKEYCODE_APOSTROPHE */
120 VK_OEM_2, /* AKEYCODE_SLASH */
121 0, /* AKEYCODE_AT */
122 0, /* AKEYCODE_NUM */
123 0, /* AKEYCODE_HEADSETHOOK */
124 0, /* AKEYCODE_FOCUS */
125 0, /* AKEYCODE_PLUS */
126 0, /* AKEYCODE_MENU */
127 0, /* AKEYCODE_NOTIFICATION */
128 0, /* AKEYCODE_SEARCH */
129 VK_MEDIA_PLAY_PAUSE, /* AKEYCODE_MEDIA_PLAY_PAUSE */
130 VK_MEDIA_STOP, /* AKEYCODE_MEDIA_STOP */
131 VK_MEDIA_NEXT_TRACK, /* AKEYCODE_MEDIA_NEXT */
132 VK_MEDIA_PREV_TRACK, /* AKEYCODE_MEDIA_PREVIOUS */
133 0, /* AKEYCODE_MEDIA_REWIND */
134 0, /* AKEYCODE_MEDIA_FAST_FORWARD */
135 0, /* AKEYCODE_MUTE */
136 VK_PRIOR, /* AKEYCODE_PAGE_UP */
137 VK_NEXT, /* AKEYCODE_PAGE_DOWN */
138 0, /* AKEYCODE_PICTSYMBOLS */
139 0, /* AKEYCODE_SWITCH_CHARSET */
140 0, /* AKEYCODE_BUTTON_A */
141 0, /* AKEYCODE_BUTTON_B */
142 0, /* AKEYCODE_BUTTON_C */
143 0, /* AKEYCODE_BUTTON_X */
144 0, /* AKEYCODE_BUTTON_Y */
145 0, /* AKEYCODE_BUTTON_Z */
146 0, /* AKEYCODE_BUTTON_L1 */
147 0, /* AKEYCODE_BUTTON_R1 */
148 0, /* AKEYCODE_BUTTON_L2 */
149 0, /* AKEYCODE_BUTTON_R2 */
150 0, /* AKEYCODE_BUTTON_THUMBL */
151 0, /* AKEYCODE_BUTTON_THUMBR */
152 0, /* AKEYCODE_BUTTON_START */
153 0, /* AKEYCODE_BUTTON_SELECT */
154 0, /* AKEYCODE_BUTTON_MODE */
155 VK_ESCAPE, /* AKEYCODE_ESCAPE */
156 VK_DELETE, /* AKEYCODE_FORWARD_DEL */
157 VK_LCONTROL, /* AKEYCODE_CTRL_LEFT */
158 VK_RCONTROL, /* AKEYCODE_CTRL_RIGHT */
159 VK_CAPITAL, /* AKEYCODE_CAPS_LOCK */
160 VK_SCROLL, /* AKEYCODE_SCROLL_LOCK */
161 VK_LWIN, /* AKEYCODE_META_LEFT */
162 VK_RWIN, /* AKEYCODE_META_RIGHT */
163 0, /* AKEYCODE_FUNCTION */
164 0, /* AKEYCODE_SYSRQ */
165 0, /* AKEYCODE_BREAK */
166 VK_HOME, /* AKEYCODE_MOVE_HOME */
167 VK_END, /* AKEYCODE_MOVE_END */
168 VK_INSERT, /* AKEYCODE_INSERT */
169 0, /* AKEYCODE_FORWARD */
170 0, /* AKEYCODE_MEDIA_PLAY */
171 0, /* AKEYCODE_MEDIA_PAUSE */
172 0, /* AKEYCODE_MEDIA_CLOSE */
173 0, /* AKEYCODE_MEDIA_EJECT */
174 0, /* AKEYCODE_MEDIA_RECORD */
175 VK_F1, /* AKEYCODE_F1 */
176 VK_F2, /* AKEYCODE_F2 */
177 VK_F3, /* AKEYCODE_F3 */
178 VK_F4, /* AKEYCODE_F4 */
179 VK_F5, /* AKEYCODE_F5 */
180 VK_F6, /* AKEYCODE_F6 */
181 VK_F7, /* AKEYCODE_F7 */
182 VK_F8, /* AKEYCODE_F8 */
183 VK_F9, /* AKEYCODE_F9 */
184 VK_F10, /* AKEYCODE_F10 */
185 VK_F11, /* AKEYCODE_F11 */
186 VK_F12, /* AKEYCODE_F12 */
187 VK_NUMLOCK, /* AKEYCODE_NUM_LOCK */
188 VK_NUMPAD0, /* AKEYCODE_NUMPAD_0 */
189 VK_NUMPAD1, /* AKEYCODE_NUMPAD_1 */
190 VK_NUMPAD2, /* AKEYCODE_NUMPAD_2 */
191 VK_NUMPAD3, /* AKEYCODE_NUMPAD_3 */
192 VK_NUMPAD4, /* AKEYCODE_NUMPAD_4 */
193 VK_NUMPAD5, /* AKEYCODE_NUMPAD_5 */
194 VK_NUMPAD6, /* AKEYCODE_NUMPAD_6 */
195 VK_NUMPAD7, /* AKEYCODE_NUMPAD_7 */
196 VK_NUMPAD8, /* AKEYCODE_NUMPAD_8 */
197 VK_NUMPAD9, /* AKEYCODE_NUMPAD_9 */
198 VK_DIVIDE, /* AKEYCODE_NUMPAD_DIVIDE */
199 VK_MULTIPLY, /* AKEYCODE_NUMPAD_MULTIPLY */
200 VK_SUBTRACT, /* AKEYCODE_NUMPAD_SUBTRACT */
201 VK_ADD, /* AKEYCODE_NUMPAD_ADD */
202 VK_DECIMAL, /* AKEYCODE_NUMPAD_DOT */
203 0, /* AKEYCODE_NUMPAD_COMMA */
204 0, /* AKEYCODE_NUMPAD_ENTER */
205 0, /* AKEYCODE_NUMPAD_EQUALS */
206 0, /* AKEYCODE_NUMPAD_LEFT_PAREN */
207 0, /* AKEYCODE_NUMPAD_RIGHT_PAREN */
208 0, /* AKEYCODE_VOLUME_MUTE */
209 0, /* AKEYCODE_INFO */
210 0, /* AKEYCODE_CHANNEL_UP */
211 0, /* AKEYCODE_CHANNEL_DOWN */
212 0, /* AKEYCODE_ZOOM_IN */
213 0, /* AKEYCODE_ZOOM_OUT */
214 0, /* AKEYCODE_TV */
215 0, /* AKEYCODE_WINDOW */
216 0, /* AKEYCODE_GUIDE */
217 0, /* AKEYCODE_DVR */
218 0, /* AKEYCODE_BOOKMARK */
219 0, /* AKEYCODE_CAPTIONS */
220 0, /* AKEYCODE_SETTINGS */
221 0, /* AKEYCODE_TV_POWER */
222 0, /* AKEYCODE_TV_INPUT */
223 0, /* AKEYCODE_STB_POWER */
224 0, /* AKEYCODE_STB_INPUT */
225 0, /* AKEYCODE_AVR_POWER */
226 0, /* AKEYCODE_AVR_INPUT */
227 0, /* AKEYCODE_PROG_RED */
228 0, /* AKEYCODE_PROG_GREEN */
229 0, /* AKEYCODE_PROG_YELLOW */
230 0, /* AKEYCODE_PROG_BLUE */
231 0, /* AKEYCODE_APP_SWITCH */
232 0, /* AKEYCODE_BUTTON_1 */
233 0, /* AKEYCODE_BUTTON_2 */
234 0, /* AKEYCODE_BUTTON_3 */
235 0, /* AKEYCODE_BUTTON_4 */
236 0, /* AKEYCODE_BUTTON_5 */
237 0, /* AKEYCODE_BUTTON_6 */
238 0, /* AKEYCODE_BUTTON_7 */
239 0, /* AKEYCODE_BUTTON_8 */
240 0, /* AKEYCODE_BUTTON_9 */
241 0, /* AKEYCODE_BUTTON_10 */
242 0, /* AKEYCODE_BUTTON_11 */
243 0, /* AKEYCODE_BUTTON_12 */
244 0, /* AKEYCODE_BUTTON_13 */
245 0, /* AKEYCODE_BUTTON_14 */
246 0, /* AKEYCODE_BUTTON_15 */
247 0, /* AKEYCODE_BUTTON_16 */
248 0, /* AKEYCODE_LANGUAGE_SWITCH */
249 0, /* AKEYCODE_MANNER_MODE */
250 0, /* AKEYCODE_3D_MODE */
251 0, /* AKEYCODE_CONTACTS */
252 0, /* AKEYCODE_CALENDAR */
253 0, /* AKEYCODE_MUSIC */
254 0, /* AKEYCODE_CALCULATOR */
255 0, /* AKEYCODE_ZENKAKU_HANKAKU */
256 0, /* AKEYCODE_EISU */
257 0, /* AKEYCODE_MUHENKAN */
258 0, /* AKEYCODE_HENKAN */
259 0, /* AKEYCODE_KATAKANA_HIRAGANA */
260 0, /* AKEYCODE_YEN */
261 0, /* AKEYCODE_RO */
262 VK_KANA, /* AKEYCODE_KANA */
263 0, /* AKEYCODE_ASSIST */
266 static const WORD vkey_to_scancode[] =
268 0, /* 0x00 undefined */
269 0, /* VK_LBUTTON */
270 0, /* VK_RBUTTON */
271 0, /* VK_CANCEL */
272 0, /* VK_MBUTTON */
273 0, /* VK_XBUTTON1 */
274 0, /* VK_XBUTTON2 */
275 0, /* 0x07 undefined */
276 0x0e, /* VK_BACK */
277 0x0f, /* VK_TAB */
278 0, /* 0x0a undefined */
279 0, /* 0x0b undefined */
280 0, /* VK_CLEAR */
281 0x1c, /* VK_RETURN */
282 0, /* 0x0e undefined */
283 0, /* 0x0f undefined */
284 0x2a, /* VK_SHIFT */
285 0x1d, /* VK_CONTROL */
286 0x38, /* VK_MENU */
287 0, /* VK_PAUSE */
288 0x3a, /* VK_CAPITAL */
289 0, /* VK_KANA */
290 0, /* 0x16 undefined */
291 0, /* VK_JUNJA */
292 0, /* VK_FINAL */
293 0, /* VK_HANJA */
294 0, /* 0x1a undefined */
295 0x01, /* VK_ESCAPE */
296 0, /* VK_CONVERT */
297 0, /* VK_NONCONVERT */
298 0, /* VK_ACCEPT */
299 0, /* VK_MODECHANGE */
300 0x39, /* VK_SPACE */
301 0x149, /* VK_PRIOR */
302 0x151, /* VK_NEXT */
303 0x14f, /* VK_END */
304 0x147, /* VK_HOME */
305 0x14b, /* VK_LEFT */
306 0x148, /* VK_UP */
307 0x14d, /* VK_RIGHT */
308 0x150, /* VK_DOWN */
309 0, /* VK_SELECT */
310 0, /* VK_PRINT */
311 0, /* VK_EXECUTE */
312 0, /* VK_SNAPSHOT */
313 0x152, /* VK_INSERT */
314 0x153, /* VK_DELETE */
315 0, /* VK_HELP */
316 0x0b, /* VK_0 */
317 0x02, /* VK_1 */
318 0x03, /* VK_2 */
319 0x04, /* VK_3 */
320 0x05, /* VK_4 */
321 0x06, /* VK_5 */
322 0x07, /* VK_6 */
323 0x08, /* VK_7 */
324 0x09, /* VK_8 */
325 0x0a, /* VK_9 */
326 0, /* 0x3a undefined */
327 0, /* 0x3b undefined */
328 0, /* 0x3c undefined */
329 0, /* 0x3d undefined */
330 0, /* 0x3e undefined */
331 0, /* 0x3f undefined */
332 0, /* 0x40 undefined */
333 0x1e, /* VK_A */
334 0x30, /* VK_B */
335 0x2e, /* VK_C */
336 0x20, /* VK_D */
337 0x12, /* VK_E */
338 0x21, /* VK_F */
339 0x22, /* VK_G */
340 0x23, /* VK_H */
341 0x17, /* VK_I */
342 0x24, /* VK_J */
343 0x25, /* VK_K */
344 0x26, /* VK_L */
345 0x32, /* VK_M */
346 0x31, /* VK_N */
347 0x18, /* VK_O */
348 0x19, /* VK_P */
349 0x10, /* VK_Q */
350 0x13, /* VK_R */
351 0x1f, /* VK_S */
352 0x14, /* VK_T */
353 0x16, /* VK_U */
354 0x2f, /* VK_V */
355 0x11, /* VK_W */
356 0x2d, /* VK_X */
357 0x15, /* VK_Y */
358 0x2c, /* VK_Z */
359 0, /* VK_LWIN */
360 0, /* VK_RWIN */
361 0, /* VK_APPS */
362 0, /* 0x5e undefined */
363 0, /* VK_SLEEP */
364 0x52, /* VK_NUMPAD0 */
365 0x4f, /* VK_NUMPAD1 */
366 0x50, /* VK_NUMPAD2 */
367 0x51, /* VK_NUMPAD3 */
368 0x4b, /* VK_NUMPAD4 */
369 0x4c, /* VK_NUMPAD5 */
370 0x4d, /* VK_NUMPAD6 */
371 0x47, /* VK_NUMPAD7 */
372 0x48, /* VK_NUMPAD8 */
373 0x49, /* VK_NUMPAD9 */
374 0x37, /* VK_MULTIPLY */
375 0x4e, /* VK_ADD */
376 0x7e, /* VK_SEPARATOR */
377 0x4a, /* VK_SUBTRACT */
378 0x53, /* VK_DECIMAL */
379 0135, /* VK_DIVIDE */
380 0x3b, /* VK_F1 */
381 0x3c, /* VK_F2 */
382 0x3d, /* VK_F3 */
383 0x3e, /* VK_F4 */
384 0x3f, /* VK_F5 */
385 0x40, /* VK_F6 */
386 0x41, /* VK_F7 */
387 0x42, /* VK_F8 */
388 0x43, /* VK_F9 */
389 0x44, /* VK_F10 */
390 0x57, /* VK_F11 */
391 0x58, /* VK_F12 */
392 0x64, /* VK_F13 */
393 0x65, /* VK_F14 */
394 0x66, /* VK_F15 */
395 0x67, /* VK_F16 */
396 0x68, /* VK_F17 */
397 0x69, /* VK_F18 */
398 0x6a, /* VK_F19 */
399 0x6b, /* VK_F20 */
400 0, /* VK_F21 */
401 0, /* VK_F22 */
402 0, /* VK_F23 */
403 0, /* VK_F24 */
404 0, /* 0x88 undefined */
405 0, /* 0x89 undefined */
406 0, /* 0x8a undefined */
407 0, /* 0x8b undefined */
408 0, /* 0x8c undefined */
409 0, /* 0x8d undefined */
410 0, /* 0x8e undefined */
411 0, /* 0x8f undefined */
412 0, /* VK_NUMLOCK */
413 0, /* VK_SCROLL */
414 0x10d, /* VK_OEM_NEC_EQUAL */
415 0, /* VK_OEM_FJ_JISHO */
416 0, /* VK_OEM_FJ_MASSHOU */
417 0, /* VK_OEM_FJ_TOUROKU */
418 0, /* VK_OEM_FJ_LOYA */
419 0, /* VK_OEM_FJ_ROYA */
420 0, /* 0x97 undefined */
421 0, /* 0x98 undefined */
422 0, /* 0x99 undefined */
423 0, /* 0x9a undefined */
424 0, /* 0x9b undefined */
425 0, /* 0x9c undefined */
426 0, /* 0x9d undefined */
427 0, /* 0x9e undefined */
428 0, /* 0x9f undefined */
429 0x2a, /* VK_LSHIFT */
430 0x36, /* VK_RSHIFT */
431 0x1d, /* VK_LCONTROL */
432 0x11d, /* VK_RCONTROL */
433 0x38, /* VK_LMENU */
434 0x138, /* VK_RMENU */
435 0, /* VK_BROWSER_BACK */
436 0, /* VK_BROWSER_FORWARD */
437 0, /* VK_BROWSER_REFRESH */
438 0, /* VK_BROWSER_STOP */
439 0, /* VK_BROWSER_SEARCH */
440 0, /* VK_BROWSER_FAVORITES */
441 0, /* VK_BROWSER_HOME */
442 0x100, /* VK_VOLUME_MUTE */
443 0x100, /* VK_VOLUME_DOWN */
444 0x100, /* VK_VOLUME_UP */
445 0, /* VK_MEDIA_NEXT_TRACK */
446 0, /* VK_MEDIA_PREV_TRACK */
447 0, /* VK_MEDIA_STOP */
448 0, /* VK_MEDIA_PLAY_PAUSE */
449 0, /* VK_LAUNCH_MAIL */
450 0, /* VK_LAUNCH_MEDIA_SELECT */
451 0, /* VK_LAUNCH_APP1 */
452 0, /* VK_LAUNCH_APP2 */
453 0, /* 0xb8 undefined */
454 0, /* 0xb9 undefined */
455 0x27, /* VK_OEM_1 */
456 0x0d, /* VK_OEM_PLUS */
457 0x33, /* VK_OEM_COMMA */
458 0x0c, /* VK_OEM_MINUS */
459 0x34, /* VK_OEM_PERIOD */
460 0x35, /* VK_OEM_2 */
461 0x29, /* VK_OEM_3 */
462 0, /* 0xc1 undefined */
463 0, /* 0xc2 undefined */
464 0, /* 0xc3 undefined */
465 0, /* 0xc4 undefined */
466 0, /* 0xc5 undefined */
467 0, /* 0xc6 undefined */
468 0, /* 0xc7 undefined */
469 0, /* 0xc8 undefined */
470 0, /* 0xc9 undefined */
471 0, /* 0xca undefined */
472 0, /* 0xcb undefined */
473 0, /* 0xcc undefined */
474 0, /* 0xcd undefined */
475 0, /* 0xce undefined */
476 0, /* 0xcf undefined */
477 0, /* 0xd0 undefined */
478 0, /* 0xd1 undefined */
479 0, /* 0xd2 undefined */
480 0, /* 0xd3 undefined */
481 0, /* 0xd4 undefined */
482 0, /* 0xd5 undefined */
483 0, /* 0xd6 undefined */
484 0, /* 0xd7 undefined */
485 0, /* 0xd8 undefined */
486 0, /* 0xd9 undefined */
487 0, /* 0xda undefined */
488 0x1a, /* VK_OEM_4 */
489 0x2b, /* VK_OEM_5 */
490 0x1b, /* VK_OEM_6 */
491 0x28, /* VK_OEM_7 */
492 0, /* VK_OEM_8 */
493 0, /* 0xe0 undefined */
494 0, /* VK_OEM_AX */
495 0x56, /* VK_OEM_102 */
496 0, /* VK_ICO_HELP */
497 0, /* VK_ICO_00 */
498 0, /* VK_PROCESSKEY */
499 0, /* VK_ICO_CLEAR */
500 0, /* VK_PACKET */
501 0, /* 0xe8 undefined */
502 0x71, /* VK_OEM_RESET */
503 0, /* VK_OEM_JUMP */
504 0, /* VK_OEM_PA1 */
505 0, /* VK_OEM_PA2 */
506 0, /* VK_OEM_PA3 */
507 0, /* VK_OEM_WSCTRL */
508 0, /* VK_OEM_CUSEL */
509 0, /* VK_OEM_ATTN */
510 0, /* VK_OEM_FINISH */
511 0, /* VK_OEM_COPY */
512 0, /* VK_OEM_AUTO */
513 0, /* VK_OEM_ENLW */
514 0, /* VK_OEM_BACKTAB */
515 0, /* VK_ATTN */
516 0, /* VK_CRSEL */
517 0, /* VK_EXSEL */
518 0, /* VK_EREOF */
519 0, /* VK_PLAY */
520 0, /* VK_ZOOM */
521 0, /* VK_NONAME */
522 0, /* VK_PA1 */
523 0x59, /* VK_OEM_CLEAR */
524 0, /* 0xff undefined */
527 static const struct
529 DWORD vkey;
530 const char *name;
531 } vkey_names[] = {
532 { VK_ADD, "Num +" },
533 { VK_BACK, "Backspace" },
534 { VK_CAPITAL, "Caps Lock" },
535 { VK_CONTROL, "Ctrl" },
536 { VK_DECIMAL, "Num Del" },
537 { VK_DELETE | 0x100, "Delete" },
538 { VK_DIVIDE | 0x100, "Num /" },
539 { VK_DOWN | 0x100, "Down" },
540 { VK_END | 0x100, "End" },
541 { VK_ESCAPE, "Esc" },
542 { VK_F1, "F1" },
543 { VK_F2, "F2" },
544 { VK_F3, "F3" },
545 { VK_F4, "F4" },
546 { VK_F5, "F5" },
547 { VK_F6, "F6" },
548 { VK_F7, "F7" },
549 { VK_F8, "F8" },
550 { VK_F9, "F9" },
551 { VK_F10, "F10" },
552 { VK_F11, "F11" },
553 { VK_F12, "F12" },
554 { VK_F13, "F13" },
555 { VK_F14, "F14" },
556 { VK_F15, "F15" },
557 { VK_F16, "F16" },
558 { VK_F17, "F17" },
559 { VK_F18, "F18" },
560 { VK_F19, "F19" },
561 { VK_F20, "F20" },
562 { VK_F21, "F21" },
563 { VK_F22, "F22" },
564 { VK_F23, "F23" },
565 { VK_F24, "F24" },
566 { VK_HELP | 0x100, "Help" },
567 { VK_HOME | 0x100, "Home" },
568 { VK_INSERT | 0x100, "Insert" },
569 { VK_LCONTROL, "Ctrl" },
570 { VK_LEFT | 0x100, "Left" },
571 { VK_LMENU, "Alt" },
572 { VK_LSHIFT, "Shift" },
573 { VK_LWIN | 0x100, "Win" },
574 { VK_MENU, "Alt" },
575 { VK_MULTIPLY, "Num *" },
576 { VK_NEXT | 0x100, "Page Down" },
577 { VK_NUMLOCK | 0x100, "Num Lock" },
578 { VK_NUMPAD0, "Num 0" },
579 { VK_NUMPAD1, "Num 1" },
580 { VK_NUMPAD2, "Num 2" },
581 { VK_NUMPAD3, "Num 3" },
582 { VK_NUMPAD4, "Num 4" },
583 { VK_NUMPAD5, "Num 5" },
584 { VK_NUMPAD6, "Num 6" },
585 { VK_NUMPAD7, "Num 7" },
586 { VK_NUMPAD8, "Num 8" },
587 { VK_NUMPAD9, "Num 9" },
588 { VK_OEM_CLEAR, "Num Clear" },
589 { VK_OEM_NEC_EQUAL | 0x100, "Num =" },
590 { VK_PRIOR | 0x100, "Page Up" },
591 { VK_RCONTROL | 0x100, "Right Ctrl" },
592 { VK_RETURN, "Return" },
593 { VK_RETURN | 0x100, "Num Enter" },
594 { VK_RIGHT | 0x100, "Right" },
595 { VK_RMENU | 0x100, "Right Alt" },
596 { VK_RSHIFT, "Right Shift" },
597 { VK_RWIN | 0x100, "Right Win" },
598 { VK_SEPARATOR, "Num ," },
599 { VK_SHIFT, "Shift" },
600 { VK_SPACE, "Space" },
601 { VK_SUBTRACT, "Num -" },
602 { VK_TAB, "Tab" },
603 { VK_UP | 0x100, "Up" },
604 { VK_VOLUME_DOWN | 0x100, "Volume Down" },
605 { VK_VOLUME_MUTE | 0x100, "Mute" },
606 { VK_VOLUME_UP | 0x100, "Volume Up" },
607 { VK_OEM_MINUS, "-" },
608 { VK_OEM_PLUS, "=" },
609 { VK_OEM_1, ";" },
610 { VK_OEM_2, "/" },
611 { VK_OEM_3, "`" },
612 { VK_OEM_4, "[" },
613 { VK_OEM_5, "\\" },
614 { VK_OEM_6, "]" },
615 { VK_OEM_7, "'" },
616 { VK_OEM_COMMA, "," },
617 { VK_OEM_PERIOD, "." },
620 static const SHORT char_vkey_map[] =
622 0x332, 0x241, 0x242, 0x003, 0x244, 0x245, 0x246, 0x247, 0x008, 0x009,
623 0x20d, 0x24b, 0x24c, 0x00d, 0x24e, 0x24f, 0x250, 0x251, 0x252, 0x253,
624 0x254, 0x255, 0x256, 0x257, 0x258, 0x259, 0x25a, 0x01b, 0x2dc, 0x2dd,
625 0x336, 0x3bd, 0x020, 0x131, 0x1de, 0x133, 0x134, 0x135, 0x137, 0x0de,
626 0x139, 0x130, 0x138, 0x1bb, 0x0bc, 0x0bd, 0x0be, 0x0bf, 0x030, 0x031,
627 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x1ba, 0x0ba,
628 0x1bc, 0x0bb, 0x1be, 0x1bf, 0x132, 0x141, 0x142, 0x143, 0x144, 0x145,
629 0x146, 0x147, 0x148, 0x149, 0x14a, 0x14b, 0x14c, 0x14d, 0x14e, 0x14f,
630 0x150, 0x151, 0x152, 0x153, 0x154, 0x155, 0x156, 0x157, 0x158, 0x159,
631 0x15a, 0x0db, 0x0dc, 0x0dd, 0x136, 0x1bd, 0x0c0, 0x041, 0x042, 0x043,
632 0x044, 0x045, 0x046, 0x047, 0x048, 0x049, 0x04a, 0x04b, 0x04c, 0x04d,
633 0x04e, 0x04f, 0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057,
634 0x058, 0x059, 0x05a, 0x1db, 0x1dc, 0x1dd, 0x1c0, 0x208
637 static UINT scancode_to_vkey( UINT scan )
639 UINT j;
641 for (j = 0; j < sizeof(vkey_to_scancode)/sizeof(vkey_to_scancode[0]); j++)
642 if (vkey_to_scancode[j] == scan)
643 return j;
644 return 0;
647 static const char* vkey_to_name( UINT vkey )
649 UINT j;
651 for (j = 0; j < sizeof(vkey_names)/sizeof(vkey_names[0]); j++)
652 if (vkey_names[j].vkey == vkey)
653 return vkey_names[j].name;
654 return NULL;
657 static BOOL get_async_key_state( BYTE state[256] )
659 BOOL ret;
661 SERVER_START_REQ( get_key_state )
663 req->tid = 0;
664 req->key = -1;
665 wine_server_set_reply( req, state, 256 );
666 ret = !wine_server_call( req );
668 SERVER_END_REQ;
669 return ret;
672 static void send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD flags )
674 INPUT input;
676 input.type = INPUT_KEYBOARD;
677 input.u.ki.wVk = vkey;
678 input.u.ki.wScan = scan;
679 input.u.ki.dwFlags = flags;
680 input.u.ki.time = 0;
681 input.u.ki.dwExtraInfo = 0;
683 __wine_send_input( hwnd, &input );
686 /***********************************************************************
687 * update_keyboard_lock_state
689 void update_keyboard_lock_state( WORD vkey, UINT state )
691 BYTE keystate[256];
693 if (!get_async_key_state( keystate )) return;
695 if (!(keystate[VK_CAPITAL] & 0x01) != !(state & AMETA_CAPS_LOCK_ON) && vkey != VK_CAPITAL)
697 TRACE( "adjusting CapsLock state (%02x)\n", keystate[VK_CAPITAL] );
698 send_keyboard_input( 0, VK_CAPITAL, 0x3a, 0 );
699 send_keyboard_input( 0, VK_CAPITAL, 0x3a, KEYEVENTF_KEYUP );
702 if (!(keystate[VK_NUMLOCK] & 0x01) != !(state & AMETA_NUM_LOCK_ON) && (vkey & 0xff) != VK_NUMLOCK)
704 TRACE( "adjusting NumLock state (%02x)\n", keystate[VK_NUMLOCK] );
705 send_keyboard_input( 0, VK_NUMLOCK, 0x45, KEYEVENTF_EXTENDEDKEY );
706 send_keyboard_input( 0, VK_NUMLOCK, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP );
709 if (!(keystate[VK_SCROLL] & 0x01) != !(state & AMETA_SCROLL_LOCK_ON) && vkey != VK_SCROLL)
711 TRACE( "adjusting ScrollLock state (%02x)\n", keystate[VK_SCROLL] );
712 send_keyboard_input( 0, VK_SCROLL, 0x46, 0 );
713 send_keyboard_input( 0, VK_SCROLL, 0x46, KEYEVENTF_KEYUP );
718 /***********************************************************************
719 * keyboard_event
721 * JNI callback, runs in the context of the Java thread.
723 jboolean keyboard_event( JNIEnv *env, jobject obj, jint win, jint action, jint keycode, jint state )
725 union event_data data;
727 if ((unsigned int)keycode >= sizeof(keycode_to_vkey)/sizeof(keycode_to_vkey[0]) ||
728 !keycode_to_vkey[keycode])
730 p__android_log_print( ANDROID_LOG_WARN, "wine",
731 "keyboard_event: win %x code %u unmapped key, ignoring", win, keycode );
732 return JNI_FALSE;
734 data.type = KEYBOARD_EVENT;
735 data.kbd.hwnd = LongToHandle( win );
736 data.kbd.lock_state = state;
737 data.kbd.input.type = INPUT_KEYBOARD;
738 data.kbd.input.u.ki.wVk = keycode_to_vkey[keycode];
739 data.kbd.input.u.ki.wScan = vkey_to_scancode[data.kbd.input.u.ki.wVk];
740 data.kbd.input.u.ki.time = 0;
741 data.kbd.input.u.ki.dwExtraInfo = 0;
742 data.kbd.input.u.ki.dwFlags = (data.kbd.input.u.ki.wScan & 0x100) ? KEYEVENTF_EXTENDEDKEY : 0;
743 if (action == AKEY_EVENT_ACTION_UP) data.kbd.input.u.ki.dwFlags |= KEYEVENTF_KEYUP;
745 p__android_log_print( ANDROID_LOG_INFO, "wine",
746 "keyboard_event: win %x code %u vkey %x scan %x meta %x",
747 win, keycode, data.kbd.input.u.ki.wVk, data.kbd.input.u.ki.wScan, state );
748 send_event( &data );
749 return JNI_TRUE;
753 /***********************************************************************
754 * ANDROID_ToUnicodeEx
756 INT CDECL ANDROID_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
757 LPWSTR buf, int size, UINT flags, HKL hkl )
759 WCHAR buffer[2];
760 BOOL shift = state[VK_SHIFT] & 0x80;
761 BOOL ctrl = state[VK_CONTROL] & 0x80;
762 BOOL numlock = state[VK_NUMLOCK] & 0x01;
764 buffer[0] = buffer[1] = 0;
766 if (scan & 0x8000) return 0; /* key up */
768 /* FIXME: hardcoded layout */
770 if (!ctrl)
772 switch (virt)
774 case VK_BACK: buffer[0] = '\b'; break;
775 case VK_OEM_1: buffer[0] = shift ? ':' : ';'; break;
776 case VK_OEM_2: buffer[0] = shift ? '?' : '/'; break;
777 case VK_OEM_3: buffer[0] = shift ? '~' : '`'; break;
778 case VK_OEM_4: buffer[0] = shift ? '{' : '['; break;
779 case VK_OEM_5: buffer[0] = shift ? '|' : '\\'; break;
780 case VK_OEM_6: buffer[0] = shift ? '}' : ']'; break;
781 case VK_OEM_7: buffer[0] = shift ? '"' : '\''; break;
782 case VK_OEM_COMMA: buffer[0] = shift ? '<' : ','; break;
783 case VK_OEM_MINUS: buffer[0] = shift ? '_' : '-'; break;
784 case VK_OEM_PERIOD: buffer[0] = shift ? '>' : '.'; break;
785 case VK_OEM_PLUS: buffer[0] = shift ? '+' : '='; break;
786 case VK_RETURN: buffer[0] = '\r'; break;
787 case VK_SPACE: buffer[0] = ' '; break;
788 case VK_TAB: buffer[0] = '\t'; break;
789 case VK_MULTIPLY: buffer[0] = '*'; break;
790 case VK_ADD: buffer[0] = '+'; break;
791 case VK_SUBTRACT: buffer[0] = '-'; break;
792 case VK_DIVIDE: buffer[0] = '/'; break;
793 default:
794 if (virt >= '0' && virt <= '9')
796 buffer[0] = shift ? ")!@#$%^&*("[virt - '0'] : virt;
797 break;
799 if (virt >= 'A' && virt <= 'Z')
801 buffer[0] = shift || (state[VK_CAPITAL] & 0x01) ? virt : virt + 'a' - 'A';
802 break;
804 if (virt >= VK_NUMPAD0 && virt <= VK_NUMPAD9 && numlock && !shift)
806 buffer[0] = '0' + virt - VK_NUMPAD0;
807 break;
809 if (virt == VK_DECIMAL && numlock && !shift)
811 buffer[0] = '.';
812 break;
814 break;
817 else /* Control codes */
819 if (virt >= 'A' && virt <= 'Z')
820 buffer[0] = virt - 'A' + 1;
821 else
823 switch (virt)
825 case VK_OEM_4:
826 buffer[0] = 0x1b;
827 break;
828 case VK_OEM_5:
829 buffer[0] = 0x1c;
830 break;
831 case VK_OEM_6:
832 buffer[0] = 0x1d;
833 break;
834 case VK_SUBTRACT:
835 buffer[0] = 0x1e;
836 break;
841 lstrcpynW( buf, buffer, size );
842 TRACE( "returning %d / %s\n", strlenW( buffer ), debugstr_wn(buf, strlenW( buffer )));
843 return strlenW( buffer );
847 /***********************************************************************
848 * ANDROID_GetKeyNameText
850 INT CDECL ANDROID_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size )
852 int scancode, vkey, len;
853 const char *name;
854 char key[2];
856 scancode = (lparam >> 16) & 0x1FF;
857 vkey = scancode_to_vkey( scancode );
859 if (lparam & (1 << 25))
861 /* Caller doesn't care about distinctions between left and
862 right keys. */
863 switch (vkey)
865 case VK_LSHIFT:
866 case VK_RSHIFT:
867 vkey = VK_SHIFT; break;
868 case VK_LCONTROL:
869 case VK_RCONTROL:
870 vkey = VK_CONTROL; break;
871 case VK_LMENU:
872 case VK_RMENU:
873 vkey = VK_MENU; break;
877 if (scancode & 0x100) vkey |= 0x100;
879 if ((vkey >= 0x30 && vkey <= 0x39) || (vkey >= 0x41 && vkey <= 0x5a))
881 key[0] = vkey;
882 if (vkey >= 0x41)
883 key[0] += 0x20;
884 key[1] = 0;
885 name = key;
887 else
889 name = vkey_to_name( vkey );
892 len = MultiByteToWideChar( CP_UTF8, 0, name, -1, buffer, size );
893 if (len) len--;
895 if (!len)
897 static const WCHAR format[] = {'K','e','y',' ','0','x','%','0','2','x',0};
898 snprintfW( buffer, size, format, vkey );
899 len = strlenW( buffer );
902 TRACE( "lparam 0x%08x -> %s\n", lparam, debugstr_w( buffer ));
903 return len;
907 /***********************************************************************
908 * ANDROID_MapVirtualKeyEx
910 UINT CDECL ANDROID_MapVirtualKeyEx( UINT code, UINT maptype, HKL hkl )
912 UINT ret = 0;
913 const char *s;
915 TRACE_(key)( "code=0x%x, maptype=%d, hkl %p\n", code, maptype, hkl );
917 switch (maptype)
919 case MAPVK_VK_TO_VSC_EX:
920 case MAPVK_VK_TO_VSC:
921 /* vkey to scancode */
922 switch (code)
924 case VK_SHIFT:
925 code = VK_LSHIFT;
926 break;
927 case VK_CONTROL:
928 code = VK_LCONTROL;
929 break;
930 case VK_MENU:
931 code = VK_LMENU;
932 break;
934 if (code < sizeof(vkey_to_scancode) / sizeof(vkey_to_scancode[0])) ret = vkey_to_scancode[code];
935 break;
936 case MAPVK_VSC_TO_VK:
937 case MAPVK_VSC_TO_VK_EX:
938 /* scancode to vkey */
939 ret = scancode_to_vkey( code );
940 if (maptype == MAPVK_VSC_TO_VK)
941 switch (ret)
943 case VK_LSHIFT:
944 case VK_RSHIFT:
945 ret = VK_SHIFT; break;
946 case VK_LCONTROL:
947 case VK_RCONTROL:
948 ret = VK_CONTROL; break;
949 case VK_LMENU:
950 case VK_RMENU:
951 ret = VK_MENU; break;
953 break;
954 case MAPVK_VK_TO_CHAR:
955 s = vkey_to_name( code );
956 if (s && (strlen( s ) == 1))
957 ret = s[0];
958 else
959 ret = 0;
960 break;
961 default:
962 FIXME( "Unknown maptype %d\n", maptype );
963 break;
965 TRACE_(key)( "returning 0x%04x\n", ret );
966 return ret;
970 /***********************************************************************
971 * ANDROID_GetKeyboardLayout
973 HKL CDECL ANDROID_GetKeyboardLayout( DWORD thread_id )
975 ULONG_PTR layout = GetUserDefaultLCID();
976 LANGID langid;
978 langid = PRIMARYLANGID(LANGIDFROMLCID( layout ));
979 if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
980 layout = MAKELONG( layout, 0xe001 ); /* IME */
981 else
982 layout |= layout << 16;
984 FIXME( "returning %lx\n", layout );
985 return (HKL)layout;
989 /***********************************************************************
990 * ANDROID_VkKeyScanEx
992 SHORT CDECL ANDROID_VkKeyScanEx( WCHAR ch, HKL hkl )
994 SHORT ret = -1;
995 if (ch < sizeof(char_vkey_map) / sizeof(char_vkey_map[0])) ret = char_vkey_map[ch];
996 TRACE_(key)( "ch %04x hkl %p -> %04x\n", ch, hkl, ret );
997 return ret;