phoneapp/phoneuicontrol/src/cphonekeyeventforwarder.cpp
branchRCL_3
changeset 62 5266b1f337bd
child 69 8baf28733c3d
equal deleted inserted replaced
61:41a7f70b3818 62:5266b1f337bd
       
     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