--- /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
+