|
1 /* |
|
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: ?Description |
|
15 * |
|
16 */ |
|
17 |
|
18 // CEikonEnv API used for retrieving resource (resId) in GetKeyName function |
|
19 #include <eikenv.h> |
|
20 // macros for resources |
|
21 #include <lcdui.rsg> |
|
22 // FeatureManager |
|
23 #include <featmgr.h> |
|
24 #include <bldvariant.hrh> |
|
25 |
|
26 #include <j2me/jdebug.h> |
|
27 /** |
|
28 @page Key Mapping. |
|
29 */ |
|
30 |
|
31 // used for retrieving CR repository codes |
|
32 #include <centralrepository.h> |
|
33 // S60 LCDUI Plugin internal keys |
|
34 #include "S60LCDUIInternalCRKeys.h" |
|
35 |
|
36 #include "CMIDKeyDecoder.h" |
|
37 // used for getting instance of ourselves from TlsStruct |
|
38 #include "CMIDMenuHandler.h" |
|
39 // using API for iRemConObserver initialization |
|
40 #include "CMIDRemConObserver.h" |
|
41 // using constants from enumeration TMediaKey (in InitSpecialKeysL) |
|
42 #include "MMIDMediaKeysListener.h" |
|
43 #include "CMIDDisplayable.h" |
|
44 #include "CMIDUIManager.h" |
|
45 |
|
46 /** |
|
47 * MIDP key codes for keys that have no corresponding |
|
48 * Unicode character, as from MIDP specs negative values |
|
49 * must be used. |
|
50 * |
|
51 * ALL characters with code >= ENonCharacterKeyBase |
|
52 * should be mapped to -ve numbers (see e32keys.h) |
|
53 */ |
|
54 const TInt KMIDKeyUpArrow = -1; |
|
55 const TInt KMIDKeyDownArrow = -2; |
|
56 const TInt KMIDKeyLeftArrow = -3; |
|
57 const TInt KMIDKeyRightArrow = -4; |
|
58 const TInt KMIDKeyClear = -8; // Clear key |
|
59 const TInt KMIDKeySelect = -5; // Selection key |
|
60 const TInt KMIDKeyEdit = -50; // Edit Key |
|
61 const TInt KMIDKeySend = -10; // Send Key |
|
62 const TInt KMIDKeyCBA1 = -6; // Left CBA |
|
63 const TInt KMIDKeyCBA2 = -7; // Right CBA |
|
64 const TInt KMIDKeyEnd = -11; // End key |
|
65 const TInt KMIDKeyApplications = -12; // Applications key |
|
66 const TInt KMIDKeyVoiceKey = -13; // Voice key |
|
67 //const TInt KMIDKeyClockWiseRotate = -16; // not used at the moment |
|
68 //const TInt KMIDKeyCounterClockWiseRotate = -17; // not used at the moment |
|
69 //const TInt KMIDKeyClockWiseFastRotate = -18; // not used at the moment |
|
70 //const TInt KMIDKeyCounterClockWiseFastRotate = -19; // not used at the moment |
|
71 const TInt KMIDKeyZoomIn = -EKeyZoomIn; // Negative value (-63582) |
|
72 const TInt KMIDKeyZoomOut = -EKeyZoomOut; // Negative value (-63583) |
|
73 |
|
74 /** The number of game actions */ |
|
75 const TInt KNumGameActions = 9; |
|
76 |
|
77 /** The max number of scan codes per game action */ |
|
78 const TInt KMaxScanCodesPerAction = 16; |
|
79 |
|
80 /** The MIDP game action codes, this array must have the same index as |
|
81 KDefaultActionScanCodes and KActionKeys.*/ |
|
82 const TInt KActionCodes[KNumGameActions] = |
|
83 { |
|
84 MMIDUtils::EActionUp, |
|
85 MMIDUtils::EActionDown, |
|
86 MMIDUtils::EActionLeft, |
|
87 MMIDUtils::EActionRight, |
|
88 MMIDUtils::EActionFire, |
|
89 |
|
90 MMIDUtils::EActionGameA, |
|
91 MMIDUtils::EActionGameB, |
|
92 MMIDUtils::EActionGameC, |
|
93 MMIDUtils::EActionGameD |
|
94 }; |
|
95 |
|
96 |
|
97 /** The MIDP game action keys in the central repository. |
|
98 These are used to override the default scan codes. |
|
99 This array must have the same index as KActionCodes. |
|
100 */ |
|
101 const TUint32 KActionKeys[KNumGameActions] = |
|
102 { |
|
103 KScanCodeUp, |
|
104 KScanCodeDown, |
|
105 KScanCodeLeft, |
|
106 KScanCodeRight, |
|
107 KScanCodeFire, |
|
108 KScanCodeGameA, |
|
109 KScanCodeGameB, |
|
110 KScanCodeGameC, |
|
111 KScanCodeGameD |
|
112 }; |
|
113 |
|
114 |
|
115 /** Default scan codes for game actions. These are only used when |
|
116 the scan codes in the central repository have not been set. |
|
117 |
|
118 Because for each action there can be one or more code, use a zero |
|
119 to indicate that there are no more codes. |
|
120 |
|
121 This array must have the same index as KActionCodes. |
|
122 |
|
123 @see CR keys, ConstructL() |
|
124 */ |
|
125 |
|
126 // ITU-T keypad with standard grid layout. |
|
127 const TInt KDefaultActionScanCodes[] = |
|
128 { |
|
129 EStdKeyUpArrow, '2', 0, // EActionUp |
|
130 EStdKeyDownArrow, '8', 0, // EActionDown |
|
131 EStdKeyLeftArrow, '4', 0, // EActionLeft |
|
132 EStdKeyRightArrow, '6', 0, // EActionRight |
|
133 EStdKeyDevice3, EStdKeyYes, '5', 0, // EActionFire |
|
134 |
|
135 '7', 0, // EActionGameA |
|
136 '9', 0, // EActionGameB |
|
137 EStdKeyNkpAsterisk, '*', 0, // EActionGameC |
|
138 EStdKeyHash, 0 // EActionGameD |
|
139 }; |
|
140 |
|
141 // Full QWERTY keyboard with screen in the middle (Table 14 in internal specs) |
|
142 const TInt KDefaultQwertyActionScanCodes[] = |
|
143 { |
|
144 EStdKeyUpArrow, 'R', 'P', 0, // EActionUp |
|
145 EStdKeyDownArrow, 'V', EStdKeyForwardSlash, 0, // EActionDown |
|
146 EStdKeyLeftArrow, 'D', 'L', 0, // EActionLeft |
|
147 EStdKeyRightArrow, 'G', EStdKeySingleQuote, 0, // EActionRight |
|
148 'A', 'J', EStdKeyDevice3, 0, // EActionFire |
|
149 |
|
150 EStdKeyHash, 'H', 0, // EActionGameA |
|
151 'S', 'K', 0, // EActionGameB |
|
152 'Q', 'U', 0, // EActionGameC |
|
153 'Z', 'M', 0 // EActionGameD |
|
154 }; |
|
155 |
|
156 |
|
157 |
|
158 /** Usual symbian two phase construction. @see ConstructL() */ |
|
159 CMIDKeyDecoder* CMIDKeyDecoder::NewL(MMIDEnv& aEnv) |
|
160 { |
|
161 CMIDKeyDecoder* self = new(ELeave) CMIDKeyDecoder(aEnv); |
|
162 CleanupStack::PushL(self); |
|
163 self->ConstructL(); |
|
164 CleanupStack::Pop(self); |
|
165 return self; |
|
166 } |
|
167 |
|
168 /** */ |
|
169 CMIDKeyDecoder::~CMIDKeyDecoder() |
|
170 { |
|
171 DEBUG("< CMIDKeyDecoder::~CMIDKeyDecoder"); |
|
172 iSpecialKeys.Close(); |
|
173 iGameActions.ResetAndDestroy(); |
|
174 |
|
175 delete iCaptureKeys; |
|
176 delete iKeyTranslator; |
|
177 |
|
178 delete iQwertyWatch; |
|
179 |
|
180 if (iUseCRScanCodes) |
|
181 { |
|
182 delete iActionScanCodes; |
|
183 } |
|
184 |
|
185 FeatureManager::UnInitializeLib(); |
|
186 |
|
187 delete iRemConObserver; |
|
188 |
|
189 DEBUG("> CMIDKeyDecoder::~CMIDKeyDecoder"); |
|
190 } |
|
191 |
|
192 /** */ |
|
193 CMIDKeyDecoder::CMIDKeyDecoder(MMIDEnv& aEnv) |
|
194 : iEnv(aEnv) |
|
195 ,iMediaKeysEnabled(EFalse) |
|
196 { |
|
197 DEBUG("< CMIDKeyDecoder::CMIDKeyDecoder"); |
|
198 DEBUG("> CMIDKeyDecoder::CMIDKeyDecoder"); |
|
199 } |
|
200 |
|
201 /** |
|
202 Creates the key translator and another accessory, the capture keys |
|
203 (needed by the key translator). The key translator can convert scan codes |
|
204 into key codes. Calls CreateGameActionsL(), which will fill iGameActions: |
|
205 for each action a set of key codes will be stored. These are MIDP key codes. |
|
206 */ |
|
207 void CMIDKeyDecoder::ConstructL() |
|
208 { |
|
209 DEBUG("< CMIDKeyDecoder::ConstructL"); |
|
210 |
|
211 iCaptureKeys = new(ELeave) CCaptureKeys; |
|
212 iCaptureKeys->Construct(); |
|
213 |
|
214 iKeyTranslator = CKeyTranslator::New(); |
|
215 |
|
216 // If Select key mapping is defined in central repository an extra MIDP |
|
217 // keycode will be used for Select key. |
|
218 // Not all the devices have rocker in their keyboard, |
|
219 // so other key can be defined instead. |
|
220 CRepository* repository = NULL; |
|
221 TInt err = KErrNone; |
|
222 TRAP(err, repository = CRepository::NewL(KCRUidMidpLcdui)); |
|
223 // 2 bytes in scan code |
|
224 TBuf8<2> scanCodeBuffer; |
|
225 CleanupStack::PushL(repository); |
|
226 err = repository->Get(KAdditionalSelectKeyMapping,scanCodeBuffer); |
|
227 CleanupStack::PopAndDestroy(repository); |
|
228 if (err == KErrNone) |
|
229 { |
|
230 TUint8 scanCodeLeft = scanCodeBuffer[0]; |
|
231 TUint8 scanCodeRight = scanCodeBuffer[1]; |
|
232 TUint scanCode = (scanCodeLeft << 8) + scanCodeRight; |
|
233 if (scanCode != 0) |
|
234 { |
|
235 iAdditionalSelectkeyMapping = scanCode; |
|
236 } |
|
237 } |
|
238 |
|
239 CreateQwertyWatchL(); |
|
240 CreateGameActionsL(); |
|
241 |
|
242 FeatureManager::InitializeLibL(); |
|
243 |
|
244 if (iEnv.MidletAttributeContainsVal( |
|
245 LcduiMidletAttributes::KAttribUIEnhancement, |
|
246 LcduiMidletAttributeValues::KUIEnhMediaKeys)) |
|
247 { |
|
248 InitRemConObserverL(); |
|
249 iMediaKeysEnabled = ETrue; |
|
250 } |
|
251 |
|
252 DEBUG("> CMIDKeyDecoder::ConstructL"); |
|
253 } |
|
254 |
|
255 /** |
|
256 Special keys that require separate handling: these are |
|
257 either non unicode keys or non standard unicode keys. |
|
258 For standard unicode keys, the MIDP key code is the |
|
259 unicode charactler. */ |
|
260 |
|
261 void CMIDKeyDecoder::InitSpecialKeysL() |
|
262 { |
|
263 iSpecialKeys.Reset(); |
|
264 |
|
265 // Keys shared by ITU-T and QWERTY modes |
|
266 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftArrow, KMIDKeyLeftArrow, R_MIDP_KEY_LEFT))); |
|
267 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightArrow, KMIDKeyRightArrow, R_MIDP_KEY_RIGHT))); |
|
268 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyUpArrow, KMIDKeyUpArrow, R_MIDP_KEY_UP))); |
|
269 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDownArrow, KMIDKeyDownArrow, R_MIDP_KEY_DOWN))); |
|
270 // If Select key mapping is defined in central repository an extra MIDP keycode will be used for Select key. |
|
271 if (iAdditionalSelectkeyMapping != 0) |
|
272 { |
|
273 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(iAdditionalSelectkeyMapping, KMIDKeySelect, R_MIDP_KEY_SELECT))); |
|
274 } |
|
275 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice3, KMIDKeySelect, R_MIDP_KEY_SELECT))); |
|
276 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightShift, KMIDKeyEdit, R_MIDP_KEY_EDIT))); |
|
277 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftShift, KMIDKeyEdit, R_MIDP_KEY_EDIT))); |
|
278 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyF21, KMIDKeyEdit, R_MIDP_KEY_EDIT))); |
|
279 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyLeftFunc, KMIDKeyEdit, R_MIDP_KEY_EDIT))); |
|
280 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyRightFunc, KMIDKeyEdit, R_MIDP_KEY_EDIT))); |
|
281 |
|
282 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyYes, KMIDKeySend, R_MIDP_KEY_SEND))); |
|
283 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice0, KMIDKeyCBA1, R_MIDP_KEY_LSK))); |
|
284 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice1, KMIDKeyCBA2, R_MIDP_KEY_RSK))); |
|
285 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNo, KMIDKeyEnd, R_MIDP_KEY_END))); |
|
286 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyApplication0,KMIDKeyApplications, R_MIDP_KEY_APPS))); |
|
287 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice6, KMIDKeyVoiceKey, R_MIDP_KEY_VOICE))); |
|
288 // QWERTY keys for qwerty and ITU-T mode with qwerty wireless keyboard. |
|
289 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeySpace,EKeySpace, R_MIDP_KEY_SPACE))); |
|
290 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyEscape,EKeyEscape, R_MIDP_KEY_ESC))); |
|
291 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyTab,EKeyTab, R_MIDP_KEY_TAB))); |
|
292 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyEnter, EKeyLineFeed, R_MIDP_KEY_ENTER))); |
|
293 // Diagonal keys for 9-way Navigation Support |
|
294 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice10, EKeyLeftUpArrow, R_MIDP_KEY_LEFT))); |
|
295 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice11,EKeyRightUpArrow, R_MIDP_KEY_RIGHT))); |
|
296 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice12,EKeyRightDownArrow, R_MIDP_KEY_RIGHT))); |
|
297 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDevice13,EKeyLeftDownArrow, R_MIDP_KEY_LEFT))); |
|
298 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyDelete,EKeyDelete, R_MIDP_KEY_DELETE))); |
|
299 if (!iQwertyModeActive) |
|
300 { // ITU-T keys with different behaviour |
|
301 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyBackspace, KMIDKeyClear, R_MIDP_KEY_CLEAR))); |
|
302 } |
|
303 else |
|
304 { // QWERTY keys with different behaviour |
|
305 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyBackspace, EKeyBackspace, R_MIDP_KEY_BACKSPACE))); |
|
306 } |
|
307 |
|
308 /* |
|
309 // Keys defined in specs but not yet present in Series 60 |
|
310 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyFormFeed, R_MIDP_KEY_FORM_FEED))); |
|
311 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyLineFeed, R_MIDP_KEY_LINE_FEED))); |
|
312 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyBell, R_MIDP_KEY_BELL))); |
|
313 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,EKeyVerticalTab, R_MIDP_KEY_VERTICAL_TAB))); |
|
314 |
|
315 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyClockWiseRotate, R_MIDP_KEY_CLOCKWISE_ROTATE))); |
|
316 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyCounterClockWiseRotate, R_MIDP_KEY_COUNTER_CLOCKWISE_ROTATE))); |
|
317 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyClockWiseFastRotate, R_MIDP_KEY_CLOCKWISE_FAST_ROTATE))); |
|
318 User::LeaveIfError(iSpecialKeys.Append(TMIDKey(EStdKeyNull,KMIDKeyCounterClockWiseFastRotate, R_MIDP_KEY_COUNTER_CLOCKWISE_FAST_ROTATE))); |
|
319 */ |
|
320 |
|
321 // Add media keys. These are used only in GetKeyName method. |
|
322 // EStdKeyNull used as a scancode as media keys don't have a real scancode. |
|
323 User::LeaveIfError(iSpecialKeys.Append( |
|
324 TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyPlay, R_MIDP_KEY_PLAY))); |
|
325 User::LeaveIfError(iSpecialKeys.Append( |
|
326 TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyPrevious, R_MIDP_KEY_PREVIOUS))); |
|
327 User::LeaveIfError(iSpecialKeys.Append( |
|
328 TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyNext, R_MIDP_KEY_NEXT))); |
|
329 User::LeaveIfError(iSpecialKeys.Append( |
|
330 TMIDKey(EStdKeyNull, MMIDMediaKeysListener::EMIDMediaKeyStop, R_MIDP_KEY_STOP))); |
|
331 |
|
332 // Zoom in and zoom out keys events support |
|
333 User::LeaveIfError(iSpecialKeys.Append( |
|
334 TMIDKey(EStdKeyApplicationC, KMIDKeyZoomIn, R_MIDP_KEY_ZOOM_IN))); |
|
335 User::LeaveIfError(iSpecialKeys.Append( |
|
336 TMIDKey(EStdKeyApplicationD, KMIDKeyZoomOut, R_MIDP_KEY_ZOOM_OUT))); |
|
337 }; |
|
338 |
|
339 |
|
340 |
|
341 /** */ |
|
342 void CMIDKeyDecoder::CreateQwertyWatchL() |
|
343 { |
|
344 iQwertyWatch = CMIDQwertyWatch::NewL(this); |
|
345 } |
|
346 |
|
347 |
|
348 void CMIDKeyDecoder::InitRemConObserverL() |
|
349 { |
|
350 if (!iRemConObserver) |
|
351 { |
|
352 iRemConObserver = CMIDRemConObserver::NewL(); |
|
353 } |
|
354 } |
|
355 |
|
356 /** */ |
|
357 void CMIDKeyDecoder::NewQwertyValueL(TInt aNewValue) |
|
358 { |
|
359 TBool oldQwertyMode = iQwertyModeActive; |
|
360 |
|
361 if (aNewValue == 1) |
|
362 { |
|
363 iQwertyModeActive = ETrue; |
|
364 } |
|
365 else |
|
366 { |
|
367 iQwertyModeActive = EFalse; |
|
368 } |
|
369 |
|
370 if (iQwertyModeActive != oldQwertyMode) |
|
371 { |
|
372 CreateGameActionsL(); |
|
373 } |
|
374 } |
|
375 |
|
376 /** |
|
377 * Gets a key code that corresponds to the specified game action on the device. |
|
378 * The implementation is required to provide a mapping for every game action, |
|
379 * so this method will always return a valid key code for every game action. |
|
380 * |
|
381 * Note that a key code is associated with at most one game action, whereas a |
|
382 * game action may be associated with several key codes. |
|
383 * |
|
384 * Returns zero if aGameAction is not a valid game action |
|
385 */ |
|
386 TInt CMIDKeyDecoder::GetKeyCode(TInt aGameAction) |
|
387 { |
|
388 DEBUG_INT("< CMIDKeyDecoder::GetKeyCode - game action is %D", aGameAction); |
|
389 for (TInt i = 0; i < KNumGameActions; ++i) |
|
390 { |
|
391 if (iGameActions[i]->iActionCode == aGameAction) |
|
392 { |
|
393 DEBUG_INT("> CMIDKeyDecoder::GetKeyCode - return code %D", iGameActions[i]->iCodes[0]); |
|
394 return iGameActions[i]->iCodes[0]; //just return the first code |
|
395 } |
|
396 } |
|
397 |
|
398 DEBUG_INT("> CMIDKeyDecoder::GetKeyCode - return code %D", 0); |
|
399 return 0; |
|
400 } |
|
401 |
|
402 /** |
|
403 * Maps EPOC scan code to negative key code required by MIDP spec. |
|
404 * For keys that have no corresponding Unicode character, |
|
405 * the implementation must use negative values. |
|
406 */ |
|
407 TInt CMIDKeyDecoder::MapNonUnicodeKey(TUint aScanCode) |
|
408 { |
|
409 DEBUG_INT("< CMIDKeyDecoder::MapNonUnicodeKey - scan code is %D", aScanCode); |
|
410 TInt numSpecialKeys = iSpecialKeys.Count(); |
|
411 for (TInt i = 0; i < numSpecialKeys; i++) |
|
412 { |
|
413 if (iSpecialKeys[i].iScanCode == aScanCode) |
|
414 { |
|
415 DEBUG_INT("> CMIDKeyDecoder::MapNonUnicodeKey - return code is %D", iSpecialKeys[i].iMIDPCode); |
|
416 return iSpecialKeys[i].iMIDPCode; |
|
417 } |
|
418 } |
|
419 |
|
420 DEBUG_INT("> CMIDKeyDecoder::MapNonUnicodeKey - return code is %D", 0); |
|
421 return 0; |
|
422 } |
|
423 |
|
424 /** |
|
425 * Gets an informative key string for a key. The string returned will resemble the text |
|
426 * physically printed on the key. This string is suitable for displaying to the user. |
|
427 * For example, on a device with function keys F1 through F4, calling this method on |
|
428 * the keyCode for the F1 key will return the string "F1". A typical use for this string |
|
429 * will be to compose help text such as "Press F1 to proceed." |
|
430 * |
|
431 * This method will return a non-empty string for every valid key code. |
|
432 * |
|
433 */ |
|
434 void CMIDKeyDecoder::GetKeyName(TDes& aText,TInt aKeyCode) |
|
435 { |
|
436 DEBUG_INT("< CMIDKeyDecoder::GetKeyName - key code is %D", aKeyCode); |
|
437 aText.Zero(); |
|
438 |
|
439 TInt resId = R_MIDP_KEY_NON_CHARACTER; |
|
440 TInt numSpecialKeys = iSpecialKeys.Count(); |
|
441 for (TInt i = 0; i < numSpecialKeys; i++) |
|
442 { |
|
443 if (iSpecialKeys[i].iMIDPCode == aKeyCode) |
|
444 { |
|
445 resId = iSpecialKeys[i].iNameResId; |
|
446 break; |
|
447 } |
|
448 } |
|
449 |
|
450 if ((resId == R_MIDP_KEY_NON_CHARACTER) && (IsUnicode(aKeyCode))) |
|
451 { |
|
452 aText.Append(TChar(aKeyCode)); |
|
453 } |
|
454 else |
|
455 { |
|
456 CEikonEnv::Static()->ReadResource(aText,resId); |
|
457 } |
|
458 |
|
459 DEBUG_STR("> CMIDKeyDecoder::GetKeyName - key name is %S", aText); |
|
460 } |
|
461 |
|
462 |
|
463 TInt CMIDKeyDecoder::GameAction(TInt aKeyCode) |
|
464 { |
|
465 DEBUG_INT("< CMIDKeyDecoder::GameAction - key code is %D", aKeyCode); |
|
466 |
|
467 for (TInt i = 0; i < KNumGameActions; ++i) |
|
468 { |
|
469 TInt numCodes = iGameActions[i]->iCodes.Count(); |
|
470 for (TInt j = 0; j < numCodes; ++j) |
|
471 { |
|
472 if (iGameActions[i]->iCodes[j] == aKeyCode) |
|
473 { |
|
474 DEBUG_INT("> CMIDKeyDecoder::GameAction -game action is %D", iGameActions[i]->iActionCode); |
|
475 return iGameActions[i]->iActionCode; |
|
476 } |
|
477 } |
|
478 } |
|
479 |
|
480 DEBUG_INT("> CMIDKeyDecoder::GameAction -game action is %D", 0); |
|
481 return 0; //invalid action |
|
482 } |
|
483 |
|
484 /** |
|
485 * Determines if a key code should be sent to MIDP applications. |
|
486 */ |
|
487 TBool CMIDKeyDecoder::IsJavaKey(TInt aScanCode) |
|
488 { |
|
489 TBool ret = (ScanToMidpCode(aScanCode) != 0); |
|
490 |
|
491 DEBUG_INT2("<> CMIDKeyDecoder::IsJavaKey - return %D for scan code %D", ret, aScanCode); |
|
492 return ret; |
|
493 } |
|
494 |
|
495 TBool CMIDKeyDecoder::MediaKeysEnabled() const |
|
496 { |
|
497 return iMediaKeysEnabled; |
|
498 } |
|
499 |
|
500 CMIDRemConObserver* CMIDKeyDecoder::GetRemConObserver() |
|
501 { |
|
502 return iRemConObserver; |
|
503 } |
|
504 |
|
505 /** Create the game actions. This method is called at startup and |
|
506 each time the qwerty availability changes. Because special keys |
|
507 also depend on qwerty availability, call InitSpecialKeysL() - |
|
508 which will reset special keys. The reset the actions and call |
|
509 LoadGameActionCodesL() - which loads the correct codes. Then |
|
510 for each action appens the codes stored in iActionScanCodes. |
|
511 Action codes in this array are separated by a null byte. */ |
|
512 void CMIDKeyDecoder::CreateGameActionsL() |
|
513 { |
|
514 DEBUG("< CMIDKeyDecoder::CreateGameActionsL"); |
|
515 |
|
516 InitSpecialKeysL(); |
|
517 iGameActions.ResetAndDestroy(); |
|
518 |
|
519 LoadGameActionCodesL(); |
|
520 ASSERT(iActionScanCodes != NULL); |
|
521 |
|
522 TInt index = 0; |
|
523 for (TInt i = 0; i < KNumGameActions; ++i) |
|
524 { |
|
525 TMIDGameAction* action = new(ELeave) TMIDGameAction(KActionCodes[i]); |
|
526 CleanupStack::PushL(action); |
|
527 |
|
528 while (iActionScanCodes[index] != 0) |
|
529 { |
|
530 AddCodeToActionL(action, iActionScanCodes[index]); |
|
531 index++; |
|
532 } |
|
533 index++; // skip null byte separating actions |
|
534 |
|
535 User::LeaveIfError(iGameActions.Append(action)); |
|
536 CleanupStack::Pop(action); |
|
537 } |
|
538 |
|
539 DEBUG("> CMIDKeyDecoder::CreateGameActionsL"); |
|
540 } |
|
541 |
|
542 /** Load the game action codes: either the default ITU-T codes |
|
543 if no qwerty input is available or load the codes |
|
544 from Central Repository (if available and if |
|
545 flag in CR indicates to do so) or load some default QWERTY codes. |
|
546 */ |
|
547 void CMIDKeyDecoder::LoadGameActionCodesL() |
|
548 { |
|
549 DEBUG("< CMIDKeyDecoder::LoadGameActionCodesL"); |
|
550 |
|
551 if (iUseCRScanCodes) |
|
552 { |
|
553 delete iActionScanCodes; |
|
554 iUseCRScanCodes = EFalse; |
|
555 } |
|
556 |
|
557 iActionScanCodes = NULL; |
|
558 |
|
559 if (!QwertyInputAvailable()) |
|
560 { // if no qwerty always use default ITU-T codes |
|
561 DEBUG(" CMIDKeyDecoder::LoadGameActionCodesL - use default ITU-T scan codes"); |
|
562 iActionScanCodes = (TInt*)&KDefaultActionScanCodes[0]; |
|
563 } |
|
564 else |
|
565 { // if there is qwerty either use CR repository codes or default qwerty codes |
|
566 CRepository* repository = NULL; |
|
567 TRAPD(crExists, repository = CRepository::NewL(KCRUidMidpLcdui)); |
|
568 |
|
569 if (crExists == KErrNone) |
|
570 { |
|
571 CleanupStack::PushL(repository); |
|
572 repository->Get(KUseCustomGameActionScanCodes, iUseCRScanCodes); |
|
573 } |
|
574 |
|
575 if (iUseCRScanCodes) |
|
576 { // use CR QWERTY codes |
|
577 DEBUG(" CMIDKeyDecoder::LoadGameActionCodesL - use central repository scan codes"); |
|
578 LoadCentralRepositoryCodesL(repository); |
|
579 } |
|
580 else |
|
581 { // use default QWERTY codes |
|
582 DEBUG(" CMIDKeyDecoder::LoadGameActionCodesL - add default qwerty scan codes"); |
|
583 iActionScanCodes = (TInt*)&KDefaultQwertyActionScanCodes[0]; |
|
584 } |
|
585 |
|
586 if (crExists == KErrNone) |
|
587 { |
|
588 CleanupStack::PopAndDestroy(repository); |
|
589 } |
|
590 } |
|
591 |
|
592 DEBUG("> CMIDKeyDecoder::LoadGameActionCodesL"); |
|
593 } |
|
594 |
|
595 /** Load the game action scan codes stored in the central repository |
|
596 database. Two bytes are available per scan code, LSB is left. Max |
|
597 number of codes per action is KMaxScanCodesPerAction. Allocate |
|
598 some memory for iActionScanCodes. |
|
599 */ |
|
600 void CMIDKeyDecoder::LoadCentralRepositoryCodesL(CRepository* aRepository) |
|
601 { |
|
602 DEBUG("< CMIDKeyDecoder::LoadCentralRepositoryCodesL"); |
|
603 |
|
604 ASSERT(aRepository != NULL); |
|
605 ASSERT(iActionScanCodes == NULL); |
|
606 |
|
607 iActionScanCodes = new(ELeave) TInt[KNumGameActions*KMaxScanCodesPerAction]; |
|
608 |
|
609 TInt index = 0; |
|
610 for (TInt i = 0; i < KNumGameActions; ++i) |
|
611 { |
|
612 //2 bytes per scan code |
|
613 TBuf8<KMaxScanCodesPerAction*2> scanCodeBuffer; |
|
614 aRepository->Get(KActionKeys[i],scanCodeBuffer); |
|
615 |
|
616 for (TInt j = 0; j < (scanCodeBuffer.Length() - 1); j++) |
|
617 { |
|
618 TUint8 scanCodeLeft = scanCodeBuffer[j++]; |
|
619 TUint8 scanCodeRight = scanCodeBuffer[j]; |
|
620 |
|
621 TUint scanCode = (scanCodeLeft << 8) + scanCodeRight; |
|
622 |
|
623 if (scanCode != 0) |
|
624 { |
|
625 iActionScanCodes[index++] = scanCode; |
|
626 } |
|
627 } |
|
628 |
|
629 iActionScanCodes[index++] = 0; //indicates end of scan codes |
|
630 } |
|
631 |
|
632 DEBUG("> CMIDKeyDecoder::LoadCentralRepositoryCodesL"); |
|
633 } |
|
634 |
|
635 /** Return true if this device supports qwerty and the qwerty keyboard |
|
636 is available */ |
|
637 TBool CMIDKeyDecoder::QwertyInputAvailable() const |
|
638 { |
|
639 return iQwertyModeActive; |
|
640 } |
|
641 |
|
642 /** |
|
643 Convert the scan code into a MIDP key code taking into account possible |
|
644 modifiers. Add the resulting MIDP key codes to the action specified as long |
|
645 as they are all different. |
|
646 */ |
|
647 void CMIDKeyDecoder::AddCodeToActionL(TMIDGameAction* aGameAction, TInt aScanCode) |
|
648 { |
|
649 DEBUG_INT("< CMIDKeyDecoder::AddCodeToActionL - scan code is %D", aScanCode); |
|
650 TInt midpCode = ScanToMidpCode(aScanCode); |
|
651 |
|
652 if (aGameAction->iCodes.Find(midpCode) == KErrNotFound && midpCode != 0) |
|
653 { |
|
654 DEBUG_INT(" CMIDKeyDecoder::AddCodeToActionL - adding midp code %D", midpCode); |
|
655 User::LeaveIfError(aGameAction->iCodes.Append(midpCode)); |
|
656 } |
|
657 |
|
658 if (IsUnicode(midpCode)) |
|
659 { |
|
660 midpCode = ScanToMidpCode(aScanCode | EModifierShift); |
|
661 |
|
662 if (aGameAction->iCodes.Find(midpCode) == KErrNotFound) |
|
663 { |
|
664 DEBUG_INT(" CMIDKeyDecoder::AddCodeToActionL - adding midp code %D", midpCode); |
|
665 User::LeaveIfError(aGameAction->iCodes.Append(midpCode)); |
|
666 } |
|
667 } |
|
668 |
|
669 DEBUG("> CMIDKeyDecoder::AddCodeToActionL"); |
|
670 } |
|
671 |
|
672 /** Take a scan code and convert it into a MIDP code. First see if it |
|
673 is one of the special keys, otherwise ask the window server to convert it. */ |
|
674 TInt CMIDKeyDecoder::ScanToMidpCode(TInt aScanCode) |
|
675 { |
|
676 DEBUG_INT("< CMIDKeyDecoder::ScanToMidpCode - scan Code is %D", aScanCode); |
|
677 TInt keyCode = MapNonUnicodeKey(aScanCode); |
|
678 |
|
679 if (keyCode == 0) |
|
680 { |
|
681 // fake a key down to convert scan code into key code |
|
682 // Note: on WINS (and WINSCW) this conversion works only for QWERTY layout |
|
683 // unless you specify the char code in the HI part of the scan code - which |
|
684 // we cannot do - hence on the emulator only QWERTY layout works. |
|
685 TKeyData keyData; |
|
686 TBool translated = iKeyTranslator->TranslateKey(aScanCode,EFalse,*iCaptureKeys,keyData); |
|
687 |
|
688 if (translated) |
|
689 { |
|
690 DEBUG_INT(" CMIDKeyDecoder::ScanToMidpCode - ws translated code is %D", keyData.iKeyCode); |
|
691 keyCode = IsUnicode(keyData.iKeyCode) ? keyData.iKeyCode : 0; |
|
692 } |
|
693 |
|
694 // fake a key up to restore modifiers |
|
695 iKeyTranslator->TranslateKey(aScanCode,ETrue,*iCaptureKeys,keyData); |
|
696 } |
|
697 |
|
698 DEBUG_INT("> CMIDKeyDecoder::ScanToMidpCode - return key code %D", keyCode); |
|
699 return keyCode; |
|
700 } |
|
701 |
|
702 /** Return true if the key code corresponds to a unicode character */ |
|
703 TBool CMIDKeyDecoder::IsUnicode(TInt aKeyCode) const |
|
704 { |
|
705 TBool ret = (aKeyCode > 0) && (aKeyCode < ENonCharacterKeyBase || |
|
706 aKeyCode >= (ENonCharacterKeyBase + ENonCharacterKeyCount)); |
|
707 |
|
708 DEBUG_INT2("<> CMIDKeyDecoder::IsUnicode - return %D for key code %D", ret, aKeyCode); |
|
709 return ret; |
|
710 } |
|
711 |
|
712 TInt CMIDKeyDecoder::AdditionalSelectionKeyMappingCode() |
|
713 { |
|
714 return iAdditionalSelectkeyMapping; |
|
715 } |