coreapplicationuis/SysAp/Src/sysapkeymanagement.cpp
changeset 0 2e3d3ce01487
child 46 eea20ed08f4b
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 /*
       
     2 * Copyright (c) 2002-2009 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:  CSysApKeyManagement implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 
       
    21 #include "sysapkeymanagement.h"
       
    22 #include "SysAp.hrh"
       
    23 #include "SysApAppUi.h"
       
    24 #include <e32debug.h>
       
    25 #include <ecom/implementationinformation.h> 
       
    26 #include <sysapkeyhandlerplugininterface.h>
       
    27  
       
    28 // CONSTANTS
       
    29 const TInt KCurrentSupportedPluginVersion=2;
       
    30 //text constant indicating that the plugin is non-resident, i.e. instantiated only when needed
       
    31 _LIT8(KNonResidentPlugin,"NonResidentPlugin");
       
    32 
       
    33 // ============================ MEMBER FUNCTIONS ===============================
       
    34 
       
    35 // ----------------------------------------------------------------------------
       
    36 // CSysApPluginInfo::CSysApPluginInfo()
       
    37 // -----------------------------------------------------------------------------
       
    38 //
       
    39 CSysApKeyManagement::CSysApPluginInfo::CSysApPluginInfo( TUid aPluginUid ) : iPluginUid(aPluginUid),
       
    40                                                                              iPtrPlugin(NULL),
       
    41                                                                              iIsKeyProvider(EFalse)
       
    42     {
       
    43     }
       
    44 
       
    45 // ----------------------------------------------------------------------------
       
    46 // CSysApPluginInfo::CSysApPluginInfo()
       
    47 // -----------------------------------------------------------------------------
       
    48 //
       
    49 CSysApKeyManagement::CSysApPluginInfo::~CSysApPluginInfo()
       
    50     {
       
    51     delete iPtrPlugin;
       
    52     iKeys.Close();
       
    53     iKeyHandles.Close();
       
    54     iUpAndDownKeyHandles.Close();
       
    55     }    
       
    56 
       
    57 // ----------------------------------------------------------------------------
       
    58 // CSysApKeyManagement::CSysApKeyManagement()
       
    59 // C++ default constructor can NOT contain any code, that
       
    60 // might leave.
       
    61 // ----------------------------------------------------------------------------
       
    62 
       
    63 CSysApKeyManagement::CSysApKeyManagement( RWindowGroup& aRootWindowGroup, MSysapCallback& aSysApCallback ):
       
    64 	iRootWindowGroup(aRootWindowGroup),
       
    65 	iSysApCallback(aSysApCallback)
       
    66     {
       
    67     TRACES( RDebug::Print( _L("CSysApKeyManagement::CSysApKeyManagement")) );	
       
    68     }
       
    69 
       
    70 // ----------------------------------------------------------------------------
       
    71 // CSysApKeyManagement::ConstructL()
       
    72 // Symbian 2nd phase constructor can leave.
       
    73 // -----------------------------------------------------------------------------
       
    74 //
       
    75 
       
    76 void CSysApKeyManagement::ConstructL()
       
    77     {
       
    78     TRACES( RDebug::Print( _L("CSysApKeyManagement::ConstructL")) );	      
       
    79     GetPluginsL(); //gets info for all available plugins
       
    80     CaptureKeys(); //registers to capture all needed keys
       
    81     }
       
    82 
       
    83 
       
    84 // ----------------------------------------------------------------------------
       
    85 // CSysApKeyManagement::NewL()
       
    86 // Two-phased constructor.
       
    87 // -----------------------------------------------------------------------------
       
    88 //
       
    89 
       
    90 CSysApKeyManagement* CSysApKeyManagement::NewL( RWindowGroup& aRootWindowGroup, MSysapCallback& aSysApCallback )
       
    91     {
       
    92     TRACES( RDebug::Print( _L("CSysApKeyManagement::NewL" ) ) );
       
    93     CSysApKeyManagement* self = new ( ELeave ) CSysApKeyManagement( aRootWindowGroup, aSysApCallback );
       
    94     CleanupStack::PushL( self );
       
    95     self->ConstructL();
       
    96     CleanupStack::Pop(self); //self
       
    97     return self;
       
    98     }
       
    99 
       
   100 
       
   101 // ----------------------------------------------------------------------------
       
   102 // CSysApKeyManagement::~CSysApKeyManagement()
       
   103 // ----------------------------------------------------------------------------
       
   104 //
       
   105 CSysApKeyManagement::~CSysApKeyManagement()
       
   106     {
       
   107     TRACES( RDebug::Print( _L("CSysApKeyManagement::~CSysApKeyManagement")) );	
       
   108 
       
   109     CancelCaptureKeys(); //first cancel the capturing of the keys
       
   110 
       
   111     iSysApPlugins.ResetAndDestroy();
       
   112     }
       
   113 
       
   114 
       
   115 // ----------------------------------------------------------------------------
       
   116 // CSysApKeyManagement::CancelCaptureKeys()
       
   117 // ----------------------------------------------------------------------------
       
   118 // 
       
   119 void CSysApKeyManagement::CancelCaptureKeys()
       
   120     {
       
   121     TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys")) );	
       
   122 
       
   123     // iterate through plugins and cancel key capture
       
   124     for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
       
   125         {
       
   126         CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
       
   127         
       
   128         for ( TInt keyHandleCounter = info->iKeyHandles.Count()-1; keyHandleCounter >= 0; keyHandleCounter-- )
       
   129             {
       
   130             iRootWindowGroup.CancelCaptureKey( info->iKeyHandles[keyHandleCounter] );
       
   131             }
       
   132         
       
   133         for ( TInt upAndDownKeyHandleCounter = info->iUpAndDownKeyHandles.Count()-1; upAndDownKeyHandleCounter >= 0; upAndDownKeyHandleCounter-- )
       
   134             {
       
   135             iRootWindowGroup.CancelCaptureKeyUpAndDowns( info->iUpAndDownKeyHandles[upAndDownKeyHandleCounter] );
       
   136             }
       
   137         }
       
   138     }
       
   139 
       
   140 
       
   141 // ----------------------------------------------------------------------------
       
   142 // CSysApKeyManagement::CaptureKeys()
       
   143 // registers to window server for the keys we want. Callback is in SysappUi
       
   144 // ----------------------------------------------------------------------------
       
   145 
       
   146 void CSysApKeyManagement::CaptureKeys()
       
   147     {
       
   148     TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys")) );	
       
   149 
       
   150     for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
       
   151         {
       
   152         CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
       
   153         
       
   154         for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
       
   155             {
       
   156             TUint captureKey = info->iKeys[keyCounter].iCode;
       
   157 
       
   158             // Special handling for flip key simulation
       
   159 			if ( captureKey == EKeyFlipOpen || captureKey == EKeyFlipClose )
       
   160 			    {
       
   161 			    // don't capture flip, it is simulated to plugins from P&S
       
   162 			    continue;
       
   163 			    }
       
   164 			
       
   165 			TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: capturing key 0x%x for plugin 0x%x"), 
       
   166                                        captureKey, info->iPluginUid ) );
       
   167 			if (info->iIsKeyProvider)
       
   168 			    {
       
   169 			    TInt captureUpDownKey = info->iKeys[keyCounter].iScanCode;
       
   170 			    TUint modifiers = info->iKeys[keyCounter].iModifiers;
       
   171 			    
       
   172                 TInt32 keyHandle = iRootWindowGroup.CaptureKey( captureKey, modifiers, modifiers );
       
   173                 
       
   174                 if ( keyHandle < KErrNone )
       
   175                     {
       
   176                     TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: error %d"), keyHandle ) );
       
   177                     continue; // other keys may be possible to capture, so continue
       
   178                     }
       
   179                 
       
   180                 if ( ( keyHandle = info->iKeyHandles.Append( keyHandle ) ) != KErrNone ) //store handle for CancelCaptureKey
       
   181                     {
       
   182                     //error of Append ignored, key will not be cancelled. We can live with that.
       
   183                     TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: Append failed, error %d"), keyHandle ) );
       
   184                     }
       
   185                 
       
   186                 TInt32 upAndDownKeyHandle = iRootWindowGroup.CaptureKeyUpAndDowns( captureUpDownKey, modifiers, modifiers );
       
   187                 
       
   188                 if ( upAndDownKeyHandle < KErrNone )
       
   189                     {
       
   190                     TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys UpAndDowns: error %d"), upAndDownKeyHandle ) );
       
   191                     continue; // other keys may be possible to capture, so continue
       
   192                     }
       
   193                 
       
   194                 if ( ( upAndDownKeyHandle = info->iUpAndDownKeyHandles.Append( upAndDownKeyHandle ) ) != KErrNone ) //store handle for CancelCaptureKeyUpAndDowns
       
   195                     {
       
   196                     //error of Append ignored, key will not be cancelled. We can live with that.
       
   197                     TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys UpAndDowns: Append failed, error %d"), upAndDownKeyHandle ) );
       
   198                     }
       
   199 			    }
       
   200 			else
       
   201 			    {
       
   202 	            TInt32 handle = iRootWindowGroup.CaptureKey( captureKey, 0, 0 );
       
   203 	            
       
   204 	            if ( handle < KErrNone )
       
   205 	                {
       
   206 	                TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: error %d"), handle ) );
       
   207 	                continue; // other keys may be possible to capture, so continue
       
   208 	                }
       
   209 	            
       
   210 	            if ( ( handle = info->iKeyHandles.Append( handle ) ) != KErrNone ) //store handle for CancelCaptureKey
       
   211 	                {
       
   212 	                //error of Append ignored, key will not be cancelled. We can live with that.
       
   213 	                TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: Append failed, error %d"), handle ) );
       
   214 	                }			    
       
   215 			    }
       
   216             }
       
   217         }
       
   218     }
       
   219 
       
   220 // ----------------------------------------------------------------------------
       
   221 // CSysApKeyManagement::GetPluginsL()
       
   222 // Gets plugins and extracts key and plugin information form them
       
   223 // ----------------------------------------------------------------------------
       
   224 
       
   225 void CSysApKeyManagement::GetPluginsL()
       
   226     {
       
   227     TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL")) );
       
   228     //lists all plugins implementing interface identified with SysapPluginUID
       
   229 
       
   230     RImplInfoPtrArray pluginInfoArray;
       
   231 
       
   232     CleanupClosePushL( pluginInfoArray );
       
   233 
       
   234     REComSession::ListImplementationsL( KSysapKeyHandlerPluginInterfaceUid, 
       
   235     									pluginInfoArray );
       
   236 
       
   237     TInt count = pluginInfoArray.Count();
       
   238 
       
   239     for ( TInt index = 0; index < count; ++index)
       
   240         {
       
   241     	//extract key from data of plugin
       
   242         CImplementationInformation* info = pluginInfoArray[index];
       
   243     	
       
   244         TInt version = info->Version();
       
   245     	
       
   246         if ( version > KCurrentSupportedPluginVersion )
       
   247             {
       
   248             TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, version conflict: version=%d"), info->ImplementationUid(), version ) );
       
   249             continue;	
       
   250             }
       
   251     	
       
   252         CSysApPluginInfo* pluginInfo = new (ELeave) CSysApPluginInfo( info->ImplementationUid() );
       
   253         CleanupStack::PushL( pluginInfo );
       
   254         
       
   255         if ( info->OpaqueData().Compare( KNonResidentPlugin ) == 0 ) //plugin tells itself in opaquedata that if it shall be resident
       
   256             {
       
   257             // do nothing for non-resident plugins
       
   258             TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x is non-resident."), pluginInfo->iPluginUid ) );
       
   259             }
       
   260         else
       
   261             {
       
   262             TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: loading resident plugin 0x%x"), pluginInfo->iPluginUid ) );
       
   263             pluginInfo->iPtrPlugin = CSysapKeyHandlerPlugin::NewL( pluginInfo->iPluginUid, &iSysApCallback );            
       
   264             if ( version > 1 )
       
   265                 {
       
   266                 //plugin is a key provider plugin (plugin version 2)
       
   267                 pluginInfo->iIsKeyProvider = ETrue;
       
   268                 }
       
   269             }
       
   270         
       
   271         TInt err = KErrNone;
       
   272     	if (pluginInfo->iIsKeyProvider)
       
   273     	    {
       
   274     	    TRAP(err, pluginInfo->iPtrPlugin->ProvideKeyEventsL(pluginInfo->iKeys));
       
   275     	    if (err == KErrNone)
       
   276     	        {
       
   277     	        err = CheckKeys(pluginInfo->iKeys);
       
   278     	        }    	    
       
   279     	    }
       
   280     	else
       
   281     	    {
       
   282             const TDesC8& data = info->DataType();  
       
   283             TLex8 lex(data); //convert data to TUint. We suppose that there is one TUint in the data
       
   284             err = GetKeys( lex, pluginInfo->iKeys );    	    
       
   285     	    }
       
   286         
       
   287         if ( err != KErrNone ) //plugin has no valid keys
       
   288     	    {
       
   289     	 	if( err == KErrAbort ) //this means that there was some error in the key definitions, which makes the plugin useless,
       
   290     	 	    {
       
   291     	 	  	TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, err=%d. Probably error in key definitons."), pluginInfo->iPluginUid, err  ) );
       
   292     	 	  	CleanupStack::PopAndDestroy( pluginInfo );
       
   293     	 	  	continue; //just ignore this plugin
       
   294     	 	  	}
       
   295             else 
       
   296                 {
       
   297                 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, err=%d.Leaving..."), pluginInfo->iPluginUid, err  ) );
       
   298                 User::Leave( err );
       
   299                 }
       
   300             }
       
   301         
       
   302         //append to array of plugins
       
   303         err = iSysApPlugins.Append( pluginInfo );
       
   304                     		    		
       
   305         if ( err != KErrNone )	 //error in append
       
   306             {
       
   307             TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: resident plugin 0x%x load failure, err=%d"), pluginInfo->iPluginUid, err  ) );
       
   308             CleanupStack::PopAndDestroy( pluginInfo ); //this deletes also ptrPlugin
       
   309             break;	//probably no more plugins can be read
       
   310             }
       
   311     		
       
   312         TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x succesfully loaded."), pluginInfo->iPluginUid ) ); 	
       
   313             
       
   314         CleanupStack::Pop( pluginInfo ); 
       
   315     	}
       
   316     
       
   317     pluginInfoArray.Close();
       
   318     	
       
   319     CleanupStack::Pop( &pluginInfoArray ); 
       
   320     }
       
   321 
       
   322 // ----------------------------------------------------------------------------
       
   323 // CSysApKeyManagement::HandleKeyEventL()
       
   324 // Handles key events. SysAppUi calls this function
       
   325 // ----------------------------------------------------------------------------
       
   326 
       
   327 TKeyResponse CSysApKeyManagement::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType )
       
   328     {
       
   329 	TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL")) );
       
   330 	
       
   331     TKeyResponse response(EKeyWasNotConsumed); //not consumed by default
       
   332     
       
   333     for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
       
   334         {
       
   335         CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
       
   336         
       
   337         for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
       
   338             {
       
   339             if (aType == EEventKey)
       
   340                 {
       
   341                 if ( info->iKeys[keyCounter].iCode == aKeyEvent.iCode )
       
   342                     {
       
   343                     //  a plug-in, don't continue
       
   344                     TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL: offering key=%d to plugin 0x%x"), 
       
   345                                                   aKeyEvent.iCode, info->iPluginUid ) );
       
   346                     
       
   347                     if ( info->iPtrPlugin )
       
   348                         {
       
   349                         response = info->iPtrPlugin->HandleKeyEventL( aKeyEvent, aType );
       
   350                         }
       
   351                     else // non-resident plug-in, needs to be loaded
       
   352                         {
       
   353                         TUid pluginuid(info->iPluginUid); //gets plugin info for this key
       
   354                         CSysapKeyHandlerPlugin* plugin = CSysapKeyHandlerPlugin::NewL( pluginuid, &iSysApCallback ); //instantiates plugin
       
   355                         CleanupStack::PushL( plugin );
       
   356                         response = plugin->HandleKeyEventL( aKeyEvent, aType );
       
   357                         CleanupStack::PopAndDestroy( plugin );
       
   358                         }
       
   359 
       
   360                     // only one plugin is allowed to capture a key event, so there is no sense to continue looping regardless
       
   361                     // whether key has been consumed or not
       
   362                     return response;                   
       
   363                     }
       
   364                 }
       
   365             else if (info->iIsKeyProvider && (aType == EEventKeyUp || aType == EEventKeyDown))
       
   366                 {
       
   367                 if ( info->iKeys[keyCounter].iScanCode == aKeyEvent.iScanCode )
       
   368                     {
       
   369                     //  a plug-in, don't continue
       
   370                     TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL: offering up or down key scancode =%d to plugin 0x%x"), 
       
   371                                                   aKeyEvent.iScanCode, info->iPluginUid ) );
       
   372                     //key provider plugins are always resident
       
   373                     return info->iPtrPlugin->HandleKeyEventL( aKeyEvent, aType );
       
   374                     }
       
   375                 }
       
   376             else
       
   377                 {
       
   378                 continue;
       
   379                 }
       
   380             }
       
   381         }
       
   382     return response;        
       
   383     }
       
   384 
       
   385 // ----------------------------------------------------------------------------
       
   386 // CSysApKeyManagement::FindKeyCode()
       
   387 // Helper function for finding a key in plugins.
       
   388 // ----------------------------------------------------------------------------
       
   389 
       
   390 TInt CSysApKeyManagement::FindKeyCode( TUint aKeycode )
       
   391     {
       
   392     for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
       
   393         {
       
   394         CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
       
   395         
       
   396         for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
       
   397             {
       
   398             if ( info->iKeys[keyCounter].iCode == aKeycode )
       
   399 				{
       
   400 				return keyCounter;	
       
   401 				}
       
   402             }
       
   403         }
       
   404     
       
   405     return KErrNotFound;
       
   406     }
       
   407 
       
   408 // ----------------------------------------------------------------------------
       
   409 // CSysApKeyManagement::FindScanCode()
       
   410 // Helper function for finding a key scancode in plugins.
       
   411 // ----------------------------------------------------------------------------
       
   412 
       
   413 TInt CSysApKeyManagement::FindScanCode( TInt aScanCode )
       
   414     {
       
   415     for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
       
   416         {
       
   417         CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
       
   418         
       
   419         for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
       
   420             {
       
   421             if ( info->iKeys[keyCounter].iScanCode == aScanCode )
       
   422                 {
       
   423                 return keyCounter;  
       
   424                 }
       
   425             }
       
   426         }
       
   427     
       
   428     return KErrNotFound;
       
   429     }
       
   430 
       
   431 
       
   432 // ----------------------------------------------------------------------------
       
   433 // CSysApKeyManagement::GetKeys()
       
   434 // Helper function for getting the keys supported by plugins
       
   435 // ----------------------------------------------------------------------------
       
   436 
       
   437 TInt CSysApKeyManagement::GetKeys( TLex8& aLex, RArray<TKeyEvent>& aKeys )
       
   438 	{
       
   439 	aLex.SkipSpace();
       
   440 	
       
   441 	TUint thiskey;
       
   442 	TInt err = aLex.Val( thiskey );
       
   443 	
       
   444 	if ( err != KErrNone ) //there must be at least one number
       
   445 		{
       
   446 		return KErrAbort;		
       
   447 		}
       
   448 	
       
   449 	while ( err == KErrNone ) //while we have a new key
       
   450 		{
       
   451 		if ( FindKeyCode( thiskey ) == KErrNotFound ) // keys not to be duplicated 
       
   452 			{
       
   453 			TKeyEvent event;
       
   454 			//other values in event not initialized, but
       
   455 			//they are not used anyway
       
   456 			event.iCode = thiskey;
       
   457 			err = aKeys.Append( event ); //append to keys.
       
   458 			
       
   459 			if ( err != KErrNone )
       
   460 				{
       
   461 				return err;
       
   462 				}
       
   463 			}
       
   464 		
       
   465 		aLex.SkipSpace();
       
   466 		
       
   467 		err = aLex.Val( thiskey ); //get next new key
       
   468 		}
       
   469 		
       
   470 	if ( aKeys.Count() == 0 ) //no valid keys		
       
   471 		{
       
   472 		return KErrAbort;		
       
   473 		}
       
   474 	
       
   475 	return KErrNone;
       
   476 	}
       
   477 
       
   478 // ----------------------------------------------------------------------------
       
   479 // CSysApKeyManagement::CheckKeys()
       
   480 // Helper function for checking plugin keys
       
   481 // ----------------------------------------------------------------------------
       
   482 
       
   483 TInt CSysApKeyManagement::CheckKeys(RArray<TKeyEvent>& aKeys )
       
   484     {
       
   485     for ( TInt keyCounter = aKeys.Count()-1;  keyCounter >= 0; keyCounter-- )
       
   486         {
       
   487         if ( FindKeyCode(aKeys[keyCounter].iCode) != KErrNotFound )
       
   488             {
       
   489             aKeys.Remove(keyCounter);
       
   490             }
       
   491         }
       
   492     //check scancodes also just to be sure
       
   493     //no duplicates should be found is TKeyEvents are properly constructed
       
   494     for ( TInt keyCounter = aKeys.Count()-1;  keyCounter >= 0; keyCounter-- )
       
   495         {
       
   496         if ( FindScanCode(aKeys[keyCounter].iScanCode) != KErrNotFound )
       
   497             {
       
   498             aKeys.Remove(keyCounter);
       
   499             }
       
   500         }
       
   501     if ( aKeys.Count() )
       
   502         {
       
   503         return KErrNone;
       
   504         }
       
   505     return KErrAbort;
       
   506     }
       
   507 	
       
   508 //  End of File
       
   509