diff -r 000000000000 -r eb1f2e154e89 textinput/peninputarc/src/peninputserverapp/keyrotator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textinput/peninputarc/src/peninputserverapp/keyrotator.cpp Tue Feb 02 01:02:04 2010 +0200 @@ -0,0 +1,467 @@ +/* +* Copyright (c) 2008-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0"" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation for peninput server key rotator +* +*/ + +#include "keyrotator.h" +#include +#include +#include +#include +#include +#include +#include +#include + +// CONSTANTS + +const TUint KAknModifiersMask = 0xFFFF0000; +// Path to wsini.ini +_LIT( KAknWsini, "z:\\system\\data\\wsini.ini" ); +// Keyword for key rotator compensation. +// Syntax: S60_KEYROTATOR +// where is one of the following: -270, -180, -90, -0, 0, 90, 180, 270 +_LIT( KAknKeyRotatorKey, "S60_KEYROTATOR" ); + +// Configure +//const TUint KAknRotateArrowKeys = 1; +const TUint KAknRotateInKeyboardDriver = 0; + +//class CKeyRotator + +CKeyRotator::~CKeyRotator() + { + iHwRotations.Close(); + iProperty.Close(); + } + +CKeyRotator* CKeyRotator::NewL() + { + CKeyRotator* self = new(ELeave) CKeyRotator; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } +// ----------------------------------------------------------------------------- +// CKeyRotator::ConstructL +// 2nd phase constructor +// ----------------------------------------------------------------------------- +// +void CKeyRotator::ConstructL() + { + if ( KAknRotateInKeyboardDriver ) + { + LoadHwStateRotationsL(); + } + + User::LeaveIfError( iProperty.Attach( KPSUidUikon, KUikLayoutState ) ); + + TRAPD( err, iKeyRotatorCompensation = GetKeyRotatorCompensationL() ); + if ( err != KErrNone ) + { + iKeyRotatorCompensation = 0; + } + } + +//Does the reverse key rotator to CKeyRotator::DoCheckRotation +//Most of the code are copied code from CKeyRotator::DoCheckRotation in AknKeyRotator +// +void CKeyRotator::DoReverseRotate(TRawEvent &aNewRawEvent) + { + + // 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 ( aNewRawEvent.ScanCode() < EStdKeyLeftArrow || + aNewRawEvent.ScanCode() > EStdKeyDownArrow ) + { + return; + } + +/* aNewRawEvent.Set(aNewRawEvent.Type(), + aNewRawEvent.ScanCode() + EModifierKeyboardExtend); + + + 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. + CWsScreenDevice* device = CCoeEnv::Static()->ScreenDevice(); + TPixelsAndRotation sizeAndRotation; + device->GetScreenModeSizeAndRotation(device->CurrentScreenMode(),sizeAndRotation); + + CFbsBitGc::TGraphicsOrientation swRotation = sizeAndRotation.iRotation; + /*aAnimGeneralFunctions.ScreenDevice()->Orientation();*/ + + + // Get HW screen rotation + // hardware rotate not implemented yet. + /* + 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 = EStdKeyUpArrow; // fixed + break; + + case CFbsBitGc::EGraphicsOrientationRotated180: + newCode = EStdKeyRightArrow; //fixed + break; + + case CFbsBitGc::EGraphicsOrientationRotated270: + newCode = EStdKeyDownArrow; + break; + default: + break; + } + break; + case EStdKeyDownArrow: + switch ( finalRotation ) + { + case CFbsBitGc::EGraphicsOrientationRotated90: + newCode = EStdKeyLeftArrow; //fixed + break; + + case CFbsBitGc::EGraphicsOrientationRotated180: + newCode = EStdKeyUpArrow; + break; + + case CFbsBitGc::EGraphicsOrientationRotated270: + newCode = EStdKeyRightArrow; + break; + default: + break; + } + break; + case EStdKeyRightArrow: + switch ( finalRotation ) + { + case CFbsBitGc::EGraphicsOrientationRotated90: + newCode = EStdKeyDownArrow; //fixed + break; + + case CFbsBitGc::EGraphicsOrientationRotated180: + newCode = EStdKeyLeftArrow; + break; + + case CFbsBitGc::EGraphicsOrientationRotated270: + newCode = EStdKeyUpArrow; + break; + default: + break; + } + break; + case EStdKeyUpArrow: + switch ( finalRotation ) + { + case CFbsBitGc::EGraphicsOrientationRotated90: + newCode = EStdKeyRightArrow; //fixed + break; + + case CFbsBitGc::EGraphicsOrientationRotated180: + newCode = EStdKeyDownArrow; + break; + + case CFbsBitGc::EGraphicsOrientationRotated270: + newCode = EStdKeyLeftArrow; + 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); + } + + } + + + +// ----------------------------------------------------------------------------- +// CKeyRotator::GeCKeyRotatorCompensationL +// Parses wsini.ini to read key rotator compensation value. +// ----------------------------------------------------------------------------- +// +TInt CKeyRotator::GetKeyRotatorCompensationL() + { + TInt result = 0; + HBufC* wsiniText = GetWsiniLC(); + + // Now look for keyword + const TInt pos = wsiniText->Find( KAknKeyRotatorKey ); + if ( pos != KErrNotFound ) + { + // Keyword was found. Check that it is the beginning of line. + // Three cases: + // 1. Keyword could be at the beginning of the file. + // 2. Keyword could be at the beginning of the file + // after byte ordering marker. + // 3. Previous character can be end of line marker. + const TInt previousPos = pos - 1; + if ( previousPos < 0 || + ( !previousPos && + IsByteOrderingMarker( (*wsiniText)[ previousPos ] ) ) || + IsEndOfLine( (*wsiniText)[ previousPos ] ) ) + { + TLex text( wsiniText->Mid( pos + KAknKeyRotatorKey().Length() ) ); + + // First, there must be at least a space after keyword. + TBool fail = !( SkipSpaces( text ) & EAknWasSpace ); + + // Then follows a sequence of digits, optionally preceded by '-'. + if ( !fail ) + { + // Check optional - + TBool negate = EFalse; + if ( !text.Eos() && text.Peek() == '-' ) + { + negate = ETrue; + text.Inc(); + } + + // Get digit sequence and convert to integer value. + TPtrC token = GetDigits( text ); + fail = !token.Length() || + ( TLex( token ).Val( result ) != KErrNone ); + + // Handle negation + if ( !fail && negate ) + { + result = -result; + } + } + + // That sequence of digits is followed by sequence of spaces until + // end of line or end of file. + fail = fail || ( SkipSpaces( text ) & EAknWasCharacter ); + + // Finally, that sequence of digits must represent + // one valid decimal value of the following: + // -270, -180, -90, 0, 90, 180, 270. + fail = fail || !CheckCompensationValue( result ); + + // If any of above checks failed, use default value 0. + if ( fail ) + { + result = 0; + } + } + } + + CleanupStack::PopAndDestroy( wsiniText ); + return result; + } + +// ----------------------------------------------------------------------------- +// CKeyRotator::IsEndOfLine +// Checks if specified character is end of line marker. +// ----------------------------------------------------------------------------- +// +inline TBool CKeyRotator::IsEndOfLine( TText aChar ) + { + return aChar == '\r' || aChar == '\n'; + } + +// ----------------------------------------------------------------------------- +// CKeyRotator::IsByteOrderingMarker +// Checks if specified character is byte ordering marker. +// ----------------------------------------------------------------------------- +// +inline TBool CKeyRotator::IsByteOrderingMarker( TText aChar ) + { + return aChar == 0xFEFF || aChar == 0xFFFE; + } + +// ----------------------------------------------------------------------------- +// CKeyRotator::GetWsiniLC +// Reads the whole wsini.ini to memory and returns in heap descriptor. +// ----------------------------------------------------------------------------- +// +HBufC* CKeyRotator::GetWsiniLC() + { + // Read the whole wsini.ini to memory + RFs fs; + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL( fs ); + + TEntry wsiniEntry; + User::LeaveIfError( fs.Entry( KAknWsini, wsiniEntry ) ); + + HBufC* wsiniText = HBufC::NewLC( ( wsiniEntry.iSize + 1 )/2 ); + TPtr wsiniPtr = wsiniText->Des(); + TPtr8 wsiniPtr8( (TText8*)wsiniPtr.Ptr(), 0, wsiniPtr.MaxLength()*2 ); + + RFile wsiniFile; + User::LeaveIfError( wsiniFile.Open( fs, KAknWsini, EFileRead | EFileShareReadersOnly ) ); + CleanupClosePushL( wsiniFile ); + + User::LeaveIfError( wsiniFile.Read( wsiniPtr8, wsiniEntry.iSize ) ); + wsiniPtr.SetLength( wsiniPtr8.Length() / 2 ); + + CleanupStack::PopAndDestroy( &wsiniFile ); + CleanupStack::Pop( wsiniText ); + CleanupStack::PopAndDestroy( &fs ); + CleanupStack::PushL( wsiniText ); + return wsiniText; + } + +// ----------------------------------------------------------------------------- +// CKeyRotator::SkipSpaces +// Skips over spaces. +// ----------------------------------------------------------------------------- +// +TInt CKeyRotator::SkipSpaces( TLex& aLex ) + { + TInt flags = 0; + // Skip spaces, but stop at end of line. + while ( !aLex.Eos() && !IsEndOfLine( aLex.Peek() ) ) + { + if ( aLex.Peek().IsSpace() ) + { + // There was a space, so ok for now. + flags |= EAknWasSpace; + aLex.Inc(); + } + else + { + flags |= EAknWasCharacter; + break; + } + } + return flags; + } + +// ----------------------------------------------------------------------------- +// CKeyRotator::SkipSpaces +// Goes over digits and returns that sequence. +// ----------------------------------------------------------------------------- +// +TPtrC CKeyRotator::GetDigits( TLex& aLex ) + { + // Mark current place and go over digits. + aLex.Mark(); + while ( !aLex.Eos() && !IsEndOfLine( aLex.Peek() ) ) + { + if ( aLex.Peek().IsDigit() ) + { + aLex.Inc(); + } + else + { + break; + } + } + return aLex.MarkedToken(); + } + +// ----------------------------------------------------------------------------- +// CKeyRotator::CheckCompensationValue +// Checks that value contains valid key rotator compensation value. +// ----------------------------------------------------------------------------- +// +inline TBool CKeyRotator::CheckCompensationValue( TInt aValue ) + { + // Check absolute value + if ( aValue < 0 ) + { + aValue = -aValue; + } + + return aValue == 0 || + aValue == 90 || + aValue == 180 || + aValue == 270; + }