|
1 /* |
|
2 * Copyright (c) 2007 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: Key event forwarder. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include <eikenv.h> |
|
21 #include <eikappui.h> |
|
22 #include <bldvariant.hrh> |
|
23 #include <featmgr.h> |
|
24 #include <PtiDefs.h> |
|
25 #include <AknUtils.h> |
|
26 |
|
27 #include "mphonestatemachine.h" |
|
28 #include "mphonekeyeventhandler.h" |
|
29 #include "cphonekeys.h" |
|
30 #include "cphonekeyeventforwarder.h" |
|
31 #include "cphonepubsubproxy.h" |
|
32 #include "cphonetimer.h" |
|
33 #include "phonelogger.h" |
|
34 #include "phoneui.pan" |
|
35 #include "mphoneviewcommandhandle.h" |
|
36 #include "cphoneqwertyhandler.h" |
|
37 #include "tphonecmdparampointer.h" |
|
38 #include "tphonecmdparamboolean.h" |
|
39 #include "mphoneqwertymodeobserver.h" |
|
40 #include "cdialer.h" |
|
41 |
|
42 // CONSTANTS |
|
43 |
|
44 //Avkon P&S keys |
|
45 const TUid KCRUidAvkon = { 0x101F876E }; |
|
46 const TUint32 KAknKeyBoardLayout = 0x0000000B; |
|
47 |
|
48 // Characters resulting from multitapping *-key. |
|
49 _LIT( KAsteriskMultitapCharacters, "*+pw" ); |
|
50 |
|
51 // Multitap delay parameter in micro seconds. |
|
52 const TInt KMultitapDelay = 1000000; |
|
53 |
|
54 |
|
55 // ============================ MEMBER FUNCTIONS =============================== |
|
56 |
|
57 // ----------------------------------------------------------------------------- |
|
58 // CPhoneKeyEventForwarder::NewL |
|
59 // ----------------------------------------------------------------------------- |
|
60 // |
|
61 CPhoneKeyEventForwarder* CPhoneKeyEventForwarder::NewL( |
|
62 const TRect& aRect, |
|
63 MPhoneStateMachine* aStateMachine, |
|
64 MPhoneViewCommandHandle* aViewCommandHandle ) |
|
65 { |
|
66 CPhoneKeyEventForwarder* self = |
|
67 new (ELeave) CPhoneKeyEventForwarder( aStateMachine, aViewCommandHandle ); |
|
68 |
|
69 CleanupStack::PushL( self ); |
|
70 self->ConstructL( aRect ); |
|
71 CleanupStack::Pop( self ); |
|
72 |
|
73 return self; |
|
74 } |
|
75 |
|
76 // ----------------------------------------------------------------------------- |
|
77 // CPhoneKeyEventForwarder::~CPhoneKeyEventForwarder |
|
78 // ----------------------------------------------------------------------------- |
|
79 // |
|
80 CPhoneKeyEventForwarder::~CPhoneKeyEventForwarder() |
|
81 { |
|
82 __LOGMETHODSTARTEND( EPhoneControl, "CPhoneKeyEventForwarder::~CPhoneKeyEventForwarder"); |
|
83 |
|
84 if ( AknLayoutUtils::PenEnabled() ) |
|
85 { |
|
86 iPeninputServer.RemovePenUiActivationHandler( this ); |
|
87 } |
|
88 |
|
89 iPeninputServer.Close(); |
|
90 |
|
91 if ( iEikonEnv ) |
|
92 { |
|
93 iEikonEnv->EikAppUi()->RemoveFromStack( this ); |
|
94 } |
|
95 delete iLongPressKeyEventTimer; |
|
96 |
|
97 delete iQwertyHandler; |
|
98 } |
|
99 |
|
100 // ----------------------------------------------------------------------------- |
|
101 // CPhoneKeyEventForwarder::CountComponentControls |
|
102 // ----------------------------------------------------------------------------- |
|
103 // |
|
104 TInt CPhoneKeyEventForwarder::CountComponentControls() const |
|
105 { |
|
106 __LOGMETHODSTARTEND( EPhoneControl, "CPhoneKeyEventForwarder::CountComponentControls"); |
|
107 return 0; |
|
108 } |
|
109 |
|
110 // ----------------------------------------------------------------------------- |
|
111 // CPhoneKeyEventForwarder::ComponentControl |
|
112 // ----------------------------------------------------------------------------- |
|
113 // |
|
114 CCoeControl* CPhoneKeyEventForwarder::ComponentControl( |
|
115 TInt /*aIndex*/ ) const |
|
116 { |
|
117 __LOGMETHODSTARTEND( EPhoneControl, "CPhoneKeyEventForwarder::ComponentControl"); |
|
118 return NULL; |
|
119 } |
|
120 |
|
121 // ----------------------------------------------------------------------------- |
|
122 // CPhoneKeyEventForwarder::SizeChanged |
|
123 // ----------------------------------------------------------------------------- |
|
124 // |
|
125 void CPhoneKeyEventForwarder::SizeChanged() |
|
126 { |
|
127 __LOGMETHODSTARTEND( EPhoneControl, "CPhoneKeyEventForwarder::SizeChanged"); |
|
128 } |
|
129 |
|
130 // ----------------------------------------------------------------------------- |
|
131 // CPhoneKeyEventForwarder::Draw |
|
132 // ----------------------------------------------------------------------------- |
|
133 // |
|
134 void CPhoneKeyEventForwarder::Draw( |
|
135 const TRect& /*aRect*/ ) const |
|
136 { |
|
137 __LOGMETHODSTARTEND( EPhoneControl, "CPhoneKeyEventForwarder::Draw"); |
|
138 } |
|
139 |
|
140 // ----------------------------------------------------------------------------- |
|
141 // CPhoneKeyEventForwarder::OfferKeyEventL |
|
142 // Checks is hte keyevent such that the number entry can be opened |
|
143 // ----------------------------------------------------------------------------- |
|
144 // |
|
145 TKeyResponse CPhoneKeyEventForwarder::OfferKeyEventL( |
|
146 const TKeyEvent& aKeyEvent, |
|
147 TEventCode aType ) |
|
148 { |
|
149 __LOGMETHODSTARTEND( EPhoneControl, |
|
150 "CPhoneKeyEventForwarder::OfferKeyEventL"); |
|
151 |
|
152 TKeyResponse ret( EKeyWasNotConsumed ); |
|
153 |
|
154 // After event key, expect to have key up event. |
|
155 iExpectKeyUpEvent = ( aType == EEventKey ); |
|
156 |
|
157 ret = OfferKeyEventBeforeControlStackL( aKeyEvent, aType ); |
|
158 |
|
159 if ( !aKeyEvent.iRepeats && aKeyEvent.iCode != EKeyEscape ) |
|
160 { |
|
161 // Convert event. Use already converted iKeyPressedDown. |
|
162 TKeyEvent keyEvent = aKeyEvent; |
|
163 if ( keyEvent.iScanCode == EStdKeyApplication0 ) |
|
164 { |
|
165 keyEvent.iCode = EKeyApplication0; |
|
166 } |
|
167 else |
|
168 { |
|
169 keyEvent.iCode = iKeyPressedDown; |
|
170 } |
|
171 |
|
172 // Do not handle dtmf tone if the type is EEventKey but we are not |
|
173 // expecting key up event. This happens if the key up event has been |
|
174 // handled by some CActiveSchedulerWait object somewhere in the execution |
|
175 // of function OfferKeyEventBeforeControlStackL. |
|
176 if ( iExpectKeyUpEvent || aType != EEventKey ) |
|
177 { |
|
178 // Start and stop dtmf |
|
179 iStateMachine->State()->HandleDtmfKeyToneL( keyEvent, aType ); |
|
180 } |
|
181 |
|
182 // Open number entry view if any allowed character key |
|
183 // is pressed on homescreen or in-call ui |
|
184 if ( aType != EEventKeyUp && IsKeyAllowedL( keyEvent ) ) |
|
185 { |
|
186 // Do not open number entry with up key |
|
187 iStateMachine->State()->HandleCreateNumberEntryL( keyEvent, aType ); |
|
188 } |
|
189 } |
|
190 |
|
191 return ret; |
|
192 } |
|
193 |
|
194 // ----------------------------------------------------------------------------- |
|
195 // CPhoneKeyEventForwarder::CPhoneKeyEventForwarder |
|
196 // ----------------------------------------------------------------------------- |
|
197 // |
|
198 CPhoneKeyEventForwarder::CPhoneKeyEventForwarder( |
|
199 MPhoneStateMachine* aStateMachine, |
|
200 MPhoneViewCommandHandle* aViewCommandHandle ) |
|
201 : iStateMachine( aStateMachine ), |
|
202 iViewCommandHandle( aViewCommandHandle ) |
|
203 { |
|
204 __LOGMETHODSTARTEND( EPhoneControl, |
|
205 "CPhoneKeyEventForwarder::CPhoneKeyEventForwarder"); |
|
206 } |
|
207 |
|
208 // ----------------------------------------------------------------------------- |
|
209 // CPhoneKeyEventForwarder::ConstructL |
|
210 // ----------------------------------------------------------------------------- |
|
211 // |
|
212 void CPhoneKeyEventForwarder::ConstructL( const TRect& aRect ) |
|
213 { |
|
214 __LOGMETHODSTARTEND( EPhoneControl, |
|
215 "CPhoneKeyEventForwarder::ConstructL"); |
|
216 |
|
217 if ( FeatureManager::FeatureSupported( KFeatureIdKeypadNoSlider ) ) |
|
218 { |
|
219 RWindowGroup& groupWin = iCoeEnv->RootWin(); |
|
220 } |
|
221 // Create invisible control. |
|
222 CreateWindowL(); |
|
223 MakeVisible( EFalse ); |
|
224 SetRect( aRect ); |
|
225 |
|
226 if ( iEikonEnv ) |
|
227 { |
|
228 iEikonEnv->EikAppUi()->AddToStackL( |
|
229 this, |
|
230 ECoeStackPriorityEnvironmentFilter, |
|
231 ECoeStackFlagRefusesFocus ); |
|
232 } |
|
233 |
|
234 // Create the long press key event timer |
|
235 iLongPressKeyEventTimer = CPhoneTimer::NewL(); |
|
236 |
|
237 // Create qwerty mode handler |
|
238 iQwertyHandler = CPhoneQwertyHandler::NewL(); |
|
239 |
|
240 TPhoneCmdParamPointer ptrParam; |
|
241 iViewCommandHandle->ExecuteCommand( EPhoneViewGetQwertyModeObserver, &ptrParam ); |
|
242 CDialer* qwertyObserver = |
|
243 static_cast<CDialer*>( ptrParam.Pointer() ); |
|
244 |
|
245 iQwertyHandler->AddQwertyModeObserverL( *qwertyObserver ); |
|
246 |
|
247 if ( AknLayoutUtils::PenEnabled() ) |
|
248 { |
|
249 User::LeaveIfError( iPeninputServer.Connect() ); |
|
250 iPeninputServer.AddPenUiActivationHandler( this, EPluginInputModeAll ); |
|
251 iVirtualKeyBoardOpen = iPeninputServer.IsVisible(); |
|
252 } |
|
253 |
|
254 CEikonEnv* env = static_cast<CEikonEnv*>( ControlEnv() ); |
|
255 if ( env ) |
|
256 { |
|
257 iMenu = env->AppUiFactory()->MenuBar(); |
|
258 } |
|
259 } |
|
260 |
|
261 // ----------------------------------------------------------------------------- |
|
262 // CPhoneKeyEventForwarder::IsKeyAllowedL |
|
263 // ----------------------------------------------------------------------------- |
|
264 // |
|
265 TBool CPhoneKeyEventForwarder::IsKeyAllowedL( const TKeyEvent& aKeyEvent ) |
|
266 { |
|
267 __LOGMETHODSTARTEND( EPhoneControl, |
|
268 "CPhoneKeyEventForwarder::IsKeyAllowedL"); |
|
269 |
|
270 TKeyEvent keyEvent( aKeyEvent ); |
|
271 |
|
272 // Check keyboard mode |
|
273 TBool isModeNumeric = iViewCommandHandle->HandleCommandL( |
|
274 EPhoneViewIsNumberEntryNumericMode ) == EPhoneViewResponseSuccess; |
|
275 |
|
276 // Check if key is a numeric key |
|
277 TBool isNumeric = CPhoneKeys::IsNumericKey( keyEvent, EEventKey ); |
|
278 |
|
279 // Check if key is alpha numeric key and alphabet input is allowed |
|
280 TBool isAllowedAlphaNumeric = |
|
281 iStateMachine->State()->IsAlphanumericSupportedAndCharInput( keyEvent ); |
|
282 |
|
283 return ( ( isModeNumeric && isNumeric ) || |
|
284 ( !isModeNumeric && isAllowedAlphaNumeric ) ); |
|
285 } |
|
286 |
|
287 // ----------------------------------------------------------------------------- |
|
288 // CPhoneKeyEventForwarder::ConvertHalfQwertySpecialChar |
|
289 // ----------------------------------------------------------------------------- |
|
290 // |
|
291 TBool CPhoneKeyEventForwarder::ConvertHalfQwertySpecialChar( TUint& aCode, |
|
292 const TKeyEvent& aKeyEvent ) |
|
293 { |
|
294 __LOGMETHODSTARTEND( EPhoneControl, |
|
295 "CPhoneKeyEventForwarder::ConvertHalfQwertySpecialChar"); |
|
296 |
|
297 TBool ret( EFalse ); |
|
298 TInt keyboard( CPhonePubSubProxy::Instance()->Value( |
|
299 KCRUidAvkon, |
|
300 KAknKeyBoardLayout ) ); |
|
301 |
|
302 if ( keyboard == EPtiKeyboardHalfQwerty ) |
|
303 { |
|
304 switch ( aKeyEvent.iScanCode ) |
|
305 { |
|
306 case EStdKeyLeftShift: |
|
307 ret = ETrue; |
|
308 aCode = KPhoneDtmfHashCharacter; |
|
309 break; |
|
310 case EStdKeyLeftFunc: |
|
311 ret = ETrue; |
|
312 aCode = KPhoneDtmfStarCharacter; |
|
313 break; |
|
314 case EStdKeySpace: |
|
315 ret = ETrue; |
|
316 aCode = KPhoneDtmf0Character; |
|
317 break; |
|
318 default: |
|
319 break; |
|
320 } |
|
321 } |
|
322 |
|
323 __PHONELOG1( EBasic, EPhoneControl, |
|
324 "CPhoneKeyEventForwarder::ConvertHalfQwertySpecialChar =%d ", |
|
325 ret ); |
|
326 |
|
327 return ret; |
|
328 } |
|
329 |
|
330 // ----------------------------------------------------------------------------- |
|
331 // CPhoneKeyEventForwarder::IsKeySimulatedByTouchDialer |
|
332 // |
|
333 // ----------------------------------------------------------------------------- |
|
334 // |
|
335 TBool CPhoneKeyEventForwarder::IsKeySimulatedByTouchDialer( |
|
336 const TKeyEvent& aKeyEvent ) const |
|
337 { |
|
338 return ( ( aKeyEvent.iModifiers & EModifierNumLock ) && |
|
339 ( aKeyEvent.iModifiers & EModifierKeypad ) ); |
|
340 } |
|
341 |
|
342 // ----------------------------------------------------------------------------- |
|
343 // CPhoneKeyEventForwarder::HandleTouchDialerKeyEventL |
|
344 // Handle EEventKey type of event from touch dialer |
|
345 // ----------------------------------------------------------------------------- |
|
346 // |
|
347 void CPhoneKeyEventForwarder::HandleTouchDialerKeyEventL( const TKeyEvent& aKeyEvent ) |
|
348 { |
|
349 TBool multitap = aKeyEvent.iScanCode == EStdKeyNkpAsterisk && |
|
350 iPreviousScanCode == EStdKeyNkpAsterisk && |
|
351 iKeyPressTime.MicroSecondsFrom( iPreviousKeyPressTime ) < KMultitapDelay; |
|
352 |
|
353 if ( multitap ) |
|
354 { |
|
355 // Update multitap index |
|
356 iMultitapIndex = ( iMultitapIndex + 1 ) % KAsteriskMultitapCharacters().Length(); |
|
357 |
|
358 // Delete the previously entered character by simulating a backspace character. |
|
359 TKeyEvent backSpaceEvent; |
|
360 backSpaceEvent.iModifiers = 0; |
|
361 backSpaceEvent.iRepeats = 0; |
|
362 backSpaceEvent.iCode = EKeyBackspace; |
|
363 backSpaceEvent.iScanCode = EStdKeyBackspace; |
|
364 iStateMachine->State()->HandleKeyEventL( backSpaceEvent, EEventKey ); |
|
365 |
|
366 TKeyEvent keyEvent( aKeyEvent ); |
|
367 |
|
368 // Modify the key event to contain the next character on multitap list. |
|
369 keyEvent.iCode = ( TInt ) KAsteriskMultitapCharacters()[ iMultitapIndex ]; |
|
370 |
|
371 // Send character to number entry. |
|
372 iStateMachine->State()->HandleKeyEventL( keyEvent, EEventKey ); |
|
373 } |
|
374 else |
|
375 { |
|
376 iMultitapIndex = 0; |
|
377 iStateMachine->State()->HandleKeyEventL( aKeyEvent, EEventKey ); |
|
378 } |
|
379 } |
|
380 |
|
381 // ----------------------------------------------------------------------------- |
|
382 // CPhoneKeyEventForwarder::OfferKeyEventBeforeControlStackL |
|
383 // Let phone handle before other components in control stack |
|
384 // ----------------------------------------------------------------------------- |
|
385 // |
|
386 TKeyResponse CPhoneKeyEventForwarder::OfferKeyEventBeforeControlStackL( |
|
387 const TKeyEvent& aKeyEvent, |
|
388 TEventCode aType ) |
|
389 { |
|
390 __LOGMETHODSTARTEND( EPhoneControl, |
|
391 "CPhoneKeyEventForwarder::OfferKeyEventBeforeControlStackL"); |
|
392 |
|
393 TKeyResponse response( EKeyWasNotConsumed ); |
|
394 |
|
395 // Handle key events before FEP |
|
396 // This is must becouse FEP consumes * key and when |
|
397 // editor is in alphanumeric mode FEP consumes all alphanumeric |
|
398 // keys |
|
399 switch( aType ) |
|
400 { |
|
401 // EEventKeyDown |
|
402 case EEventKeyDown: |
|
403 response = HandleEventKeyDownBeforeControlStackL( aKeyEvent ); |
|
404 break; |
|
405 // EEventKey |
|
406 case EEventKey: |
|
407 response = HandleEventKeyBeforeControlStackL( aKeyEvent ); |
|
408 break; |
|
409 // EEventKeyUp |
|
410 case EEventKeyUp: |
|
411 response = HandleEventKeyUpBeforeControlStackL( aKeyEvent ); |
|
412 break; |
|
413 default: |
|
414 break; |
|
415 } |
|
416 |
|
417 return response; |
|
418 } |
|
419 |
|
420 |
|
421 // ----------------------------------------------------------------------------- |
|
422 // CPhoneKeyEventForwarder::OfferKeyEventAfterControlStackL |
|
423 // Let phone handle keys if no one has done it already |
|
424 // ----------------------------------------------------------------------------- |
|
425 // |
|
426 TKeyResponse CPhoneKeyEventForwarder::OfferKeyEventAfterControlStackL( |
|
427 const TKeyEvent& aKeyEvent, |
|
428 TEventCode aType ) |
|
429 { |
|
430 __LOGMETHODSTARTEND( EPhoneControl, |
|
431 "CPhoneKeyEventForwarder::OfferKeyEventAfterControlStackL"); |
|
432 |
|
433 // Send key to editor |
|
434 iStateMachine->State()->HandleKeyEventL( aKeyEvent, aType ); |
|
435 |
|
436 if ( EEventKeyUp == aType && EKeyNull != iKeyPressedDown ) |
|
437 { |
|
438 // EKeyEnter is always offered to Telephony so don´t offer it |
|
439 // to state if there is menu or a dialog open. |
|
440 if ( !( EKeyEnter == iKeyPressedDown |
|
441 && iDisplayingMenuOrDialogOnEventKeyDown ) ) |
|
442 { |
|
443 // Handle short key press |
|
444 iStateMachine->State()->HandleKeyMessageL( |
|
445 MPhoneKeyEvents::EPhoneKeyShortPress, |
|
446 TKeyCode( iKeyPressedDown ) ); |
|
447 } |
|
448 // Reset key code |
|
449 iScanCode = EStdKeyNull; |
|
450 iKeyPressedDown = EKeyNull; |
|
451 iDisplayingMenuOrDialogOnEventKeyDown = EFalse; |
|
452 } |
|
453 |
|
454 return EKeyWasNotConsumed; |
|
455 } |
|
456 |
|
457 // --------------------------------------------------------------------------- |
|
458 // CPhoneKeyEventForwarder::OnPeninputUiDeactivated |
|
459 // |
|
460 // Gets called when the virtual keyboard editor is closed. |
|
461 // --------------------------------------------------------------------------- |
|
462 // |
|
463 void CPhoneKeyEventForwarder::OnPeninputUiDeactivated() |
|
464 { |
|
465 __LOGMETHODSTARTEND( EPhoneControl, |
|
466 "CPhoneKeyEventForwarder::OnPeninputUiDeactivated"); |
|
467 iVirtualKeyBoardOpen = EFalse; |
|
468 } |
|
469 |
|
470 // --------------------------------------------------------------------------- |
|
471 // CPhoneKeyEventForwarder::OnPeninputUiActivated |
|
472 // |
|
473 // Gets called when the virtual keyboard editor is opened. |
|
474 // --------------------------------------------------------------------------- |
|
475 // |
|
476 void CPhoneKeyEventForwarder::OnPeninputUiActivated() |
|
477 { |
|
478 __LOGMETHODSTARTEND( EPhoneControl, |
|
479 "CPhoneKeyEventForwarder::OnPeninputUiActivated"); |
|
480 iVirtualKeyBoardOpen = ETrue; |
|
481 } |
|
482 |
|
483 // ----------------------------------------------------------- |
|
484 // CPhoneKeyEventForwarder::HandleEventKeyDownBeforeControlStackL |
|
485 // ----------------------------------------------------------- |
|
486 // |
|
487 TKeyResponse CPhoneKeyEventForwarder::HandleEventKeyDownBeforeControlStackL( |
|
488 const TKeyEvent& aKeyEvent ) |
|
489 { |
|
490 __LOGMETHODSTARTEND( EPhoneControl, |
|
491 "CPhoneKeyEventForwarder::HandleEventKeyDownBeforeControlStackL"); |
|
492 |
|
493 // Convert key code |
|
494 ConvertKeyCodeL( iKeyPressedDown, aKeyEvent ); |
|
495 // Save key scan code |
|
496 iScanCode = aKeyEvent.iScanCode; |
|
497 |
|
498 // Store the previous keypress time. |
|
499 iPreviousKeyPressTime = iKeyPressTime; |
|
500 |
|
501 // Start the key press timer |
|
502 iKeyPressTime.UniversalTime(); |
|
503 |
|
504 // Cancel the long press key event timer, if it is active |
|
505 if ( iLongPressKeyEventTimer->IsActive() ) |
|
506 { |
|
507 iLongPressKeyEventTimer->CancelTimer(); |
|
508 } |
|
509 |
|
510 // Don't initiate long tap timer if all these are true |
|
511 // a) key event is not from virtual dialer |
|
512 // b) device is in qwerty mode |
|
513 // c) phone number editor is alpha mode, i.e. not in numeric mode |
|
514 // This is to prevent phone app's long tap functionality with qwerty |
|
515 // long presses, and to have the normal editor long press behaviour |
|
516 // instead. |
|
517 TBool preventLongTap = |
|
518 !IsKeySimulatedByTouchDialer( aKeyEvent ) && |
|
519 iQwertyHandler->IsQwertyInput() && |
|
520 iViewCommandHandle->HandleCommandL( EPhoneViewIsNumberEntryNumericMode ) != EPhoneViewResponseSuccess; |
|
521 |
|
522 // Prevent long tap functionality for key events coming from virtual touch keyboard. |
|
523 // Virtual touch keyboard has own editing functionality for long presses, and telephony |
|
524 // should not add conflicting behaviour on top of that. |
|
525 preventLongTap = preventLongTap || iVirtualKeyBoardOpen; |
|
526 |
|
527 if ( !preventLongTap ) |
|
528 { |
|
529 // Start long press timer |
|
530 iLongPressKeyEventTimer->After( |
|
531 KPhoneLongPressKeyEventDuration, |
|
532 TCallBack( DoHandleLongPressKeyEventCallbackL, |
|
533 this ) ); |
|
534 } |
|
535 |
|
536 // Check if dialog or menu is open |
|
537 // EikAppUi()->IsDisplayingMenuOrDialog doesn´t always return correct |
|
538 // value for menubar, so ask visibility also from CEikMenuBar |
|
539 iDisplayingMenuOrDialogOnEventKeyDown = ( iViewCommandHandle->HandleCommandL( |
|
540 EPhoneViewIsDisplayingMenuOrDialog ) == |
|
541 EPhoneViewResponseSuccess ) || ( iMenu && iMenu->IsDisplayed() ); |
|
542 |
|
543 |
|
544 return ( EKeyWasNotConsumed ); |
|
545 } |
|
546 |
|
547 // ----------------------------------------------------------- |
|
548 // CPhoneKeyEventForwarder::HandleEventKeyBeforeControlStackL |
|
549 // Both short key press event (iRepeats == 0) and |
|
550 // long key press event (iRepeats == 1) are handled here |
|
551 // ----------------------------------------------------------- |
|
552 // |
|
553 TKeyResponse CPhoneKeyEventForwarder::HandleEventKeyBeforeControlStackL( |
|
554 const TKeyEvent& aKeyEvent ) |
|
555 { |
|
556 __LOGMETHODSTARTEND( EPhoneControl, |
|
557 "CPhoneKeyEventForwarder::HandleEventKeyBeforeControlStackL"); |
|
558 |
|
559 TKeyResponse response( EKeyWasNotConsumed ); |
|
560 TKeyEvent keyEvent( aKeyEvent ); |
|
561 |
|
562 // Special handling for virtual dialer keys events |
|
563 const TBool simulatedByDialer = IsKeySimulatedByTouchDialer( keyEvent ); |
|
564 if ( simulatedByDialer ) |
|
565 { |
|
566 // feed the event directly to number entry |
|
567 HandleTouchDialerKeyEventL( keyEvent ); |
|
568 response = EKeyWasConsumed; |
|
569 } |
|
570 else |
|
571 { |
|
572 // If not simulated by dialer, multitap related fields are reset. |
|
573 // Any key event not originating from dialer interrupts multitap |
|
574 // behaviour. |
|
575 iMultitapIndex = 0; |
|
576 iPreviousScanCode = 0; |
|
577 } |
|
578 |
|
579 // Special handling for QWERTY numeric mode key events |
|
580 if ( response == EKeyWasNotConsumed ) |
|
581 { |
|
582 // FEP does not handle numeric characters 0123456789+*#pw correctly |
|
583 // when in QWERTY mode and number mode. If nothing is done about it, |
|
584 // these problems result in non-hybrid mode qwerty: |
|
585 // +, # and * cannot be typed without pressing Fn-key |
|
586 // Fn + <p/0> produces 0 although p is expected. |
|
587 // Fn + <w/2> produces 2 although w is expected. |
|
588 // To avoid this problems we do the following. |
|
589 |
|
590 // Take numeric keyevent, pass it to number entry and consume it. |
|
591 TBool numericMode = iViewCommandHandle->HandleCommandL( |
|
592 EPhoneViewIsNumberEntryNumericMode ) == EPhoneViewResponseSuccess; |
|
593 |
|
594 TPhoneCmdParamBoolean blockingDialog; |
|
595 iViewCommandHandle->ExecuteCommandL( EPhoneViewGetBlockingDialogStatus, |
|
596 &blockingDialog ); |
|
597 |
|
598 // Handle and consume keyevent only if in qwerty mode, editor is |
|
599 // in numeric mode, menu is not shown and there is no blocking dialog. |
|
600 if ( iQwertyHandler->IsQwertyInput() && numericMode && |
|
601 ( !iMenu || !iMenu->IsDisplayed() ) && !blockingDialog.Boolean() ) |
|
602 { |
|
603 iQwertyHandler->ConvertToNumeric( keyEvent ); |
|
604 |
|
605 // Send key to editor only if a) it is not a repeating keyevent and |
|
606 // it is a valid number entry character (0123456789+*#pw). |
|
607 if ( aKeyEvent.iRepeats == 0 && |
|
608 ( CPhoneKeys::IsDtmfTone( keyEvent, EEventKey ) || |
|
609 CPhoneKeys::IsExtraChar( keyEvent.iCode ) ) ) |
|
610 { |
|
611 iStateMachine->State()->HandleKeyEventL( keyEvent, EEventKey ); |
|
612 response = EKeyWasConsumed; |
|
613 } |
|
614 } |
|
615 } |
|
616 |
|
617 return response; |
|
618 } |
|
619 |
|
620 // ----------------------------------------------------------- |
|
621 // CPhoneKeyEventForwarder::HandleEventKeyUpBeforeControlStackL |
|
622 // ----------------------------------------------------------- |
|
623 // |
|
624 TKeyResponse CPhoneKeyEventForwarder::HandleEventKeyUpBeforeControlStackL( |
|
625 const TKeyEvent& aKeyEvent ) |
|
626 { |
|
627 __LOGMETHODSTARTEND( EPhoneControl, |
|
628 "CPhoneKeyEventForwarder::HandleEventKeyUpBeforeControlStackL"); |
|
629 |
|
630 // Send a long press key event to the current state provided |
|
631 // that the key scan code is the same as the key that was pressed |
|
632 if ( iScanCode == aKeyEvent.iScanCode ) |
|
633 { |
|
634 // Pass the key press duration to the current state |
|
635 TTime now; |
|
636 now.UniversalTime(); |
|
637 TTimeIntervalMicroSeconds keyPressDuration = now.MicroSecondsFrom( |
|
638 iKeyPressTime ); |
|
639 iStateMachine->State()->HandleKeyPressDurationL( |
|
640 TKeyCode( iKeyPressedDown ), |
|
641 keyPressDuration ); |
|
642 |
|
643 // Cancel the long press timer, if it is active. Otherwise |
|
644 // ignore the key event since it was already handled as a long press |
|
645 // key event. |
|
646 if ( iLongPressKeyEventTimer->IsActive() ) |
|
647 { |
|
648 iLongPressKeyEventTimer->CancelTimer(); |
|
649 } |
|
650 } |
|
651 |
|
652 // Store the previous scan code |
|
653 iPreviousScanCode = iScanCode; |
|
654 |
|
655 // Consume dialer simulated key events, pass others on |
|
656 return EKeyWasNotConsumed; |
|
657 } |
|
658 |
|
659 // --------------------------------------------------------- |
|
660 // CPhoneKeyEventForwarder::DoHandleLongPressKeyEventCallback |
|
661 // |
|
662 // This routine is called when the long press key event timer expires |
|
663 // after KPhoneLongPressKeyEventDuration. |
|
664 // --------------------------------------------------------- |
|
665 // |
|
666 TInt CPhoneKeyEventForwarder::DoHandleLongPressKeyEventCallbackL( TAny* aAny ) |
|
667 { |
|
668 __LOGMETHODSTARTEND( EPhoneControl, |
|
669 "CPhoneKeyEventForwarder::DoHandleLongPressKeyEventCallbackL"); |
|
670 |
|
671 __ASSERT_DEBUG( aAny, |
|
672 Panic( EPhoneCtrlUnknownPanic ) ); |
|
673 |
|
674 reinterpret_cast< CPhoneKeyEventForwarder* >( aAny )-> |
|
675 HandleLongPressKeyEventL(); |
|
676 |
|
677 return KErrNone; |
|
678 } |
|
679 |
|
680 // --------------------------------------------------------- |
|
681 // CPhoneKeyEventForwarder::HandleLongPressKeyEventL |
|
682 // Handle long press key event |
|
683 // --------------------------------------------------------- |
|
684 // |
|
685 void CPhoneKeyEventForwarder::HandleLongPressKeyEventL() |
|
686 { |
|
687 __LOGMETHODSTARTEND( EPhoneControl, |
|
688 "CPhoneKeyEventForwarder::HandleLongPressKeyEventL"); |
|
689 |
|
690 // In alphanumeric mode EEventKey-event is not received so we must |
|
691 // compare also with scan code. |
|
692 if ( KPhoneDtmfHashCharacter == iKeyPressedDown ) |
|
693 { |
|
694 // Separate handling for long hash key because there is so much |
|
695 // different functionality under it and it works differently |
|
696 // in different protocols. |
|
697 iStateMachine->State()->HandleLongHashL(); |
|
698 } |
|
699 else if ( KPhoneDtmfStarCharacter == iKeyPressedDown ) |
|
700 { |
|
701 // KPhoneDtmfStarCharacter value used in configuration file for |
|
702 // long key press application launching |
|
703 iStateMachine->State()->HandleKeyMessageL( |
|
704 MPhoneKeyEvents::EPhoneKeyLongPress, |
|
705 TKeyCode( KPhoneDtmfStarCharacter ) ); |
|
706 } |
|
707 else |
|
708 { |
|
709 __PHONELOG1( |
|
710 EBasic, EPhoneControl, |
|
711 "CPhoneKeyEventHandler::HandleLongPressKeyEventL iCode(%d)", |
|
712 iKeyPressedDown ); |
|
713 iStateMachine->State()->HandleKeyMessageL( |
|
714 MPhoneKeyEvents::EPhoneKeyLongPress, |
|
715 TKeyCode( iKeyPressedDown ) ); |
|
716 } |
|
717 |
|
718 // Reset key code |
|
719 iScanCode = EStdKeyNull; |
|
720 iKeyPressedDown = EKeyNull; |
|
721 } |
|
722 |
|
723 // ----------------------------------------------------------- |
|
724 // CPhoneKeyEventForwarder::ConvertKeyCodeL |
|
725 // ----------------------------------------------------------- |
|
726 // |
|
727 void CPhoneKeyEventForwarder::ConvertKeyCodeL( TUint& aCode, |
|
728 const TKeyEvent& aKeyEvent ) |
|
729 { |
|
730 __LOGMETHODSTARTEND( EPhoneControl, |
|
731 "CPhoneKeyEventForwarder::ConvertKeyCodeL"); |
|
732 |
|
733 // Handler for special device key mapping in case iScanCode |
|
734 // to iCode conversion hasn't been handled by CAknAppUi::GetAliasKeyCodeL |
|
735 __PHONELOG1( EBasic, EPhoneControl, |
|
736 "CPhoneKeyEventHandler::ConvertKeyCodeL scan code (%d)", |
|
737 aKeyEvent.iScanCode ); |
|
738 |
|
739 if ( !ConvertHalfQwertySpecialChar( aCode, aKeyEvent ) ) |
|
740 { |
|
741 TBool numMode = iViewCommandHandle->HandleCommandL( |
|
742 EPhoneViewIsNumberEntryNumericMode ) == EPhoneViewResponseSuccess; |
|
743 TBool simulatedByDialer = IsKeySimulatedByTouchDialer( aKeyEvent ); |
|
744 |
|
745 if ( iQwertyHandler->IsQwertyInput() && numMode && !simulatedByDialer ) |
|
746 { |
|
747 TUint numCode = iQwertyHandler->NumericKeyCode( aKeyEvent ); |
|
748 if ( numCode ) |
|
749 { |
|
750 aCode = numCode; |
|
751 } |
|
752 else |
|
753 { |
|
754 aCode = aKeyEvent.iScanCode; |
|
755 } |
|
756 } |
|
757 else |
|
758 { |
|
759 switch ( aKeyEvent.iScanCode ) |
|
760 { |
|
761 case EStdKeyEnter: |
|
762 case EStdKeyNkpEnter: |
|
763 aCode = EKeyEnter; |
|
764 break; |
|
765 case EStdKeyYes: |
|
766 aCode = EKeyYes; |
|
767 break; |
|
768 case EStdKeyEnd: // End key is emulated if the device has combined power and end key |
|
769 case EStdKeyNo: |
|
770 aCode = EKeyNo; |
|
771 break; |
|
772 case EStdKeyDeviceF: |
|
773 aCode = EKeyDeviceF; // EStdKeyDeviceF mapping for unlock switch. |
|
774 break; |
|
775 case EStdKeyHash: |
|
776 aCode = KPhoneDtmfHashCharacter; |
|
777 break; |
|
778 case EStdKeyNkpAsterisk: |
|
779 aCode = KPhoneDtmfStarCharacter; |
|
780 break; |
|
781 case EStdKeyApplication0: |
|
782 aCode = EKeyApplication0; |
|
783 break; |
|
784 default: |
|
785 aCode = aKeyEvent.iScanCode; // Use default code |
|
786 break; |
|
787 } |
|
788 } |
|
789 } |
|
790 |
|
791 __PHONELOG1( EBasic, EPhoneControl, |
|
792 "CPhoneKeyEventHandler::ConvertKeyCodeL aCode (%d)", aCode ); |
|
793 } |
|
794 |
|
795 // End of File |
|
796 |