phoneapp/phoneuicontrol/src/cphonekeyeventforwarder.cpp
branchRCL_3
changeset 25 91c2fb4b78df
parent 19 544e34b3255a
child 31 ba54057fe027
--- a/phoneapp/phoneuicontrol/src/cphonekeyeventforwarder.cpp	Wed Apr 14 15:56:42 2010 +0300
+++ b/phoneapp/phoneuicontrol/src/cphonekeyeventforwarder.cpp	Tue Apr 27 16:37:10 2010 +0300
@@ -79,10 +79,9 @@
     {
     __LOGMETHODSTARTEND( EPhoneControl, "CPhoneKeyEventForwarder::~CPhoneKeyEventForwarder");
 
-    CEikonEnv* env = static_cast<CEikonEnv*>(ControlEnv());
-    if( env )
+    if ( iEikonEnv )
         {
-        env->EikAppUi()->RemoveFromStack( this );
+        iEikonEnv->EikAppUi()->RemoveFromStack( this );
         }
     delete iLongPressKeyEventTimer;
     
@@ -142,25 +141,20 @@
         "CPhoneKeyEventForwarder::OfferKeyEventL");
 
     TKeyResponse ret( EKeyWasNotConsumed );
-    TKeyEvent keyEvent = aKeyEvent;
 
     ret = OfferKeyEventBeforeControlStackL( aKeyEvent, aType );
 
-    // Convert event. Use already converted iKeyPressedDown.
-    // Do not convert other than DTMF tones
-    if( CPhoneKeys::IsDtmfTone( aKeyEvent, aType ) )
+    if ( !aKeyEvent.iRepeats )
         {
+        // Convert event. Use already converted iKeyPressedDown.
+        TKeyEvent keyEvent = aKeyEvent;
         keyEvent.iCode = iKeyPressedDown;
-        }
-
-    if ( !keyEvent.iRepeats )
-        {
+        
         // Start and stop dtmf
         iStateMachine->State()->HandleDtmfKeyToneL( keyEvent, aType );
-        if( aType != EEventKeyUp &&
-            ( CPhoneKeys::IsNumericKey( keyEvent, aType ) ||
-              IsAlphaNumericKey( keyEvent ) )
-          )
+        // Open number entry view if any allowed character key
+        // is pressed on homescreen or in-call ui
+        if ( aType != EEventKeyUp && IsKeyAllowed( keyEvent ) )
             {
             // Do not open number entry with up key
             iStateMachine->State()->HandleCreateNumberEntryL( keyEvent, aType );
@@ -202,10 +196,9 @@
     MakeVisible( EFalse );
     SetRect( aRect );
 
-    CEikonEnv* env = static_cast<CEikonEnv*>(ControlEnv());
-    if( env )
+    if ( iEikonEnv )
         {
-        env->EikAppUi()->AddToStackL(
+        iEikonEnv->EikAppUi()->AddToStackL(
             this,
             ECoeStackPriorityEnvironmentFilter,
             ECoeStackFlagRefusesFocus );
@@ -215,7 +208,7 @@
     iLongPressKeyEventTimer = CPhoneTimer::NewL();
     
     // Create qwerty mode handler
-    iQwertyHandler = CPhoneQwertyHandler::NewL(); 
+    iQwertyHandler = CPhoneQwertyHandler::NewL();
     
     TPhoneCmdParamPointer ptrParam;
     iViewCommandHandle->ExecuteCommand( EPhoneViewGetQwertyModeObserver, &ptrParam );
@@ -223,22 +216,32 @@
             static_cast<CDialer*>( ptrParam.Pointer() );
             
     iQwertyHandler->AddQwertyModeObserverL( *qwertyObserver );
-
     }
 
 // -----------------------------------------------------------------------------
 // CPhoneKeyEventForwarder::IsAlphaNumericKey
 // -----------------------------------------------------------------------------
 //
-TBool CPhoneKeyEventForwarder::IsAlphaNumericKey( const TKeyEvent& aKeyEvent )
+TBool CPhoneKeyEventForwarder::IsKeyAllowed( const TKeyEvent& aKeyEvent )
     {
     __LOGMETHODSTARTEND( EPhoneControl,
         "CPhoneKeyEventForwarder::IsAlphaNumericKey");
 
-    TBool alphaNumeric =
-       iStateMachine->State()->IsAlphanumericSupportedAndCharInput( aKeyEvent );
+    TKeyEvent keyEvent( aKeyEvent );
+    
+    // Check keyboard mode
+    TBool isModeNumeric = iViewCommandHandle->HandleCommandL(
+          EPhoneViewIsNumberEntryNumericMode ) == EPhoneViewResponseSuccess;
 
-    return alphaNumeric;
+    // Check if key is a numeric key
+    TBool isNumeric = CPhoneKeys::IsNumericKey( keyEvent, EEventKey );
+    
+    // Check if key is alpha numeric key and alphabet input is allowed
+    TBool isAllowedAlphaNumeric =
+       iStateMachine->State()->IsAlphanumericSupportedAndCharInput( keyEvent );
+
+    return ( ( isModeNumeric && isNumeric ) || 
+             ( !isModeNumeric && isAllowedAlphaNumeric ) );
     }
 
 // -----------------------------------------------------------------------------
@@ -256,7 +259,7 @@
           KCRUidAvkon,
           KAknKeyBoardLayout ) );
 
-    if( keyboard == EPtiKeyboardHalfQwerty )
+    if ( keyboard == EPtiKeyboardHalfQwerty )
         {
         switch ( aKeyEvent.iScanCode )
            {
@@ -285,11 +288,23 @@
     }
 
 // -----------------------------------------------------------------------------
-// CPhoneKeyEventForwarder::HandleTouchDialerKeyEventL
+// CPhoneKeyEventForwarder::IsKeySimulatedByTouchDialer
 // 
 // -----------------------------------------------------------------------------
 //
-void CPhoneKeyEventForwarder::HandleTouchDialerKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
+TBool CPhoneKeyEventForwarder::IsKeySimulatedByTouchDialer( 
+        const TKeyEvent& aKeyEvent ) const
+    {
+    return ( ( aKeyEvent.iModifiers & EModifierNumLock ) &&
+             ( aKeyEvent.iModifiers & EModifierKeypad ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CPhoneKeyEventForwarder::HandleTouchDialerKeyEventL
+// Handle EEventKey type of event from touch dialer
+// -----------------------------------------------------------------------------
+//
+void CPhoneKeyEventForwarder::HandleTouchDialerKeyEventL( const TKeyEvent& aKeyEvent )
     {
     TBool multitap = aKeyEvent.iScanCode == EStdKeyNkpAsterisk && 
             iPreviousScanCode == EStdKeyNkpAsterisk &&
@@ -297,19 +312,16 @@
     
     if ( multitap )
         {
-        if ( aType == EEventKeyDown )
-            {
-            // Update multitap index
-            iMultitapIndex = ( iMultitapIndex + 1 ) % KAsteriskMultitapCharacters().Length();
-            
-            // Delete the previously entered character by simulating a backspace character.
-            TKeyEvent backSpaceEvent;
-            backSpaceEvent.iModifiers = 0;
-            backSpaceEvent.iRepeats = 0;
-            backSpaceEvent.iCode = EKeyBackspace;
-            backSpaceEvent.iScanCode = EStdKeyBackspace;
-            iStateMachine->State()->HandleKeyEventL( backSpaceEvent, EEventKey );
-            }
+        // Update multitap index
+        iMultitapIndex = ( iMultitapIndex + 1 ) % KAsteriskMultitapCharacters().Length();
+        
+        // Delete the previously entered character by simulating a backspace character.
+        TKeyEvent backSpaceEvent;
+        backSpaceEvent.iModifiers = 0;
+        backSpaceEvent.iRepeats = 0;
+        backSpaceEvent.iCode = EKeyBackspace;
+        backSpaceEvent.iScanCode = EStdKeyBackspace;
+        iStateMachine->State()->HandleKeyEventL( backSpaceEvent, EEventKey );
         
         TKeyEvent keyEvent( aKeyEvent );
         
@@ -317,18 +329,12 @@
         keyEvent.iCode = ( TInt ) KAsteriskMultitapCharacters()[ iMultitapIndex ];
         
         // Send character to number entry.
-        iStateMachine->State()->HandleKeyEventL( keyEvent, aType );
+        iStateMachine->State()->HandleKeyEventL( keyEvent, EEventKey );
         }
-    
     else 
         {
         iMultitapIndex = 0;
-        iStateMachine->State()->HandleKeyEventL( aKeyEvent, aType );
-        }
-    
-    if ( aType == EEventKeyUp )
-        {
-        iPreviousScanCode = aKeyEvent.iScanCode;
+        iStateMachine->State()->HandleKeyEventL( aKeyEvent, EEventKey );
         }
     }
 
@@ -367,26 +373,6 @@
         default:
             break;
         }
-    
-    // Check if keyEvent is simulated by Dialer.
-    const TBool simulatedByDialer = 
-        ( ( aKeyEvent.iModifiers & ( EModifierNumLock | EModifierKeypad ) ) 
-                == ( EModifierNumLock | EModifierKeypad ) );
-    
-    if( simulatedByDialer )
-        {
-        HandleTouchDialerKeyEventL( aKeyEvent, aType );
-        response = EKeyWasConsumed;
-        }
-    
-    else 
-        {
-        // If not simulated by dialer, multitap related fields are reset.
-        // Any key event not originating from dialer interrupts multitap
-        // behaviour.
-        iMultitapIndex = 0;
-        iPreviousScanCode = 0;
-        }
 
     return response;
     }
@@ -407,8 +393,7 @@
     // Send key to editor
     iStateMachine->State()->HandleKeyEventL( aKeyEvent, aType );
     
-    if( EEventKeyUp == aType 
-            && EKeyNull != iKeyPressedDown )
+    if ( EEventKeyUp == aType && EKeyNull != iKeyPressedDown )
         {
         // Handle short key press
         iStateMachine->State()->HandleKeyMessageL( 
@@ -472,16 +457,60 @@
         "CPhoneKeyEventForwarder::HandleEventKeyBeforeControlStackL");
 
     TKeyResponse response( EKeyWasNotConsumed );
+    TKeyEvent keyEvent( aKeyEvent );
 
-    // Convert event.
-    TKeyEvent keyEvent = aKeyEvent;
-    keyEvent.iCode = iKeyPressedDown;
+    // Special handling for virtual dialer keys events
+    const TBool simulatedByDialer = IsKeySimulatedByTouchDialer( keyEvent );
+    if ( simulatedByDialer )
+        {
+        // feed the event directly to number entry
+        HandleTouchDialerKeyEventL( keyEvent );
+        response = EKeyWasConsumed;
+        }
+    else 
+        {
+        // If not simulated by dialer, multitap related fields are reset.
+        // Any key event not originating from dialer interrupts multitap
+        // behaviour.
+        iMultitapIndex = 0;
+        iPreviousScanCode = 0;
+        }
 
-    if(  aKeyEvent.iRepeats > 0 &&
-        CPhoneKeys::IsDtmfTone( keyEvent, EEventKey ) )
+    // Special handling for QWERTY numeric mode key events
+    if ( response == EKeyWasNotConsumed )
         {
-        // Do not repeat dtmf characters
-        response = EKeyWasConsumed;
+        // FEP treats numeric QWERTY mode of Phone editor as a special case where most
+        // key events flow through directly to the Phone app (but some don't).
+        // To ensure consistent handling of numeric mode keys and QWERTY modifiers, 
+        // handle those keys manually before FEP has a chance to mess things up.
+        TBool numericMode = iViewCommandHandle->HandleCommandL(
+              EPhoneViewIsNumberEntryNumericMode ) == EPhoneViewResponseSuccess;
+
+        if ( iQwertyHandler->IsQwertyInput() && numericMode )
+            {
+            iQwertyHandler->ConvertToNumeric( keyEvent );
+            // Send key to editor unless this is a repeat event for dtmf character
+            if ( aKeyEvent.iRepeats == 0 ||
+                 !CPhoneKeys::IsDtmfTone( keyEvent, EEventKey ) )
+                {
+                iStateMachine->State()->HandleKeyEventL( keyEvent, EEventKey );
+                }
+            response = EKeyWasConsumed;
+            }
+        }
+    
+    // Prevent repeats of DTMF keys anyway
+    if ( response == EKeyWasNotConsumed )
+        {
+        // Convert event.
+        keyEvent.iCode = iKeyPressedDown;
+        if ( aKeyEvent.iRepeats > 0 &&
+             aKeyEvent.iCode != EKeyF18 &&   // EKeyF18 is used for AknCCPU support
+             CPhoneKeys::IsDtmfTone( keyEvent, EEventKey ) )
+            {
+            // Do not repeat dtmf characters
+            response = EKeyWasConsumed;
+            }
         }
 
     return response;
@@ -519,6 +548,9 @@
             }
         }
 
+    // Store the previous scan code
+    iPreviousScanCode = iScanCode;
+
     return EKeyWasNotConsumed;
     }
 
@@ -602,35 +634,53 @@
         "CPhoneKeyEventHandler::ConvertKeyCode scan code (%d)",
         aKeyEvent.iScanCode );
 
-    if( !ConvertHalfQwertySpecialChar( aCode, aKeyEvent ) )
+    if ( !ConvertHalfQwertySpecialChar( aCode, aKeyEvent ) )
         {
-        switch ( aKeyEvent.iScanCode )
+        TBool numMode = iViewCommandHandle->HandleCommandL(
+              EPhoneViewIsNumberEntryNumericMode ) == EPhoneViewResponseSuccess;
+        TBool simulatedByDialer = IsKeySimulatedByTouchDialer( aKeyEvent );
+    
+        if ( iQwertyHandler->IsQwertyInput() && numMode && !simulatedByDialer )
+            {
+            TUint numCode = iQwertyHandler->NumericKeyCode( aKeyEvent );
+            if ( numCode )
+                {
+                aCode = numCode;
+                }
+            else
+                {
+                aCode = aKeyEvent.iScanCode;
+                }
+            }
+        else 
             {
-            case EStdKeyEnter:
-                aCode = EKeyEnter;
-                break;
-            case EStdKeyYes:
-                aCode = EKeyYes;
-                break;
-            case EStdKeyNo:
-                aCode = EKeyNo;
-                break;
-            case EStdKeyDeviceF:
-                aCode = EKeyDeviceF;  // EStdKeyDeviceF mapping for unlock switch.
-                break;
-            case EStdKeyHash:
-                aCode = KPhoneDtmfHashCharacter;
-                break;
-            case EStdKeyNkpAsterisk:
-                aCode = KPhoneDtmfStarCharacter;
-                break;              
-            case EStdKeyApplication0:
-                aCode = EKeyApplication0;
-                break;
-
-            default:
-                aCode = aKeyEvent.iScanCode; // Use default code
-                break;
+            switch ( aKeyEvent.iScanCode )
+                {
+                case EStdKeyEnter:
+                    aCode = EKeyEnter;
+                    break;
+                case EStdKeyYes:
+                    aCode = EKeyYes;
+                    break;
+                case EStdKeyNo:
+                    aCode = EKeyNo;
+                    break;
+                case EStdKeyDeviceF:
+                    aCode = EKeyDeviceF;  // EStdKeyDeviceF mapping for unlock switch.
+                    break;
+                case EStdKeyHash:
+                    aCode = KPhoneDtmfHashCharacter;
+                    break;
+                case EStdKeyNkpAsterisk:
+                    aCode = KPhoneDtmfStarCharacter;
+                    break;
+                case EStdKeyApplication0:
+                    aCode = EKeyApplication0;
+                    break;
+                default:
+                    aCode = aKeyEvent.iScanCode; // Use default code
+                    break;
+                }
             }
         }