|
1 /* |
|
2 * Copyright (c) 2009 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: Functional implementation of key event service |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include "HtiKeyEventServicePlugin.h" |
|
21 #include "KeyEventHandler.h" |
|
22 |
|
23 #include <apgtask.h> |
|
24 #include <HtiDispatcherInterface.h> |
|
25 #include <HtiLogging.h> |
|
26 |
|
27 |
|
28 // CONSTANTS |
|
29 _LIT8( KErrorServiceNotReady, "Service is busy - possibly executing long running typetext or long key press functionality" ); |
|
30 _LIT8( KErrorUnrecognizedCommand, "Unrecognized command" ); |
|
31 _LIT8( KErrorEmptyUnicodeArray, "Unicode char array was empty" ); |
|
32 _LIT8( KErrorInvalidUnicodeCharArray, "Invalid unicode character array" ); |
|
33 _LIT8( KErrorInvalidScancode, "Invalid scancode. Wrong length" ); |
|
34 _LIT8( KErrorTypeTextFailure, "Internal typetext failure" ); |
|
35 _LIT8( KErrorLongKeyPressFailure, "Internal long key press failure" ); |
|
36 |
|
37 const TInt KKeyboardFuncDataLength = 2; // scancode with 2 bytes |
|
38 const TInt KLongKeyPressDataLength = 4; // scancode 2 bytes + time 2 bytes |
|
39 const TInt KPressKeySequenceMinDataLength = 6; // hold time 2 bytes + key press interval 2 bytes + at least one scancode 2 bytes |
|
40 const TInt KTypeTextDelayBetweenCharsInMicroSeconds = 50000; // 50 milliseconds |
|
41 const TInt KTypeTextStartPausing = 200; // start pausing after this many characters |
|
42 const TInt KTypeTextPauseInterval = 50; // how many chars to type before pausing |
|
43 const TInt KTypeTextPauseInMicroSeconds = 800000; // 0.8 sec |
|
44 |
|
45 |
|
46 // ---------------------------------------------------------------------------- |
|
47 // UintValue() |
|
48 // Helper: aPtr must point to 16 bits area where the value will be extracted |
|
49 // ---------------------------------------------------------------------------- |
|
50 TUint UintValue( const TUint8* aPtr ) |
|
51 { |
|
52 // This is short way to do it.. |
|
53 //return (aPtr[1]<<8) + aPtr[0]; |
|
54 |
|
55 TUint8 uInt8Low = *aPtr; |
|
56 TUint8 uInt8High = *(aPtr+1); |
|
57 |
|
58 HTI_LOG_FORMAT( "UintValue:: Low: %d", uInt8Low ); |
|
59 HTI_LOG_FORMAT( "UintValue:: High: %d", uInt8High ); |
|
60 |
|
61 TUint16 uInt16 = (TUint16)uInt8High; |
|
62 uInt16 = (uInt16 << 8); |
|
63 uInt16 = uInt16 + (TUint)uInt8Low; |
|
64 |
|
65 HTI_LOG_FORMAT( "UintValue:: 16-bit value: %d", uInt16 ); |
|
66 |
|
67 TUint uInt = (TUint)uInt16; |
|
68 HTI_LOG_FORMAT( "UintValue:: 32-bit value: %d", uInt ); |
|
69 |
|
70 return uInt; |
|
71 } |
|
72 |
|
73 // ---------------------------------------------------------------------------- |
|
74 // CKeyEventHandler::NewL() |
|
75 // ---------------------------------------------------------------------------- |
|
76 CKeyEventHandler* CKeyEventHandler::NewL() |
|
77 { |
|
78 HTI_LOG_FUNC_IN( "CKeyEventHandler::NewL" ); |
|
79 CKeyEventHandler* self = new (ELeave) CKeyEventHandler(); |
|
80 CleanupStack::PushL ( self ); |
|
81 self->ConstructL(); |
|
82 CleanupStack::Pop(); |
|
83 HTI_LOG_FUNC_OUT( "CKeyEventHandler::Done" ); |
|
84 return self; |
|
85 } |
|
86 |
|
87 // ---------------------------------------------------------------------------- |
|
88 // CKeyEventHandler::CKeyEventHandler() |
|
89 // ---------------------------------------------------------------------------- |
|
90 CKeyEventHandler::CKeyEventHandler() |
|
91 : CActive( CActive::EPriorityStandard ), iReady( ETrue ), iCommand( 0 ), |
|
92 iHoldingScanCode( 0 ) |
|
93 |
|
94 { |
|
95 } |
|
96 |
|
97 // ---------------------------------------------------------------------------- |
|
98 // CKeyEventHandler::~CKeyEventHandler() |
|
99 // ---------------------------------------------------------------------------- |
|
100 CKeyEventHandler::~CKeyEventHandler() |
|
101 { |
|
102 HTI_LOG_TEXT( "CKeyEventHandler destroy" ); |
|
103 Cancel(); |
|
104 iTimer.Close(); |
|
105 iWsSession.Close(); |
|
106 delete iUnicodeChars; |
|
107 iUnicodeChars = NULL; |
|
108 } |
|
109 |
|
110 // ---------------------------------------------------------------------------- |
|
111 // CKeyEventHandler::ConstructL() |
|
112 // ---------------------------------------------------------------------------- |
|
113 void CKeyEventHandler::ConstructL() |
|
114 { |
|
115 HTI_LOG_TEXT( "CKeyEventHandler::ConstructL" ); |
|
116 User::LeaveIfError( iWsSession.Connect() ); |
|
117 User::LeaveIfError( iTimer.CreateLocal() ); |
|
118 CActiveScheduler::Add( this ); |
|
119 } |
|
120 |
|
121 // ---------------------------------------------------------------------------- |
|
122 // CKeyEventHandler::SetDispatcher() |
|
123 // ---------------------------------------------------------------------------- |
|
124 void CKeyEventHandler::SetDispatcher( MHtiDispatcher* aDispatcher ) |
|
125 { |
|
126 iDispatcher = aDispatcher; |
|
127 } |
|
128 |
|
129 // ---------------------------------------------------------------------------- |
|
130 // CKeyEventHandler::RunL() |
|
131 // ---------------------------------------------------------------------------- |
|
132 void CKeyEventHandler::RunL() |
|
133 { |
|
134 HTI_LOG_FUNC_IN( "CKeyEventHandler::RunL" ); |
|
135 |
|
136 if ( iCommand == ELongKeyPress ) |
|
137 { |
|
138 KeyUp( iHoldingScanCode ); |
|
139 SendOkMsgL(); |
|
140 iReady = ETrue; |
|
141 HTI_LOG_TEXT( "CKeyEventHandler::RunL: LongKeyPress has finished" ); |
|
142 } |
|
143 |
|
144 else if ( iCommand == ETypeText || iCommand == ETypeTextPassword ) |
|
145 { |
|
146 SimulateKeyEventL( *iUnicodeChars, iUnicodeCharIndex ); |
|
147 |
|
148 if ( iUnicodeCharIndex == iUnicodeChars->Length() / 2 - 1 ) |
|
149 { |
|
150 delete iUnicodeChars; |
|
151 iUnicodeChars = NULL; |
|
152 SendOkMsgL(); |
|
153 iReady = ETrue; |
|
154 HTI_LOG_TEXT( "CKeyEventHandler::RunL: TypeText has finished: OK" ); |
|
155 } |
|
156 else |
|
157 { |
|
158 iUnicodeCharIndex++; |
|
159 TypeTextWithDelay( iUnicodeCharIndex ); |
|
160 } |
|
161 } |
|
162 |
|
163 else if ( iCommand == EPressKeySequence ) |
|
164 { |
|
165 PressKeySequenceKeyL(); |
|
166 } |
|
167 |
|
168 HTI_LOG_FUNC_OUT( "CKeyEventHandler::RunL" ); |
|
169 } |
|
170 |
|
171 // ---------------------------------------------------------------------------- |
|
172 // CKeyEventHandler::RunError() |
|
173 // ---------------------------------------------------------------------------- |
|
174 TInt CKeyEventHandler::RunError( TInt aError ) |
|
175 { |
|
176 TInt dispatchResult = KErrNone; |
|
177 |
|
178 if ( iCommand == ELongKeyPress ) |
|
179 { |
|
180 HTI_LOG_FORMAT( "CKeyEventHandler::RunError: LongKeyPress failure: %d.", aError ); |
|
181 dispatchResult = iDispatcher->DispatchOutgoingErrorMessage( aError, |
|
182 KErrorLongKeyPressFailure, KKeyEventServiceUid ); |
|
183 } |
|
184 |
|
185 else // it's TypeText |
|
186 { |
|
187 HTI_LOG_FORMAT( "CKeyEventHandler::RunError: TypeText failure: %d.", aError ); |
|
188 dispatchResult = iDispatcher->DispatchOutgoingErrorMessage( aError, |
|
189 KErrorTypeTextFailure, KKeyEventServiceUid ); |
|
190 } |
|
191 |
|
192 if ( dispatchResult != KErrNone ) |
|
193 { |
|
194 HTI_LOG_FORMAT( "CKeyEventHandler::RunError: Failed to send error report to framework: %d.", dispatchResult ); |
|
195 } |
|
196 iReady = ETrue; |
|
197 return KErrNone; |
|
198 } |
|
199 |
|
200 // ---------------------------------------------------------------------------- |
|
201 // CKeyEventHandler::DoCancel() |
|
202 // ---------------------------------------------------------------------------- |
|
203 void CKeyEventHandler::DoCancel() |
|
204 { |
|
205 iTimer.Cancel(); |
|
206 delete iUnicodeChars; |
|
207 iUnicodeChars = NULL; |
|
208 } |
|
209 |
|
210 // ---------------------------------------------------------------------------- |
|
211 // CKeyEventHandler::ProcessMessageL() |
|
212 // ---------------------------------------------------------------------------- |
|
213 void CKeyEventHandler::ProcessMessageL( const TDesC8& aMessage, |
|
214 THtiMessagePriority /*aPriority*/ ) |
|
215 { |
|
216 HTI_LOG_FUNC_IN("CKeyEventHandler::ProcessMessageL"); |
|
217 HTI_LOG_FORMAT("Msg len: %d.", aMessage.Length()); |
|
218 |
|
219 if ( !iReady ) |
|
220 { |
|
221 SendErrorMessageL( ENotReadyCommand, KErrorServiceNotReady ); |
|
222 return; |
|
223 } |
|
224 |
|
225 iCommand = aMessage.Ptr()[0]; |
|
226 switch ( iCommand ) |
|
227 { |
|
228 case EPressKey: |
|
229 case EKeyDown: |
|
230 case EKeyUp: |
|
231 HandleKeyboardFuncL( aMessage.Right( aMessage.Length() - 1 ) ); |
|
232 break; |
|
233 case ETypeText: |
|
234 case ETypeTextPassword: |
|
235 HandleTypeTextFuncL( aMessage.Right( aMessage.Length() - 1 ) ); |
|
236 break; |
|
237 case ELongKeyPress: |
|
238 HandleLongKeyPressFuncL( aMessage.Right( aMessage.Length() - 1 ) ); |
|
239 break; |
|
240 case EPressKeySequence: |
|
241 HandlePressKeySequenceFuncL( aMessage.Right( aMessage.Length() - 1 ) ); |
|
242 break; |
|
243 default: |
|
244 SendErrorMessageL( EUnrecognizedCommand, |
|
245 KErrorUnrecognizedCommand ); |
|
246 break; |
|
247 } |
|
248 |
|
249 HTI_LOG_FUNC_OUT( "CKeyEventHandler::ProcessMessageL: Done" ); |
|
250 } |
|
251 |
|
252 // ---------------------------------------------------------------------------- |
|
253 // CKeyEventHandler::HandleTypeTextFuncL() |
|
254 // Handle request to send one or more unicode characters to top most |
|
255 // focused UI application. |
|
256 // ---------------------------------------------------------------------------- |
|
257 void CKeyEventHandler::HandleTypeTextFuncL( |
|
258 const TDesC8& aUnicodeChars ) |
|
259 { |
|
260 HTI_LOG_FUNC_IN( "CKeyEventHandler::HandleTypeTextFunc" ); |
|
261 |
|
262 // For UCS-2 and common unicode key code areas, see |
|
263 // http://czyborra.com/unicode/characters.html |
|
264 // "How are the Unicode characters numbered?" |
|
265 |
|
266 if ( aUnicodeChars.Size() == 0 ) |
|
267 { |
|
268 SendErrorMessageL( EEmptyUnicodeCharArray, KErrorEmptyUnicodeArray ); |
|
269 return; |
|
270 } |
|
271 |
|
272 #ifdef __ENABLE_LOGGING__ |
|
273 CArrayFixFlat<TInt> *windowGroups = new (ELeave) CArrayFixFlat<TInt>(5); |
|
274 iWsSession.WindowGroupList(windowGroups); |
|
275 HTI_LOG_FORMAT("WindowGroupList, %d groups:",windowGroups->Count()); |
|
276 for ( TInt i = 0; i < windowGroups->Count(); i++ ) |
|
277 { |
|
278 TBuf<125> wgname; // max length for wg name? |
|
279 iWsSession.GetWindowGroupNameFromIdentifier((*windowGroups)[i], wgname); |
|
280 |
|
281 TBuf<145> logmsg; |
|
282 logmsg.AppendFormat(_L("WgId %3d - \""), (*windowGroups)[i]); |
|
283 logmsg.Append(wgname); |
|
284 logmsg.Append(_L("\"")); |
|
285 HTI_LOG_DES(logmsg); |
|
286 } |
|
287 delete windowGroups; |
|
288 #endif |
|
289 |
|
290 // Get the front most focused window group. Note that this might |
|
291 // not necessarily be the front-most window group, as |
|
292 // window groups can disable keyboard focus. |
|
293 iFocusedWindowGroup = iWsSession.GetFocusWindowGroup(); |
|
294 |
|
295 HTI_LOG_TEXT("FocusWindowGroup name :"); |
|
296 TBuf<125> focusWindowGroupName; // max length for wg name? |
|
297 iWsSession.GetWindowGroupNameFromIdentifier(iFocusedWindowGroup, focusWindowGroupName); |
|
298 HTI_LOG_DES(focusWindowGroupName); |
|
299 |
|
300 // ...exception to above! (in EKA2) : |
|
301 // When we are in idle state the text must be sent to 'Telephone' task's |
|
302 // windowgroup because 'idle' windowgroup does not handle keyevents. |
|
303 // |
|
304 // Also when typing in idle state we need EKeyUp event to prevent the key |
|
305 // beeing stuck in the pressed position. |
|
306 // |
|
307 // Window group name contains UID - we are using UID to find the |
|
308 // 'Idle' window group so it will be found also with different |
|
309 // localizations. The name 'Idle' cannot be used since the name is |
|
310 // localized. |
|
311 |
|
312 if ( ( focusWindowGroupName.Find( _L( "101fd64c" ) ) != KErrNotFound ) || |
|
313 ( focusWindowGroupName.Find( _L( "102750f0" ) ) != KErrNotFound ) ) |
|
314 { |
|
315 HTI_LOG_TEXT( "FocusWindowGroup is \"Idle\". Sending text to \"Telephone\" task." ); |
|
316 TApaTaskList taskList( iWsSession ); |
|
317 TApaTask telephoneTask = taskList.FindApp( TUid::Uid( 0x100058b3 ) ); |
|
318 if ( !telephoneTask.Exists() ) |
|
319 { |
|
320 HTI_LOG_FUNC_OUT( "CKeyEventHandler::SimulateKeyEventL: \"Telephone\" task does not exist" ); |
|
321 User::Leave( KErrNotFound ); |
|
322 } |
|
323 |
|
324 iFocusedWindowGroup = telephoneTask.WgId(); |
|
325 |
|
326 // We must also get focus to 'Telephone' task for it |
|
327 // to receive our text. |
|
328 TWsEvent event; |
|
329 event.SetType( EEventFocusGained ); |
|
330 iWsSession.SendEventToWindowGroup( telephoneTask.WgId(), event ); |
|
331 } |
|
332 |
|
333 if ( aUnicodeChars.Size() % 2 == 1 ) |
|
334 { |
|
335 // aUnicodeChars descriptor must be divisible by two, |
|
336 // because expecting two-byte characters |
|
337 SendErrorMessageL( EInvalidUnicodeCharArray, |
|
338 KErrorInvalidUnicodeCharArray ); |
|
339 return; |
|
340 } |
|
341 |
|
342 // Start work |
|
343 if ( iUnicodeChars ) |
|
344 { |
|
345 delete iUnicodeChars; |
|
346 iUnicodeChars = NULL; |
|
347 } |
|
348 |
|
349 // If the string begins with unicode byte order mark 0xfffe, strip it away |
|
350 if ( ( aUnicodeChars[0] == 0xff && aUnicodeChars[1] == 0xfe ) ) |
|
351 { |
|
352 HTI_LOG_TEXT( "Ignoring Unicode BOM (first 2 bytes) from the string" ); |
|
353 iUnicodeChars = aUnicodeChars.Mid( 2 ).AllocL(); |
|
354 } |
|
355 else // take the string as it is |
|
356 { |
|
357 iUnicodeChars = aUnicodeChars.AllocL(); |
|
358 } |
|
359 iReady = EFalse; |
|
360 |
|
361 TypeTextWithDelay( 0 ); |
|
362 |
|
363 HTI_LOG_FUNC_OUT("CKeyEventHandler::HandleTypeTextFunc: Done (operation started)"); |
|
364 } |
|
365 |
|
366 // ---------------------------------------------------------------------------- |
|
367 // CKeyEventHandler::TypeTextWithDelay() |
|
368 // ---------------------------------------------------------------------------- |
|
369 void CKeyEventHandler::TypeTextWithDelay( TInt aNextIndex ) |
|
370 { |
|
371 iUnicodeCharIndex = aNextIndex; |
|
372 // Keep a longer pause in some character intervals if the given text |
|
373 // is very long to avoid losing characters. |
|
374 if ( iUnicodeCharIndex > KTypeTextStartPausing && |
|
375 iUnicodeCharIndex % KTypeTextPauseInterval == 0 ) |
|
376 { |
|
377 iTimer.After( iStatus, KTypeTextPauseInMicroSeconds ); |
|
378 } |
|
379 else |
|
380 { |
|
381 iTimer.After( iStatus, KTypeTextDelayBetweenCharsInMicroSeconds ); |
|
382 } |
|
383 SetActive(); |
|
384 } |
|
385 |
|
386 // ---------------------------------------------------------------------------- |
|
387 // CKeyEventHandler::SimulateKeyEventL() |
|
388 // ---------------------------------------------------------------------------- |
|
389 void CKeyEventHandler::SimulateKeyEventL( const TDesC8& aUnicodeChars, |
|
390 TInt aIndex ) |
|
391 { |
|
392 |
|
393 // Expect aUnicodeChars to be Unicode characters (each two bytes) |
|
394 // Note: aIndex is within range of 0 to aUnicodeChars/2 |
|
395 |
|
396 HTI_LOG_FUNC_IN("CKeyEventHandler::SimulateKeyEventL"); |
|
397 TKeyEvent keyEvent; |
|
398 const TUint8* rawDataStart = aUnicodeChars.Ptr(); |
|
399 keyEvent.iCode = *( (TUint16*) ( rawDataStart + aIndex * 2 ) ); |
|
400 // Set modifier to treat key events as events from external keyboard |
|
401 // so that AknFep won't interfere with numbers and * and # characters. |
|
402 keyEvent.iModifiers = EModifierKeyboardExtend; |
|
403 keyEvent.iRepeats = 0; |
|
404 //keyEvent.iScanCode = EStdKeyNull; |
|
405 // change because FEP got confused about EStdKeyNull in key-up event and |
|
406 // opened the edit menu |
|
407 keyEvent.iScanCode = 255; |
|
408 |
|
409 TWsEvent event; |
|
410 *event.Key() = keyEvent; |
|
411 |
|
412 if ( iCommand == ETypeTextPassword ) |
|
413 { |
|
414 // Typing a password needs only EEventKey. |
|
415 // Otherwise it will appear to be pressed twice. |
|
416 HTI_LOG_FORMAT( "EEventKey 0x%x", keyEvent.iCode ); |
|
417 event.SetType( EEventKey ); |
|
418 iWsSession.SendEventToWindowGroup( iFocusedWindowGroup, event ); |
|
419 } |
|
420 else |
|
421 { |
|
422 // EEventKeyUp is needed when typing a SMS or MMS. Otherwise the |
|
423 // counters will not be updated and message will be corrupt. |
|
424 // Also typing in idle state requires EEventKeyUp for the key to be |
|
425 // released. |
|
426 HTI_LOG_FORMAT( "EEventKey&EEventKeyUp 0x%x", keyEvent.iCode ); |
|
427 event.SetType( EEventKey ); |
|
428 iWsSession.SendEventToWindowGroup( iFocusedWindowGroup, event ); |
|
429 |
|
430 event.SetType( EEventKeyUp ); |
|
431 iWsSession.SendEventToWindowGroup( iFocusedWindowGroup, event ); |
|
432 } |
|
433 |
|
434 HTI_LOG_FUNC_OUT( "CKeyEventHandler::SimulateKeyEventL" ); |
|
435 } |
|
436 |
|
437 // ---------------------------------------------------------------------------- |
|
438 // CKeyEventHandler::KeyUp() |
|
439 // ---------------------------------------------------------------------------- |
|
440 void CKeyEventHandler::KeyUp( TUint aCode ) |
|
441 { |
|
442 HTI_LOG_FUNC_IN( "CKeyEventHandler::KeyUp: Starting" ); |
|
443 TRawEvent rawEvent; |
|
444 rawEvent.Set( TRawEvent::EKeyUp, aCode ); |
|
445 iWsSession.SimulateRawEvent( rawEvent ); |
|
446 iWsSession.Flush(); |
|
447 HTI_LOG_FUNC_OUT( "CKeyEventHandler::KeyUp: Done" ); |
|
448 } |
|
449 |
|
450 // ---------------------------------------------------------------------------- |
|
451 // CKeyEventHandler::KeyDown() |
|
452 // ---------------------------------------------------------------------------- |
|
453 void CKeyEventHandler::KeyDown( TUint aCode ) |
|
454 { |
|
455 HTI_LOG_FUNC_IN( "CKeyEventHandler::KeyDown: Starting" ); |
|
456 User::ResetInactivityTime(); |
|
457 TRawEvent rawEvent; |
|
458 rawEvent.Set( TRawEvent::EKeyDown, aCode ); |
|
459 iWsSession.SimulateRawEvent( rawEvent ); |
|
460 iWsSession.Flush(); |
|
461 HTI_LOG_FUNC_OUT( "CKeyEventHandler::KeyDown: Done" ); |
|
462 } |
|
463 |
|
464 // ---------------------------------------------------------------------------- |
|
465 // CKeyEventHandler::HandleKeyboardFuncL() |
|
466 // Handle request to emulate pressing keyboard keys in sequence. |
|
467 // ---------------------------------------------------------------------------- |
|
468 void CKeyEventHandler::HandleKeyboardFuncL( const TDesC8& aData ) |
|
469 { |
|
470 HTI_LOG_FUNC_IN( "CKeyEventHandler::HandleKeyboardFuncL" ); |
|
471 |
|
472 HTI_LOG_FORMAT( "CKeyEventHandler::HandleKeyboardFuncL: Size of data: %d", aData.Length() ); |
|
473 HTI_LOG_TEXT( "CKeyEventHandler::HandleKeyboardFuncL: Data: " ); |
|
474 HTI_LOG_DES( aData ); |
|
475 |
|
476 // <scancode> is unsigned short integer, a scancode of |
|
477 // keyboard key. Theses are defined in E32KEYS.H. It depends on |
|
478 // device how these are mapped to actual keyboard keys in the |
|
479 // device. |
|
480 // |
|
481 // Client note: each call to KEYDOWN should be followed by KEYUP |
|
482 // with the same scancode at some point. |
|
483 |
|
484 if ( aData.Length() != KKeyboardFuncDataLength ) |
|
485 { |
|
486 // HTI_LOG_FORMAT( "PRESSKEY: Invalid scancode length: %d (expecting 2 bytes).", ptr.Length() - 1); |
|
487 SendErrorMessageL( EInvalidScancode, KErrorInvalidScancode ); |
|
488 return; |
|
489 } |
|
490 |
|
491 iReady = EFalse; |
|
492 |
|
493 TUint scanCode = UintValue( aData.Ptr() ); |
|
494 |
|
495 switch ( iCommand ) |
|
496 { |
|
497 case EPressKey: |
|
498 KeyDown( scanCode ); |
|
499 KeyUp( scanCode ); |
|
500 break; |
|
501 |
|
502 case EKeyDown: |
|
503 KeyDown( scanCode ); |
|
504 break; |
|
505 |
|
506 case EKeyUp: |
|
507 KeyUp( scanCode ); |
|
508 break; |
|
509 |
|
510 default: |
|
511 break; |
|
512 } |
|
513 SendOkMsgL(); |
|
514 iReady = ETrue; |
|
515 HTI_LOG_FUNC_OUT("CKeyEventHandler::HandleKeyboardFuncL: Done"); |
|
516 } |
|
517 |
|
518 // ---------------------------------------------------------------------------- |
|
519 // CKeyEventHandler::HandleLongKeyPressFuncL() |
|
520 // Handle request to emulate holding a key down for specified time. |
|
521 // ---------------------------------------------------------------------------- |
|
522 void CKeyEventHandler::HandleLongKeyPressFuncL( const TDesC8& aData ) |
|
523 { |
|
524 HTI_LOG_FUNC_IN( "CKeyEventHandler::HanldeLongKeyPressFuncL" ); |
|
525 |
|
526 if ( aData.Length() != KLongKeyPressDataLength ) |
|
527 { |
|
528 SendErrorMessageL( EInvalidScancode, KErrorInvalidScancode ); |
|
529 return; |
|
530 } |
|
531 |
|
532 iReady = EFalse; |
|
533 iHoldingScanCode = UintValue( aData.Ptr() ); |
|
534 TTimeIntervalMicroSeconds32 holdTime( UintValue( aData.Ptr() + 2 ) * 1000 ); |
|
535 KeyDown( iHoldingScanCode ); |
|
536 iTimer.After( iStatus, holdTime ); |
|
537 SetActive(); |
|
538 |
|
539 HTI_LOG_FUNC_OUT( "CKeyEventHandler::HanldeLongKeyPressFuncL" ); |
|
540 } |
|
541 |
|
542 // ---------------------------------------------------------------------------- |
|
543 // CKeyEventHandler::HandlePressKeySequenceFuncL() |
|
544 // Handle request to press keys in sequence. |
|
545 // ---------------------------------------------------------------------------- |
|
546 void CKeyEventHandler::HandlePressKeySequenceFuncL( const TDesC8& aData ) |
|
547 { |
|
548 HTI_LOG_FUNC_IN( "CKeyEventHandler::HandlePressKeySequenceFuncL" ); |
|
549 |
|
550 if ( aData.Length() % 2 != 0 ) |
|
551 { |
|
552 HTI_LOG_FORMAT( "Invalid data length: %d", aData.Length() ); |
|
553 SendErrorMessageL( EInvalidUnicodeCharArray, KErrorInvalidUnicodeCharArray ); |
|
554 return; |
|
555 } |
|
556 |
|
557 if ( aData.Length() < KPressKeySequenceMinDataLength ) |
|
558 { |
|
559 HTI_LOG_FORMAT( "Too short data: %d", aData.Length() ); |
|
560 SendErrorMessageL( EEmptyUnicodeCharArray, KErrorEmptyUnicodeArray ); |
|
561 return; |
|
562 } |
|
563 |
|
564 iReady = EFalse; |
|
565 |
|
566 iKeySequenceHoldTime = UintValue( aData.Ptr() ) * 1000; |
|
567 iKeySequenceInterval = UintValue( aData.Ptr() + 2 ) * 1000; |
|
568 HTI_LOG_FORMAT( "Parsed key sequence hold time: %d", iKeySequenceHoldTime.Int() / 1000 ); |
|
569 HTI_LOG_FORMAT( "Parsed key sequence interval: %d", iKeySequenceInterval.Int() / 1000 ); |
|
570 if ( iKeySequenceInterval.Int() < KTypeTextDelayBetweenCharsInMicroSeconds ) |
|
571 { |
|
572 HTI_LOG_TEXT( "Given key sequence interval too low, using the default value" ); |
|
573 iKeySequenceInterval = KTypeTextDelayBetweenCharsInMicroSeconds; |
|
574 } |
|
575 |
|
576 if(iUnicodeChars) |
|
577 { |
|
578 delete iUnicodeChars; |
|
579 iUnicodeChars = NULL; |
|
580 } |
|
581 |
|
582 iUnicodeChars = aData.Mid( 4 ).AllocL(); |
|
583 iUnicodeCharIndex = 0; |
|
584 iHoldingKey = EFalse; |
|
585 |
|
586 PressKeySequenceKeyL(); |
|
587 |
|
588 HTI_LOG_FUNC_OUT( "CKeyEventHandler::HandlePressKeySequenceFuncL" ); |
|
589 } |
|
590 |
|
591 // ---------------------------------------------------------------------------- |
|
592 // CKeyEventHandler::PressKeySequenceKeyL() |
|
593 // Handle a single key press from press keys in sequence command. |
|
594 // ---------------------------------------------------------------------------- |
|
595 void CKeyEventHandler::PressKeySequenceKeyL() |
|
596 { |
|
597 HTI_LOG_FUNC_IN( "CKeyEventHandler::PressKeySequenceKeyL" ); |
|
598 |
|
599 if ( iHoldingKey ) |
|
600 { |
|
601 KeyUp( iHoldingScanCode ); |
|
602 iHoldingKey = EFalse; |
|
603 |
|
604 HTI_LOG_FORMAT( "Released key: %d", iHoldingScanCode ); |
|
605 |
|
606 if ( iUnicodeChars->Length() > iUnicodeCharIndex ) |
|
607 { |
|
608 iTimer.After( iStatus, iKeySequenceInterval ); |
|
609 SetActive(); |
|
610 } |
|
611 else |
|
612 { |
|
613 HTI_LOG_TEXT( "PressKeySequence has finished: OK" ); |
|
614 SendOkMsgL(); |
|
615 iReady = ETrue; |
|
616 } |
|
617 } |
|
618 else |
|
619 { |
|
620 iHoldingScanCode = UintValue( iUnicodeChars->Ptr() + iUnicodeCharIndex ); |
|
621 iUnicodeCharIndex += 2; |
|
622 |
|
623 KeyDown( iHoldingScanCode ); |
|
624 iHoldingKey = ETrue; |
|
625 |
|
626 HTI_LOG_FORMAT( "Holding down key: %d", iHoldingScanCode ); |
|
627 |
|
628 iTimer.After( iStatus, iKeySequenceHoldTime ); |
|
629 SetActive(); |
|
630 } |
|
631 |
|
632 HTI_LOG_FUNC_OUT( "CKeyEventHandler::HandlePressKeySequenceFuncL" ); |
|
633 } |
|
634 |
|
635 // ---------------------------------------------------------------------------- |
|
636 // CKeyEventHandler::SendOkMsgL() |
|
637 // ---------------------------------------------------------------------------- |
|
638 void CKeyEventHandler::SendOkMsgL() |
|
639 { |
|
640 HTI_LOG_FUNC_IN("CKeyEventHandler::SendOkMsgL: Starting"); |
|
641 |
|
642 User::LeaveIfNull( iDispatcher ); |
|
643 TBuf8<1> response; |
|
644 response.Append( EResultOk ); |
|
645 HBufC8* respH8 = response.AllocL(); |
|
646 User::LeaveIfError( iDispatcher->DispatchOutgoingMessage( |
|
647 respH8, KKeyEventServiceUid ) ); |
|
648 |
|
649 HTI_LOG_FUNC_OUT("CKeyEventHandler::SendOkMsgL: Done"); |
|
650 } |
|
651 |
|
652 // ---------------------------------------------------------------------------- |
|
653 // CKeyEventHandler::SendErrorMessageL() |
|
654 // ---------------------------------------------------------------------------- |
|
655 void CKeyEventHandler::SendErrorMessageL( TInt aError, |
|
656 const TDesC8& aDescription ) |
|
657 { |
|
658 HTI_LOG_FUNC_IN("CKeyEventHandler::SendErrorMessageL: Starting"); |
|
659 User::LeaveIfNull( iDispatcher ); |
|
660 User::LeaveIfError( iDispatcher->DispatchOutgoingErrorMessage( |
|
661 aError, aDescription, KKeyEventServiceUid ) ); |
|
662 HTI_LOG_FUNC_OUT("CKeyEventHandler::SendErrorMessageL: Done"); |
|
663 } |