idlefw/plugins/wsplugin/src/numerickeyhandler.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:22:09 +0100
branchRCL_3
changeset 114 a5a39a295112
child 130 67f2ed48ad91
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2005-2007 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:  Numeric key forwarding handler implementation for Active Idle 
*                WS Plug-in.
*
*/


#include "numerickeyhandler.h"
#include "uistate.h"

#include <e32property.h>
#include <centralrepository.h>
#include <w32adll.h>

#include <easydialingcrkeys.h>
#include <spsettings.h>
#include <featmgr.h>

#include <PtiEngine.h>
#include <activeidle2domainpskeys.h>
#include <AvkonInternalCRKeys.h>
#include <AknFepInternalCRKeys.h>

#include <aiutility.h>
#include <aipspropertyobserver.h>

namespace AiWsPlugin {


CNumericKeyHandler::CNumericKeyHandler
        ( TInt aTargetWgId, MAnimGeneralFunctionsWindowExtension* aWindowExt ) :
    iTargetWgId( aTargetWgId ), 
    iWindowExt( aWindowExt )
    {
    }
    
void CNumericKeyHandler::ConstructL()
    {
    // Read capability: ReadUserData.
    _LIT_SECURITY_POLICY_C1( KReadUserPolicy, ECapabilityReadUserData ); 
    // Write capability: WriteDeviceData.
    _LIT_SECURITY_POLICY_C1( KWriteDevicePolicy, ECapabilityWriteDeviceData );

    RProperty::Define( 
         	KPSUidAiInformation,
         	KActiveIdleState,
         	RProperty::EInt,
            KReadUserPolicy,
            KWriteDevicePolicy );
                    
	iQwertyObserver = AiUtility::CreatePSPropertyObserverL(
			TCallBack( HandleQwertyModeChanged, this ),
        	KCRUidAvkon, KAknQwertyInputModeActive );
	
	iInputLanguageRepository = CRepository::NewL( KCRUidAknFep );
	iInputLanguageObserver = CCenRepNotifyHandler::NewL(*this, *iInputLanguageRepository);
	iInputLanguageObserver->StartListeningL(); 
	
	RProperty::Get(KCRUidAvkon, KAknQwertyInputModeActive, iQwertyMode);
	iInputLanguageRepository->Get( KAknFepInputTxtLang, iInputLanguage );
          
    // Load numeric keys mapping for qwerty 
    if ( iQwertyMode )
        {
        LoadInputLanguageKeyBindings( iInputLanguage );            
        }
    }

CNumericKeyHandler* CNumericKeyHandler::NewLC
        ( TInt aTargetWgId, MAnimGeneralFunctionsWindowExtension* aWindowExt )
    {
    CNumericKeyHandler* self = new(ELeave) CNumericKeyHandler
        ( aTargetWgId, aWindowExt );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }
    
CNumericKeyHandler::~CNumericKeyHandler()
    {
    if( iInputLanguageObserver )
        {
        iInputLanguageObserver->StopListening();
        }
    delete iInputLanguageObserver;
    delete iInputLanguageRepository;
    Release(iQwertyObserver);
    iNumericKeys.Close();
    }

void CNumericKeyHandler::SetUiStateQuery( MUiState& aUiState )
    {
    iUiState = &aUiState;
    }

void CNumericKeyHandler::FocusChanged( TBool /*aState*/ )
    {
    }
    
TBool CNumericKeyHandler::OfferRawEvent(const TRawEvent& aRawEvent)
    {
    switch( aRawEvent.Type() )
        {
        case TRawEvent::EKeyDown:
            {
            if ( iUiState->HasFocus() && CheckPostToTarget( aRawEvent ) )
                {
                TInt forwardKeys = EPSAiForwardNumericKeysToPhone;       
                
                TInt err = RProperty::Get(
                        KPSUidAiInformation,
                        KActiveIdleForwardNumericKeysToPhone,
                        forwardKeys);
                // Key event forwarding disabled => Ignore the keys
                if ( err == KErrNone && 
                        forwardKeys == EPSAiDontForwardNumericKeysToPhone )
                    {
                    return EFalse;
                    }
    			// Phone app is listening this key and knows that next
                // focus event from window server is becuase key events
                // are coming to it.                        
                RProperty::Set(
                 	KPSUidAiInformation, 
                    KActiveIdleState,
                	EPSAiNumberEntry );

                // Switch focus to Phone app
                if( iWindowExt )
                    {
                    iWindowExt->SetOrdinalPosition( iTargetWgId, 0, 0 );
                    }
                }
            break;
            }
        }
    
    // Never consume the key event as we want target application to process it
    return EFalse;
    }

/**
 * Returns true if event should be forwarded to Phone app.
 */
TBool CNumericKeyHandler::CheckPostToTarget(const TRawEvent& aRawEvent ) const
    {
    const TInt scanCode = aRawEvent.ScanCode();
    const TUint modifiers = iUiState->Modifiers();

    if ( iQwertyMode ) 
        {
        // Don't pass the check if shift is pressed.		
        if(( modifiers & EModifierShift ) == 0 )
            {
            TInt numericKeysCount = iNumericKeys.Count();
            while( numericKeysCount-- )
                {
                TPtiNumericKeyBinding numKeyBind = iNumericKeys[numericKeysCount];
                if( numKeyBind.iKey == scanCode )
                    {
                    return ETrue;
                    }
                }
            }
        }
    else
        {
        // Normal check ignore modifiers
        static const TInt KIdPlgScanCodes[] = 
            { '1','2','3','4','5','6','7','8','9','0',
              '*',EStdKeyNkpAsterisk,EStdKeyHash,EStdKeyNkpPlus };
        static const TInt KIdPlgScanCodeCount = 
            sizeof( KIdPlgScanCodes ) / sizeof( KIdPlgScanCodes[0] );
        TInt count = KIdPlgScanCodeCount;
        while( count-- )
            {
            const TInt refCode = KIdPlgScanCodes[ count ];
            // Is one of [0,1,2,3,4,5,6,7,8,9,*,#]?
            if( refCode == scanCode )
                {
                return ETrue;
                }
            }
        }
    
    // Homescreen should open dialer also with alpha characters, if dialer is in 
    // mode that accepts alpha characters into number entry (ou1cimx1#299396)    
    
    const TInt  KPhoneKeyStart = 33;
    const TInt  KPhoneKeyEnd   = 127;
    
    return ( ( AllowAlphaNumericMode() ) && ( ( scanCode >= KPhoneKeyStart &&
             scanCode <= KPhoneKeyEnd ) || modifiers & EModifierSpecial ) );
    }


/**
 * Load input locales.
 */
void CNumericKeyHandler::LoadInputLanguageKeyBindings( TInt aLanguage )
    {
    iNumericKeys.Reset();
    
    TRAPD( err, 
        {
        CPtiEngine* ptiEngine = CPtiEngine::NewL();
        CleanupStack::PushL( ptiEngine );
        ptiEngine->GetNumericModeKeysForQwertyL( aLanguage, 
                                                 iNumericKeys );         
        CleanupStack::PopAndDestroy( ptiEngine );                                                 
        } ); // TRAP
        
    if ( err )        
        {
        iNumericKeys.Reset();
        iQwertyMode = 0; // To default mode
        }
    else
        {
        // remove numeric chars that not open number entry
        TInt numericKeysCount = iNumericKeys.Count();
        while ( numericKeysCount-- )
            {
            TPtiNumericKeyBinding numKeyBind = iNumericKeys[numericKeysCount];
            
            if ( numKeyBind.iChar == 'w' ||
                 numKeyBind.iChar == 'p' 
#ifndef RD_INTELLIGENT_TEXT_INPUT
                 /*
                 * The following code is commented because
                 * For GQF requirement Space is mapped to "0"
                 */
                 || numKeyBind.iKey == EPtiKeyQwertySpace  
#endif
               )
                 {
                 iNumericKeys.Remove( numericKeysCount );                    
                 }
            }    
        }
    }
    
/**
 * Handles qwerty mode change.
 */
TInt CNumericKeyHandler::HandleQwertyModeChanged( TAny *aPtr )
    {
    CNumericKeyHandler* self = static_cast<CNumericKeyHandler*>( aPtr );
    if( self )
        {
        TInt value = self->iQwertyMode;
        TInt err = self->iQwertyObserver->Get( value );

        if( err == KErrNone )
            {
            self->SetQwertyMode( value );
            }
        // Load key bindings if not already loaded
#ifdef RD_INTELLIGENT_TEXT_INPUT
        if ( self->iQwertyMode )
            {
            self->iNumericKeys.Reset();
#else 
        if ( self->iQwertyMode && !self->iNumericKeys.Count() )
            {
#endif
        	self->LoadInputLanguageKeyBindings( self->iInputLanguage );
            }
        }
    return KErrNone;
    }

/**
 * Handles input language change.
 */
TInt CNumericKeyHandler::HandleInputLanguageChanged( TInt aNewValue )
	{    	
	SetInputLanguage( aNewValue );
	LoadInputLanguageKeyBindings( aNewValue );
    return KErrNone;
	}
    
/**
 * Set qwerty mode.
 */
void CNumericKeyHandler::SetQwertyMode( TInt aValue )
	{
	iQwertyMode = aValue;
	}
    
/**
 * Set input language.
 */
void CNumericKeyHandler::SetInputLanguage( TInt aValue )
    {
    iInputLanguage = aValue;
    }

/**
 * Check alpha numeric mode.
 */
TBool CNumericKeyHandler::AllowAlphaNumericMode() const
    {
    return ( EasyDialingEnabled() || VoIPSupported() );
    }

/**
 * Check if voip supported.
 */
TBool CNumericKeyHandler::VoIPSupported() const
    {
    TBool voipSupported( EFalse );
    CSPSettings* serviceProviderSettings( NULL );

    TRAP_IGNORE( serviceProviderSettings = CSPSettings::NewL() );   

    if ( serviceProviderSettings )
        {
        voipSupported = serviceProviderSettings->IsFeatureSupported( 
                ESupportInternetCallFeature );
        
        delete serviceProviderSettings;
        }

    return voipSupported;
    }

/**
 * Check if easy dialing enabled.
 */
TBool CNumericKeyHandler::EasyDialingEnabled() const
    {
    TBool easyDialingEnabled( EFalse );
    if ( FeatureManager::FeatureSupported( 
            KFeatureIdProductIncludesHomeScreenEasyDialing ) )
        {
        CRepository* cenrep( NULL );
        TInt easyDialingSetting;

        TRAP_IGNORE( cenrep = CRepository::NewL( KCRUidEasyDialSettings ) );

        if ( cenrep )
            {
            TInt err = cenrep->Get( KEasyDialing, easyDialingSetting );
            if ( !err && easyDialingSetting )
                {
                easyDialingEnabled = ETrue;
                }

            delete cenrep;        
            }
        }

    return easyDialingEnabled;
    }

void CNumericKeyHandler::HandleNotifyGeneric(TUint32 aKey)
    {
    if( aKey == KAknFepInputTxtLang )
        {
        TInt newValue = iInputLanguage;
        iInputLanguageRepository->Get( KAknFepInputTxtLang, newValue );
        HandleInputLanguageChanged( newValue );
        }
    }
    
void CNumericKeyHandler::HandleNotifyError
        (TUint32 /*aKey*/, TInt /*aError*/, CCenRepNotifyHandler* /*aHandler*/)
    {
    }

} // namespace AiWsPlugin