FreeRDP
Loading...
Searching...
No Matches
KeyboardMapper.java
1/*
2 Android Keyboard Mapping
3
4 Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
5
6 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
7 If a copy of the MPL was not distributed with this file, You can obtain one at
8 http://mozilla.org/MPL/2.0/.
9*/
10
11package com.freerdp.freerdpcore.utils;
12
13import android.content.Context;
14import android.view.KeyCharacterMap;
15import android.view.KeyEvent;
16
17import com.freerdp.freerdpcore.R;
18
19public class KeyboardMapper
20{
21 public static final int KEYBOARD_TYPE_FUNCTIONKEYS = 1;
22 public static final int KEYBOARD_TYPE_NUMPAD = 2;
23 public static final int KEYBOARD_TYPE_CURSOR = 3;
24
25 // defines key states for modifier keys - locked means on and no auto-release if an other key is
26 // pressed
27 public static final int KEYSTATE_ON = 1;
28 public static final int KEYSTATE_LOCKED = 2;
29 public static final int KEYSTATE_OFF = 3;
30 final static int VK_LBUTTON = 0x01;
31 final static int VK_RBUTTON = 0x02;
32 final static int VK_CANCEL = 0x03;
33 final static int VK_MBUTTON = 0x04;
34 final static int VK_XBUTTON1 = 0x05;
35 final static int VK_XBUTTON2 = 0x06;
36 final static int VK_BACK = 0x08;
37 final static int VK_TAB = 0x09;
38 final static int VK_CLEAR = 0x0C;
39 final static int VK_RETURN = 0x0D;
40 final static int VK_SHIFT = 0x10;
41 final static int VK_CONTROL = 0x11;
42 final static int VK_MENU = 0x12;
43 final static int VK_PAUSE = 0x13;
44 final static int VK_CAPITAL = 0x14;
45 final static int VK_KANA = 0x15;
46 final static int VK_HANGUEL = 0x15;
47 final static int VK_HANGUL = 0x15;
48 final static int VK_JUNJA = 0x17;
49 final static int VK_FINAL = 0x18;
50 final static int VK_HANJA = 0x19;
51 final static int VK_KANJI = 0x19;
52 final static int VK_ESCAPE = 0x1B;
53 final static int VK_CONVERT = 0x1C;
54 final static int VK_NONCONVERT = 0x1D;
55 final static int VK_ACCEPT = 0x1E;
56 final static int VK_MODECHANGE = 0x1F;
57 final static int VK_SPACE = 0x20;
58 final static int VK_PRIOR = 0x21;
59 final static int VK_NEXT = 0x22;
60 final static int VK_END = 0x23;
61 final static int VK_HOME = 0x24;
62 final static int VK_LEFT = 0x25;
63 final static int VK_UP = 0x26;
64 final static int VK_RIGHT = 0x27;
65 final static int VK_DOWN = 0x28;
66 final static int VK_SELECT = 0x29;
67 final static int VK_PRINT = 0x2A;
68 final static int VK_EXECUTE = 0x2B;
69 final static int VK_SNAPSHOT = 0x2C;
70 final static int VK_INSERT = 0x2D;
71 final static int VK_DELETE = 0x2E;
72 final static int VK_HELP = 0x2F;
73 final static int VK_KEY_0 = 0x30;
74 final static int VK_KEY_1 = 0x31;
75 final static int VK_KEY_2 = 0x32;
76 final static int VK_KEY_3 = 0x33;
77 final static int VK_KEY_4 = 0x34;
78 final static int VK_KEY_5 = 0x35;
79 final static int VK_KEY_6 = 0x36;
80 final static int VK_KEY_7 = 0x37;
81 final static int VK_KEY_8 = 0x38;
82 final static int VK_KEY_9 = 0x39;
83 final static int VK_KEY_A = 0x41;
84 final static int VK_KEY_B = 0x42;
85 final static int VK_KEY_C = 0x43;
86 final static int VK_KEY_D = 0x44;
87 final static int VK_KEY_E = 0x45;
88 final static int VK_KEY_F = 0x46;
89 final static int VK_KEY_G = 0x47;
90 final static int VK_KEY_H = 0x48;
91 final static int VK_KEY_I = 0x49;
92 final static int VK_KEY_J = 0x4A;
93 final static int VK_KEY_K = 0x4B;
94 final static int VK_KEY_L = 0x4C;
95 final static int VK_KEY_M = 0x4D;
96 final static int VK_KEY_N = 0x4E;
97 final static int VK_KEY_O = 0x4F;
98 final static int VK_KEY_P = 0x50;
99 final static int VK_KEY_Q = 0x51;
100 final static int VK_KEY_R = 0x52;
101 final static int VK_KEY_S = 0x53;
102 final static int VK_KEY_T = 0x54;
103 final static int VK_KEY_U = 0x55;
104 final static int VK_KEY_V = 0x56;
105 final static int VK_KEY_W = 0x57;
106 final static int VK_KEY_X = 0x58;
107 final static int VK_KEY_Y = 0x59;
108 final static int VK_KEY_Z = 0x5A;
109 final static int VK_LWIN = 0x5B;
110 final static int VK_RWIN = 0x5C;
111 final static int VK_APPS = 0x5D;
112 final static int VK_SLEEP = 0x5F;
113 final static int VK_NUMPAD0 = 0x60;
114 final static int VK_NUMPAD1 = 0x61;
115 final static int VK_NUMPAD2 = 0x62;
116 final static int VK_NUMPAD3 = 0x63;
117 final static int VK_NUMPAD4 = 0x64;
118 final static int VK_NUMPAD5 = 0x65;
119 final static int VK_NUMPAD6 = 0x66;
120 final static int VK_NUMPAD7 = 0x67;
121 final static int VK_NUMPAD8 = 0x68;
122 final static int VK_NUMPAD9 = 0x69;
123 final static int VK_MULTIPLY = 0x6A;
124 final static int VK_ADD = 0x6B;
125 final static int VK_SEPARATOR = 0x6C;
126 final static int VK_SUBTRACT = 0x6D;
127 final static int VK_DECIMAL = 0x6E;
128 final static int VK_DIVIDE = 0x6F;
129 final static int VK_F1 = 0x70;
130 final static int VK_F2 = 0x71;
131 final static int VK_F3 = 0x72;
132 final static int VK_F4 = 0x73;
133 final static int VK_F5 = 0x74;
134 final static int VK_F6 = 0x75;
135 final static int VK_F7 = 0x76;
136 final static int VK_F8 = 0x77;
137 final static int VK_F9 = 0x78;
138 final static int VK_F10 = 0x79;
139 final static int VK_F11 = 0x7A;
140 final static int VK_F12 = 0x7B;
141 final static int VK_F13 = 0x7C;
142 final static int VK_F14 = 0x7D;
143 final static int VK_F15 = 0x7E;
144 final static int VK_F16 = 0x7F;
145 final static int VK_F17 = 0x80;
146 final static int VK_F18 = 0x81;
147 final static int VK_F19 = 0x82;
148 final static int VK_F20 = 0x83;
149 final static int VK_F21 = 0x84;
150 final static int VK_F22 = 0x85;
151 final static int VK_F23 = 0x86;
152 final static int VK_F24 = 0x87;
153 final static int VK_NUMLOCK = 0x90;
154 final static int VK_SCROLL = 0x91;
155 final static int VK_LSHIFT = 0xA0;
156 final static int VK_RSHIFT = 0xA1;
157 final static int VK_LCONTROL = 0xA2;
158 final static int VK_RCONTROL = 0xA3;
159 final static int VK_LMENU = 0xA4;
160 final static int VK_RMENU = 0xA5;
161 final static int VK_BROWSER_BACK = 0xA6;
162 final static int VK_BROWSER_FORWARD = 0xA7;
163 final static int VK_BROWSER_REFRESH = 0xA8;
164 final static int VK_BROWSER_STOP = 0xA9;
165 final static int VK_BROWSER_SEARCH = 0xAA;
166 final static int VK_BROWSER_FAVORITES = 0xAB;
167 final static int VK_BROWSER_HOME = 0xAC;
168 final static int VK_VOLUME_MUTE = 0xAD;
169 final static int VK_VOLUME_DOWN = 0xAE;
170 final static int VK_VOLUME_UP = 0xAF;
171 final static int VK_MEDIA_NEXT_TRACK = 0xB0;
172 final static int VK_MEDIA_PREV_TRACK = 0xB1;
173 final static int VK_MEDIA_STOP = 0xB2;
174 final static int VK_MEDIA_PLAY_PAUSE = 0xB3;
175 final static int VK_LAUNCH_MAIL = 0xB4;
176 final static int VK_LAUNCH_MEDIA_SELECT = 0xB5;
177 final static int VK_LAUNCH_APP1 = 0xB6;
178 final static int VK_LAUNCH_APP2 = 0xB7;
179 final static int VK_OEM_1 = 0xBA;
180 final static int VK_OEM_PLUS = 0xBB;
181 final static int VK_OEM_COMMA = 0xBC;
182 final static int VK_OEM_MINUS = 0xBD;
183 final static int VK_OEM_PERIOD = 0xBE;
184 final static int VK_OEM_2 = 0xBF;
185 final static int VK_OEM_3 = 0xC0;
186 final static int VK_ABNT_C1 = 0xC1;
187 final static int VK_ABNT_C2 = 0xC2;
188 final static int VK_OEM_4 = 0xDB;
189 final static int VK_OEM_5 = 0xDC;
190 final static int VK_OEM_6 = 0xDD;
191 final static int VK_OEM_7 = 0xDE;
192 final static int VK_OEM_8 = 0xDF;
193 final static int VK_OEM_102 = 0xE2;
194 final static int VK_PROCESSKEY = 0xE5;
195 final static int VK_PACKET = 0xE7;
196 final static int VK_ATTN = 0xF6;
197 final static int VK_CRSEL = 0xF7;
198 final static int VK_EXSEL = 0xF8;
199 final static int VK_EREOF = 0xF9;
200 final static int VK_PLAY = 0xFA;
201 final static int VK_ZOOM = 0xFB;
202 final static int VK_NONAME = 0xFC;
203 final static int VK_PA1 = 0xFD;
204 final static int VK_OEM_CLEAR = 0xFE;
205 final static int VK_UNICODE = 0x80000000;
206 final static int VK_EXT_KEY = 0x00000100;
207 // key codes to switch between custom keyboard
208 private final static int EXTKEY_KBFUNCTIONKEYS = 0x1100;
209 private final static int EXTKEY_KBNUMPAD = 0x1101;
210 private final static int EXTKEY_KBCURSOR = 0x1102;
211 // this flag indicates if we got a VK or a unicode character in our translation map
212 private static final int KEY_FLAG_UNICODE = 0x80000000;
213 // this flag indicates if the key is a toggle key (remains down when pressed and goes up if
214 // pressed again)
215 private static final int KEY_FLAG_TOGGLE = 0x40000000;
216 private static int[] keymapAndroid;
217 private static int[] keymapExt;
218 private static boolean initialized = false;
219 private KeyProcessingListener listener = null;
220 private boolean shiftPressed = false;
221 private boolean ctrlPressed = false;
222 private boolean altPressed = false;
223 private boolean winPressed = false;
224 private long lastModifierTime;
225 private int lastModifierKeyCode = -1;
226 private boolean isShiftLocked = false;
227 private boolean isCtrlLocked = false;
228 private boolean isAltLocked = false;
229 private boolean isWinLocked = false;
230 private boolean isWinKeyDown = false;
231 private boolean isWinComboUsed = false;
232
233 public void init(Context context)
234 {
235 if (initialized)
236 return;
237
238 keymapAndroid = new int[256];
239
240 keymapAndroid[KeyEvent.KEYCODE_0] = VK_KEY_0;
241 keymapAndroid[KeyEvent.KEYCODE_1] = VK_KEY_1;
242 keymapAndroid[KeyEvent.KEYCODE_2] = VK_KEY_2;
243 keymapAndroid[KeyEvent.KEYCODE_3] = VK_KEY_3;
244 keymapAndroid[KeyEvent.KEYCODE_4] = VK_KEY_4;
245 keymapAndroid[KeyEvent.KEYCODE_5] = VK_KEY_5;
246 keymapAndroid[KeyEvent.KEYCODE_6] = VK_KEY_6;
247 keymapAndroid[KeyEvent.KEYCODE_7] = VK_KEY_7;
248 keymapAndroid[KeyEvent.KEYCODE_8] = VK_KEY_8;
249 keymapAndroid[KeyEvent.KEYCODE_9] = VK_KEY_9;
250
251 keymapAndroid[KeyEvent.KEYCODE_A] = VK_KEY_A;
252 keymapAndroid[KeyEvent.KEYCODE_B] = VK_KEY_B;
253 keymapAndroid[KeyEvent.KEYCODE_C] = VK_KEY_C;
254 keymapAndroid[KeyEvent.KEYCODE_D] = VK_KEY_D;
255 keymapAndroid[KeyEvent.KEYCODE_E] = VK_KEY_E;
256 keymapAndroid[KeyEvent.KEYCODE_F] = VK_KEY_F;
257 keymapAndroid[KeyEvent.KEYCODE_G] = VK_KEY_G;
258 keymapAndroid[KeyEvent.KEYCODE_H] = VK_KEY_H;
259 keymapAndroid[KeyEvent.KEYCODE_I] = VK_KEY_I;
260 keymapAndroid[KeyEvent.KEYCODE_J] = VK_KEY_J;
261 keymapAndroid[KeyEvent.KEYCODE_K] = VK_KEY_K;
262 keymapAndroid[KeyEvent.KEYCODE_L] = VK_KEY_L;
263 keymapAndroid[KeyEvent.KEYCODE_M] = VK_KEY_M;
264 keymapAndroid[KeyEvent.KEYCODE_N] = VK_KEY_N;
265 keymapAndroid[KeyEvent.KEYCODE_O] = VK_KEY_O;
266 keymapAndroid[KeyEvent.KEYCODE_P] = VK_KEY_P;
267 keymapAndroid[KeyEvent.KEYCODE_Q] = VK_KEY_Q;
268 keymapAndroid[KeyEvent.KEYCODE_R] = VK_KEY_R;
269 keymapAndroid[KeyEvent.KEYCODE_S] = VK_KEY_S;
270 keymapAndroid[KeyEvent.KEYCODE_T] = VK_KEY_T;
271 keymapAndroid[KeyEvent.KEYCODE_U] = VK_KEY_U;
272 keymapAndroid[KeyEvent.KEYCODE_V] = VK_KEY_V;
273 keymapAndroid[KeyEvent.KEYCODE_W] = VK_KEY_W;
274 keymapAndroid[KeyEvent.KEYCODE_X] = VK_KEY_X;
275 keymapAndroid[KeyEvent.KEYCODE_Y] = VK_KEY_Y;
276 keymapAndroid[KeyEvent.KEYCODE_Z] = VK_KEY_Z;
277
278 keymapAndroid[KeyEvent.KEYCODE_DEL] = VK_BACK;
279 keymapAndroid[KeyEvent.KEYCODE_ENTER] = VK_RETURN;
280 keymapAndroid[KeyEvent.KEYCODE_SPACE] = VK_SPACE;
281 keymapAndroid[KeyEvent.KEYCODE_TAB] = VK_TAB;
282 keymapAndroid[KeyEvent.KEYCODE_ESCAPE] = VK_ESCAPE;
283 keymapAndroid[KeyEvent.KEYCODE_CAPS_LOCK] = VK_CAPITAL;
284 // keymapAndroid[KeyEvent.KEYCODE_SHIFT_LEFT] = VK_LSHIFT;
285 // keymapAndroid[KeyEvent.KEYCODE_SHIFT_RIGHT] = VK_RSHIFT;
286
287 keymapAndroid[KeyEvent.KEYCODE_DPAD_DOWN] = VK_DOWN | VK_EXT_KEY;
288 keymapAndroid[KeyEvent.KEYCODE_DPAD_LEFT] = VK_LEFT | VK_EXT_KEY;
289 keymapAndroid[KeyEvent.KEYCODE_DPAD_RIGHT] = VK_RIGHT | VK_EXT_KEY;
290 keymapAndroid[KeyEvent.KEYCODE_DPAD_UP] = VK_UP | VK_EXT_KEY;
291 keymapAndroid[KeyEvent.KEYCODE_MOVE_HOME] = VK_HOME | VK_EXT_KEY;
292 keymapAndroid[KeyEvent.KEYCODE_MOVE_END] = VK_END | VK_EXT_KEY;
293 keymapAndroid[KeyEvent.KEYCODE_PAGE_UP] = VK_PRIOR | VK_EXT_KEY;
294 keymapAndroid[KeyEvent.KEYCODE_PAGE_DOWN] = VK_NEXT | VK_EXT_KEY;
295 keymapAndroid[KeyEvent.KEYCODE_FORWARD_DEL] = VK_DELETE | VK_EXT_KEY;
296 keymapAndroid[KeyEvent.KEYCODE_INSERT] = VK_INSERT | VK_EXT_KEY;
297
298 keymapAndroid[KeyEvent.KEYCODE_MINUS] = VK_OEM_MINUS;
299 keymapAndroid[KeyEvent.KEYCODE_EQUALS] = VK_OEM_PLUS;
300 keymapAndroid[KeyEvent.KEYCODE_LEFT_BRACKET] = VK_OEM_4;
301 keymapAndroid[KeyEvent.KEYCODE_RIGHT_BRACKET] = VK_OEM_6;
302 keymapAndroid[KeyEvent.KEYCODE_BACKSLASH] = VK_OEM_5;
303 keymapAndroid[KeyEvent.KEYCODE_SEMICOLON] = VK_OEM_1;
304 keymapAndroid[KeyEvent.KEYCODE_APOSTROPHE] = VK_OEM_7;
305 keymapAndroid[KeyEvent.KEYCODE_GRAVE] = VK_OEM_3;
306 keymapAndroid[KeyEvent.KEYCODE_COMMA] = VK_OEM_COMMA;
307 keymapAndroid[KeyEvent.KEYCODE_PERIOD] = VK_OEM_PERIOD;
308 keymapAndroid[KeyEvent.KEYCODE_SLASH] = VK_OEM_2;
309
310 keymapAndroid[KeyEvent.KEYCODE_F1] = VK_F1;
311 keymapAndroid[KeyEvent.KEYCODE_F2] = VK_F2;
312 keymapAndroid[KeyEvent.KEYCODE_F3] = VK_F3;
313 keymapAndroid[KeyEvent.KEYCODE_F4] = VK_F4;
314 keymapAndroid[KeyEvent.KEYCODE_F5] = VK_F5;
315 keymapAndroid[KeyEvent.KEYCODE_F6] = VK_F6;
316 keymapAndroid[KeyEvent.KEYCODE_F7] = VK_F7;
317 keymapAndroid[KeyEvent.KEYCODE_F8] = VK_F8;
318 keymapAndroid[KeyEvent.KEYCODE_F9] = VK_F9;
319 keymapAndroid[KeyEvent.KEYCODE_F10] = VK_F10;
320 keymapAndroid[KeyEvent.KEYCODE_F11] = VK_F11;
321 keymapAndroid[KeyEvent.KEYCODE_F12] = VK_F12;
322
323 keymapAndroid[KeyEvent.KEYCODE_NUM_LOCK] = VK_NUMLOCK;
324 keymapAndroid[KeyEvent.KEYCODE_SCROLL_LOCK] = VK_SCROLL;
325 keymapAndroid[KeyEvent.KEYCODE_SYSRQ] = VK_SNAPSHOT | VK_EXT_KEY;
326 keymapAndroid[KeyEvent.KEYCODE_BREAK] = VK_PAUSE;
327
328 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_0] = VK_NUMPAD0;
329 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_1] = VK_NUMPAD1;
330 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_2] = VK_NUMPAD2;
331 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_3] = VK_NUMPAD3;
332 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_4] = VK_NUMPAD4;
333 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_5] = VK_NUMPAD5;
334 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_6] = VK_NUMPAD6;
335 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_7] = VK_NUMPAD7;
336 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_8] = VK_NUMPAD8;
337 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_9] = VK_NUMPAD9;
338 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_DIVIDE] = VK_DIVIDE | VK_EXT_KEY;
339 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_MULTIPLY] = VK_MULTIPLY;
340 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_SUBTRACT] = VK_SUBTRACT;
341 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_ADD] = VK_ADD;
342 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_DOT] = VK_DECIMAL;
343 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_COMMA] = VK_DECIMAL;
344 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_ENTER] = VK_RETURN | VK_EXT_KEY;
345 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_EQUALS] = KEY_FLAG_UNICODE | 61;
346 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN] = KEY_FLAG_UNICODE | 40;
347 keymapAndroid[KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN] = KEY_FLAG_UNICODE | 41;
348
349 // special keys mapping
350 keymapExt = new int[256];
351 keymapExt[context.getResources().getInteger(R.integer.keycode_F1)] = VK_F1;
352 keymapExt[context.getResources().getInteger(R.integer.keycode_F2)] = VK_F2;
353 keymapExt[context.getResources().getInteger(R.integer.keycode_F3)] = VK_F3;
354 keymapExt[context.getResources().getInteger(R.integer.keycode_F4)] = VK_F4;
355 keymapExt[context.getResources().getInteger(R.integer.keycode_F5)] = VK_F5;
356 keymapExt[context.getResources().getInteger(R.integer.keycode_F6)] = VK_F6;
357 keymapExt[context.getResources().getInteger(R.integer.keycode_F7)] = VK_F7;
358 keymapExt[context.getResources().getInteger(R.integer.keycode_F8)] = VK_F8;
359 keymapExt[context.getResources().getInteger(R.integer.keycode_F9)] = VK_F9;
360 keymapExt[context.getResources().getInteger(R.integer.keycode_F10)] = VK_F10;
361 keymapExt[context.getResources().getInteger(R.integer.keycode_F11)] = VK_F11;
362 keymapExt[context.getResources().getInteger(R.integer.keycode_F12)] = VK_F12;
363 keymapExt[context.getResources().getInteger(R.integer.keycode_tab)] = VK_TAB;
364 keymapExt[context.getResources().getInteger(R.integer.keycode_print)] = VK_PRINT;
365 keymapExt[context.getResources().getInteger(R.integer.keycode_insert)] =
366 VK_INSERT | VK_EXT_KEY;
367 keymapExt[context.getResources().getInteger(R.integer.keycode_delete)] =
368 VK_DELETE | VK_EXT_KEY;
369 keymapExt[context.getResources().getInteger(R.integer.keycode_home)] = VK_HOME | VK_EXT_KEY;
370 keymapExt[context.getResources().getInteger(R.integer.keycode_end)] = VK_END | VK_EXT_KEY;
371 keymapExt[context.getResources().getInteger(R.integer.keycode_pgup)] =
372 VK_PRIOR | VK_EXT_KEY;
373 keymapExt[context.getResources().getInteger(R.integer.keycode_pgdn)] = VK_NEXT | VK_EXT_KEY;
374
375 // numpad mapping
376 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_0)] = VK_NUMPAD0;
377 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_1)] = VK_NUMPAD1;
378 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_2)] = VK_NUMPAD2;
379 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_3)] = VK_NUMPAD3;
380 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_4)] = VK_NUMPAD4;
381 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_5)] = VK_NUMPAD5;
382 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_6)] = VK_NUMPAD6;
383 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_7)] = VK_NUMPAD7;
384 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_8)] = VK_NUMPAD8;
385 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_9)] = VK_NUMPAD9;
386 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_numlock)] = VK_NUMLOCK;
387 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_add)] = VK_ADD;
388 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_comma)] = VK_DECIMAL;
389 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_divide)] =
390 VK_DIVIDE | VK_EXT_KEY;
391 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_enter)] =
392 VK_RETURN | VK_EXT_KEY;
393 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_multiply)] =
394 VK_MULTIPLY;
395 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_subtract)] =
396 VK_SUBTRACT;
397 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_equals)] =
398 (KEY_FLAG_UNICODE | 61);
399 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_left_paren)] =
400 (KEY_FLAG_UNICODE | 40);
401 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_right_paren)] =
402 (KEY_FLAG_UNICODE | 41);
403
404 // cursor key codes
405 keymapExt[context.getResources().getInteger(R.integer.keycode_up)] = VK_UP | VK_EXT_KEY;
406 keymapExt[context.getResources().getInteger(R.integer.keycode_down)] = VK_DOWN | VK_EXT_KEY;
407 keymapExt[context.getResources().getInteger(R.integer.keycode_left)] = VK_LEFT | VK_EXT_KEY;
408 keymapExt[context.getResources().getInteger(R.integer.keycode_right)] =
409 VK_RIGHT | VK_EXT_KEY;
410 keymapExt[context.getResources().getInteger(R.integer.keycode_enter)] =
411 VK_RETURN | VK_EXT_KEY;
412 keymapExt[context.getResources().getInteger(R.integer.keycode_backspace)] = VK_BACK;
413
414 // shared keys
415 keymapExt[context.getResources().getInteger(R.integer.keycode_win)] = VK_LWIN | VK_EXT_KEY;
416 keymapExt[context.getResources().getInteger(R.integer.keycode_menu)] = VK_APPS | VK_EXT_KEY;
417 keymapExt[context.getResources().getInteger(R.integer.keycode_esc)] = VK_ESCAPE;
418
419 /* keymapExt[context.getResources().getInteger(R.integer.keycode_modifier_ctrl)] =
420 VK_LCONTROL; keymapExt[context.getResources().getInteger(R.integer.keycode_modifier_alt)]
421 = VK_LMENU;
422 keymapExt[context.getResources().getInteger(R.integer.keycode_modifier_shift)] =
423 VK_LSHIFT;
424 */
425 // get custom keyboard key codes
426 keymapExt[context.getResources().getInteger(R.integer.keycode_specialkeys_keyboard)] =
427 EXTKEY_KBFUNCTIONKEYS;
428 keymapExt[context.getResources().getInteger(R.integer.keycode_numpad_keyboard)] =
429 EXTKEY_KBNUMPAD;
430 keymapExt[context.getResources().getInteger(R.integer.keycode_cursor_keyboard)] =
431 EXTKEY_KBCURSOR;
432
433 keymapExt[context.getResources().getInteger(R.integer.keycode_toggle_shift)] =
434 (KEY_FLAG_TOGGLE | VK_LSHIFT);
435 keymapExt[context.getResources().getInteger(R.integer.keycode_toggle_ctrl)] =
436 (KEY_FLAG_TOGGLE | VK_LCONTROL);
437 keymapExt[context.getResources().getInteger(R.integer.keycode_toggle_alt)] =
438 (KEY_FLAG_TOGGLE | VK_LMENU);
439 keymapExt[context.getResources().getInteger(R.integer.keycode_toggle_win)] =
440 (KEY_FLAG_TOGGLE | VK_LWIN);
441
442 initialized = true;
443 }
444
445 public void reset(KeyProcessingListener listener)
446 {
447 shiftPressed = false;
448 ctrlPressed = false;
449 altPressed = false;
450 winPressed = false;
451 isWinKeyDown = false;
452 isWinComboUsed = false;
453 setKeyProcessingListener(listener);
454 }
455
456 public void setKeyProcessingListener(KeyProcessingListener listener)
457 {
458 this.listener = listener;
459 }
460
461 public boolean processAndroidKeyEvent(KeyEvent event)
462 {
463 switch (event.getAction())
464 {
465 // we only process down events
466 case KeyEvent.ACTION_UP:
467 {
468 if (event.getKeyCode() == KeyEvent.KEYCODE_META_LEFT ||
469 event.getKeyCode() == KeyEvent.KEYCODE_META_RIGHT)
470 {
471 if (!isWinKeyDown)
472 return false;
473 isWinKeyDown = false;
474 if (!isWinComboUsed)
475 {
476 listener.processVirtualKey(VK_LWIN | VK_EXT_KEY, true);
477 listener.processVirtualKey(VK_LWIN | VK_EXT_KEY, false);
478 }
479 isWinComboUsed = false;
480 return true;
481 }
482 return false;
483 }
484
485 case KeyEvent.ACTION_DOWN:
486 {
487 /* Physical Win key: buffer until release to distinguish tap vs combo. */
488 if (event.getKeyCode() == KeyEvent.KEYCODE_META_LEFT ||
489 event.getKeyCode() == KeyEvent.KEYCODE_META_RIGHT)
490 {
491 isWinKeyDown = true;
492 isWinComboUsed = false;
493 return true;
494 }
495
496 if (isWinKeyDown)
497 isWinComboUsed = true;
498
499 boolean modifierActive = isModifierPressed();
500 // if a modifier is pressed we will send a VK event (if possible) so that key
501 // combinations will be recognized correctly. Otherwise we will send the unicode
502 // key. At the end we will reset all modifiers and notify our listener.
503 int vkcode = getVirtualKeyCode(event.getKeyCode());
504 if ((vkcode & KEY_FLAG_UNICODE) != 0)
505 listener.processUnicodeKey(vkcode & (~KEY_FLAG_UNICODE));
506 // if we got a valid vkcode send it - except for letters/numbers if a modifier is
507 // active
508 else if (vkcode > 0 && !event.isSymPressed())
509 {
510 boolean sendCtrl = !ctrlPressed && event.isCtrlPressed();
511 boolean sendAlt = !altPressed && event.isAltPressed();
512 boolean sendWin = !winPressed && isWinKeyDown;
513 boolean sendShift = !shiftPressed && event.isShiftPressed();
514
515 if (sendCtrl)
516 listener.processVirtualKey(VK_LCONTROL, true);
517 if (sendAlt)
518 listener.processVirtualKey(VK_LMENU, true);
519 if (sendWin)
520 listener.processVirtualKey(VK_LWIN | VK_EXT_KEY, true);
521 if (sendShift)
522 listener.processVirtualKey(VK_LSHIFT, true);
523
524 listener.processVirtualKey(vkcode, true);
525 listener.processVirtualKey(vkcode, false);
526
527 if (sendShift)
528 listener.processVirtualKey(VK_LSHIFT, false);
529 if (sendWin)
530 listener.processVirtualKey(VK_LWIN | VK_EXT_KEY, false);
531 if (sendAlt)
532 listener.processVirtualKey(VK_LMENU, false);
533 if (sendCtrl)
534 listener.processVirtualKey(VK_LCONTROL, false);
535 }
536 else if (event.getUnicodeChar() != 0)
537 listener.processUnicodeKey(event.getUnicodeChar());
538 else
539 return false;
540
541 // reset any pending toggle states if a modifier was pressed
542 if (modifierActive)
543 resetModifierKeysAfterInput(false);
544 return true;
545 }
546
547 case KeyEvent.ACTION_MULTIPLE:
548 {
549 String str = event.getCharacters();
550 if (str != null)
551 {
552 for (int i = 0; i < str.length(); i++)
553 listener.processUnicodeKey(str.charAt(i));
554 }
555 return true;
556 }
557
558 default:
559 break;
560 }
561 return false;
562 }
563
564 public void processCustomKeyEvent(int keycode)
565 {
566 int extCode = getExtendedKeyCode(keycode);
567 if (extCode == 0)
568 return;
569
570 // toggle button pressed?
571 if ((extCode & KEY_FLAG_TOGGLE) != 0)
572 {
573 processToggleButton(extCode & (~KEY_FLAG_TOGGLE));
574 return;
575 }
576
577 // keyboard switch button pressed?
578 if (extCode == EXTKEY_KBFUNCTIONKEYS || extCode == EXTKEY_KBNUMPAD ||
579 extCode == EXTKEY_KBCURSOR)
580 {
581 switchKeyboard(extCode);
582 return;
583 }
584
585 // nope - see if we got a unicode or vk
586 if ((extCode & KEY_FLAG_UNICODE) != 0)
587 listener.processUnicodeKey(extCode & (~KEY_FLAG_UNICODE));
588 else
589 {
590 listener.processVirtualKey(extCode, true);
591 listener.processVirtualKey(extCode, false);
592 }
593
594 resetModifierKeysAfterInput(false);
595 }
596
597 public void processUnicodeFallback(int unicodeKey)
598 {
599 KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
600 KeyEvent[] events = kcm.getEvents(new char[] { (char)unicodeKey });
601 if (events == null)
602 return;
603 for (KeyEvent event : events)
604 {
605 int vkcode = fallbackVkcode(event.getKeyCode());
606 if (vkcode > 0)
607 listener.processVirtualKey(vkcode, event.getAction() == KeyEvent.ACTION_DOWN);
608 }
609 }
610
611 private int fallbackVkcode(int keycode)
612 {
613 switch (keycode)
614 {
615 case KeyEvent.KEYCODE_SHIFT_LEFT:
616 case KeyEvent.KEYCODE_SHIFT_RIGHT:
617 return VK_LSHIFT;
618 case KeyEvent.KEYCODE_ALT_LEFT:
619 case KeyEvent.KEYCODE_ALT_RIGHT:
620 return VK_LMENU;
621 case KeyEvent.KEYCODE_CTRL_LEFT:
622 case KeyEvent.KEYCODE_CTRL_RIGHT:
623 return VK_LCONTROL;
624 default:
625 return getVirtualKeyCode(keycode);
626 }
627 }
628
629 public void sendAltF4()
630 {
631 listener.processVirtualKey(VK_LMENU, true);
632 listener.processVirtualKey(VK_F4, true);
633 listener.processVirtualKey(VK_F4, false);
634 listener.processVirtualKey(VK_LMENU, false);
635 }
636
637 private boolean isModifierPressed()
638 {
639 return (shiftPressed || ctrlPressed || altPressed || winPressed);
640 }
641
642 public int getModifierState(int keycode)
643 {
644 int modifierCode = getExtendedKeyCode(keycode);
645
646 // check and get real modifier keycode
647 if ((modifierCode & KEY_FLAG_TOGGLE) == 0)
648 return -1;
649 modifierCode = modifierCode & (~KEY_FLAG_TOGGLE);
650
651 switch (modifierCode)
652 {
653 case VK_LSHIFT:
654 {
655 return (shiftPressed ? (isShiftLocked ? KEYSTATE_LOCKED : KEYSTATE_ON)
656 : KEYSTATE_OFF);
657 }
658 case VK_LCONTROL:
659 {
660 return (ctrlPressed ? (isCtrlLocked ? KEYSTATE_LOCKED : KEYSTATE_ON)
661 : KEYSTATE_OFF);
662 }
663 case VK_LMENU:
664 {
665 return (altPressed ? (isAltLocked ? KEYSTATE_LOCKED : KEYSTATE_ON) : KEYSTATE_OFF);
666 }
667 case VK_LWIN:
668 {
669 return (winPressed ? (isWinLocked ? KEYSTATE_LOCKED : KEYSTATE_ON) : KEYSTATE_OFF);
670 }
671 }
672
673 return -1;
674 }
675
676 private int getVirtualKeyCode(int keycode)
677 {
678 if (keycode >= 0 && keycode <= 0xFF)
679 return keymapAndroid[keycode];
680 return 0;
681 }
682
683 private int getExtendedKeyCode(int keycode)
684 {
685 if (keycode >= 0 && keycode <= 0xFF)
686 return keymapExt[keycode];
687 return 0;
688 }
689
690 private void processToggleButton(int keycode)
691 {
692 switch (keycode)
693 {
694 case VK_LSHIFT:
695 {
696 if (!checkToggleModifierLock(VK_LSHIFT))
697 {
698 isShiftLocked = false;
699 shiftPressed = !shiftPressed;
700 listener.processVirtualKey(VK_LSHIFT, shiftPressed);
701 }
702 else
703 isShiftLocked = true;
704 break;
705 }
706 case VK_LCONTROL:
707 {
708 if (!checkToggleModifierLock(VK_LCONTROL))
709 {
710 isCtrlLocked = false;
711 ctrlPressed = !ctrlPressed;
712 listener.processVirtualKey(VK_LCONTROL, ctrlPressed);
713 }
714 else
715 isCtrlLocked = true;
716 break;
717 }
718 case VK_LMENU:
719 {
720 if (!checkToggleModifierLock(VK_LMENU))
721 {
722 isAltLocked = false;
723 altPressed = !altPressed;
724 listener.processVirtualKey(VK_LMENU, altPressed);
725 }
726 else
727 isAltLocked = true;
728 break;
729 }
730 case VK_LWIN:
731 {
732 if (!checkToggleModifierLock(VK_LWIN))
733 {
734 isWinLocked = false;
735 winPressed = !winPressed;
736 listener.processVirtualKey(VK_LWIN | VK_EXT_KEY, winPressed);
737 }
738 else
739 isWinLocked = true;
740 break;
741 }
742 }
743 listener.modifiersChanged();
744 }
745
746 public void clearlAllModifiers()
747 {
748 resetModifierKeysAfterInput(true);
749 }
750
751 private void resetModifierKeysAfterInput(boolean force)
752 {
753 if (shiftPressed && (!isShiftLocked || force))
754 {
755 listener.processVirtualKey(VK_LSHIFT, false);
756 shiftPressed = false;
757 }
758 if (ctrlPressed && (!isCtrlLocked || force))
759 {
760 listener.processVirtualKey(VK_LCONTROL, false);
761 ctrlPressed = false;
762 }
763 if (altPressed && (!isAltLocked || force))
764 {
765 listener.processVirtualKey(VK_LMENU, false);
766 altPressed = false;
767 }
768 if (winPressed && (!isWinLocked || force))
769 {
770 listener.processVirtualKey(VK_LWIN | VK_EXT_KEY, false);
771 winPressed = false;
772 }
773
774 if (listener != null)
775 listener.modifiersChanged();
776 }
777
778 private void switchKeyboard(int keycode)
779 {
780 switch (keycode)
781 {
782 case EXTKEY_KBFUNCTIONKEYS:
783 {
784 listener.switchKeyboard(KEYBOARD_TYPE_FUNCTIONKEYS);
785 break;
786 }
787
788 case EXTKEY_KBNUMPAD:
789 {
790 listener.switchKeyboard(KEYBOARD_TYPE_NUMPAD);
791 break;
792 }
793
794 case EXTKEY_KBCURSOR:
795 {
796 listener.switchKeyboard(KEYBOARD_TYPE_CURSOR);
797 break;
798 }
799
800 default:
801 break;
802 }
803 }
804
805 private boolean checkToggleModifierLock(int keycode)
806 {
807 long now = System.currentTimeMillis();
808
809 // was the same modifier hit?
810 if (lastModifierKeyCode != keycode)
811 {
812 lastModifierKeyCode = keycode;
813 lastModifierTime = now;
814 return false;
815 }
816
817 // within a certain time interval?
818 if (lastModifierTime + 800 > now)
819 {
820 lastModifierTime = 0;
821 return true;
822 }
823 else
824 {
825 lastModifierTime = now;
826 return false;
827 }
828 }
829
830 // interface that gets called for input handling
831 public interface KeyProcessingListener {
832 void processVirtualKey(int virtualKeyCode, boolean down);
833
834 void processUnicodeKey(int unicodeKey);
835
836 void switchKeyboard(int keyboardType);
837
838 void modifiersChanged();
839 }
840}