coreapplicationuis/SysAp/Src/sysapkeymanagement.cpp
changeset 0 2e3d3ce01487
child 19 924385140d98
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/coreapplicationuis/SysAp/Src/sysapkeymanagement.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,509 @@
+/*
+* Copyright (c) 2002-2009 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:  CSysApKeyManagement implementation.
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "sysapkeymanagement.h"
+#include "SysAp.hrh"
+#include "SysApAppUi.h"
+#include <e32debug.h>
+#include <ecom/implementationinformation.h> 
+#include <sysapkeyhandlerplugininterface.h>
+ 
+// CONSTANTS
+const TInt KCurrentSupportedPluginVersion=2;
+//text constant indicating that the plugin is non-resident, i.e. instantiated only when needed
+_LIT8(KNonResidentPlugin,"NonResidentPlugin");
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// ----------------------------------------------------------------------------
+// CSysApPluginInfo::CSysApPluginInfo()
+// -----------------------------------------------------------------------------
+//
+CSysApKeyManagement::CSysApPluginInfo::CSysApPluginInfo( TUid aPluginUid ) : iPluginUid(aPluginUid),
+                                                                             iPtrPlugin(NULL),
+                                                                             iIsKeyProvider(EFalse)
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// CSysApPluginInfo::CSysApPluginInfo()
+// -----------------------------------------------------------------------------
+//
+CSysApKeyManagement::CSysApPluginInfo::~CSysApPluginInfo()
+    {
+    delete iPtrPlugin;
+    iKeys.Close();
+    iKeyHandles.Close();
+    iUpAndDownKeyHandles.Close();
+    }    
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::CSysApKeyManagement()
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ----------------------------------------------------------------------------
+
+CSysApKeyManagement::CSysApKeyManagement( RWindowGroup& aRootWindowGroup, MSysapCallback& aSysApCallback ):
+	iRootWindowGroup(aRootWindowGroup),
+	iSysApCallback(aSysApCallback)
+    {
+    TRACES( RDebug::Print( _L("CSysApKeyManagement::CSysApKeyManagement")) );	
+    }
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::ConstructL()
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+
+void CSysApKeyManagement::ConstructL()
+    {
+    TRACES( RDebug::Print( _L("CSysApKeyManagement::ConstructL")) );	      
+    GetPluginsL(); //gets info for all available plugins
+    CaptureKeys(); //registers to capture all needed keys
+    }
+
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::NewL()
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+
+CSysApKeyManagement* CSysApKeyManagement::NewL( RWindowGroup& aRootWindowGroup, MSysapCallback& aSysApCallback )
+    {
+    TRACES( RDebug::Print( _L("CSysApKeyManagement::NewL" ) ) );
+    CSysApKeyManagement* self = new ( ELeave ) CSysApKeyManagement( aRootWindowGroup, aSysApCallback );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop(self); //self
+    return self;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::~CSysApKeyManagement()
+// ----------------------------------------------------------------------------
+//
+CSysApKeyManagement::~CSysApKeyManagement()
+    {
+    TRACES( RDebug::Print( _L("CSysApKeyManagement::~CSysApKeyManagement")) );	
+
+    CancelCaptureKeys(); //first cancel the capturing of the keys
+
+    iSysApPlugins.ResetAndDestroy();
+    }
+
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::CancelCaptureKeys()
+// ----------------------------------------------------------------------------
+// 
+void CSysApKeyManagement::CancelCaptureKeys()
+    {
+    TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys")) );	
+
+    // iterate through plugins and cancel key capture
+    for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
+        {
+        CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
+        
+        for ( TInt keyHandleCounter = info->iKeyHandles.Count()-1; keyHandleCounter >= 0; keyHandleCounter-- )
+            {
+            iRootWindowGroup.CancelCaptureKey( info->iKeyHandles[keyHandleCounter] );
+            }
+        
+        for ( TInt upAndDownKeyHandleCounter = info->iUpAndDownKeyHandles.Count()-1; upAndDownKeyHandleCounter >= 0; upAndDownKeyHandleCounter-- )
+            {
+            iRootWindowGroup.CancelCaptureKeyUpAndDowns( info->iUpAndDownKeyHandles[upAndDownKeyHandleCounter] );
+            }
+        }
+    }
+
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::CaptureKeys()
+// registers to window server for the keys we want. Callback is in SysappUi
+// ----------------------------------------------------------------------------
+
+void CSysApKeyManagement::CaptureKeys()
+    {
+    TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys")) );	
+
+    for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
+        {
+        CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
+        
+        for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
+            {
+            TUint captureKey = info->iKeys[keyCounter].iCode;
+
+            // Special handling for flip key simulation
+			if ( captureKey == EKeyFlipOpen || captureKey == EKeyFlipClose )
+			    {
+			    // don't capture flip, it is simulated to plugins from P&S
+			    continue;
+			    }
+			
+			TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: capturing key 0x%x for plugin 0x%x"), 
+                                       captureKey, info->iPluginUid ) );
+			if (info->iIsKeyProvider)
+			    {
+			    TInt captureUpDownKey = info->iKeys[keyCounter].iScanCode;
+			    TUint modifiers = info->iKeys[keyCounter].iModifiers;
+			    
+                TInt32 keyHandle = iRootWindowGroup.CaptureKey( captureKey, modifiers, modifiers );
+                
+                if ( keyHandle < KErrNone )
+                    {
+                    TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: error %d"), keyHandle ) );
+                    continue; // other keys may be possible to capture, so continue
+                    }
+                
+                if ( ( keyHandle = info->iKeyHandles.Append( keyHandle ) ) != KErrNone ) //store handle for CancelCaptureKey
+                    {
+                    //error of Append ignored, key will not be cancelled. We can live with that.
+                    TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: Append failed, error %d"), keyHandle ) );
+                    }
+                
+                TInt32 upAndDownKeyHandle = iRootWindowGroup.CaptureKeyUpAndDowns( captureUpDownKey, modifiers, modifiers );
+                
+                if ( upAndDownKeyHandle < KErrNone )
+                    {
+                    TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys UpAndDowns: error %d"), upAndDownKeyHandle ) );
+                    continue; // other keys may be possible to capture, so continue
+                    }
+                
+                if ( ( upAndDownKeyHandle = info->iUpAndDownKeyHandles.Append( upAndDownKeyHandle ) ) != KErrNone ) //store handle for CancelCaptureKeyUpAndDowns
+                    {
+                    //error of Append ignored, key will not be cancelled. We can live with that.
+                    TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys UpAndDowns: Append failed, error %d"), upAndDownKeyHandle ) );
+                    }
+			    }
+			else
+			    {
+	            TInt32 handle = iRootWindowGroup.CaptureKey( captureKey, 0, 0 );
+	            
+	            if ( handle < KErrNone )
+	                {
+	                TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: error %d"), handle ) );
+	                continue; // other keys may be possible to capture, so continue
+	                }
+	            
+	            if ( ( handle = info->iKeyHandles.Append( handle ) ) != KErrNone ) //store handle for CancelCaptureKey
+	                {
+	                //error of Append ignored, key will not be cancelled. We can live with that.
+	                TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: Append failed, error %d"), handle ) );
+	                }			    
+			    }
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::GetPluginsL()
+// Gets plugins and extracts key and plugin information form them
+// ----------------------------------------------------------------------------
+
+void CSysApKeyManagement::GetPluginsL()
+    {
+    TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL")) );
+    //lists all plugins implementing interface identified with SysapPluginUID
+
+    RImplInfoPtrArray pluginInfoArray;
+
+    CleanupClosePushL( pluginInfoArray );
+
+    REComSession::ListImplementationsL( KSysapKeyHandlerPluginInterfaceUid, 
+    									pluginInfoArray );
+
+    TInt count = pluginInfoArray.Count();
+
+    for ( TInt index = 0; index < count; ++index)
+        {
+    	//extract key from data of plugin
+        CImplementationInformation* info = pluginInfoArray[index];
+    	
+        TInt version = info->Version();
+    	
+        if ( version > KCurrentSupportedPluginVersion )
+            {
+            TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, version conflict: version=%d"), info->ImplementationUid(), version ) );
+            continue;	
+            }
+    	
+        CSysApPluginInfo* pluginInfo = new (ELeave) CSysApPluginInfo( info->ImplementationUid() );
+        CleanupStack::PushL( pluginInfo );
+        
+        if ( info->OpaqueData().Compare( KNonResidentPlugin ) == 0 ) //plugin tells itself in opaquedata that if it shall be resident
+            {
+            // do nothing for non-resident plugins
+            TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x is non-resident."), pluginInfo->iPluginUid ) );
+            }
+        else
+            {
+            TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: loading resident plugin 0x%x"), pluginInfo->iPluginUid ) );
+            pluginInfo->iPtrPlugin = CSysapKeyHandlerPlugin::NewL( pluginInfo->iPluginUid, &iSysApCallback );            
+            if ( version > 1 )
+                {
+                //plugin is a key provider plugin (plugin version 2)
+                pluginInfo->iIsKeyProvider = ETrue;
+                }
+            }
+        
+        TInt err = KErrNone;
+    	if (pluginInfo->iIsKeyProvider)
+    	    {
+    	    TRAP(err, pluginInfo->iPtrPlugin->ProvideKeyEventsL(pluginInfo->iKeys));
+    	    if (err == KErrNone)
+    	        {
+    	        err = CheckKeys(pluginInfo->iKeys);
+    	        }    	    
+    	    }
+    	else
+    	    {
+            const TDesC8& data = info->DataType();  
+            TLex8 lex(data); //convert data to TUint. We suppose that there is one TUint in the data
+            err = GetKeys( lex, pluginInfo->iKeys );    	    
+    	    }
+        
+        if ( err != KErrNone ) //plugin has no valid keys
+    	    {
+    	 	if( err == KErrAbort ) //this means that there was some error in the key definitions, which makes the plugin useless,
+    	 	    {
+    	 	  	TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, err=%d. Probably error in key definitons."), pluginInfo->iPluginUid, err  ) );
+    	 	  	CleanupStack::PopAndDestroy( pluginInfo );
+    	 	  	continue; //just ignore this plugin
+    	 	  	}
+            else 
+                {
+                TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, err=%d.Leaving..."), pluginInfo->iPluginUid, err  ) );
+                User::Leave( err );
+                }
+            }
+        
+        //append to array of plugins
+        err = iSysApPlugins.Append( pluginInfo );
+                    		    		
+        if ( err != KErrNone )	 //error in append
+            {
+            TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: resident plugin 0x%x load failure, err=%d"), pluginInfo->iPluginUid, err  ) );
+            CleanupStack::PopAndDestroy( pluginInfo ); //this deletes also ptrPlugin
+            break;	//probably no more plugins can be read
+            }
+    		
+        TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x succesfully loaded."), pluginInfo->iPluginUid ) ); 	
+            
+        CleanupStack::Pop( pluginInfo ); 
+    	}
+    
+    pluginInfoArray.Close();
+    	
+    CleanupStack::Pop( &pluginInfoArray ); 
+    }
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::HandleKeyEventL()
+// Handles key events. SysAppUi calls this function
+// ----------------------------------------------------------------------------
+
+TKeyResponse CSysApKeyManagement::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType )
+    {
+	TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL")) );
+	
+    TKeyResponse response(EKeyWasNotConsumed); //not consumed by default
+    
+    for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
+        {
+        CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
+        
+        for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
+            {
+            if (aType == EEventKey)
+                {
+                if ( info->iKeys[keyCounter].iCode == aKeyEvent.iCode )
+                    {
+                    //  a plug-in, don't continue
+                    TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL: offering key=%d to plugin 0x%x"), 
+                                                  aKeyEvent.iCode, info->iPluginUid ) );
+                    
+                    if ( info->iPtrPlugin )
+                        {
+                        response = info->iPtrPlugin->HandleKeyEventL( aKeyEvent, aType );
+                        }
+                    else // non-resident plug-in, needs to be loaded
+                        {
+                        TUid pluginuid(info->iPluginUid); //gets plugin info for this key
+                        CSysapKeyHandlerPlugin* plugin = CSysapKeyHandlerPlugin::NewL( pluginuid, &iSysApCallback ); //instantiates plugin
+                        CleanupStack::PushL( plugin );
+                        response = plugin->HandleKeyEventL( aKeyEvent, aType );
+                        CleanupStack::PopAndDestroy( plugin );
+                        }
+
+                    // only one plugin is allowed to capture a key event, so there is no sense to continue looping regardless
+                    // whether key has been consumed or not
+                    return response;                   
+                    }
+                }
+            else if (info->iIsKeyProvider && (aType == EEventKeyUp || aType == EEventKeyDown))
+                {
+                if ( info->iKeys[keyCounter].iScanCode == aKeyEvent.iScanCode )
+                    {
+                    //  a plug-in, don't continue
+                    TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL: offering up or down key scancode =%d to plugin 0x%x"), 
+                                                  aKeyEvent.iScanCode, info->iPluginUid ) );
+                    //key provider plugins are always resident
+                    return info->iPtrPlugin->HandleKeyEventL( aKeyEvent, aType );
+                    }
+                }
+            else
+                {
+                continue;
+                }
+            }
+        }
+    return response;        
+    }
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::FindKeyCode()
+// Helper function for finding a key in plugins.
+// ----------------------------------------------------------------------------
+
+TInt CSysApKeyManagement::FindKeyCode( TUint aKeycode )
+    {
+    for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
+        {
+        CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
+        
+        for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
+            {
+            if ( info->iKeys[keyCounter].iCode == aKeycode )
+				{
+				return keyCounter;	
+				}
+            }
+        }
+    
+    return KErrNotFound;
+    }
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::FindScanCode()
+// Helper function for finding a key scancode in plugins.
+// ----------------------------------------------------------------------------
+
+TInt CSysApKeyManagement::FindScanCode( TInt aScanCode )
+    {
+    for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- )
+        {
+        CSysApPluginInfo* info = iSysApPlugins[pluginCounter];
+        
+        for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- )
+            {
+            if ( info->iKeys[keyCounter].iScanCode == aScanCode )
+                {
+                return keyCounter;  
+                }
+            }
+        }
+    
+    return KErrNotFound;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::GetKeys()
+// Helper function for getting the keys supported by plugins
+// ----------------------------------------------------------------------------
+
+TInt CSysApKeyManagement::GetKeys( TLex8& aLex, RArray<TKeyEvent>& aKeys )
+	{
+	aLex.SkipSpace();
+	
+	TUint thiskey;
+	TInt err = aLex.Val( thiskey );
+	
+	if ( err != KErrNone ) //there must be at least one number
+		{
+		return KErrAbort;		
+		}
+	
+	while ( err == KErrNone ) //while we have a new key
+		{
+		if ( FindKeyCode( thiskey ) == KErrNotFound ) // keys not to be duplicated 
+			{
+			TKeyEvent event;
+			//other values in event not initialized, but
+			//they are not used anyway
+			event.iCode = thiskey;
+			err = aKeys.Append( event ); //append to keys.
+			
+			if ( err != KErrNone )
+				{
+				return err;
+				}
+			}
+		
+		aLex.SkipSpace();
+		
+		err = aLex.Val( thiskey ); //get next new key
+		}
+		
+	if ( aKeys.Count() == 0 ) //no valid keys		
+		{
+		return KErrAbort;		
+		}
+	
+	return KErrNone;
+	}
+
+// ----------------------------------------------------------------------------
+// CSysApKeyManagement::CheckKeys()
+// Helper function for checking plugin keys
+// ----------------------------------------------------------------------------
+
+TInt CSysApKeyManagement::CheckKeys(RArray<TKeyEvent>& aKeys )
+    {
+    for ( TInt keyCounter = aKeys.Count()-1;  keyCounter >= 0; keyCounter-- )
+        {
+        if ( FindKeyCode(aKeys[keyCounter].iCode) != KErrNotFound )
+            {
+            aKeys.Remove(keyCounter);
+            }
+        }
+    //check scancodes also just to be sure
+    //no duplicates should be found is TKeyEvents are properly constructed
+    for ( TInt keyCounter = aKeys.Count()-1;  keyCounter >= 0; keyCounter-- )
+        {
+        if ( FindScanCode(aKeys[keyCounter].iScanCode) != KErrNotFound )
+            {
+            aKeys.Remove(keyCounter);
+            }
+        }
+    if ( aKeys.Count() )
+        {
+        return KErrNone;
+        }
+    return KErrAbort;
+    }
+	
+//  End of File
+