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