textinput/peninputarc/src/peninputserverapp/keyrotator.cpp
changeset 0 eb1f2e154e89
child 3 f5a1e66df979
equal deleted inserted replaced
-1:000000000000 0:eb1f2e154e89
       
     1 /*
       
     2 * Copyright (c) 2008-2008 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:  Implementation for peninput server key rotator
       
    15 *
       
    16 */
       
    17 
       
    18 #include "keyrotator.h"
       
    19 #include <UikonInternalPSKeys.h>
       
    20 #include <PSVariables.h>
       
    21 #include <aknpriv.rsg>
       
    22 #include <barsread.h>
       
    23 #include <barsc.h>
       
    24 #include <bautils.h>
       
    25 #include <w32adll.h>
       
    26 #include <coemain.h>
       
    27 
       
    28 // CONSTANTS
       
    29 
       
    30 const TUint KAknModifiersMask = 0xFFFF0000;
       
    31 // Path to wsini.ini
       
    32 _LIT( KAknWsini, "z:\\system\\data\\wsini.ini" );
       
    33 // Keyword for key rotator compensation.
       
    34 // Syntax: S60_KEYROTATOR <value>
       
    35 // where <value> is one of the following: -270, -180, -90, -0, 0, 90, 180, 270
       
    36 _LIT( KAknKeyRotatorKey, "S60_KEYROTATOR" );
       
    37 
       
    38 // Configure
       
    39 //const TUint KAknRotateArrowKeys = 1;
       
    40 const TUint KAknRotateInKeyboardDriver = 0;
       
    41 
       
    42 //class CKeyRotator
       
    43     
       
    44 CKeyRotator::~CKeyRotator()    
       
    45     {
       
    46     iHwRotations.Close();
       
    47     iProperty.Close();
       
    48     }
       
    49 
       
    50 CKeyRotator* CKeyRotator::NewL()
       
    51     {
       
    52     CKeyRotator* self = new(ELeave) CKeyRotator;
       
    53     CleanupStack::PushL(self);
       
    54     self->ConstructL();
       
    55     CleanupStack::Pop(self);
       
    56     return self;
       
    57     }
       
    58 // -----------------------------------------------------------------------------
       
    59 // CKeyRotator::ConstructL
       
    60 // 2nd phase constructor
       
    61 // -----------------------------------------------------------------------------
       
    62 //
       
    63 void CKeyRotator::ConstructL()
       
    64     {
       
    65     if ( KAknRotateInKeyboardDriver )
       
    66         {
       
    67         LoadHwStateRotationsL();
       
    68         }
       
    69     
       
    70     User::LeaveIfError( iProperty.Attach( KPSUidUikon, KUikLayoutState ) );
       
    71     
       
    72     TRAPD( err, iKeyRotatorCompensation = GetKeyRotatorCompensationL() );
       
    73     if ( err != KErrNone )
       
    74         {
       
    75         iKeyRotatorCompensation = 0;
       
    76         }
       
    77     }
       
    78     
       
    79 //Does the reverse key rotator to CKeyRotator::DoCheckRotation
       
    80 //Most of the code are copied code from CKeyRotator::DoCheckRotation in AknKeyRotator    
       
    81 //
       
    82 void CKeyRotator::DoReverseRotate(TRawEvent &aNewRawEvent)
       
    83     {
       
    84    
       
    85     // Current implementation is only for arrow keys
       
    86     /*
       
    87     if ( !KAknRotateArrowKeys )
       
    88         {
       
    89         return;
       
    90         }
       
    91     
       
    92     // Do not rotate external keyboard events.
       
    93     if ( aNewRawEvent.ScanCode() & EModifierKeyboardExtend )
       
    94         {
       
    95         return;
       
    96         }    
       
    97     */    
       
    98     // Also check only the arrow keys
       
    99     if ( aNewRawEvent.ScanCode() < EStdKeyLeftArrow ||
       
   100          aNewRawEvent.ScanCode() > EStdKeyDownArrow )
       
   101         {
       
   102         return;
       
   103         }
       
   104     
       
   105 /*    aNewRawEvent.Set(aNewRawEvent.Type(),
       
   106                     aNewRawEvent.ScanCode() + EModifierKeyboardExtend);
       
   107 
       
   108     
       
   109     return;*/
       
   110     // If 'newCode' is changed something else than -1, 
       
   111     // a new event will be generated
       
   112     TInt newCode = KErrNotFound;
       
   113     
       
   114     // Check the rotation on down event. Use the same rotation for up event.
       
   115     
       
   116     // finalRotation variable at the end of this function is used to determine
       
   117     // the new scan code.
       
   118     CFbsBitGc::TGraphicsOrientation finalRotation = 
       
   119         CFbsBitGc::EGraphicsOrientationNormal;
       
   120     
       
   121     if ( aNewRawEvent.Type() == TRawEvent::EKeyUp || 
       
   122          aNewRawEvent.Type() == TRawEvent::EKeyRepeat )
       
   123         {
       
   124         // Use the same orintation for up event.
       
   125         finalRotation = iUsedRotationForDownEvent;
       
   126         }
       
   127     else // For down event, find out the rotation.
       
   128         {
       
   129         // Get SW screen rotation compared to the keyboard i.e. app orientation.
       
   130         CWsScreenDevice* device = CCoeEnv::Static()->ScreenDevice();
       
   131         TPixelsAndRotation sizeAndRotation;
       
   132         device->GetScreenModeSizeAndRotation(device->CurrentScreenMode(),sizeAndRotation);
       
   133         
       
   134         CFbsBitGc::TGraphicsOrientation swRotation = sizeAndRotation.iRotation;
       
   135             /*aAnimGeneralFunctions.ScreenDevice()->Orientation();*/
       
   136         
       
   137     
       
   138         // Get HW screen rotation
       
   139         // hardware rotate not implemented yet.
       
   140         /* 
       
   141         CFbsBitGc::TGraphicsOrientation hwRotation = 
       
   142             CFbsBitGc::EGraphicsOrientationNormal;
       
   143         TInt hwState;
       
   144         if ( KAknRotateInKeyboardDriver && 
       
   145              ( iProperty.Get(hwState) == KErrNone ) )
       
   146             {
       
   147             if ( hwState < iHwRotations.Count() )
       
   148                 {
       
   149                 hwRotation = iHwRotations[hwState];
       
   150                 }
       
   151             }
       
   152         */
       
   153         // Calculate the difference
       
   154 	    TInt finalRotationInt = swRotation*90;
       
   155 	    /*
       
   156 	    if ( KAknRotateInKeyboardDriver )
       
   157 	        {
       
   158 	        // If the rotation is also done in the driver level, 
       
   159 	        // the rotation needs to be compensated so we do not 
       
   160 	        // rotate twice.
       
   161 	        finalRotationInt -= hwRotation*90;
       
   162 	        }
       
   163 	*/
       
   164         finalRotationInt += iKeyRotatorCompensation;
       
   165 
       
   166         // Keep the value between 0 and 270.
       
   167 	    while ( finalRotationInt < 0 )
       
   168 	        {
       
   169 	        finalRotationInt += 360;
       
   170 	        }
       
   171 	    while ( finalRotationInt > 270 )
       
   172 	        {
       
   173 	        finalRotationInt -= 360;
       
   174 	        }
       
   175 	        
       
   176 	    finalRotation = 
       
   177 	        (CFbsBitGc::TGraphicsOrientation)( finalRotationInt / 90 );
       
   178 
       
   179 	    iUsedRotationForDownEvent = finalRotation;
       
   180         }
       
   181 	
       
   182 	// Find the new scan code from the rotation.
       
   183     switch( aNewRawEvent.ScanCode() )
       
   184         {
       
   185         case EStdKeyLeftArrow:
       
   186             switch ( finalRotation )
       
   187                 {
       
   188                 case CFbsBitGc::EGraphicsOrientationRotated90:
       
   189                     newCode = EStdKeyUpArrow; // fixed
       
   190                     break;
       
   191                     
       
   192                 case CFbsBitGc::EGraphicsOrientationRotated180:
       
   193                     newCode = EStdKeyRightArrow; //fixed
       
   194                     break;
       
   195                     
       
   196                 case CFbsBitGc::EGraphicsOrientationRotated270:
       
   197                     newCode = EStdKeyDownArrow;
       
   198                     break;
       
   199                 default:
       
   200                     break;
       
   201                 }
       
   202             break;
       
   203         case EStdKeyDownArrow:
       
   204             switch ( finalRotation )
       
   205                 {
       
   206                 case CFbsBitGc::EGraphicsOrientationRotated90:
       
   207                     newCode = EStdKeyLeftArrow; //fixed
       
   208                     break;
       
   209                     
       
   210                 case CFbsBitGc::EGraphicsOrientationRotated180:
       
   211                     newCode = EStdKeyUpArrow;
       
   212                     break;
       
   213                     
       
   214                 case CFbsBitGc::EGraphicsOrientationRotated270:
       
   215                     newCode = EStdKeyRightArrow;
       
   216                     break;
       
   217                 default:
       
   218                     break;
       
   219                 }
       
   220             break;
       
   221         case EStdKeyRightArrow:
       
   222             switch ( finalRotation )
       
   223                 {
       
   224                 case CFbsBitGc::EGraphicsOrientationRotated90:
       
   225                     newCode = EStdKeyDownArrow; //fixed
       
   226                     break;
       
   227                     
       
   228                 case CFbsBitGc::EGraphicsOrientationRotated180:
       
   229                     newCode = EStdKeyLeftArrow;
       
   230                     break;
       
   231                     
       
   232                 case CFbsBitGc::EGraphicsOrientationRotated270:
       
   233                     newCode = EStdKeyUpArrow;
       
   234                     break;
       
   235                 default:
       
   236                     break;
       
   237                 }
       
   238             break;
       
   239         case EStdKeyUpArrow:
       
   240             switch ( finalRotation )
       
   241                 {
       
   242                 case CFbsBitGc::EGraphicsOrientationRotated90:
       
   243                     newCode = EStdKeyRightArrow; //fixed
       
   244                     break;
       
   245                     
       
   246                 case CFbsBitGc::EGraphicsOrientationRotated180:
       
   247                     newCode = EStdKeyDownArrow;
       
   248                     break;
       
   249                     
       
   250                 case CFbsBitGc::EGraphicsOrientationRotated270:
       
   251                     newCode = EStdKeyLeftArrow;
       
   252                     break;
       
   253                 default:
       
   254                     break;
       
   255                 }
       
   256             break;
       
   257         default:
       
   258             break;    
       
   259         }
       
   260         
       
   261     // If the 'newCode' was updated, add that value as the new scancode with existing modifiers.
       
   262     if ( newCode != KErrNotFound )
       
   263         {
       
   264         aNewRawEvent.Set(
       
   265             aNewRawEvent.Type(),
       
   266             (aNewRawEvent.ScanCode()&KAknModifiersMask) + newCode);
       
   267         }
       
   268         
       
   269     }
       
   270     
       
   271   
       
   272 
       
   273 // -----------------------------------------------------------------------------
       
   274 // CKeyRotator::GeCKeyRotatorCompensationL
       
   275 // Parses wsini.ini to read key rotator compensation value.
       
   276 // -----------------------------------------------------------------------------
       
   277 //
       
   278 TInt CKeyRotator::GetKeyRotatorCompensationL()
       
   279     {
       
   280     TInt result = 0;
       
   281     HBufC* wsiniText = GetWsiniLC();
       
   282     
       
   283     // Now look for keyword
       
   284     const TInt pos = wsiniText->Find( KAknKeyRotatorKey );
       
   285     if ( pos != KErrNotFound )
       
   286         {        
       
   287         // Keyword was found. Check that it is the beginning of line.
       
   288         // Three cases:
       
   289         // 1. Keyword could be at the beginning of the file.
       
   290         // 2. Keyword could be at the beginning of the file 
       
   291         //    after byte ordering marker.
       
   292         // 3. Previous character can be end of line marker.
       
   293         const TInt previousPos = pos - 1;
       
   294         if ( previousPos < 0 || 
       
   295              ( !previousPos && 
       
   296                IsByteOrderingMarker( (*wsiniText)[ previousPos ] ) ) || 
       
   297              IsEndOfLine( (*wsiniText)[ previousPos ] ) )
       
   298             {
       
   299             TLex text( wsiniText->Mid( pos + KAknKeyRotatorKey().Length() ) );
       
   300             
       
   301             // First, there must be at least a space after keyword.
       
   302             TBool fail = !( SkipSpaces( text ) & EAknWasSpace );
       
   303                    
       
   304             // Then follows a sequence of digits, optionally preceded by '-'.
       
   305             if ( !fail )
       
   306                 {
       
   307                 // Check optional -
       
   308                 TBool negate = EFalse;
       
   309                 if ( !text.Eos() && text.Peek() == '-' )
       
   310                     {
       
   311                     negate = ETrue;
       
   312                     text.Inc();
       
   313                     }
       
   314                     
       
   315                 // Get digit sequence and convert to integer value.
       
   316                 TPtrC token = GetDigits( text );
       
   317                 fail = !token.Length() || 
       
   318                        ( TLex( token ).Val( result ) != KErrNone );
       
   319                 
       
   320                 // Handle negation
       
   321                 if ( !fail && negate )
       
   322                     {
       
   323                     result = -result;
       
   324                     }
       
   325                 }
       
   326 
       
   327             // That sequence of digits is followed by sequence of spaces until
       
   328             // end of line or end of file.
       
   329             fail = fail || ( SkipSpaces( text ) & EAknWasCharacter );
       
   330             
       
   331             // Finally, that sequence of digits must represent
       
   332             // one valid decimal value of the following: 
       
   333             // -270, -180, -90, 0, 90, 180, 270.
       
   334             fail = fail || !CheckCompensationValue( result );               
       
   335                 
       
   336             // If any of above checks failed, use default value 0.
       
   337             if ( fail )
       
   338                 {
       
   339                 result = 0;
       
   340                 }
       
   341             }
       
   342         }
       
   343         
       
   344     CleanupStack::PopAndDestroy( wsiniText );   
       
   345     return result;
       
   346     }
       
   347 
       
   348 // -----------------------------------------------------------------------------
       
   349 // CKeyRotator::IsEndOfLine
       
   350 // Checks if specified character is end of line marker.
       
   351 // -----------------------------------------------------------------------------
       
   352 //
       
   353 inline TBool CKeyRotator::IsEndOfLine( TText aChar )
       
   354     {
       
   355     return aChar == '\r' || aChar == '\n';
       
   356     }
       
   357 
       
   358 // -----------------------------------------------------------------------------
       
   359 // CKeyRotator::IsByteOrderingMarker
       
   360 // Checks if specified character is byte ordering marker.
       
   361 // -----------------------------------------------------------------------------
       
   362 //
       
   363 inline TBool CKeyRotator::IsByteOrderingMarker( TText aChar )
       
   364     {
       
   365     return aChar == 0xFEFF || aChar == 0xFFFE;
       
   366     }
       
   367 
       
   368 // -----------------------------------------------------------------------------
       
   369 // CKeyRotator::GetWsiniLC
       
   370 // Reads the whole wsini.ini to memory and returns in heap descriptor.
       
   371 // -----------------------------------------------------------------------------
       
   372 //
       
   373 HBufC* CKeyRotator::GetWsiniLC()
       
   374     {
       
   375     // Read the whole wsini.ini to memory
       
   376     RFs fs;
       
   377     User::LeaveIfError( fs.Connect() );
       
   378     CleanupClosePushL( fs );
       
   379     
       
   380     TEntry wsiniEntry;
       
   381     User::LeaveIfError( fs.Entry( KAknWsini, wsiniEntry ) );
       
   382 	
       
   383     HBufC* wsiniText = HBufC::NewLC( ( wsiniEntry.iSize + 1 )/2 );
       
   384     TPtr wsiniPtr = wsiniText->Des();
       
   385     TPtr8 wsiniPtr8( (TText8*)wsiniPtr.Ptr(), 0, wsiniPtr.MaxLength()*2 );
       
   386 
       
   387     RFile wsiniFile;
       
   388     User::LeaveIfError( wsiniFile.Open( fs, KAknWsini, EFileRead | EFileShareReadersOnly ) );
       
   389     CleanupClosePushL( wsiniFile );
       
   390 	
       
   391     User::LeaveIfError( wsiniFile.Read( wsiniPtr8, wsiniEntry.iSize ) );
       
   392     wsiniPtr.SetLength( wsiniPtr8.Length() / 2 );
       
   393 	
       
   394     CleanupStack::PopAndDestroy( &wsiniFile );
       
   395     CleanupStack::Pop( wsiniText );
       
   396     CleanupStack::PopAndDestroy( &fs );
       
   397     CleanupStack::PushL( wsiniText );
       
   398     return wsiniText;
       
   399     }
       
   400 
       
   401 // -----------------------------------------------------------------------------
       
   402 // CKeyRotator::SkipSpaces
       
   403 // Skips over spaces.
       
   404 // -----------------------------------------------------------------------------
       
   405 //
       
   406 TInt CKeyRotator::SkipSpaces( TLex& aLex )
       
   407     {
       
   408     TInt flags = 0;
       
   409     // Skip spaces, but stop at end of line.
       
   410     while ( !aLex.Eos() && !IsEndOfLine( aLex.Peek() ) )
       
   411         {
       
   412         if ( aLex.Peek().IsSpace() )
       
   413             {
       
   414             // There was a space, so ok for now.
       
   415             flags |= EAknWasSpace;
       
   416             aLex.Inc();
       
   417             }
       
   418         else
       
   419             {
       
   420             flags |= EAknWasCharacter;
       
   421             break;
       
   422             }
       
   423         }
       
   424     return flags;
       
   425     }
       
   426 
       
   427 // -----------------------------------------------------------------------------
       
   428 // CKeyRotator::SkipSpaces
       
   429 // Goes over digits and returns that sequence.
       
   430 // -----------------------------------------------------------------------------
       
   431 //
       
   432 TPtrC CKeyRotator::GetDigits( TLex& aLex )
       
   433     {
       
   434     // Mark current place and go over digits.
       
   435     aLex.Mark();
       
   436     while ( !aLex.Eos() && !IsEndOfLine( aLex.Peek() ) )
       
   437         {
       
   438         if ( aLex.Peek().IsDigit() )
       
   439             {
       
   440             aLex.Inc();
       
   441             }
       
   442         else
       
   443             {
       
   444             break;
       
   445             }
       
   446         }
       
   447     return aLex.MarkedToken();
       
   448     }
       
   449 
       
   450 // -----------------------------------------------------------------------------
       
   451 // CKeyRotator::CheckCompensationValue
       
   452 // Checks that value contains valid key rotator compensation value.
       
   453 // -----------------------------------------------------------------------------
       
   454 //
       
   455 inline TBool CKeyRotator::CheckCompensationValue( TInt aValue )
       
   456     {
       
   457     // Check absolute value
       
   458     if ( aValue < 0 )
       
   459         {
       
   460         aValue = -aValue;
       
   461         }
       
   462         
       
   463     return aValue == 0 ||
       
   464            aValue == 90 ||
       
   465            aValue == 180 ||
       
   466            aValue == 270;
       
   467     }