2 * Copyright (C) 2012-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "AndroidKey.h"
22 #include "AndroidExtra.h"
24 #include "guilib/Key.h"
25 #include "windowing/WinEvents.h"
26 #include "android/jni/KeyCharacterMap.h"
34 static KeyMap keyMap[] = {
35 { AKEYCODE_UNKNOWN , XBMCK_LAST },
36 { AKEYCODE_SOFT_LEFT , XBMCK_LEFT },
37 { AKEYCODE_SOFT_RIGHT , XBMCK_RIGHT },
38 { AKEYCODE_HOME , XBMCK_HOME },
39 { AKEYCODE_BACK , XBMCK_BACKSPACE },
40 { AKEYCODE_CALL , XBMCK_LAST },
41 { AKEYCODE_ENDCALL , XBMCK_LAST },
42 { AKEYCODE_0 , XBMCK_0 },
43 { AKEYCODE_1 , XBMCK_1 },
44 { AKEYCODE_2 , XBMCK_2 },
45 { AKEYCODE_3 , XBMCK_3 },
46 { AKEYCODE_4 , XBMCK_4 },
47 { AKEYCODE_5 , XBMCK_5 },
48 { AKEYCODE_6 , XBMCK_6 },
49 { AKEYCODE_7 , XBMCK_7 },
50 { AKEYCODE_8 , XBMCK_8 },
51 { AKEYCODE_9 , XBMCK_9 },
52 { AKEYCODE_STAR , XBMCK_ASTERISK },
53 { AKEYCODE_POUND , XBMCK_HASH },
54 { AKEYCODE_DPAD_UP , XBMCK_UP },
55 { AKEYCODE_DPAD_DOWN , XBMCK_DOWN },
56 { AKEYCODE_DPAD_LEFT , XBMCK_LEFT },
57 { AKEYCODE_DPAD_RIGHT , XBMCK_RIGHT },
58 { AKEYCODE_DPAD_CENTER , XBMCK_RETURN },
59 { AKEYCODE_VOLUME_UP , XBMCK_PLUS },
60 { AKEYCODE_VOLUME_DOWN , XBMCK_MINUS },
61 { AKEYCODE_POWER , XBMCK_POWER },
62 { AKEYCODE_CAMERA , XBMCK_LAST },
63 { AKEYCODE_CLEAR , XBMCK_LAST },
64 { AKEYCODE_A , XBMCK_a },
65 { AKEYCODE_B , XBMCK_b },
66 { AKEYCODE_C , XBMCK_c },
67 { AKEYCODE_D , XBMCK_d },
68 { AKEYCODE_E , XBMCK_e },
69 { AKEYCODE_F , XBMCK_f },
70 { AKEYCODE_G , XBMCK_g },
71 { AKEYCODE_H , XBMCK_h },
72 { AKEYCODE_I , XBMCK_i },
73 { AKEYCODE_J , XBMCK_j },
74 { AKEYCODE_K , XBMCK_k },
75 { AKEYCODE_L , XBMCK_l },
76 { AKEYCODE_M , XBMCK_m },
77 { AKEYCODE_N , XBMCK_n },
78 { AKEYCODE_O , XBMCK_o },
79 { AKEYCODE_P , XBMCK_p },
80 { AKEYCODE_Q , XBMCK_q },
81 { AKEYCODE_R , XBMCK_r },
82 { AKEYCODE_S , XBMCK_s },
83 { AKEYCODE_T , XBMCK_t },
84 { AKEYCODE_U , XBMCK_u },
85 { AKEYCODE_V , XBMCK_v },
86 { AKEYCODE_W , XBMCK_w },
87 { AKEYCODE_X , XBMCK_x },
88 { AKEYCODE_Y , XBMCK_y },
89 { AKEYCODE_Z , XBMCK_z },
90 { AKEYCODE_COMMA , XBMCK_COMMA },
91 { AKEYCODE_PERIOD , XBMCK_PERIOD },
92 { AKEYCODE_ALT_LEFT , XBMCK_LALT },
93 { AKEYCODE_ALT_RIGHT , XBMCK_RALT },
94 { AKEYCODE_SHIFT_LEFT , XBMCK_LSHIFT },
95 { AKEYCODE_SHIFT_RIGHT , XBMCK_RSHIFT },
96 { AKEYCODE_TAB , XBMCK_TAB },
97 { AKEYCODE_SPACE , XBMCK_SPACE },
98 { AKEYCODE_SYM , XBMCK_LAST },
99 { AKEYCODE_EXPLORER , XBMCK_LAST },
100 { AKEYCODE_ENVELOPE , XBMCK_LAST },
101 { AKEYCODE_ENTER , XBMCK_RETURN },
102 { AKEYCODE_DEL , XBMCK_BACKSPACE },
103 { AKEYCODE_GRAVE , XBMCK_BACKQUOTE },
104 { AKEYCODE_MINUS , XBMCK_MINUS },
105 { AKEYCODE_EQUALS , XBMCK_EQUALS },
106 { AKEYCODE_LEFT_BRACKET , XBMCK_LEFTBRACKET },
107 { AKEYCODE_RIGHT_BRACKET , XBMCK_RIGHTBRACKET },
108 { AKEYCODE_BACKSLASH , XBMCK_BACKSLASH },
109 { AKEYCODE_SEMICOLON , XBMCK_SEMICOLON },
110 { AKEYCODE_APOSTROPHE , XBMCK_QUOTE },
111 { AKEYCODE_SLASH , XBMCK_SLASH },
112 { AKEYCODE_AT , XBMCK_AT },
113 { AKEYCODE_NUM , XBMCK_NUMLOCK },
114 { AKEYCODE_HEADSETHOOK , XBMCK_LAST },
115 { AKEYCODE_FOCUS , XBMCK_LAST }, // *Camera* focus
116 { AKEYCODE_PLUS , XBMCK_PLUS },
117 { AKEYCODE_MENU , XBMCK_MENU },
118 { AKEYCODE_NOTIFICATION , XBMCK_LAST },
119 { AKEYCODE_SEARCH , XBMCK_LAST },
120 { AKEYCODE_MEDIA_PLAY_PAUSE, XBMCK_MEDIA_PLAY_PAUSE },
121 { AKEYCODE_MEDIA_STOP , XBMCK_MEDIA_STOP },
122 { AKEYCODE_MEDIA_NEXT , XBMCK_MEDIA_NEXT_TRACK },
123 { AKEYCODE_MEDIA_PREVIOUS , XBMCK_MEDIA_PREV_TRACK },
124 { AKEYCODE_MEDIA_REWIND , XBMCK_MEDIA_REWIND },
125 { AKEYCODE_MEDIA_FAST_FORWARD , XBMCK_MEDIA_FASTFORWARD },
126 { AKEYCODE_MUTE , XBMCK_VOLUME_MUTE },
127 { AKEYCODE_PAGE_UP , XBMCK_PAGEUP },
128 { AKEYCODE_PAGE_DOWN , XBMCK_PAGEDOWN },
129 { AKEYCODE_PICTSYMBOLS , XBMCK_LAST },
130 { AKEYCODE_SWITCH_CHARSET , XBMCK_LAST },
131 { AKEYCODE_BUTTON_A , XBMCK_LAST },
132 { AKEYCODE_BUTTON_B , XBMCK_LAST },
133 { AKEYCODE_BUTTON_C , XBMCK_LAST },
134 { AKEYCODE_BUTTON_X , XBMCK_LAST },
135 { AKEYCODE_BUTTON_Y , XBMCK_LAST },
136 { AKEYCODE_BUTTON_Z , XBMCK_LAST },
137 { AKEYCODE_BUTTON_L1 , XBMCK_LAST },
138 { AKEYCODE_BUTTON_R1 , XBMCK_LAST },
139 { AKEYCODE_BUTTON_L2 , XBMCK_LAST },
140 { AKEYCODE_BUTTON_R2 , XBMCK_LAST },
141 { AKEYCODE_BUTTON_THUMBL , XBMCK_LAST },
142 { AKEYCODE_BUTTON_THUMBR , XBMCK_LAST },
143 { AKEYCODE_BUTTON_START , XBMCK_LAST },
144 { AKEYCODE_BUTTON_SELECT , XBMCK_LAST },
145 { AKEYCODE_BUTTON_MODE , XBMCK_LAST },
146 { AKEYCODE_ESCAPE , XBMCK_ESCAPE },
147 { AKEYCODE_FORWARD_DEL , XBMCK_DELETE },
148 { AKEYCODE_CTRL_LEFT , XBMCK_LCTRL },
149 { AKEYCODE_CTRL_RIGHT , XBMCK_RCTRL },
150 { AKEYCODE_CAPS_LOCK , XBMCK_CAPSLOCK },
151 { AKEYCODE_SCROLL_LOCK , XBMCK_SCROLLOCK },
152 { AKEYCODE_INSERT , XBMCK_INSERT },
153 { AKEYCODE_FORWARD , XBMCK_MEDIA_FASTFORWARD },
154 { AKEYCODE_MEDIA_PLAY , XBMCK_MEDIA_PLAY_PAUSE },
155 { AKEYCODE_MEDIA_EJECT , XBMCK_EJECT },
158 bool CAndroidKey::onKeyboardEvent(AInputEvent *event)
163 int32_t flags = AKeyEvent_getFlags(event);
164 int32_t state = AKeyEvent_getMetaState(event);
165 int32_t action = AKeyEvent_getAction(event);
166 int32_t repeat = AKeyEvent_getRepeatCount(event);
167 int32_t keycode = AKeyEvent_getKeyCode(event);
169 int32_t deviceId = AInputEvent_getDeviceId(event);
170 CJNIKeyCharacterMap map = CJNIKeyCharacterMap::load(deviceId);
171 uint16_t unicode = map.get(keycode, state);
173 // Check if we got some special key
174 uint16_t sym = XBMCK_UNKNOWN;
175 for (unsigned int index = 0; index < sizeof(keyMap) / sizeof(KeyMap); index++)
177 if (keycode == keyMap[index].nativeKey)
179 sym = keyMap[index].xbmcKey;
184 // check if this is a key we don't want to handle
185 if (sym == XBMCK_LAST || sym == XBMCK_UNKNOWN)
188 uint16_t modifiers = 0;
189 if (state & AMETA_ALT_LEFT_ON)
190 modifiers |= XBMCKMOD_LALT;
191 if (state & AMETA_ALT_RIGHT_ON)
192 modifiers |= XBMCKMOD_RALT;
193 if (state & AMETA_SHIFT_LEFT_ON)
194 modifiers |= XBMCKMOD_LSHIFT;
195 if (state & AMETA_SHIFT_RIGHT_ON)
196 modifiers |= XBMCKMOD_RSHIFT;
198 if (state & AMETA_SYM_ON)
199 modifiers |= 0x000?;*/
203 case AKEY_EVENT_ACTION_DOWN:
205 CXBMCApp::android_printf("CAndroidKey: key down (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
206 keycode, repeat, flags,
207 (state & AMETA_ALT_ON) ? "yes" : "no",
208 (state & AMETA_SHIFT_ON) ? "yes" : "no",
209 (state & AMETA_SYM_ON) ? "yes" : "no");
211 XBMC_Key((uint8_t)keycode, sym, modifiers, unicode, false);
214 case AKEY_EVENT_ACTION_UP:
216 CXBMCApp::android_printf("CAndroidKey: key up (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
217 keycode, repeat, flags,
218 (state & AMETA_ALT_ON) ? "yes" : "no",
219 (state & AMETA_SHIFT_ON) ? "yes" : "no",
220 (state & AMETA_SYM_ON) ? "yes" : "no");
222 XBMC_Key((uint8_t)keycode, sym, modifiers, unicode, true);
225 case AKEY_EVENT_ACTION_MULTIPLE:
227 CXBMCApp::android_printf("CAndroidKey: key multiple (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
228 keycode, repeat, flags,
229 (state & AMETA_ALT_ON) ? "yes" : "no",
230 (state & AMETA_SHIFT_ON) ? "yes" : "no",
231 (state & AMETA_SYM_ON) ? "yes" : "no");
237 CXBMCApp::android_printf("CAndroidKey: unknown key (code: %d; repeat: %d; flags: 0x%0X; alt: %s; shift: %s; sym: %s)",
238 keycode, repeat, flags,
239 (state & AMETA_ALT_ON) ? "yes" : "no",
240 (state & AMETA_SHIFT_ON) ? "yes" : "no",
241 (state & AMETA_SYM_ON) ? "yes" : "no");
249 void CAndroidKey::XBMC_Key(uint8_t code, uint16_t key, uint16_t modifiers, uint16_t unicode, bool up)
252 memset(&newEvent, 0, sizeof(newEvent));
254 unsigned char type = up ? XBMC_KEYUP : XBMC_KEYDOWN;
255 newEvent.type = type;
256 newEvent.key.type = type;
257 newEvent.key.keysym.scancode = code;
258 newEvent.key.keysym.sym = (XBMCKey)key;
259 newEvent.key.keysym.unicode = unicode;
260 newEvent.key.keysym.mod = (XBMCMod)modifiers;
262 //CXBMCApp::android_printf("XBMC_Key(%u, %u, 0x%04X, %d)", code, key, modifiers, up);
263 CWinEvents::MessagePush(&newEvent);