diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/AknAppUi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/AknAppUi.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,2418 @@ +/* +* Copyright (c) 2002 - 2008 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: App UI +* +*/ + +#include +#include "aknappui.h" +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif +#include +#include "aknconsts.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include // KAknQwertyInputModeActive (and others) +#include // KAknFepHashKeySelection +#include // KSettingsAutolockStatus +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "aknshut.h" +#include "aknenv.h" +#include +#include "aknanimdllstd.h" + +#include +#include +#include +#include +#include +#include + +#include +#include "AknDebug.h" +#include + +#include // for Transition effect enumerations +#include +#include + +#include +#include +#include + +#include "transitionmanager.h" +#include +#include + +#include +#include + +#ifdef RD_SCALABLE_UI_V2 +#include +#include +#endif + +#include +#include + +#include + +// UIDS for dialler view +const TUid KPhoneAppUid = { 0x100058B3 }; +const TUid KAknDiallerViewUid = {0x10282D81}; +const TUid KDiallerVievCommand = {0x1}; +const TUid KVoiceUiUID = { 0x101F8543 }; +_LIT( KVoiceDialApplication, "z:\\sys\\bin\\vuivoicerecognition.exe" ); //SIVC + +#include "akncompaif.h" // touch compatibility mode + +const TUid KActiveIdle2Uid = {0x102750F0}; +const TUid KActiveIdleView = {0x1}; + +#ifndef APPLICATIONORIENTATION_H +const TUid KCRUidDefaultAppOrientation = {0x200159ED}; +#endif + +//const TInt KAknAppUiViewsGranularity = 1; + +NONSHARABLE_CLASS(CAknAppUiExtension) + : public CBase, + public MCenRepNotifyHandlerCallback, + public MCoeViewActivationObserver + { +public: + static CAknAppUiExtension* NewL(); + ~CAknAppUiExtension(); + + // From MCenRepNotifyHandlerCallback + void HandleNotifyInt(TUint32 aId, TInt aNewValue); + + // from MCoeViewActivationObserver + void HandleViewActivation(const TVwsViewId& aNewlyActivatedViewId,const TVwsViewId& aViewIdToBeDeactivated); + +private: + CAknAppUiExtension(); + void ConstructL(); + +public: + MAknAliasKeyCodeResolver* iAknAliasKeyCodeResolver; + + // Handle to Central Repository. + CRepository* iCenRep; + + // For CenRep value change notifications. + CCenRepNotifyHandler* iCenRepNotifyHandler; + + // PubSub property for qwerty mode status. + RProperty iQwertyModeStatusProperty; + + // more app UI flags + enum TAknExtFlags + { + EHashKeyDown, // Indicates whether hash key is down. + EHashKeyMarking, // Caches the value of CenRep key KAknFepHashKeySelection. + ESimulatingEvent, + EAppIsHiddenInBackground, + EFocusLost + }; + TBitFlags iFlags; + + TInt iDisabledScanCode; + + TUid iLastActivatedViewId; + }; + + +CAknAppUiExtension* CAknAppUiExtension::NewL() + { + CAknAppUiExtension* self = new (ELeave) CAknAppUiExtension(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +CAknAppUiExtension::CAknAppUiExtension(): + iDisabledScanCode( -1 ) + { + } + +void CAknAppUiExtension::ConstructL() + { + // Start listening a CenRep key indicating whether hash key selection is active. + TRAPD(err, iCenRep = CRepository::NewL(KCRUidAknFep)); + if (err == KErrNone) + { + iCenRepNotifyHandler = CCenRepNotifyHandler::NewL(*this, + *iCenRep, + CCenRepNotifyHandler::EIntKey, + KAknFepHashKeySelection); + + iCenRepNotifyHandler->StartListeningL(); + TBool hashKeyMarking; + if (iCenRep->Get(KAknFepHashKeySelection, hashKeyMarking) == KErrNone) + iFlags.Assign(EHashKeyMarking, hashKeyMarking); + } + + // Attach to qwerty mode status property. Hash key marking is disabled when qwerty + // mode is active. Attach success also even if the value doesn't exist. + User::LeaveIfError(iQwertyModeStatusProperty.Attach(KCRUidAvkon, KAknQwertyInputModeActive)); + } + +CAknAppUiExtension::~CAknAppUiExtension() + { + // Stop listening CenRep. + if (iCenRepNotifyHandler) + { + iCenRepNotifyHandler->StopListening(); + } + delete iCenRepNotifyHandler; + delete iCenRep; + + // Close PubSub handle. + iQwertyModeStatusProperty.Close(); + } + +// ----------------------------------------------------------------------------- +// CAknAppUiExtension::HandleNotifyInt +// ----------------------------------------------------------------------------- +// +void CAknAppUiExtension::HandleNotifyInt(TUint32 aId, TInt aNewValue) + { + if (aId == KAknFepHashKeySelection) + { + iFlags.Assign(EHashKeyMarking, aNewValue); + } + } + +void CAknAppUiExtension::HandleViewActivation(const TVwsViewId& aNewlyActivatedViewId,const TVwsViewId& aViewIdToBeDeactivated) + { + CEikonEnv& eikEnv = *CEikonEnv::Static(); + TUid thisAppUid = eikEnv.EikAppUi()->Application()->AppDllUid(); + // if changing from another app to a new view in this app, clear the redraw stores + if (aViewIdToBeDeactivated.iAppUid != thisAppUid && + ( (iLastActivatedViewId != TUid::Null() && + aNewlyActivatedViewId.iViewUid != iLastActivatedViewId) || + eikEnv.ScreenDevice()->CurrentScreenMode() != CAknSgcClient::ScreenMode().ModeNumber())) + eikEnv.WsSession().ClearAllRedrawStores(); + if (aNewlyActivatedViewId.iAppUid == thisAppUid) + iLastActivatedViewId = aNewlyActivatedViewId.iViewUid; + } + + +enum TAknAppUiBaseFlags + { + EEmbedded, + EFaded, + EContainerWasForeground, + EContainerWasPartialForeground, + EFullScreen, + EPartialForeground, + ELayoutAwareApp, // Deprecated + EOrientationSpecified, + EOrientationLandscape, + EOrientationAutomatic, + EMSKEnabled, + EForegroundOrPartialForeground, + EAppClosing, + ETouchCompatible, + ESingleClickCompatible + }; + + +// CLASS DECLARATION + +/** + * A class to launch the dialler or SIVC from non used send key press + */ + +NONSHARABLE_CLASS ( CAknDiallerLauncher ) : public CCoeControl + { +public: + static CAknDiallerLauncher* NewL(CAknCompaIf*& aCompaIf); + ~CAknDiallerLauncher(); + void SetFlags( const TInt aFlags ); +private: // From CCoeControl + TKeyResponse OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType); + +private: + CAknDiallerLauncher(CAknCompaIf*& aCompaIf); + void ConstructL(); + void StartKeyTimerL(); + void StopKeyTimer(); + void LaunchDiallerL(); + void LaunchVoiceCommandL(); + static TInt ReportLongPressL( TAny* aThis ); + +private: + CPeriodic* iKeyTimer; + CAknCompaIf*& iCompaIf; // touch compatibility mode + TInt iKeyFlags; + }; + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CAknDiallerLauncher* CAknDiallerLauncher::NewL(CAknCompaIf*& aCompaIf) + { + CAknDiallerLauncher* self = new ( ELeave ) CAknDiallerLauncher(aCompaIf); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::CAknDiallerLauncher +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +CAknDiallerLauncher::CAknDiallerLauncher(CAknCompaIf*& aCompaIf): + iCompaIf(aCompaIf) + { + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::ConstructL +// Symbian 2nd phase constructor. +// ----------------------------------------------------------------------------- +// +void CAknDiallerLauncher::ConstructL() + { + iKeyFlags = 0; + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CAknDiallerLauncher::~CAknDiallerLauncher() + { + delete iKeyTimer; + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::SetFlags +// ----------------------------------------------------------------------------- +// +void CAknDiallerLauncher::SetFlags( const TInt aFlags ) + { + iKeyFlags = aFlags; + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::OfferKeyEventL +// Returns always EKeyWasNotConsumed +// ----------------------------------------------------------------------------- +// +TKeyResponse CAknDiallerLauncher::OfferKeyEventL( + const TKeyEvent &aKeyEvent, TEventCode aType ) + { + + if ( aKeyEvent.iScanCode != EStdKeyYes ) + { + return EKeyWasNotConsumed; + } + + if ( iKeyFlags & CAknAppUiBase::EDisableSendKeyLong && + iKeyFlags & CAknAppUiBase::EDisableSendKeyShort ) + { + return EKeyWasNotConsumed; + } + + // Check if autolock is on (if there is a an active call ongoing + // and sendkey is pressed, keyevent ends up here and must be dismissed + // to avoid opening dialler) + CRepository* repository = CRepository::NewL(KCRUidSecuritySettings); + + TInt lockStatus(0); + TInt lockStatusErr = repository->Get(KSettingsAutolockStatus, lockStatus); + + delete repository; + repository = NULL; + + // If lock is on, nothing should be done so we can just return. + // Also return if status could't be fetched (just in case). + if ( lockStatus == 1 || lockStatusErr != KErrNone ) + { + return EKeyWasNotConsumed; + } + + TInt curVal( 0 ); + TInt err = RProperty::Get( KPSUidStartup, KPSStartupUiPhase, curVal ); + if ( curVal != EStartupUiPhaseAllDone ) + { + return EKeyWasNotConsumed; + } + + // if it's alerting & Ringing status, ignore the send key event + TInt callVal( 0 ); + TInt errCall = RProperty::Get( KPSUidCtsyCallInformation, KCTsyCallState, callVal ); + if ( err == KErrNone && ( callVal == EPSCTsyCallStateDialling || EPSCTsyCallStateRinging == callVal ) ) + { + return EKeyWasNotConsumed; + } + + // if it's emerency calls status, ignore the send key event + TInt emergVal( 0 ); + TInt errEmerg = RProperty::Get( KPSUidCtsyEmergencyCallInfo, KCTSYEmergencyCallInfo, emergVal ); + if ( errEmerg == KErrNone && emergVal == 1 ) + { + return EKeyWasNotConsumed; + } + + if ( aType == EEventKeyDown ) + { + StartKeyTimerL(); + } + + if ( aType == EEventKeyUp && + iKeyTimer && iKeyTimer->IsActive() ) + { + StopKeyTimer(); + if ( iKeyFlags & CAknAppUiBase::EDisableSendKeyShort ) + { + return EKeyWasNotConsumed; + } + + TBool launch = AknLayoutUtils::PenEnabled(); + // In touch compatibility mode current layout (QVGA) doesn't have + // pen enabled. But dialler can be launched as it executes in + // "native" layout where pen is enabled. + launch = launch || ( iCompaIf && iCompaIf->IsForeground() ); + if ( launch ) + { + LaunchDiallerL(); + } + } + return EKeyWasNotConsumed; + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::StartKeyTimerL +// Starts the timer for the long press. Timer is constructed when used for the +// first time +// ----------------------------------------------------------------------------- +// +void CAknDiallerLauncher::StartKeyTimerL() + { + if ( !iKeyTimer ) + { + iKeyTimer = CPeriodic::NewL( CActive::EPriorityStandard ); + } + else if ( iKeyTimer->IsActive() ) + { + iKeyTimer->Cancel(); + } + iKeyTimer->Start( KAknKeyboardRepeatInitialDelay, + KAknKeyboardRepeatInitialDelay, + TCallBack ( ReportLongPressL, this ) ); + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::StopKeyTimer +// ----------------------------------------------------------------------------- +// +void CAknDiallerLauncher::StopKeyTimer() + { + if ( iKeyTimer && iKeyTimer->IsActive() ) + { + iKeyTimer->Cancel(); + } + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::ReportLongPressL +// ----------------------------------------------------------------------------- +// +TInt CAknDiallerLauncher::ReportLongPressL( TAny* aThis ) + { + CAknDiallerLauncher* self = + reinterpret_cast ( aThis ); + self->StopKeyTimer(); + if ( iAvkonAppUi->IsForeground() ) + { + self->LaunchVoiceCommandL(); + } + return 1; // CPeriodic ignores return value + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::LaunchDiallerL +// ----------------------------------------------------------------------------- +// +void CAknDiallerLauncher::LaunchDiallerL() + { + TVwsViewId diallerView( KPhoneAppUid, KAknDiallerViewUid ); + iAvkonAppUi->CreateActivateViewEventL( diallerView, + KDiallerVievCommand, KNullDesC8() ); + } + +// ----------------------------------------------------------------------------- +// CAknDiallerLauncher::LaunchVoiceCommandL +// ----------------------------------------------------------------------------- +// +void CAknDiallerLauncher::LaunchVoiceCommandL() + { + if ( iKeyFlags & CAknAppUiBase::EDisableSendKeyLong ) + { + return; + } + + // Touch compatibility mode + if (iCompaIf) + { + // Voice command launches itself in QHD layout on top of compa-mode + // application. The screen gets messed up. Compa-mode application is + // using wserv offset support to switch screen right (center the QVGA + // application window). When it shows behind another non-offsetting + // application, the shith is lost and screen is messed up. + // A workaroundfor for this is to switch idle screen to foreground + // before voice commander is launched. + TVwsViewId idleView(KActiveIdle2Uid, KActiveIdleView); + if (iCompaIf->IsForeground()) + { + iAvkonAppUi->CreateActivateViewEventL(idleView, KNullUid, + KNullDesC8()); + } + } + + TApaTaskList apaTaskList( iCoeEnv->WsSession() ); + TApaTask apaTask = apaTaskList.FindApp( KVoiceUiUID ); + + if ( apaTask.Exists() ) + { + apaTask.BringToForeground(); + } + else + { + RApaLsSession apa; + User::LeaveIfError( apa.Connect() ); + CleanupClosePushL( apa ); + CApaCommandLine* cmdLine = CApaCommandLine::NewLC(); + cmdLine->SetExecutableNameL( KVoiceDialApplication ); + cmdLine->SetCommandL( EApaCommandRunWithoutViews ); + User::LeaveIfError( apa.StartApp( *cmdLine ) ); + CleanupStack::PopAndDestroy( 2 ); // cmdLine, apa + } + + } + +class CAknAppUiBaseExtension : public CBase + { +public: + CAknAppUiBaseExtension(); + TRect iApplicationRect; // Application rect stored inside appui so that we dont need to call wserv methods when someone asks for application rect. + TInt iDefaultRotation; + TAknUiZoom iLocalUiZoom; + TInt iScreenMode; + TInt iMSKEnabled; //CenRep value cached here + CTouchFeedbackAdaptation* iFeedbackAdaptation; + + CAknDiallerLauncher* iDiallerLauncher; + CAknCompaIf* iCompaIf; // touch compatibility mode + CAknPointerEventModifier* iPointerEventModifier; + }; + +CAknAppUiBaseExtension::CAknAppUiBaseExtension() + : iLocalUiZoom(EAknUiZoomAutomatic), iScreenMode(KAknScreenModeUnset) + { + } + +EXPORT_C CAknAppUiBase::~CAknAppUiBase() + { + if (iAppUiBaseExtension) + { + MTouchFeedback::DestroyInstance(); + iAppUiBaseExtension->iFeedbackAdaptation = NULL; + RemoveFromStack( iAppUiBaseExtension->iDiallerLauncher ); + delete iAppUiBaseExtension->iDiallerLauncher; + iAppUiBaseExtension->iDiallerLauncher = NULL; + delete iAppUiBaseExtension->iCompaIf; + delete iAppUiBaseExtension->iPointerEventModifier; + } + delete iAppUiBaseExtension; + iAppUiBaseExtension = NULL; + delete iEventMonitor; + delete iKeySounds; + } + +EXPORT_C CAknAppUiBase::CAknAppUiBase() : CEikAppUi() + { + SetFullScreenApp(ETrue); + } + +EXPORT_C void CAknAppUiBase::HandleForegroundEventL(TBool aForeground) + { + CAknSgcClient::SetKeyboardRepeatRate(EAknApplicationDefaulRepeatRate); + iAknFlags.Clear(EContainerWasForeground); // no longer need this flag + iAknFlags.Clear(EContainerWasPartialForeground); // no longer need this flag + iAknFlags.Clear(EPartialForeground); // now either foreground or background + + CEikAppUi::HandleForegroundEventL( aForeground ); + + CAknSgcClient::HandleChangeL(); + } + +EXPORT_C void CAknAppUiBase::ConstructL() + { + // Should Implement + BaseConstructL(0); + } + +void CAknAppUiBase::SetAppUiAndLeaveIfErrorL( TInt aError ) + { + if ( aError < KErrNone ) + { + iContainerAppUi = static_cast(iEikonEnv->SetAppUi( this )); + User::Leave( aError ); + } + } + +EXPORT_C void CAknAppUiBase::BaseConstructL( TInt aAppUiFlags ) + { +#ifdef AVKON_RDEBUG_INFO + RDebug::Print(_L("CAknAppUiBase::BaseConstructL()")); +#endif + + // note that the extension may have already been created by some other API call + // for example SetLocalUiZoomL + + if(!iAppUiBaseExtension) + { + // To avoid having to test on this extension everywhere, we need to Leave if the alloc fails. + TRAPD( err,iAppUiBaseExtension = new(ELeave) CAknAppUiBaseExtension); + // ensure that CCoeEnv takes ownership before leaving + SetAppUiAndLeaveIfErrorL( err ); + } + + // enable receipt of changes to screen state + iEikonEnv->RootWin().EnableScreenChangeEvents(); + + iAppUiBaseExtension->iApplicationRect = iCoeEnv->ScreenDevice()->SizeInPixels(); + + if (!iAppUiBaseExtension->iFeedbackAdaptation ) + { + iAppUiBaseExtension->iFeedbackAdaptation = CTouchFeedbackAdaptation::NewL(); + } + +#ifdef AVKON_RDEBUG_INFO + RDebug::Print(_L("CAknAppUiBase::BaseConstructL() application rect set")); +#endif + CRepository* repository = NULL; + TRAPD(ret, repository = CRepository::NewL(KCRUidAvkon)); + if (ret == KErrNone) + { + ret = repository->Get(KAknDefaultAppOrientation, iAppUiBaseExtension->iDefaultRotation); + ret = repository->Get(KAknMiddleSoftkeyEnabled, iAppUiBaseExtension->iMSKEnabled); + } +#ifdef AVKON_RDEBUG_INFO + RDebug::Print(_L("CAknAppUiBase::BaseConstructL() orientation ok")); +#endif + + TInt orientationFlags = aAppUiFlags; + CRepository* defaultOrientationCr = NULL; + TRAPD( err, defaultOrientationCr = CRepository::NewL( KCRUidDefaultAppOrientation ) ); + if (err == KErrNone) + { + // Repository found, check if the orientation has been set + TInt value = 0; + err = defaultOrientationCr->Get( RProcess().SecureId().iId, value ); + if( err == KErrNone && value ) + { + // Application key found and orientation has been set + orientationFlags = value; + } + delete defaultOrientationCr; + defaultOrientationCr = NULL; + } + iAknFlags.Assign(EOrientationSpecified, orientationFlags&EAppOrientationSpecifiedFlag); + iAknFlags.Assign(EOrientationLandscape, orientationFlags&EAppOrientationLandscapeFlag); + iAknFlags.Assign(EOrientationAutomatic, orientationFlags&EAppOrientationAutomaticFlag); + iAknFlags.Assign(EMSKEnabled, aAppUiFlags&EAknEnableMSKflag); + iAknFlags.Assign( ESingleClickCompatible, + aAppUiFlags & EAknSingleClickCompatibleFlag ); + + if ( aAppUiFlags & EAknTouchCompatibleFlag ) + { + iAknFlags.Set( ETouchCompatible ); + } + else + { + RProcess process; + TFileName fileName = process.FileName(); + _LIT(KRomDrive,"z:"); + + if ( fileName.FindF( KRomDrive ) == 0 ) + { + iAknFlags.Set( ETouchCompatible ); + } + } + +#ifdef AVKON_RDEBUG_INFO + RDebug::Print(_L("Entering CEikAppUi::BaseConstructL()")); +#endif + + // Touch compatibility mode. Change application screen mode before + // a call to CEikAppUi::BaseConstructL(). This way application + // starts in a correct screen mode and there are no + // HandleResourceChangeL() calls due to screen mode change. + TInt compaScreenMode = KErrNotFound; + TBool screenModeChanged = EFalse; + // Check if the application doesn't need compa-mode or compa-mode is + // disabled + if (CAknCompaIf::IsNeeded(aAppUiFlags, repository)) + { + // Compa-mode may be needed. Instantiate ecom plugin to check + // further. Change application screen mode if compa-mode is needed. + TBool isConsoleApp; + TRAPD(compaModeErr, + iAppUiBaseExtension->iCompaIf = CAknCompaIf::NewL(); + // SetCompaAppScreenModeL() returns KErrNotFound if compa-mode + // is not needed + compaScreenMode = + iAppUiBaseExtension->iCompaIf->SetCompaAppScreenModeL( + screenModeChanged, isConsoleApp, aAppUiFlags, *this, + *iCoeEnv, *repository)); + delete repository; repository = NULL; + // Ensure that CCoeEnv takes ownership before leaving + SetAppUiAndLeaveIfErrorL(compaModeErr); + if (compaScreenMode == KErrNotFound) + { + delete iAppUiBaseExtension->iCompaIf; + iAppUiBaseExtension->iCompaIf = NULL; + } + else + { + if (isConsoleApp) + { + // If console application is run in compa-mode, allow status + // bar to be created. Status bar is required to be able to set + // application screen mode. + aAppUiFlags &= ~CEikAppUi::ENoScreenFurniture; + } + } + } + delete repository; repository = NULL; + + CEikAppUi::BaseConstructL( aAppUiFlags ); + + if ( !iAppUiBaseExtension->iDiallerLauncher ) + { + iAppUiBaseExtension->iDiallerLauncher = + CAknDiallerLauncher::NewL(iAppUiBaseExtension->iCompaIf); + AddToStackL( iAppUiBaseExtension->iDiallerLauncher, -100, + ECoeStackFlagRefusesFocus ); + } + + iAvkonEnv->TransitionEvent(KAknTransitionEventFlags); //look at fullsceen flags + + +#ifdef AVKON_RDEBUG_INFO + RDebug::Print(_L("CEikAppUi::BaseConstructL() out ")); +#endif + + if (iEikonEnv->StartedAsServerApp()) + EnableExternalViewSwitches(EFalse); + + // Note: iKeySounds is left uninitialized // + + iEventMonitor = CAknWsEventMonitor::NewL(); + + if(!(aAppUiFlags & EAknExplicitStartupEffectCompletion)) //does start idle time + iAvkonEnv->TransitionEvent(AknTransEffect::EAppStartComplete);//normal case + + // Touch compatibility mode + if (iAppUiBaseExtension->iCompaIf) + { + // Create compatibility mode keyboard and make it visible in the case + // of a normal application. Compa-keyboard is also created for servers + // that display global/notes notifications but left invisible. + iAppUiBaseExtension->iCompaIf->CreateKbL(compaScreenMode, + screenModeChanged); + // Tactile feedback needs to be informed about layout change, because + // otherwise it won't get correct information about pen support + // (Tactile Feedback was instantiated earlier in this function, when + // pen was still enabled). + iAppUiBaseExtension->iFeedbackAdaptation->LayoutChanged(); + } + else + { + // Pointer event modifier is not needed while in compatibility mode so + // its creation is delayed until here. + // + // Leaves during construction are ignored since pointer event modifier + // isn't mandatory i.e. the device should be usable also without it. + TRAP_IGNORE( iAppUiBaseExtension->iPointerEventModifier = CAknPointerEventModifier::NewL() ) + } + } + +EXPORT_C TBool CAknAppUiBase::IsFaded() const + { + return CAknSgcClient::IsSystemFaded(); + } + +/** + * Returns the object which allows events to be spyed upon in addition to + * normal event handling + */ +EXPORT_C CAknWsEventMonitor* CAknAppUiBase::EventMonitor() const + { + return iEventMonitor; + } + +EXPORT_C CAknKeySoundSystem* CAknAppUiBase::KeySounds() const + { + return iKeySounds; + } + +EXPORT_C void CAknAppUiBase::ReplaceKeySoundsL( TInt aUid ) + { + delete iKeySounds; + iKeySounds = NULL; + iKeySounds = CAknKeySoundSystem::NewL(aUid); + } + +EXPORT_C TTypeUid::Ptr CAknAppUiBase::MopSupplyObject(TTypeUid aId) + { + // We give tactile feedback client as object provider for + // MCoeControlStateObserver interface, so that feedback + // areas of dimmed and invisible controls can be + // disabled automatically. + if ( aId.iUid == MCoeControlStateObserver::ETypeId && + iAppUiBaseExtension && + iAppUiBaseExtension->iFeedbackAdaptation ) + { + return aId.MakePtr( + static_cast( + iAppUiBaseExtension->iFeedbackAdaptation ) ); + } + else + { + // Touch compatibility mode. AknCapServer needs access to interface. + if (aId.iUid == CAknCompaIf::ETypeId) + { + CAknCompaIf* compaIf = iAppUiBaseExtension ? + iAppUiBaseExtension->iCompaIf : NULL; + return aId.MakePtr(compaIf); + } + return CEikAppUi::MopSupplyObject(aId); + } + } + +EXPORT_C void CAknAppUiBase::SetFullScreenApp(TBool aIsFullScreen) + { + iAknFlags.Assign(EFullScreen, aIsFullScreen); + } + +EXPORT_C TBool CAknAppUiBase::IsFullScreenApp() const + { + return iAknFlags[EFullScreen]; + } + +TBool CAknAppUiBase::IsMSKEnabledApp() const + { + return iAknFlags[EMSKEnabled]; + } + +EXPORT_C TBool CAknAppUiBase::IsLayoutAwareApp() const + { + return ETrue; + } + +EXPORT_C void CAknAppUiBase::SetLayoutAwareApp(TBool /*aLayoutAwareApp*/) + { + } + +EXPORT_C TBool CAknAppUiBase::IsForeground() const + { + return static_cast(iEikonEnv->EikAppUi()) == this && ThreadIsForeground(); + } + +EXPORT_C TBool CAknAppUiBase::IsPartialForeground() const + { + return iAknFlags[EPartialForeground]; + } + +EXPORT_C void CAknAppUiBase::HandleApplicationSpecificEventL(TInt aType,const TWsEvent& aEvent) +/** Handles an application-specific event. + + +@param aType The type of the event that occurred. This should be a unique +identifier constant. +@param aEvent The window server event that occurred. +@see CCoeAppUi */ + { + if (aType == KEikPartialForeground) + { + iAknFlags.Set(EPartialForeground); + iAknFlags.Clear(EContainerWasPartialForeground); // no longer need this flag + HandleResourceChangeL(KEikPartialForeground); + CAknSgcClient::HandleChangeL(); + } + else if (aType == KEikClearPartialForegroundState) + { + iAknFlags.Clear(EPartialForeground); + CAknSgcClient::HandleChangeL(); + } + else if (aType == KEikDynamicLayoutVariantSwitch || + aType == KEikInputLanguageChange || + aType == KAknHardwareLayoutSwitch || + aType == KAknLocalZoomLayoutSwitch || + aType == KAknILDInstallationLayoutSwitch) + { + UpdateSettingCacheAndForwardEventL( aType ); + // Update application rect + iAppUiBaseExtension->iApplicationRect = iCoeEnv->ScreenDevice()->SizeInPixels(); + } + else if ( aType == KEikHasBecomeCurrentAppUiWhileEmbeddedAppUiDeletes ) + { + TBool thisWasForeground = IsForeground(); + TRAPD(ignore, CAknEnv::Static()->LoadAknLayoutL()); + TRAP(ignore,HandleResourceChangeL(KEikMessageEmbedLevelChange)); + HandleStackedControlsResourceChange(KEikMessageEmbedLevelChange); + TRAP(ignore, SimulateWsEventL( + EventForForegroundState( + IsPartialForeground() || iAknFlags[EContainerWasPartialForeground], + thisWasForeground || (iAknFlags[EContainerWasForeground] ) + ) ) ); + } + else if ( aType == KEikNotifyPreCreateEmbeddedL ) + { + iAknFlags.Assign(EContainerWasForeground, ThreadIsForeground()); + iAknFlags.Assign(EContainerWasPartialForeground, + static_cast(iContainerAppUi)->IsPartialForeground() ); + static_cast(iContainerAppUi)->SimulateWsEventL(EEventFocusLost); // TSOI-56GJ6M + } + else if ( aType == KEikNotifyPostCreateEmbeddedL ) + { + TWsEvent focusEvent; + focusEvent.SetType(EventForForegroundState(iAknFlags[EContainerWasPartialForeground], iAknFlags[EContainerWasForeground])); + iEikonEnv->WsSession().SendEventToWindowGroup(iEikonEnv->RootWin().Identifier(), focusEvent); + } + else if ( aType == KEikPostCoeAppUiConstructL ) + { + ApplyLayoutChangeL(EFalse); + iAppUiBaseExtension->iApplicationRect = iCoeEnv->ScreenDevice()->SizeInPixels(); + } + else if ( aType == KAknShutOrHideApp ) + { + CAknEnv::ShutOrHideAppL(); + } + else + { + CEikAppUi::HandleApplicationSpecificEventL( aType, aEvent); + } + } + +EXPORT_C void CAknAppUiBase::HandleScreenDeviceChangedL() + { + // By-pass CEikAppUi's call (It would do too-early status pane reload) + CCoeAppUi::HandleScreenDeviceChangedL(); + UpdateSettingCacheAndForwardEventL(KAknHardwareLayoutSwitch); + iAppUiBaseExtension->iApplicationRect = iCoeEnv->ScreenDevice()->SizeInPixels(); + } + +EXPORT_C void CAknAppUiBase::HandleResourceChangeL(TInt aType) + { + if (aType == KEikDynamicLayoutVariantSwitch) + { + // update application rect. + iAppUiBaseExtension->iApplicationRect = iCoeEnv->ScreenDevice()->SizeInPixels(); + + // Tactile feedback needs to be informed about new layout, + // because pen support may have been changed. + if ( iAppUiBaseExtension->iFeedbackAdaptation ) + { + iAppUiBaseExtension->iFeedbackAdaptation->LayoutChanged(); + } + } + CEikAppUi::HandleResourceChangeL( aType ); + } + +EXPORT_C TRect CAknAppUiBase::ApplicationRect() const + { + TRect rect(iAppUiBaseExtension->iApplicationRect); + return rect; + } + +EXPORT_C void CAknAppUiBase::PrepareToExit() +/** Performs pre-exit processing to ensure the application will exit cleanly. */ + { + iAknFlags.Assign(EAppClosing, ETrue); + CEikAppUi::PrepareToExit(); + + // If this app is dying while in partial foreground, get app beneath to activate its view +/* if (IsPartialForeground()) + { + TInt nextWgId = KErrNotFound; + TRAP_IGNORE(nextWgId = FindAppWgIdBelowMeL()); + if (nextWgId != KErrNotFound) + { + TWsEvent event; + event.SetType(EEventUser); + *(TApaSystemEvent*)(event.EventData())=EApaSystemEventBroughtToForeground; + event.SetTimeNow(); + iEikonEnv->WsSession().SendEventToWindowGroup(nextWgId, event); + } + } +*/ } + +TBool CAknAppUiBase::IsAppClosing() const + { + return iAknFlags[EAppClosing]; + } + + +void CAknAppUiBase::UpdateSettingCacheAndForwardEventL( TInt aEventId ) + { + CAknEnv* env = iAvkonEnv; + CAknSettingCache& cache = env->SettingCache(); + TBool changed = cache.Update( aEventId ); + + if ( changed || AlwaysForwardEvent(aEventId) ) + { + TBool reportEvent = ETrue; + TInt originalEventId = aEventId; + if (originalEventId == KAknHardwareLayoutSwitch || + originalEventId == KAknLocalZoomLayoutSwitch || + originalEventId == KAknILDInstallationLayoutSwitch) + { + aEventId = KEikDynamicLayoutVariantSwitch; // all layout changes are sent to apps as KEikDynamicLayoutVariantSwitch + } + + if (aEventId == KEikDynamicLayoutVariantSwitch) + { + RelinquishPriorityToForegroundAppLC(); + if(originalEventId == KAknILDInstallationLayoutSwitch) + { + // always reload the current layout configuration, as we are expecting + // a change in the actual layout pack instances that will be loaded, + // and always report the event to all app uis + env->ReloadAknLayoutL(); + } + else + { + reportEvent = env->LoadAknLayoutL(); + } + } + + if (reportEvent) + { + // report resource changed to all app uis + for ( CEikAppUi* appUi = iEikonEnv->EikAppUi(); + appUi; + appUi = appUi->ContainerAppUi() ) + { + appUi->ReportResourceChangedToAppL( aEventId ); + } + } + + + // Unblank screen if screen blanking is done at KEikDynamicLayoutVariantSwitch at aknglobaui side. + if (IsForeground() && aEventId == KEikDynamicLayoutVariantSwitch) + { + RAknUiServer* client = CAknSgcClient::AknSrv(); + if (client && client->Handle()) + client->UnblankScreen(); + } + + if (aEventId == KEikDynamicLayoutVariantSwitch) + { + CleanupStack::PopAndDestroy(); // RelinquishPriorityToForegroundAppLC + } + } + } + +void CAknAppUiBase::RelinquishPriorityToForegroundAppLC() + { + CAknSgcClient::RelinquishPriorityToForegroundAppLC(iAknFlags[EForegroundOrPartialForeground] || IsForeground()); + } + +TBool CAknAppUiBase::AlwaysForwardEvent( TInt aEventId ) + { + switch(aEventId) + { + case KAknILDInstallationLayoutSwitch: + // - If an ILD layout has been installed, then all application layouts + // must be updated + return ETrue; + case KAknHardwareLayoutSwitch: + case KEikDynamicLayoutVariantSwitch: + // - For non-full screen apps, they need to follow the foreground + // application's orientation. + return !IsFullScreenApp(); + default: + return EFalse; + }; + } + +EXPORT_C CAknAppUiBase::TAppUiOrientation CAknAppUiBase::Orientation() const + { + CAknAppUiBase::TAppUiOrientation orientation = EAppUiOrientationUnspecified; + if (!iAknFlags[EOrientationSpecified]) + { + if (iAppUiBaseExtension->iDefaultRotation >= 0 && iAppUiBaseExtension->iDefaultRotation <= 2) + { + // Product specific orientation configuration for applications that do not + // set any orientation flag is done here. + // + // Return value: orientation + // EAppUiOrientationUnspecified: Follows device orientation. + // EAppUiOrientationPortrait: Applications runs in portrait mode + // EAppUiOrientationLandscape: Applications runs in landscape mode + orientation = (CAknAppUiBase::TAppUiOrientation)iAppUiBaseExtension->iDefaultRotation; + } + } + else if (iAknFlags[EOrientationAutomatic]) + orientation = EAppUiOrientationUnspecified; + else if (iAknFlags[EOrientationLandscape]) + orientation = EAppUiOrientationLandscape; + else + orientation = EAppUiOrientationPortrait; + + return orientation; + } + +EXPORT_C TBool CAknAppUiBase::OrientationCanBeChanged() const + { + // parameters affecting ability to set mode + TBool isFullScreen = IsFullScreenApp(); + TInt fixedMode = iAppUiBaseExtension ? iAppUiBaseExtension->iScreenMode : KAknScreenModeUnset; + + // Get portrait and landscape screen modes + CAknLayoutConfig::TScreenMode portraitMode = + CAknSgcClient::CalculateScreenMode(isFullScreen, ETrue, EFalse, fixedMode); + + CAknLayoutConfig::TScreenMode landscapeMode = + CAknSgcClient::CalculateScreenMode(isFullScreen, ETrue, ETrue, fixedMode); + + // are the portrait and landscape modes different? + return portraitMode.ModeNumber() != landscapeMode.ModeNumber(); + } + +EXPORT_C void CAknAppUiBase::SetOrientationL(TAppUiOrientation aOrientation) + { + if (aOrientation != Orientation()) + { + iAknFlags.Assign(EOrientationSpecified, aOrientation != EAppUiOrientationUnspecified); + iAknFlags.Assign(EOrientationLandscape, aOrientation == EAppUiOrientationLandscape); + iAknFlags.Assign(EOrientationAutomatic, aOrientation == EAppUiOrientationAutomatic); + ApplyLayoutChangeL(ETrue); + if(IsForeground()) + { + RAknUiServer* client = CAknSgcClient::AknSrv(); + if (client && client->Handle()) + { + client->UnblankScreen(); + } + } + } + } + +TBool CAknAppUiBase::ThreadIsForeground() const + { + RWsSession& ws = iEikonEnv->WsSession(); + TThreadId focusThreadId; + ws.GetWindowGroupClientThreadId(ws.GetFocusWindowGroup(), focusThreadId); + RThread myThread; + return myThread.Id() == focusThreadId; + } + + +// deprecated +TInt CAknAppUiBase::FindAppWgIdBelowMeL() + { +/* RWsSession& wsSession=iEikonEnv->WsSession(); + TInt count=wsSession.NumWindowGroups(0); + CArrayFixFlat* wgIds = new (ELeave) CArrayFixFlat(count); + CleanupStack::PushL(wgIds); + User::LeaveIfError(wsSession.WindowGroupList(0,wgIds)); + count = wgIds->Count(); + TInt nextWgId = KErrNotFound; + TThreadId nextThreadId; + TInt myWgId = iEikonEnv->RootWin().Identifier(); + TThreadId myThreadId; + wsSession.GetWindowGroupClientThreadId(myWgId, myThreadId); + for (TInt ii=count-1; ii>=0; ii--) + { + TInt wgId = wgIds->At(ii); + if (wgId == myWgId) + break; + // only record window groups if they belong to a different thread - prevents sending an event back to this thread + wsSession.GetWindowGroupClientThreadId(wgId, nextThreadId); + if (nextThreadId != myThreadId) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(wsSession, wgId); + if (wgName->IsAppReady()) + nextWgId = wgId; + CleanupStack::PopAndDestroy(); + } + } + CleanupStack::PopAndDestroy(wgIds); +*/ + return KErrNotSupported; //nextWgId; + } + +/** + * Simulate a foreground event by passing it straight into HandleWsEventL. + * Used for telling embedding app to lose the foreground, part of fix for TSOI-56GJ6M + * + * @param aForeground if EFalse, send to background, otherwise send to foreground + * + */ +void CAknAppUiBase::SimulateWsEventL(TInt aEventId) + { + TWsEvent event; + event.SetType(aEventId); + event.SetHandle(0); + HandleWsEventL(event, NULL); + } + +TInt CAknAppUiBase::EventForForegroundState(TBool aPartialFg, TBool aForeground) + { + if (aPartialFg) + return KEikPartialForeground; + else if (aForeground) + return EEventFocusGained; + else + return EEventFocusLost; + } + +EXPORT_C void CAknAppUiBase::Exit() +/** Closes the app UI. */ + { + // Exit() leaves. The app UI is deleted during exit, and processing must stop immediately. + if (iContainerAppUi) + { + delete this; + User::Leave(KLeaveWithoutAlert); // stop this event here! + } + else + { + // default reason for exiting is EEikCmdExit. If server exists, + // clients must be told. Other exit reasons should be notified + // before they call Exit(). + CEikAppServer* server = iEikonEnv->AppServer(); + if (server) + server->NotifyServerExit(EEikCmdExit); + + CBaActiveScheduler::Exit(); + } + } + +EXPORT_C void CAknAppUiBase::SetFadedL(TBool aFaded) + { + const TInt message=(aFaded? KEikMessageFadeAllWindows : KEikMessageUnfadeWindows); + TRAPD(ignore, ReportResourceChangedToAppL(message)); + if (IsForeground()) + CAknSgcClient::SetSystemFaded(aFaded); + TRAP(ignore, ReportResourceChangedToAppL(KEikMessageWindowsFadeChange)); + } + +EXPORT_C TAknUiZoom CAknAppUiBase::LocalUiZoom() const + { + CAknEnv* env = iAvkonEnv; + TInt value = EAknUiZoomAutomatic; + CAknSettingCache& cache = env->SettingCache(); + // get the value from the top plugin + TInt err = cache.PluginValue(KAknLocalZoomLayoutSwitch, value); + // if there are no plugins, just use the real local value + if(err != KErrNone && iAppUiBaseExtension) + { + value = iAppUiBaseExtension->iLocalUiZoom; + } + return static_cast(value); + } + +EXPORT_C void CAknAppUiBase::SetLocalUiZoom(TAknUiZoom aZoom) + { + TInt err = KErrNone; + if(!iAppUiBaseExtension) + { + // we must have been called by application before their call to BaseConstructL + // therefore we need to create the extension. + // if it leaves, BaseConstructL will try to construct the extension again, + // and the side effect will be that normal zoom level is incorrectly used. + TRAP(err, iAppUiBaseExtension = new(ELeave) CAknAppUiBaseExtension()); + } + if(!err) + { + iAppUiBaseExtension->iLocalUiZoom = aZoom; + } + } + +EXPORT_C void CAknAppUiBase::ApplyLayoutChangeL(TBool aReportChange) + { + CAknSgcClient::HandleChangeL(); + if (iAvkonEnv->LoadAknLayoutL()) + { + if(aReportChange) + { + ReportResourceChangedToAppL(KEikDynamicLayoutVariantSwitch); + } + } + } + +TBool CAknAppUiBase::HasFullOrPartialForeground() const + { + return iAknFlags[EForegroundOrPartialForeground]; + } + +void CAknAppUiBase::SetScreenModeL(TInt aModeNumber) + { + TInt err = KErrNone; + if(!iAppUiBaseExtension) + { + // we must have been called by application before their call to BaseConstructL + // therefore we need to create the extension. + // if it leaves, BaseConstructL will try to construct the extension again, + // and the side effect will be that the natural screen mode is used. + TRAP(err, iAppUiBaseExtension = new(ELeave) CAknAppUiBaseExtension()); + } + if(!err) + { + iAppUiBaseExtension->iScreenMode = aModeNumber; + // use iEventMonitor's existence to check if this is + // fully constructed yet. If so, change the layout. + if (iEventMonitor) + ApplyLayoutChangeL(ETrue); + } + } + +TInt CAknAppUiBase::ScreenMode() const + { + return iAppUiBaseExtension ? + iAppUiBaseExtension->iScreenMode : + KAknScreenModeUnset; + } + +EXPORT_C void CAknAppUiBase::SetKeyEventFlags( const TInt aFlags ) + { + iAppUiBaseExtension->iDiallerLauncher->SetFlags( aFlags ); + } + +EXPORT_C CAknPointerEventModifier* CAknAppUiBase::PointerEventModifier() + { + if ( iAppUiBaseExtension ) + { + return iAppUiBaseExtension->iPointerEventModifier; + } + + return NULL; + } + +EXPORT_C TBool CAknAppUiBase::IsTouchCompatible() const + { + return iAknFlags.IsSet( ETouchCompatible ); + } + + +EXPORT_C TBool CAknAppUiBase::IsSingleClickCompatible() const + { + return iAknFlags.IsSet( ESingleClickCompatible ) + && AknLayoutUtils::PenEnabled(); + } + + +//=============== +// class CAknAppUi +//=============== + +void CAknAppUi::DecideWsClientBufferSizesL() + { + RWsSession &ws = iEikonEnv->WsSession(); + ws.SetMaxBufferSizeL(KAknDefaultWsBufferSize); + } + +EXPORT_C void CAknAppUi::ConstructL() + { + // Should implement to catch those who do not implement MyApp::ConstructL() + // Or ASSERT? + CAknAppUi::BaseConstructL(); + } + +EXPORT_C void CAknAppUi::BaseConstructL(TInt aAppUiFlags) + { + // Initialize AppUi-specific skin parameters and skin support + // Trap errors and leave after BaseConstructL() if any. + TInt skinParamErr = KErrNone; + if( (aAppUiFlags&EAknEnableSkinFlag) != 0 ) + { + TRAP( skinParamErr, AknsUtils::SetAvkonSkinEnabledL( ETrue ) ); + } + TRAPD( skinErr, AknsUtils::InitSkinSupportL() ); + TRAPD( allocErr, DecideWsClientBufferSizesL() ); + // No leaving function calls before BaseConstructL(). + CAknAppUiBase::BaseConstructL(aAppUiFlags); + + User::LeaveIfError( allocErr ); + User::LeaveIfError( skinParamErr ); + User::LeaveIfError( skinErr ); + + // Ensures that embedded applications get the right parameter + if( (aAppUiFlags&EAknEnableSkinFlag) != 0 ) + { + AknsUtils::SetAvkonSkinEnabledL( ETrue ); + } + + if( (aAppUiFlags & EAknDisableHighlightAnimationFlag) != 0 ) + { + AknsUtils::SetAvkonHighlightAnimationEnabledL( EFalse ); + } + +#ifdef RD_SCALABLE_UI_V2 + if ( CAknTouchPane* tp = TouchPane() ) + { + tp->SetObserver( this ); + if ( EventMonitor() ) + { + EventMonitor()->AddObserverL( tp ); + EventMonitor()->Enable(); + } + } +#endif + + if (StatusPane()) + StatusPane()->SetObserver(this); + + TInt uid = KErrNotFound; + if (Application()) + { + // Only assign uid if an application is present + // This is true for all Avkon apps, but not for Java MIDP + uid = Application()->AppDllUid().iUid; + } + + ReplaceKeySoundsL(uid); + + AddViewDeactivationObserverL(this); + + iAppShutter = CAknAppShutter::NewL(*iEikonEnv, this, &iAppShutter); + if(!iExtension) + { + iExtension = CAknAppUiExtension::NewL(); + } + + AddViewActivationObserverL(iExtension); + + if (ExitHidesInBackground()) + { + TBool isBackground = !IsForeground(); + HideApplicationFromFSW(isBackground); + iExtension->iFlags.Assign(CAknAppUiExtension::EAppIsHiddenInBackground, isBackground); + } + } + +EXPORT_C void CAknAppUi::HandleTouchPaneSizeChange() + { + } + +EXPORT_C void CAknAppUi::HandleStatusPaneSizeChange() + { + } + +EXPORT_C CAknAppUi::~CAknAppUi() + { + if (iExtension) + { + RemoveViewActivationObserver(iExtension); + } + + delete iExtension; + // embedded apps need to let the shutter live till long enough to handle the app exit leave + if (iAppShutter) + iAppShutter->DeleteSelfWhenReady(); + + RemoveViewDeactivationObserver(this); + + // Delete skin parameter singleton (if one exists) + delete CCoeEnv::Static( KAknsAppUiParametersTls ); + } + +EXPORT_C CEikStatusPane* CAknAppUi::StatusPane() + { + return iEikonEnv->AppUiFactory()->StatusPane(); + } + +EXPORT_C void CAknAppUi::ProcessCommandL(TInt aCommand) + { + MEikAppUiFactory* appUiFactory = (iEikonEnv)->AppUiFactory(); + ASSERT(appUiFactory); + if (appUiFactory->Popup()) + ClosePopup(); + else if (appUiFactory->MenuBar()) + StopDisplayingMenuBar(); + // Test for 'options' command + if (aCommand == EAknSoftkeyOptions) + { + appUiFactory->MenuBar()->TryDisplayMenuBarL(); + return; + } + if (aCommand == EAknSoftkeyContextOptions) + { + appUiFactory->MenuBar()->TryDisplayContextMenuBarL(); + return; + } + if (aCommand == EAknCmdExit) + { + StopDisplayingPopupToolbar(); + CAknEnv::RunAppShutter(); + return; + } + if ( aCommand != EEikCmdCanceled ) + HandleCommandL(aCommand); + } + +EXPORT_C CEikButtonGroupContainer* CAknAppUi::Cba() + { + return iEikonEnv->AppUiFactory()->ToolBar(); + } + +EXPORT_C void CAknAppUi::HandleErrorL(TInt aError, HBufC** aErrorDesc, TBool aShowNote ) + { + // Lets Create TextResolver instance for error resolving + CTextResolver* textresolver = CTextResolver::NewLC(); + + TUint flags( 0 ); + TInt id( 0 ); + + // Resolve the Error +// TBuf errorstring = + if (!aErrorDesc) + User::Leave(KErrNotSupported); + + // This is nasty, we alloc memory for error handling -> KErrNoMemory might fail + // Anyway, it will be handled in eikon env, so we can allow this fail + *aErrorDesc = + textresolver->ResolveErrorString( aError, id, flags, CTextResolver::ECtxNoCtx ).AllocL(); + + if ( flags & EErrorResOOMFlag || (*aErrorDesc)->Length() == 0 ) + { + User::Leave(KErrNoMemory); // let EikEnv preallocated error handling take care of showing note. + } + + if ( !(flags & ETextResolverBlankErrorFlag) ) + { + // There is no need create Note before we know that error will displayed i.e. is not blank + CAknGlobalNote* note = 0; + + if (aShowNote) + { + note = CAknGlobalNote::NewL(); + CleanupStack::PushL( note ); + } + + TText contextChar = ((*aErrorDesc)->Des())[0]; // this is a colon + + // remove context character and line end character + (*aErrorDesc)->Des().Delete( 0, 2 ); + + // Solving the application name asing AppArc.lib + RApaLsSession apparcSession; + User::LeaveIfError( apparcSession.Connect() ); + CleanupClosePushL( apparcSession ); + TApaAppInfo appInfo; + TInt err = apparcSession.GetAppInfo( appInfo, this->Application()->AppDllUid() ); + + // +2 for colon and line end + HBufC* captionBuffer = + HBufC::NewLC( KApaMaxAppCaption + KAknBidiExtraSpacePerLine + 2 ); + +// CleanupStack::PushL( captionBuffer ); + TPtr caption = captionBuffer->Des(); + + if ( err == KErrNone ) + { + caption = appInfo.iCaption; + } + + // Lets remove trailing spaces + caption.TrimRight(); + + // Insert the application name into the beginning of the error string + if ( caption.Length() != 0 ) + { + HBufC* result = HBufC::NewLC((*aErrorDesc)->Des().MaxLength() + 5 * (KAknBidiExtraSpacePerLine + 1)); // wasting more memory ... + + CArrayFix* lineWidthArray = + new( ELeave ) CArrayFixFlat( 4 ); + + CleanupStack::PushL( lineWidthArray ); + + TRect mainPane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EPopupParent, mainPane ); + + const TInt lineVariety( 2 ); // Equals 5 lines, which adapt. layer uses here. + + AknLayoutUtils::TAknCbaLocation cbaLocation( AknLayoutUtils::CbaLocation() ); + TInt softkeyVariety( lineVariety ); // Defaults to bottom cbalocation value + + // Modify the softkeyVariety in case cba is at either side + if ( cbaLocation == AknLayoutUtils::EAknCbaLocationRight ) + { + softkeyVariety += 3; + } + else if ( cbaLocation == AknLayoutUtils::EAknCbaLocationLeft ) + { + softkeyVariety += 6; + } + + TAknLayoutRect popupLayoutRect; + popupLayoutRect.LayoutRect( mainPane, + AknLayoutScalable_Avkon::popup_note_window( softkeyVariety ) ); + + TRect popupRect = popupLayoutRect.Rect(); + + TAknLayoutText firstLineLayoutText; + firstLineLayoutText.LayoutText( popupRect, + AknLayoutScalable_Avkon::popup_note_window_t1( lineVariety ) ); + + const CFont* font = firstLineLayoutText.Font(); + + TAknLayoutText textRect; + TAknTextComponentLayout textLayout; + + for ( TInt i = 1; i <= 4; ++i ) + { + textLayout = AknLayoutScalable_Avkon::popup_note_window_t( i, lineVariety ); + textRect.LayoutText( popupRect, textLayout.LayoutLine() ); + lineWidthArray->AppendL( textRect.TextRect().Width() ); + } + + TPtr ptr = result->Des(); + + // convert error string to visual order + AknBidiTextUtils::ConvertToVisualAndWrapToStringL( + (*aErrorDesc)->Des(), + *lineWidthArray, + *font, + ptr, + ETrue ); // insert truncation char if doesn't fit + + CleanupStack::PopAndDestroy(); // lineWidthArray + + // in visual order now + CleanupStack::Pop(); // result + delete *aErrorDesc; + *aErrorDesc = result; // ownership to caller + + // add the caption + + TInt captionLength = firstLineLayoutText.TextRect().Width() - + font->CharWidthInPixels( contextChar ); + + // Here we truncate the application name to fit in the first row of the note + AknBidiTextUtils::ConvertToVisualAndClipL( + caption, + *font, + captionLength, + captionLength ); + + TBuf<1> buf; + buf.Append( contextChar ); + + // in mirrored layout, ':' is the leftmost character + if ( AknLayoutUtils::LayoutMirrored() ) + { + caption.Insert( 0, buf ); + } + // in non-mirrored layout, ':' is the rightmost character + else + { + caption.Append( buf ); + } + + caption.Append( '\n' ); + + // Insert caption row, in visual order. + // The line end after it exists in string already. + (*aErrorDesc)->Des().Insert( 0, caption ); + } + if ( note ) + { + if ( aError == KErrDiskFull ) + { + note->SetSoftkeys(R_AVKON_SOFTKEYS_OK_EMPTY__OK); + } + + // If there was a caption, we processed the text ourselves + if ( caption.Length() ) + { + note->SetTextProcessing( EFalse ); + } + + + // secondary display needs to be informed about the error note + SAknIntegerUpdate s = + { + EAknTrappedError, + aError + }; + TPckg pck(s); + CAknSDData* sdData = CAknSDData::NewL( KAknSecondaryDisplayCategory, EAknErrorNote, pck ); + note->SetSecondaryDisplayData( sdData ); + + // Finally, let's show the global note + note->ShowNoteL( EAknGlobalErrorNote, (*aErrorDesc)->Des() ); + + CleanupStack::PopAndDestroy( 3 ); // note, apparcSession, captionBuffer + } + else + { + CleanupStack::PopAndDestroy( 2 ); // apparcSession, captionBuffer + } + } + else + { + (*aErrorDesc)->Des().Zero(); // make text lenght 0 if error is blank + } + + CleanupStack::PopAndDestroy(); // error resolver + } + +EXPORT_C TErrorHandlerResponse CAknAppUi::HandleError(TInt aError, + const SExtendedError& /*aExtErr*/, + TDes& /*aErrorText*/, + TDes& /*aContextText*/ ) + { + HBufC* buf = 0; + TRAPD(err, HandleErrorL(aError, &buf)); + delete buf; + + if ( !err ) + { + return(ENoDisplay); // Error handled proper way. + } + + return(EErrorNotHandled); // Error not handled, let EIKENV handle the error. + } + +EXPORT_C void CAknAppUi::HandleSystemEventL(const TWsEvent& aEvent) + { + switch (*(TApaSystemEvent*)(aEvent.EventData())) + { + case EApaSystemEventShutdown: + if((static_cast(iCoeEnv)->IsSystem())) + { + break; + } + // else fall-through + case EApaSystemEventSecureShutdown: + StopDisplayingPopupToolbar(); + CAknEnv::RunAppShutter(); + break; + default: + CEikAppUi::HandleSystemEventL(aEvent); + break; + } + } + +EXPORT_C void CAknAppUi::Reserved_MtsmPosition() + { + } + +EXPORT_C void CAknAppUi::Reserved_MtsmObject() + { + } + +EXPORT_C void CAknAppUi::HandleForegroundEventL(TBool aForeground) + { +#ifdef RD_SCALABLE_UI_V2 + TVwsViewId viewId; + TInt err = GetActiveViewId( viewId ); + if ( ( err == KErrNotFound || viewId.iAppUid == viewId.iViewUid ) && CurrentFixedToolbar() ) + { + CurrentFixedToolbar()->HandleResourceChange( KAknToolbarSetVisible ); + } +#endif + if ( KeySounds() && IsForeground() ) // IsForeground() used because aForeground may already be out of date + { + KeySounds()->BringToForeground(); + } + +#ifdef RD_SCALABLE_UI_V2 + if ( TouchPane() && aForeground ) + { + TouchPane()->RefreshL(); + } + + if ( !aForeground ) + { + HandleStackedControlsResourceChange(KAknMessageFocusLost); + } +#endif + + if (aForeground && iExtension->iFlags[CAknAppUiExtension::EAppIsHiddenInBackground]) + { + HideApplicationFromFSW(EFalse); + iExtension->iFlags.Clear(CAknAppUiExtension::EAppIsHiddenInBackground); + } + + CEikAppUi::HandleForegroundEventL(aForeground); + } + +EXPORT_C void CAknAppUi::HandleViewDeactivation(const TVwsViewId& /*aViewIdToBeDeactivated*/, const TVwsViewId &/*aNewlyActivatedViewId*/) + { + iAvkonEnv->CloseAllIntermediateStates(); + } + +EXPORT_C void CAknAppUi::PrepareToExit() + { + if( IsForeground() && Document() ) + { + //only if focused, otherwise next app HandleForeground may never come. + iAvkonEnv->TransitionEvent(AknTransEffect::EApplicationExit, Application()->AppDllUid()); + } + else + { + iAvkonEnv->TransitionEvent(AknTransEffect::EApplicationExit); + } + + if ( StatusPane() ) + { + StatusPane()->PrepareForAppExit(); + } + CAknAppUiBase::PrepareToExit(); + } + +EXPORT_C void CAknAppUi::RunAppShutter() + { + if (!iAppShutter) + { + // the app shutter may not exist if a previous shut attempt failed, + // eg because KLeaveExit was trapped, or the app did not call Exit() in response to EEikCmdExit. + TRAP_IGNORE(iAppShutter = CAknAppShutter::NewL(*iEikonEnv, this, &iAppShutter)); + } + + if (iAppShutter) + iAppShutter->Start(); + } + +EXPORT_C TBool CAknAppUi::IsAppShutterRunning() const + { + return iAppShutter ? iAppShutter->IsActive() : EFalse; + } + +TBool CAknAppUi::IsAppHiddenInBackground() const + { + return iExtension && iExtension->iFlags[CAknAppUiExtension::EAppIsHiddenInBackground]; + } + +EXPORT_C void CAknAppUi::HandleWsEventL(const TWsEvent& aEvent,CCoeControl* aDestination) + { + iAvkonEnv->TransitionEvent(KAknTransitionEventAvkon); + if (EventMonitor() && EventMonitor()->IsEnabled()) + { + EventMonitor()->HandleWsEventL(aEvent,aDestination); + } + + TInt eventType = aEvent.Type(); + // block these two here to avoid any extra execution beneath avkon level + if (eventType == KAknFullOrPartialForegroundLost || + eventType == KAknFullOrPartialForegroundGained ) + { + iAknFlags.Assign(EForegroundOrPartialForeground, eventType == KAknFullOrPartialForegroundGained); + return; + } + + // This method call practically adds a shift modifier to hash key + joystick events. + // This is because of marking in lists and editors when edit there is no edit key in device. + if (SimulateHashKeyMarkingEvent(aEvent)) + { + return; + } + + // ---- To turn on key code conversion by default ----- + // must be done before passing to base classes + if (eventType == EEventKey && iExtension && !iExtension->iFlags[CAknAppUiExtension::ESimulatingEvent]) + { + TKeyEvent key = *(aEvent.Key()); + TUint code = key.iCode; + + GetAliasKeyCodeL(key.iCode, key, EEventKey); + + // if key conversion returned something different from original + if (code != key.iCode) + { + iExtension->iFlags.Set(CAknAppUiExtension::ESimulatingEvent); + TRAPD(err, iCoeEnv->SimulateKeyEventL(key, EEventKey)); + iExtension->iFlags.Clear(CAknAppUiExtension::ESimulatingEvent); + User::LeaveIfError(err); + + return; // block handling of this event. + } + } + +#ifdef RD_SCALABLE_UI_V2 + if ( eventType == EEventPointer ) + { + if ( PointerEventModifier() ) + { + PointerEventModifier()->HandlePointerEvent( *aEvent.Pointer(), aDestination ); + } + + if ( aEvent.Pointer()->iType == TPointerEvent::EButton1Down ) + { + if ( iExtension ) + { + iExtension->iFlags.Clear(CAknAppUiExtension::EFocusLost); + } + + CAknToolbar* toolbar = CurrentPopupToolbar(); + + // Non-focusing toolbar takes focus away from its embedded editor + // or other component control if a control other than toolbar is + // tapped. Focus is not removed if the tapped control is CBA, + // touchpane or a non-fullscreen dialog. + if ( toolbar && toolbar->IsShown() && toolbar != aDestination ) + { + if ( TouchPane() != aDestination ) + { + CEikDialog* dlg = aDestination->MopGetObject( dlg ); + + TBool focusLost = ETrue; + + if ( dlg ) + { + TInt flags = dlg->DialogFlags(); + + if ( flags != EEikDialogFlagFillScreen && + flags != EEikDialogFlagFillAppClientRect ) + { + focusLost = EFalse; + } + } + else + { + CEikCba* cba = aDestination->MopGetObject( cba ); + + if ( cba == aDestination ) + { + focusLost = EFalse; + } + } + + if ( focusLost ) + { + toolbar->PrepareForFocusLossL(); + } + } + } + } + else if ( iExtension && iExtension->iFlags[CAknAppUiExtension::EFocusLost] ) + { + aDestination->IgnoreEventsUntilNextPointerUp(); + iExtension->iFlags.Clear(CAknAppUiExtension::EFocusLost); + } + } +#endif // RD_SCALABLE_UI_V2 + + + + + if ( eventType == EEventPointer && iExtension && + aEvent.Pointer()->iType == TPointerEvent::EButton1Up ) + { + iExtension->iDisabledScanCode = -1; + } + + + + + if (!iDumpNextControl) + { + CAknAppUiBase::HandleWsEventL(aEvent, aDestination); + } + switch (eventType) + { + case EEventFocusGained: + UpdateKeyBlockMode(); + GfxTransEffect::Enable(); + iAvkonEnv->TransitionEvent(AknTransEffect::EApplicationActivate); + if (iExtension) + { +#ifdef RD_SCALABLE_UI_V2 + iExtension->iFlags.Clear(CAknAppUiExtension::EFocusLost); +#endif + } + break; + case EEventFocusLost: + if (iExtension) + { + iExtension->iFlags.Clear(CAknAppUiExtension::EHashKeyDown); + +#ifdef RD_SCALABLE_UI_V2 + iExtension->iFlags.Set(CAknAppUiExtension::EFocusLost); +#endif + } + + break; + case EEventKey: + { + TKeyEvent* key = aEvent.Key(); + + TInt disabledScanCode = iExtension ? iExtension->iDisabledScanCode : -1; + + if ( key->iRepeats && KeySounds() && key->iScanCode != disabledScanCode ) + { + KeySounds()->PlaySound(*key); + } + + +#ifdef _DEBUG + if (key->iCode == CTRL('i') && (key->iModifiers&EAllStdModifiers)==EAllStdModifiers) + { + iDumpNextControl = ETrue; + } +#endif + // Launch help application. + if (key->iCode == EKeyHelp && !key->iRepeats) + { + // Some applications do not handle EAknCmdHelp, but define their own command. + // So first check if help context is available. + CArrayFix *helpContext = iEikonEnv->EikAppUi()->AppHelpContextL(); + if ( helpContext && helpContext->Count()) + { + // Help context is available, launch help directly from here. + // Still need to check if stuff from ProcessCommandL's beginning is needed + // (eg. close menu & pop-up's) or are they handled by focus lost/gain. + HlpLauncher::LaunchHelpApplicationL(iEikonEnv->WsSession(), helpContext); + return; + } + else + { + // Help context was not available. App either does not support help + // or creates the context manually. Send EAknCmdHelp to the application. + // This will work if the application handles EAknCmdHelp instead of defining + // its own command for help. If the app didn't return help context and does + // not handle EAknCmdHelp, we can not launch help. + ProcessCommandL(EAknCmdHelp); + return; + } + } + break; + } +#ifdef _DEBUG + case EEventPointer: + { + if (iDumpNextControl) + { + iDumpNextControl = EFalse; + RDebug debug; + DumpControl(aDestination, 0, debug); + } + break; + } +#endif + case KUidValueAknsSkinChangeEvent: + { + RelinquishPriorityToForegroundAppLC(); + + HandleResourceChangeL(KAknsMessageSkinChange); + HandleStackedControlsResourceChange(KAknsMessageSkinChange); + + // Pass the event to container AppUi in case we are embedded + CEikAppUi* container = ContainerAppUi(); + if (container) + { + container->HandleResourceChangeL(KAknsMessageSkinChange); + container->HandleStackedControlsResourceChange(KAknsMessageSkinChange); + } + + CleanupStack::PopAndDestroy(); // RelinquishPriorityToForegroundAppLC + break; + } + + case KAknUidValueEndKeyCloseEvent: + { + CEikonEnv* env = iEikonEnv; + if ( env && !env->IsSystem() ) // System apps are not closed + { + // Close or hide the application. + TWsEvent event; + event.SetType( KAknShutOrHideApp ); + event.SetTimeNow(); + CAknAppUiBase::HandleWsEventL( event, aDestination ); + } + break; + } + + + default: + break; + } + + } + +// This method watches for hash key presses, and adds a shift modifier to all arrow key +// and ok key events, if hash key is simultaneously down. This is done because of making the +// edit key optional in the device. Therefore, hash key with joystick (or single hash press, +// see eiklbx.cpp) can be used for marking in lists and editors. +TBool CAknAppUi::SimulateHashKeyMarkingEvent(const TWsEvent& aEvent) + { + TInt eventType = aEvent.Type(); + + if (iExtension && + iExtension->iFlags[CAknAppUiExtension::EHashKeyMarking] && + (eventType == EEventKeyDown || eventType == EEventKeyUp || eventType == EEventKey) && + !iExtension->iFlags[CAknAppUiExtension::ESimulatingEvent]) + { + TKeyEvent key = *(aEvent.Key()); + + if (eventType == EEventKeyDown && key.iScanCode == EStdKeyHash) + { + iExtension->iFlags.Set(CAknAppUiExtension::EHashKeyDown); + } + else if (eventType == EEventKeyUp && key.iScanCode == EStdKeyHash) + { + iExtension->iFlags.Clear(CAknAppUiExtension::EHashKeyDown); + } + else if (iExtension->iFlags[CAknAppUiExtension::EHashKeyDown] && eventType == EEventKey && + (key.iCode == EKeyUpArrow || + key.iCode == EKeyDownArrow || + key.iCode == EKeyLeftArrow || + key.iCode == EKeyRightArrow || + key.iCode == EKeyOK)) + { + // Fetch the qwerty mode status from pubsub. No error handling needed. + TBool qwertyMode = EFalse; + iExtension->iQwertyModeStatusProperty.Get(qwertyMode); + + if (!qwertyMode) + { + TKeyEvent keyEvent; + keyEvent.iCode = key.iCode; + keyEvent.iScanCode = key.iScanCode; + keyEvent.iRepeats = key.iRepeats; + keyEvent.iModifiers = key.iModifiers|EModifierShift; // Adds shift. + + iExtension->iFlags.Set(CAknAppUiExtension::ESimulatingEvent); + TRAPD(err, iCoeEnv->SimulateKeyEventL(keyEvent, EEventKey)); + iExtension->iFlags.Clear(CAknAppUiExtension::ESimulatingEvent); + User::LeaveIfError(err); + + return ETrue; // block handling of this event. + } + } + } + + return EFalse; + } + +EXPORT_C void CAknAppUi::SetKeyBlockMode(TAknKeyBlockMode aMode) + { + iBlockMode = aMode; + UpdateKeyBlockMode(); + } + + +void CAknAppUi::UpdateKeyBlockMode() + { + CAknSgcClient::SetKeyBlockMode((TAknKeySoundOpcode)iBlockMode); + } + +#ifdef _DEBUG +const TInt KDumpIndentWidth = 2; + +class CPublicCCoeControl : public CCoeControl + { +public: + TInt CountComponentControls() const { return 0; } + CCoeControl* ComponentControl(TInt /*aIndex*/) const { return 0; } + }; + +void CAknAppUi::DumpControl(CCoeControl* aControl, TInt aLevel, RDebug& aDebug) + { + TInt indent = KDumpIndentWidth * aLevel; + aDebug.Print(_L("%*cAddress = (CCoeControl*)0x%08x"), indent, ' ', aControl); + + _LIT(KDumpIs, "is"); + _LIT(KDumpHas, "has"); + _LIT(KDumpNo, "no"); + _LIT(KDumpNot, "not"); + aDebug.Print(_L("%*c%S visible, %S dimmed, %S focused, %S border, %S focusable, %S window owning"), indent, ' ', + aControl->IsVisible() ? &KDumpIs : &KDumpNot, + aControl->IsDimmed() ? &KDumpIs : &KDumpNot, + aControl->IsFocused() ? &KDumpIs : &KDumpNot, + aControl->HasBorder() ? &KDumpHas : &KDumpNo, + aControl->IsNonFocusing() ? &KDumpNot : &KDumpIs, + aControl->OwnsWindow() ? &KDumpIs : &KDumpNot + ); + + TPoint pos = aControl->PositionRelativeToScreen(); + TRect rect = aControl->Rect(); + aDebug.Print(_L("%*cscreen pos = (%d,%d) top left = (%d,%d) bottom right = (%d,%d) size = (%d,%d)"), + indent, ' ', pos.iX, pos.iY, rect.iTl.iX, rect.iTl.iY, + rect.iBr.iX, rect.iBr.iY, rect.Width(), rect.Height()); + + CPublicCCoeControl* pub = reinterpret_cast(aControl); + TInt count = pub->CountComponentControls(); + aDebug.Print(_L("%*c%d sub control(s)"), indent, ' ', count); + for (TInt ii=0; iiComponentControl(ii), aLevel+1, aDebug); + } + } + +#endif + +EXPORT_C void CAknAppUi::HideApplicationFromFSW(TBool aHide) + { + RAknUiServer* client = CAknSgcClient::AknSrv(); + if ( client && client->Handle()) + { + client->HideApplicationFromFsw(aHide, Application()->AppDllUid().iUid); + } + else + { + // if CAknSgcClient connection to capserver client + // is not available, make a new connection + RAknUiServer cap; + cap.HideApplicationFromFsw(aHide, Application()->AppDllUid().iUid); + cap.Close(); + } + } + +EXPORT_C CAknTouchPane* CAknAppUi::TouchPane() + { +#ifdef RD_SCALABLE_UI_V2 + return static_cast(iEikonEnv->AppUiFactory())->TouchPane(); +#else + return NULL; +#endif + } + +EXPORT_C CAknToolbar* CAknAppUi::PopupToolbar() const + { + return static_cast(iEikonEnv->AppUiFactory())->PopupToolbar(); + } + +EXPORT_C CAknToolbar* CAknAppUi::CurrentPopupToolbar() const + { + return static_cast(iEikonEnv->AppUiFactory())->CurrentPopupToolbar(); + } + +EXPORT_C CAknToolbar* CAknAppUi::CurrentFixedToolbar() const + { + return static_cast(iEikonEnv->AppUiFactory())->CurrentFixedToolbar(); + } + + +EXPORT_C void CAknAppUi::StopDisplayingPopupToolbar() + { + if (CurrentPopupToolbar()) + { + CurrentPopupToolbar()->SetToolbarVisibility( EFalse ); + } + if (PopupToolbar()) + { + PopupToolbar()->SetToolbarVisibility( EFalse ); + } + } + +EXPORT_C void CAknAppUi::GetAliasKeyCodeL(TUint& aCode, const TKeyEvent& aKeyEvent,TEventCode aType) + { + if (iExtension && iExtension->iAknAliasKeyCodeResolver) + { + User::LeaveIfError(iExtension->iAknAliasKeyCodeResolver->GetAliasKeyCode(aCode,aKeyEvent,aType)); + return; + } + + aCode = aKeyEvent.iCode; + RAknUiServer* cap = CAknSgcClient::AknSrv(); + if (cap && cap->Handle()) + { + User::LeaveIfError(cap->GetAliasKeyCode(aCode, aKeyEvent, aType)); + } + } + +EXPORT_C void CAknAppUi::SetAliasKeyCodeResolverL(MAknAliasKeyCodeResolver* aResolver) + { + if(!iExtension) + { + iExtension = CAknAppUiExtension::NewL(); + } + iExtension->iAknAliasKeyCodeResolver = aResolver; + } + + + +EXPORT_C TInt32 CAknAppUi::CaptureKey(TUint aKeycode, TUint aModifierMask, TUint aModifier) + { + TInt err = KErrNone; + TInt32 handle = 0; + TRAP(err, CaptureKeyL(aKeycode, aModifierMask, aModifier, handle)); + + if (err != KErrNone) + { + return err; + } + + return handle; + } + + +EXPORT_C void CAknAppUi::CaptureKeyL(TUint aKeycode, TUint aModifierMask, TUint aModifier, TInt32& aHandle) + { + TBool qwertyOn = EFalse; + User::LeaveIfError(RProperty::Get(KCRUidAvkon, KAknQwertyInputModeActive, qwertyOn)); + + RWindowGroup& group = iCoeEnv->RootWin(); + + if (qwertyOn) + { + RArray numMaps; + CPtiEngine* pti = NULL; + + CAknSettingCache& settingsCache = CAknEnv::Static()->SettingCache(); + + pti = CPtiEngine::NewL(); + CleanupStack::PushL(pti); + + pti->GetNumericModeKeysForQwertyL(settingsCache.InputLanguage(), numMaps); + + TPtiKey starScanCode = (TPtiKey)0; + TInt i = 0; + for (; i < numMaps.Count(); i++) + { + if (numMaps[i].iChar == '*') + { + starScanCode = numMaps[i].iKey; + break; + } + } + + if (starScanCode) + { + CPtiCoreLanguage* lang = static_cast(pti->GetLanguage(ELangEnglish)); + if (lang) + { + CPtiQwertyKeyMappings* qmap = static_cast(lang->GetQwertyKeymappings()); + if (qmap) + { + TBuf<50> keyData; + qmap->GetDataForKey(starScanCode, keyData, numMaps[i].iCase); + if (keyData.Length()) + { + aKeycode = keyData[0]; + } + else + { + User::Leave(KErrNotFound); + } + } + } + } + + CleanupStack::PopAndDestroy(); // pti + numMaps.Close(); + } + + aHandle = group.CaptureKey( aKeycode, aModifierMask, aModifier ); + User::LeaveIfError(aHandle); + } + +EXPORT_C TBool CAknAppUi::ExitHidesInBackground() const + { + TBool hide = EFalse; + if (!iEikonEnv->StartedAsServerApp()) + TRAP_IGNORE(hide = ExitHidesInBackgroundL()); + return hide; + } + +TBool CAknAppUi::ExitHidesInBackgroundL() const + { + // Detect whether or not the application should attempt a fake exit. + // Configuration is through a cenrep keyspace listing the application UIDs which should fake exit. + CEikApplication* app = Application(); + if (!app) + return EFalse; + TInt uid = app->AppDllUid().iUid; + CRepository* repository = CRepository::NewLC(KCRUidLeaveAppsInMemory); + RArray keys; + repository->FindEqL(KLeaveAppsInMemoryAppListKeyRange, + KLeaveAppsInMemoryAppListKeyMask, + uid, + keys); + TBool hide = keys.Count() != 0; + keys.Close(); + CleanupStack::PopAndDestroy(repository); + return hide; + } + +EXPORT_C void CAknAppUi::HideInBackground() + { + /* + Call EApplicationExit effect start here since for the user hiding app in background + is still exiting an app. So this call changes the application switch effect to an application + exit effect. + */ + CEikApplication* app = Application(); + + const TInt focusWGroupId = iEikonEnv->WsSession().GetFocusWindowGroup(); + const TInt thisApplicationWgId = iEikonEnv->RootWin().Identifier(); + + if ( focusWGroupId == thisApplicationWgId ) + { + GfxTransEffect::BeginFullScreen( AknTransEffect::EApplicationExit, TRect(), + AknTransEffect::EParameterType, AknTransEffect::GfxTransParam( app->AppDllUid() ) ); + } + + // Hide the application in the background. + // This performs the push-to-background and hide-from-FSW operations necessary to make the application look as if it has exited. + HideApplicationFromFSW(ETrue); + iExtension->iFlags.Set(CAknAppUiExtension::EAppIsHiddenInBackground); + CAknSgcClient::MoveApp(iEikonEnv->RootWin().Identifier(), ESgcMoveAppToBackground); + } + + +EXPORT_C void CAknAppUi::DisableNextKeySound( TInt aScanCode ) + { + if ( iExtension ) + { + iExtension->iDisabledScanCode = aScanCode; + } + if ( KeySounds() ) + { + KeySounds()->DisableNextKeySound( aScanCode ); + } + } + +// End of File +