// -----------------------------------------------------------------------------
// CAknKeyRotatorImpl::CheckRotation
// Check if this is our own generated event.
// -----------------------------------------------------------------------------
//
TBool CAknKeyRotatorImpl::CheckRotation( 
    const TRawEvent &aRawEvent,
    MAnimGeneralFunctions& aAnimGeneralFunctions )
    {
    if ( KMaxTInt == iKeyRotatorCompensation )
        {
        // Key rotator is disabled - wsini.ini contains "S60_KEYROTATOR DISABLED".
        return EFalse;
        }

    // Check first that we are not processing just generated event again.
    if ( iRotatedRawEvent )
        {
        // This is the generated avent from the last round. Do not modify again.
        iRotatedRawEvent = EFalse;
        }
    else if ( aRawEvent.Type() == TRawEvent::EKeyDown || 
              aRawEvent.Type() == TRawEvent::EKeyUp || 
              aRawEvent.Type() == TRawEvent::EKeyRepeat )
        {
        // We get new event. Let's see if we need to modify that.
        TRawEvent newRawEvent( aRawEvent );
        DoCheckRotation( newRawEvent, aAnimGeneralFunctions );
        if ( aRawEvent.ScanCode() != newRawEvent.ScanCode() )   
            {
            // Generate new event,
            iRotatedRawEvent = ETrue;
            aAnimGeneralFunctions.PostRawEvent( newRawEvent ); // Calls this function again!
            return ETrue;
            }
        }
    
    return EFalse;
    }
// -----------------------------------------------------------------------------
// CAknKeyRotatorImpl::DoCheckRotation
// Checks the scan codes and the orientations. Decides if we need to generate
// a new raw event.
// -----------------------------------------------------------------------------
//
void CAknKeyRotatorImpl::DoCheckRotation(
    TRawEvent& aNewRawEvent,
    MAnimGeneralFunctions& aAnimGeneralFunctions )
    {   
    // Current implementation is only for arrow keys
    if ( !KAknRotateArrowKeys )
        {
        return;
        }
    
    // Do not rotate external keyboard events.
    if ( aNewRawEvent.ScanCode() & EModifierKeyboardExtend )
        {
        return;
        }    
        
    // Also check only the arrow keys
    if ( !IsArrowScanCode( aNewRawEvent.ScanCode ()) )
        {
        return;
        }
    
    // If 'newCode' is changed something else than -1, 
    // a new event will be generated
    TInt newCode = KErrNotFound;
    
    // Check the rotation on down event. Use the same rotation for up event.
    
    // finalRotation variable at the end of this function is used to determine
    // the new scan code.
    CFbsBitGc::TGraphicsOrientation finalRotation = 
        CFbsBitGc::EGraphicsOrientationNormal;
    
    if ( aNewRawEvent.Type() == TRawEvent::EKeyUp || 
         aNewRawEvent.Type() == TRawEvent::EKeyRepeat )
        {
        // Use the same orintation for up event.
        finalRotation = iUsedRotationForDownEvent;
        }
    else // For down event, find out the rotation.
        {
        // Get SW screen rotation compared to the keyboard i.e. app orientation.
        CFbsBitGc::TGraphicsOrientation swRotation = 
            aAnimGeneralFunctions.ScreenDevice()->Orientation();
    
        // Get HW screen rotation
        CFbsBitGc::TGraphicsOrientation hwRotation = 
            CFbsBitGc::EGraphicsOrientationNormal;
        TInt hwState;
        if ( KAknRotateInKeyboardDriver && 
             ( iProperty.Get(hwState) == KErrNone ) )
            {
            if ( hwState < iHwRotations.Count() )
                {
                hwRotation = iHwRotations[hwState];
                }
            }
    
        // Calculate the difference
        TInt finalRotationInt = swRotation*90;
    
        if ( KAknRotateInKeyboardDriver )
            {
            // If the rotation is also done in the driver level, 
            // the rotation needs to be compensated so we do not 
            // rotate twice.
            finalRotationInt -= hwRotation*90;
            }
    
        finalRotationInt += iKeyRotatorCompensation;

        // Keep the value between 0 and 270.
        while ( finalRotationInt < 0 )
            {
            finalRotationInt += 360;
            }
        while ( finalRotationInt > 270 )
            {
            finalRotationInt -= 360;
            }
            
        finalRotation = 
            (CFbsBitGc::TGraphicsOrientation)( finalRotationInt / 90 );

        iUsedRotationForDownEvent = finalRotation;
        }
    
    // Find the new scan code from the rotation.
    switch( aNewRawEvent.ScanCode() )
        {
        case EStdKeyLeftArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = EStdKeyDownArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = EStdKeyRightArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = EStdKeyUpArrow;
                    break;
                default:
                    break;
                }
            break;
        case EStdKeyDownArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = EStdKeyRightArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = EStdKeyUpArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = EStdKeyLeftArrow;
                    break;
                default:
                    break;
                }
            break;
        case EStdKeyRightArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = EStdKeyUpArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = EStdKeyLeftArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = EStdKeyDownArrow;
                    break;
                default:
                    break;
                }
            break;
        case EStdKeyUpArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = EStdKeyLeftArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = EStdKeyDownArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = EStdKeyRightArrow;
                    break;
                default:
                    break;
                }
            break;

        // Diagonal events
        case KAknStdLeftUpArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = KAknStdLeftDownArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = KAknStdRightDownArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = KAknStdRightUpArrow;
                    break;
                default:
                    break;
                }
            break;

        case KAknStdRightUpArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = KAknStdLeftUpArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = KAknStdLeftDownArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = KAknStdRightDownArrow;
                    break;
                default:
                    break;
                }
            break;

        case KAknStdLeftDownArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = KAknStdRightDownArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = KAknStdRightUpArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = KAknStdLeftUpArrow;
                    break;
                default:
                    break;
                }
            break;

        case KAknStdRightDownArrow:
            switch ( finalRotation )
                {
                case CFbsBitGc::EGraphicsOrientationRotated90:
                    newCode = KAknStdRightUpArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated180:
                    newCode = KAknStdLeftUpArrow;
                    break;
                case CFbsBitGc::EGraphicsOrientationRotated270:
                    newCode = KAknStdLeftDownArrow;
                    break;
                default:
                    break;
                }
            break;

        default:
            break;    
        }
        
    // If the 'newCode' was updated, add that value as the new scancode with existing modifiers.
    if ( newCode != KErrNotFound )
        {
        aNewRawEvent.Set(
            aNewRawEvent.Type(),
            (aNewRawEvent.ScanCode()&KAknModifiersMask) + newCode);
        }
    }