/*
* Copyright (c) 2005-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:
*
*/
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <uikon/eikdefconst.h>
#include <uikon/eikenvinterface.h>
#endif
#include <eikstart.h>
#include <AknDef.h>
#include <barsread.h>
#include <bautils.h>
#include <e32std.h>
#include <e32property.h>
#include <UikonInternalPSKeys.h> // KUikLayoutState, KPSUidUikon, KUikAppHiddenList
#include <AknFepInternalCRKeys.h> // KAknFepHashKeySelection, KAknFepEditTextSubmenu
#ifdef RD_INTELLIGENT_TEXT_INPUT
#include <AknFepInternalPSKeys.h> // KAknFepFnKeyState
#endif
#include "avkoninternalpskeys.h" // KAknIdleAppWindowGroupId
#include <AknCapServerDefs.h>
#include <activeidle2domainpskeys.h>
#include <eikpriv.rsg>
#include <coedef.h>
#include <eiksvdef.h>
#include <aknconsts.h>
#include <AknsConstants.h>
#include <apgwgnam.h>
#include "AknCapServerDefs.h"
#include "AknCapServerEntry.h"
#include "AknCapServer.h"
#include "AknFastswapWindowControl.h"
#include "AknMemoryCardDialogImpl.h"
#include "oommonitor.h"
#include "AknKeyFilter.h"
#include <AknWsEventObserver.h>
#include <PtiEngine.h>
#include <PtiKeyMappings.h>
#include <PtiDefs.h>
// For Gs to initiate OFN status
#include <settingsinternalcrkeys.h>
#include <aknenv.h>
#include <AknSettingCache.h>
#include <eikspane.h>
#include "aknstatuspanedatapublisher.h"
#include <syslangutil.h> // SysLangUtil::GetInstalledLanguages
#include <featmgr.h>
#include <centralrepository.h>
#include "aknmessagereaderlongpressdetector.h" // MAknMessageReaderLongPressDetector
#include <akncapserveralternatefsplugin.h>
#include <akncapserveralternatefspluginconst.hrh>
#ifdef RD_UI_TRANSITION_EFFECTS_LAYOUT_SWITCH
#include <gfxtranseffect/gfxtranseffect.h>
#include <akntranseffect.h> // for Transition effect enumerations
#endif
#ifdef SYMBIAN_BUILD_GCE
#include <alf/alfclientbase.h>
#endif
#ifdef RD_INTELLIGENT_TEXT_INPUT
#include <AvkonInternalCRKeys.h>
#include "akncapserverdiscreetpopuphandler.h"
const TUid KPtiEnginePSUid = {0x101F8610}; // Same as PtiEngine dll
enum TPtiEnginePSKeys
{
EKeyMapPropertyCount,
EKeyMapPropertyData,
EKeyMapPropertyCount2,
EKeyMapPropertyData2,
EKeyMapPropertyCount3,
EKeyMapPropertyData3
};
// Read capability: AlwaysPass.
_LIT_SECURITY_POLICY_PASS( KCapServerPtiEngineAlwaysPass );
_LIT_SECURITY_POLICY_S1( KCapServerPtiEngineWritePolicy, 0x10207218, ECapabilityWriteDeviceData);
#endif
// External keyboard modifier
const TUint KModifierExternalKeyboard = 0x00200000;
const TInt KWgPriorityCoverEverything = 10000;
const TInt KKeyEventICodeThreshold = 0x001f;
const TInt KMaxLanguageCodeLength = 6; // 5 digits + separator
const TInt KRemoveBlankDelay = 200000; // 0.2s
_LIT(KEikSrvUIResFileName, "z:\\resource\\eiksrvui.rsc");
_LIT_SECURITY_POLICY_PASS(KPassReadPolicy);
_LIT_SECURITY_POLICY_C1(KWriteDDPolicy, ECapabilityWriteDeviceData);
_LIT_SECURITY_POLICY_C1(KReadPolicy, ECapability_None);
_LIT( KSeparator, " " );
CAknCapServerApplication::CAknCapServerApplication()
{
}
void CAknCapServerApplication::NewAppServerL(CApaAppServer*& aAppServer)
{
CAknCapServer* server = new (ELeave) CAknCapServer();
CleanupStack::PushL(server);
server->CreateDynamicSoftNoteEventManagerL();
CleanupStack::Pop(server);
server->SetPriority(EActivePriorityIpcEventsHigh);
aAppServer=&*server;
iCapServer = server;
}
CApaDocument* CAknCapServerApplication::CreateDocumentL()
{
return new (ELeave) CAknCapAppServerDocument(*this);
}
CEikAppUi* CAknCapAppServerDocument::CreateAppUiL()
{
CAknCapServerApplication* app = static_cast<CAknCapServerApplication*>(iApp);
CAknCapServer* server = app->CapServer();
CAknCapAppServerAppUi* ret = new (ELeave) CAknCapAppServerAppUi( server );
return ret;
}
CAknCapAppServerAppUi::CAknCapAppServerAppUi( CAknCapServer* aCapServer ) : iCapServer( aCapServer )
{
iIdleActive = ETrue;
}
CAknCapAppServerAppUi::~CAknCapAppServerAppUi()
{
delete iAlternateFS;
delete iTelephonyIdleUidSubscriber;
delete iGlobalNotesAllowedSubscriber;
if (iKeyCaptureControl)
{
RemoveFromStack(iKeyCaptureControl); // ownership in stack
}
delete iFSControl;
if (iResourceFileOffset)
{
iCoeEnv->DeleteResourceFile(iResourceFileOffset);
}
delete iHiddenList;
delete iMMCUnlock;
delete iIdler;
iEikSrv.Close(); // this shouldn't be connected here anyway
delete iPtiEngine;
iAlfClient.Close();
}
_LIT(KProductSpecificHalFile, "z:\\system\\data\\ProductSpecificHalParams.txt");
void DoProductSpecificHalFunction()
{
RFs& fs = CCoeEnv::Static()->FsSession();
RFile file;
if (fs.Handle() && file.Open(fs,KProductSpecificHalFile, EFileRead)==KErrNone)
{
TBuf8<30> desc;
file.Read(desc);
TLex8 lex(desc);
TInt i[4];
TInt ii = 0;
for (;ii < 4; ii++)
{
if (lex.Val(i[ii]))
{
ii = KErrArgument;
break;
}
lex.SkipSpace();
}
if (ii != KErrArgument)
{
UserSvr::HalFunction(i[0], i[1], &i[2], &i[3]);
}
file.Close();
}
}
TInt StartOOM(TAny* aThis)
{
// By running idle priority active object twice, we allow idle priority objects
// scheduled after AppUi::ConstructL() run at least once.
CAknCapAppServerAppUi* me = (CAknCapAppServerAppUi*)aThis;
if (!me->iHasRunOnce)
{
DoProductSpecificHalFunction();
me->iHasRunOnce = ETrue;
me->iIdler->Start(TCallBack(StartOOM, aThis));
return KErrNone;
}
// free resources of idler
delete me->iIdler;
me->iIdler = 0;
// do the actual startup
TRAPD( err, CreateOOMWatcherThreadL());
// we panic here if something goes wrong as startup will fail anyway.
__ASSERT_ALWAYS(err==KErrNone, User::Invariant());
me->iEikSrv.AllowNotifierAppServersToLoad();
me->iEikSrv.Close(); // currently there is no use to keep this session alive.
#ifdef SYMBIAN_BUILD_GCE
TRAP(err, CAlfAsynchStartup::StartL());
#endif
return err;
}
void CAknCapAppServerAppUi::LoadAlternateFsPlugin()
{
// List all plugins
RImplInfoPtrArray implInfoArray;
TRAPD( error, REComSession::ListImplementationsL(
TUid::Uid( KAknCapServerAlternateFsPluginInterfaceUid ), implInfoArray ) );
if ( error == KErrNone && implInfoArray.Count() )
{
TUid uid = implInfoArray[0]->ImplementationUid();
TRAP_IGNORE( iAlternateFS = CAknCapAppServerAlternateFs::NewL( uid ) );
}
implInfoArray.ResetAndDestroy();
}
void CAknCapAppServerAppUi::ShowOrDismissAlternateFs()
{
if ( !iAlternateFS )
{
return;
}
if ( iAlternateFS->IsVisible() )
{
iAlternateFS->HandleLongAppKeyPress();
}
else
{
iAlternateFS->Show();
}
}
void CAknCapAppServerAppUi::ConstructL()
{
User::SetCritical(User::ESystemCritical);
InitiateOFNStatus();
iEikonEnv->SetSystem( ETrue );
// install default FEP if none set before
if (iEikonEnv->FepUid() == KNullUid)
{
iEikonEnv->InstallFepL(TUid::Uid(0x101FD65A));
}
// define and set the PS key listing installed languages
PublishInstalledLanguagesL();
TInt value = 1;
if ( FeatureManager::FeatureSupported( KFeatureIdEditKey ) )
{
// The edit key exists in the device. Hash-key selection disabled and
// edit text sub-menu removed from the options menu
value = 0;
}
CRepository* repository = CRepository::NewL(KCRUidAknFep);
// Return value of repository->Set() ignored.
repository->Set(KAknFepHashKeySelection, value);
repository->Set(KAknFepEditTextSubmenu, value);
delete repository;
repository = NULL;
// kick eikon server in (in case it is not running yet)
TInt error = iEikSrv.Connect();
__ASSERT_ALWAYS(error == KErrNone, User::Invariant());
// base call
CAknNotifierAppServerAppUi::ConstructL();
RWsSession& wsSession=iEikonEnv->WsSession();
iBackdropWindowGroup=RWindowGroup(wsSession);
User::LeaveIfError(iBackdropWindowGroup.Construct((TUint32)&iBackdropWindowGroup, EFalse));
iBackdropWindowGroup.AutoForeground(EFalse);
CApaWindowGroupName* apaName =
CApaWindowGroupName::NewLC(wsSession, (TUint32)&iBackdropWindowGroup);
apaName->SetHidden(ETrue);
apaName->SetSystem(ETrue);
apaName->SetCaptionL(EIKON_SERVER_BACKDROP_WINDOW_GROUP_NAME);
User::LeaveIfError(apaName->SetWindowGroupName(iBackdropWindowGroup));
CleanupStack::PopAndDestroy(); //apaName
iBackdropWindowGroup.SetOrdinalPosition(1, ECoeWinPriorityNormal);
// to make sure that wserv does not change our priority even we lose foreground
wsSession.ComputeMode(RWsSession::EPriorityControlDisabled);
wsSession.SetDoubleClick(KTimeBetweenClicks,KDoubleClickDistance);
// AKNLAF
wsSession.SetKeyboardRepeatRate(KAknKeyboardRepeatInitialDelay, KAknStandardKeyboardRepeatRate);
// Disable some of wserv hotkeys if not in RnD mode.
if (!BaflUtils::FileExists( iEikonEnv->FsSession(), KRDSupport ))
{
User::LeaveIfError(wsSession.ClearHotKeys(EHotKeyOfDeath));
// Symbian already protects this in urel mode, but just to play it safe
User::LeaveIfError(wsSession.ClearHotKeys(EHotKeyShutDown));
User::LeaveIfError(wsSession.ClearHotKeys(EHotKeyOff));
}
// Create statuspane & SGcs
if (iEikonEnv->StatusPaneCoreResId())
{
iStatusPane = CEikServStatusPane::NewL(
*iEikonEnv,
&iBackdropWindowGroup,
iEikonEnv->StatusPaneCoreResId());
}
iSgcs = CEikSgcServer::NewL();
iSgcs->SetStatusPane(iStatusPane);
iSgcs->SetAknCapAppServerAppUi(this);
RWindowGroup& rootWin = iCoeEnv->RootWin();
rootWin.EnableGroupListChangeEvents();
rootWin.EnableScreenChangeEvents();
rootWin.EnableFocusChangeEvents (); // For cover UI/status pane refresh problems
iSgcs->HandleWindowGroupParamChangeL(rootWin.Identifier(), EFalse, 0, 0, KAknScreenModeUnset);
// create a high priority key filter
// i.e. capture Apps-Key
iKeyCaptureControl=new(ELeave) CAknServKeyFilter();
iKeyCaptureControl->ConstructL(*this);
TFileName fileName(KEikSrvUIResFileName);
BaflUtils::NearestLanguageFile(iEikonEnv->FsSession(),fileName);
iResourceFileOffset=iCoeEnv->AddResourceFileL(fileName);
// MMC unlocker
iMMCUnlock = CAknMMCPasswordRequester::NewL();
// Boost our priority similar to eikon server.
RThread thread;
#if defined(__EPOC32__)
thread.SetProcessPriority(EPriorityHigh);
#else
thread.SetPriority(EPriorityAbsoluteForeground);
#endif
// Start OOM watcher thread when scheduler is running
// effectively this frees eikon server thread also.
iIdler = CIdle::NewL(CActive::EPriorityIdle);
iIdler->Start(TCallBack(StartOOM, this));
SetAliasKeyCodeResolverL(this);
// Define the property for Idle application window group id. This cannot be done in AknIcon,
// because the property is internal in classicui domain.
TInt err = RProperty::Define(
KPSUidAvkonInternal,
KAknIdleAppWindowGroupId,
RProperty::EInt,
KPassReadPolicy, // None
KWriteDDPolicy); // WriteDeviceData
if (err != KErrAlreadyExists)
{
User::LeaveIfError(err);
}
// Define a PubSub key indicate menu option has the task swapper item or not
err = RProperty::Define(
KPSUidAvkonInternal,
KAknMenuOptionNoTaskSwapper,
RProperty::EInt);
if ( err != KErrNone && err != KErrAlreadyExists )
{
User::LeaveIfError( err );
}
#ifdef RD_INTELLIGENT_TEXT_INPUT
// Define the property for Idle application window group id. This cannot be done in AknIcon,
// because the property is internal in classicui domain.
err = RProperty::Define(
KPSUidAknFep,
KAknFepFnKeyState,
RProperty::EInt,
KPassReadPolicy, // None
KWriteDDPolicy); // WriteDeviceData
if (err != KErrAlreadyExists)
{
User::LeaveIfError(err);
}
#endif
// Start listening "global notes allowed" property. When global notes are allowed,
// we know that the boot is finished and the Idle app window group id can be fetched.
User::LeaveIfError(iGlobalNotesAllowedProperty.Attach(
KPSUidUikon,
KUikGlobalNotesAllowed));
iGlobalNotesAllowedSubscriber = new (ELeave) CPropertySubscriber(
TCallBack(GlobalNotesAllowedCallBack, this),
iGlobalNotesAllowedProperty);
iGlobalNotesAllowedSubscriber->Subscribe();
// Start listening "telephony idle uid" property.
User::LeaveIfError(iTelephonyIdleUidProperty.Attach(
KPSUidAiInformation,
KActiveIdleUid));
iTelephonyIdleUidSubscriber = new (ELeave) CPropertySubscriber(
TCallBack(TelephonyIdleUidCallBack, this),
iTelephonyIdleUidProperty);
iTelephonyIdleUidSubscriber->Subscribe();
#ifdef RD_INTELLIGENT_TEXT_INPUT
TInt err1 = 0;
err1 = RProperty::Define(KPtiEnginePSUid, EKeyMapPropertyCount, RProperty::EInt,
KCapServerPtiEngineAlwaysPass, KCapServerPtiEngineWritePolicy);
err1 |= RProperty::Set(KPtiEnginePSUid, EKeyMapPropertyCount, 0);
err1 |= RProperty::Define(KPtiEnginePSUid, EKeyMapPropertyData, RProperty::EByteArray,
KCapServerPtiEngineAlwaysPass, KCapServerPtiEngineWritePolicy);
err1 |= RProperty::Define(KPtiEnginePSUid, EKeyMapPropertyData2, RProperty::EByteArray,
KCapServerPtiEngineAlwaysPass, KCapServerPtiEngineWritePolicy);
err1 |= RProperty::Define(KPtiEnginePSUid, EKeyMapPropertyCount2, RProperty::EInt,
KCapServerPtiEngineAlwaysPass, KCapServerPtiEngineWritePolicy);
err1 |= RProperty::Set(KPtiEnginePSUid, EKeyMapPropertyCount2, 0);
err1 |= RProperty::Define(KPtiEnginePSUid, EKeyMapPropertyData3, RProperty::EByteArray,
KCapServerPtiEngineAlwaysPass, KCapServerPtiEngineWritePolicy);
err1 |= RProperty::Define(KPtiEnginePSUid, EKeyMapPropertyCount3, RProperty::EInt,
KCapServerPtiEngineAlwaysPass, KCapServerPtiEngineWritePolicy);
err1 |= RProperty::Set(KPtiEnginePSUid, EKeyMapPropertyCount3, 0);
// Create ptiengine instance for key code resolver.
if (err1 == KErrNone && !iPtiEngine)
{
// create PtiEngine already here because only cap server process has write rights to
// above properties and several PtiEngine cores want to cache language
// bindings to those properties.
TRAP_IGNORE(iPtiEngine = CPtiEngine::NewL(ETrue));
}
#endif
// Create capserver discreetpopuphandler
CAknCapServerDiscreetPopupHandler::CreateDiscreetPopupHandlerL();
LoadAlternateFsPlugin();
// Create FSW
if ( iAlternateFS == NULL )
{
iFSControl= new (ELeave) CAknFastSwapWindowControl(*this);
iFSControl->ConstructL();
}
ProcessInitFlipStatus();
}
TKeyResponse CAknCapAppServerAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
{
return CAknNotifierAppServerAppUi::HandleKeyEventL(aKeyEvent, aType);
}
// This must not leave if aAddCount == 0.
void CAknCapAppServerAppUi::SuppressAppSwitchingL(TInt aAddCount, TInt aClientId)
{
TInt index = KErrNotFound;
for (TInt ii=0;ii<iAppsKeyArray.Count();ii++)
{
if (iAppsKeyArray[ii].iUid == aClientId)
{
index = ii;
}
}
if (aAddCount == EAknAppsKeyBlockRemoveClient && aClientId) // client is exiting
{
if (index != KErrNotFound)
{
iAppsKeyArray.Remove(index);
}
return;
}
// create client entry (did not previosly exist)
if (index == KErrNotFound)
{
__ASSERT_DEBUG(aAddCount == EAknAppsKeyBlockAddCount, User::Invariant());
SSuppressInfo info = SSuppressInfo(aClientId);
User::LeaveIfError(iAppsKeyArray.Insert(info,0));
index = 0;
}
// Add aAddcount to client data
iAppsKeyArray[index].iReferenceCount += aAddCount;
if ( IsAppsKeySuppressed() )
{
TInt err = RProperty::Set(
KPSUidAvkonInternal,
KAknMenuOptionNoTaskSwapper, ENoTaskSwapper );
if ( err!=KErrNone )
{
User::LeaveIfError( err );
}
}
else
{
TInt err = RProperty::Set(
KPSUidAvkonInternal,
KAknMenuOptionNoTaskSwapper, ETaskSwapper );
if ( err!=KErrNone )
{
User::LeaveIfError( err );
}
}
}
void CAknCapAppServerAppUi::KillAppL(const RMessage2& aMessage)
{
aMessage.Complete(KErrNotSupported);
}
void CAknCapAppServerAppUi::DoTaskListCommandL(const RMessage2& aMessage)
{
switch (aMessage.Function())
{
case EAknSEnableTaskList:
{
TInt err = EnableTaskList(aMessage.Int0());
aMessage.Complete(err);
break;
}
case EAknsLaunchTaskList:
{
if (iTaskListEnabled)
{
if ( iAlternateFS && iAlternateFS->IsReady() )
{
if ( aMessage.Int0() )
{
iAlternateFS->Show();
}
else
{
iAlternateFS->Dismiss();
}
}
else
{
if ( iFSControl )
{
if ( aMessage.Int0() )
{
TInt err = KErrNone;
TRAP( err, iFSControl->InitializeWindowGroupListL( EFalse ));
if ( !err )
{
iFSControl->RunFastSwapL();
}
}
else
{
iFSControl->CloseFastSwap();
}
}
}
}
aMessage.Complete(KErrNone);
break;
}
case EAknSRefreshTaskList:
{
TInt err = UpdateTaskListL( ETrue );
if ( err != KErrNone )
{
if ( iFSControl )
{
iFSControl->CloseFastSwap();
}
}
aMessage.Complete(err);
break;
}
default:
{
aMessage.Complete(KErrNotSupported);
break;
}
}
}
TBool CAknCapAppServerAppUi::IsAppsKeySuppressed()
{
if (!iTaskListEnabled)
{
return ETrue;
}
for(TInt ii = 0; ii < iAppsKeyArray.Count(); ii++)
{
if (iAppsKeyArray[ii].iReferenceCount)
{
return ETrue;
}
}
return EFalse;
}
void CAknCapAppServerAppUi::HideApplicationFromFswL(TInt aUid,TBool aDisable)
{
if (!iHiddenList)
{
iHiddenList = new (ELeave) CArrayFixFlat<TInt>(1); // This won't grow very big I hope
// the appui server reserves a property where it stores the hidden list.
RProperty::Define(KPSUidUikon, KUikAppHiddenList, RProperty::ELargeByteArray);
}
TBool foundUid( EFalse );
for (TInt i = 0; i < iHiddenList->Count(); i++)
{
if (aUid == iHiddenList->At(i))
{
iHiddenList->Delete(i);
foundUid = ETrue;
break;
}
}
if (aDisable)
{
iHiddenList->AppendL(aUid);
// visible uid hidden -> refresh tasklist
if ( !foundUid )
{
UpdateTaskListL( ETrue );
}
}
else
{
// hidden uid set to visible -> refresh tasklist
if ( foundUid )
{
UpdateTaskListL( ETrue );
}
}
// when the hidden list is ready it get's published to P&S service
PublishHiddenList();
}
void CAknCapAppServerAppUi::ProcessInitFlipStatus()
{
// we remove the definition from hal_switch.h
enum
{
ECoverSwitch,
EHalGroupSwitch = 29
};
const TInt KFeatureIdFfSliderLandscapeStartsApp_LocalDefinition = 5126; //we have to define it here because of some header exporting problem
if (FeatureManager::FeatureSupported(KFeatureIdFfSliderLandscapeStartsApp_LocalDefinition))
{
// check the state of phone slide, if it is open during startup,
// we enable the landscape orientation
TBool flipStatus(EFalse); // flipStatus true : flip open / false : flip close
TInt err = UserSvr::HalFunction(EHalGroupSwitch, ECoverSwitch, &flipStatus, reinterpret_cast<TAny*>(EFalse));
if (KErrNone == err && flipStatus)
{
TRAP_IGNORE(RotateScreenL());
}
}
}
// For Gs to initiate OFN status
void CAknCapAppServerAppUi::InitiateOFNStatus()
{
// For Gs to initiate OFN status
enum TFidOFNFunctionForGs
{
EOFNSetPowerON, // OFN Powering (ON/OFF)
EHalGroupOFN = 28
};
const TInt KFeatureId_Ff_Ofn_Feature = 193;
const TInt KSettingsOptical_Joystick_Status = 0x00000019;
// For Gs to initiate OFN status
if( FeatureManager::FeatureSupported( KFeatureId_Ff_Ofn_Feature ) )
{
CRepository* personalizationRepository = NULL;
TRAPD( errCode, personalizationRepository = CRepository::NewL( KCRUidPersonalizationSettings ) );
if (errCode == KErrNone)
{
TInt ofnStatus = 0;
personalizationRepository->Get( KSettingsOptical_Joystick_Status, ofnStatus );
delete personalizationRepository;
UserSvr::HalFunction( EHalGroupOFN, EOFNSetPowerON, reinterpret_cast<TAny*>( ofnStatus ),
reinterpret_cast<TAny*>( ofnStatus ) );
}
}
}
void CAknCapAppServerAppUi::PublishHiddenList()
{
// 1. the creation of hidden list array
TBuf16 <2*KMaxHiddenApps> hiddenList;
TInt i;
TUint16 upperBits;
// the limit of hidden application uids
TInt hiddenCount = ( iHiddenList->Count() > KMaxHiddenApps ) ?
KMaxHiddenApps : iHiddenList->Count();
for ( i = 0; i < hiddenCount; i++)
{
// 32-bit integer is appended in two parst to 16-bit buffer
upperBits = iHiddenList->At(i) >> 16;
hiddenList.Append( upperBits );
// upper values are automatically truncated
hiddenList.Append( iHiddenList->At(i) );
}
// the end of hidden list is marked null (0x00000000)
if ( i < KMaxHiddenApps )
{
hiddenList.Append( 0x0000 );
hiddenList.Append( 0x0000 );
}
// 2. setting the property value
RProperty::Set(KPSUidUikon, KUikAppHiddenList, hiddenList);
}
TBool CAknCapAppServerAppUi::HiddenFromFSW( TInt aUid )
{
if ( iHiddenList )
{
for ( TInt i = 0; i < iHiddenList->Count(); i++)
{
if (aUid == iHiddenList->At(i))
{
return ETrue;
}
}
}
return EFalse;
}
TInt CAknCapAppServerAppUi::EnableTaskList(TBool aEnable)
{
TInt err = KErrNone;
iTaskListEnabled = aEnable;
if ( IsAppsKeySuppressed() )
{
err = RProperty::Set(KPSUidAvkonInternal, KAknMenuOptionNoTaskSwapper, ENoTaskSwapper);
}
else
{
err = RProperty::Set(KPSUidAvkonInternal, KAknMenuOptionNoTaskSwapper, ETaskSwapper);
}
return err;
}
TBool CAknCapAppServerAppUi::HandleShortAppsKeyPressL()
{
if(iAlternateFS && iAlternateFS->IsReady() && iAlternateFS->IsVisible())
{
iAlternateFS->HandleShortAppKeyPress();
return ETrue;
}
if ( iFSControl )
{
if (iFSControl->IsVisible())
{
iFSControl->HandleShortAppsKeyPressL();
return ETrue;
}
}
return EFalse;
}
TBool CAknCapAppServerAppUi::HandleLongAppsKeyPressL()
{
if (iTaskListEnabled)
{
if ( iAlternateFS && iAlternateFS->IsReady() )
{
ShowOrDismissAlternateFs();
}
else
{
if ( iFSControl )
{
if ( iFSControl->IsVisible())
{
iFSControl->HandleLongAppsKeyPressL();
}
else
{
if (iFSControl->VisibleWindowGroupsCountL()<1)
{
return EFalse;
}
else
{
iFSControl->RunFastSwapL();
}
}
}
}
}
return ETrue;
}
void CAknCapAppServerAppUi::SetStatusPaneFlags(TInt aFlags)
{
if (iStatusPane)
{
iStatusPane->SetFlags(aFlags);
}
}
void CAknCapAppServerAppUi::SetStatusPaneLayoutL(TInt aLayoutResId)
{
if (iStatusPane)
{
iStatusPane->SwitchLayoutL(aLayoutResId);
}
}
TInt CAknCapAppServerAppUi::RemoveBlankCallBack( TAny* aThis )
{
static_cast<CAknCapAppServerAppUi*>( aThis )->DoRemoveBlank();
return EFalse;
}
void CAknCapAppServerAppUi::BlankScreenL(TBool aBlank, TBool /* aToForeground */)
{
if (aBlank)
{
if (++iBlankWinRefCount == 1)
{
delete iRemoveBlankCallBack;
iRemoveBlankCallBack = NULL;
// We are ignoring the foreground parameter because we only have one
// type of blanking behaviour in AlfClient. Act as if ETrue
iAlfClient.BlankScreen(ETrue);
iForegroundBlankScreen = ETrue; // always as if foreground blanking
/*
ASSERT(!iBlankWin);
if (aToForeground)
{
iBackdropWindowGroup.SetOrdinalPosition(0, KWgPriorityCoverEverything);
}
else
{
iBackdropWindowGroup.SetOrdinalPosition(1, ECoeWinPriorityNormal);
}
iBlankWin = CAknServBlankWin::NewL(iBackdropWindowGroup, iStatusPane);
iForegroundBlankScreen = aToForeground;
*/
}
}
else if (--iBlankWinRefCount <= 0)
{
iBlankWinRefCount = 0;
// Blanking IPC is delayed or restarted
delete iRemoveBlankCallBack;
iRemoveBlankCallBack = NULL;
iRemoveBlankCallBack = CPeriodic::NewL(CActive::EPriorityLow);
iRemoveBlankCallBack->Start(
KRemoveBlankDelay,
KRemoveBlankDelay,
TCallBack(RemoveBlankCallBack, this));
/* if (iForegroundBlankScreen)
{
*/
#ifdef RD_UI_TRANSITION_EFFECTS_LAYOUT_SWITCH
/*
CWsScreenDevice* screen = iEikonEnv->ScreenDevice();
RWsSession& ws = iEikonEnv->WsSession();
TInt wgId = ws.GetFocusWindowGroup();
CApaWindowGroupName* wgName = CApaWindowGroupName::NewL(ws, wgId);
CleanupStack::PushL( wgName );
TUid appUid = wgName->AppUid();
CleanupStack::PopAndDestroy( wgName );
*/
//GfxTransEffect::BeginFullScreen( AknTransEffect::ELayoutSwitch,
// TRect( screen->SizeInPixels() ),
// AknTransEffect::EParameterType,
// AknTransEffect::GfxTransParam( KTfxServerUid )
// );
// GfxTransEffect::EndFullScreen();
#endif
/* iBackdropWindowGroup.SetOrdinalPosition(1, ECoeWinPriorityNormal);
}
delete iBlankWin;
iBlankWin = 0;
*/
iForegroundBlankScreen = EFalse;
}
}
void CAknCapAppServerAppUi::DoRemoveBlank()
{
RDebug::Print( _L("CAknCapAppServerAppUi::DoRemoveBlank"));
iAlfClient.BlankScreen(EFalse);
delete iRemoveBlankCallBack;
iRemoveBlankCallBack = NULL;
}
void CAknCapAppServerAppUi::SwapLayoutSwitchBlankScreenL()
{
/*
if (iBlankWin)
{
if (!iForegroundBlankScreen)
{
iBackdropWindowGroup.SetOrdinalPosition(0, KWgPriorityCoverEverything);
}
iForegroundBlankScreen = ETrue;
CAknServBlankWin* newBlankWin = CAknServBlankWin::NewL(iBackdropWindowGroup, iStatusPane);
newBlankWin->SetLayoutBlank(ETrue);
delete iBlankWin;
iBlankWin = newBlankWin;
}
*/
}
TBool CAknCapAppServerAppUi::IsDisplayingForegroundBlankScreen() const
{
return iForegroundBlankScreen;
}
void CAknCapAppServerAppUi::HandleResourceChangeL(TInt aType)
{
if (aType == KAknInternalFSWClose) // for notifiers running inside this thread
{
if (iFSControl)
{
iFSControl->CloseFastSwap();
// This cancels power menu when keys are locked / soft note accepted.
Manager()->CancelNotifier(KAknGlobalListQueryUid);
}
return; // don't pass this outside this class
}
if ( aType == KEikDynamicLayoutVariantSwitch )
{
iCapServer->RefreshLongTapAnimation();
}
CAknNotifierAppServerAppUi::HandleResourceChangeL(aType);
if (iFSControl)
{
if ( aType == KAknsMessageSkinChange )
{
UpdateTaskListL( ETrue );
}
iFSControl->HandleResourceChange(aType);
}
if (iStatusPane)
{
iStatusPane->HandleResourceChange(aType);
}
if (aType == KAknsMessageSkinChange )
{
iSgcs->FadeBitmapGenerationL();
iSgcs->FadeColorGenerationL();
}
}
void CAknCapAppServerAppUi::HandleWsEventL(const TWsEvent& aEvent,CCoeControl* aDestination)
{
if ( iMessageReaderLongPressDetector &&
!IsAppsKeySuppressed() &&
( iFSControl == NULL || !iFSControl->IsDisplayed() ) )
{
// Message Reader can be launched by long pressing left soft key
// events need to be intercepted/consumed before they are forwarded to cba
if ( iMessageReaderLongPressDetector->HandleWsEventL( aEvent, aDestination ) )
{
return;
}
}
switch( aEvent.Type() )
{
case EEventFocusGroupChanged: // For cover UI/status pane refresh problems
case EEventWindowGroupListChanged:
{
// only updated if application has informed about it's intentions to exit
UpdateTaskListL( EFalse );
iSgcs->HandleWindowGroupListChangeL();
break;
}
case KUidValueAknsSkinChangeEvent:
{
HandleResourceChangeL(KAknsMessageSkinChange);
HandleStackedControlsResourceChange(KAknsMessageSkinChange);
break;
}
default:
{
CAknNotifierAppServerAppUi::HandleWsEventL(aEvent, aDestination);
if (EventMonitor())
{
EventMonitor()->HandleWsEventL(aEvent, aDestination); // for ecs
}
}
}
}
void CAknCapAppServerAppUi::SetCurrentAppStatuspaneResourceIdL(TInt aResourceId)
{
iStatusPane->SetCurrentAppStatuspaneResourceId(aResourceId);
}
TInt CAknCapAppServerAppUi::CurrentAppStatuspaneResourceIdL()
{
return iStatusPane->CurrentAppStatuspaneResourceId();
}
void CAknCapAppServerAppUi::RotateScreenL()
{
iSgcs->RotateScreenL();
}
// ---------------------------------------------------------
// CAknCapAppServerAppUi::UpdateTaskListL
// Tasklist will be updated when its visible and when
// when the old tasklist is no longer valid
// ---------------------------------------------------------
//
TInt CAknCapAppServerAppUi::UpdateTaskListL( TBool aTaskListRefreshNeeded )
{
TInt err = KErrNone;
if ( iFSControl && iFSControl->IsDisplayed() )
{
// update window group list (task list)
TInt windowGroupListChanged = ETrue;
TRAP( err, windowGroupListChanged = iFSControl->InitializeWindowGroupListL(
!aTaskListRefreshNeeded ) );
if ( windowGroupListChanged || aTaskListRefreshNeeded )
{
TRAP( err, iFSControl->HandleChangeInWindowGroupListL() );
}
}
return err;
}
LOCAL_C TBool IsQwertyKey(TPtiKey aKey)
{
if ((aKey >= EPtiKeyQwertyA && aKey <= EPtiKeyQwertyZ) ||
(aKey >= EPtiKeyQwerty0 && aKey <= EPtiKeyQwerty9) ||
aKey == EPtiKeyQwertyPlus ||
aKey == EPtiKeyQwertyMinus ||
aKey == EPtiKeyQwertyComma ||
aKey == EPtiKeyQwertySemicolon ||
aKey == EPtiKeyQwertyFullstop ||
aKey == EPtiKeyQwertyHash ||
aKey == EPtiKeyQwertySlash ||
aKey == EPtiKeyQwertyApostrophe
#ifdef RD_INTELLIGENT_TEXT_INPUT
|| aKey == EPtiKeyQwertySpace
|| aKey == EPtiKeyQwertyAtCharacter
#endif
)
{
return ETrue;
}
return EFalse;
}
#ifdef RD_INTELLIGENT_TEXT_INPUT
TBool CAknCapAppServerAppUi::IsCharacterCategoryNumber(TUint aChar) const
{
TChar::TBdCategory numCategory;
TBool isNumber = EFalse;
numCategory = (TChar(aChar)).GetBdCategory();
isNumber = ((numCategory == TChar::EEuropeanNumber) || (numCategory == TChar::EArabicNumber) ||
(numCategory == TChar::EEuropeanNumberTerminator) ||
( numCategory == TChar::EEuropeanNumberSeparator ) ||
(aChar == 0x2E) ||
(aChar == 0x2A) || (aChar == 0x3D) || (aChar == 0x2F));
return isNumber;
}
#endif
TInt CAknCapAppServerAppUi::GetAliasKeyCode(TUint& aCode, const TKeyEvent& aKeyEvent,TEventCode /*aType*/)
{
aCode = aKeyEvent.iCode;
#ifdef RD_INTELLIGENT_TEXT_INPUT
TKeyEvent keyEventLocal = aKeyEvent;
#if defined(__WINS__)
if ( keyEventLocal.iScanCode == EStdKeyNkpPlus )
{
// Workaround solution for the qwerty '+' key in emulator environment.
// I did not find a way how to to configure epoc_352x416_Qwerty.ini to send '+' keyevent.
keyEventLocal.iScanCode = 0x2b; // '+' key.
}
#endif
#endif
if (!iQwertyStatus || (aKeyEvent.iModifiers & EModifierSpecial) != 0)
{
// Only qwerty events are converted. Coversion is also rejected if EModifierSpecial
// bit is set. That can be used for disabling conversion for simulated
// key events.
return KErrNone;
}
#ifdef RD_INTELLIGENT_TEXT_INPUT
if (IsQwertyKey((TPtiKey)keyEventLocal.iScanCode))
#else
if (IsQwertyKey((TPtiKey)aKeyEvent.iScanCode))
#endif
{
// We know in advance that iCode values below this threshold are not
// going to be converted, so just return.
if (aCode <= KKeyEventICodeThreshold)
{
return KErrNone;
}
if (aKeyEvent.iModifiers & KModifierExternalKeyboard)
{
// The event is coming from external keyboard, do not convert.
return KErrNone;
}
TInt err = KErrNone;
if (!iPtiEngine)
{
TRAP(err, iPtiEngine = CPtiEngine::NewL(ETrue));
if (err != KErrNone)
{
return err;
}
}
CAknSettingCache& settingsCache = CAknEnv::Static()->SettingCache();
const TInt KMaxNumCharsPerCase = 50;
TBuf<KMaxNumCharsPerCase> keys;
const TBool shifted = (aKeyEvent.iModifiers & EModifierLeftShift) ||
(aKeyEvent.iModifiers & EModifierRightShift);
#ifdef RD_INTELLIGENT_TEXT_INPUT
TInt fnState;
RProperty::Get(KPSUidAknFep,KAknFepFnKeyState, fnState);
const TBool functionized = (keyEventLocal.iModifiers & EModifierRightFunc) ;
//|| (fnState == 6);
const TBool isCtrl = (aKeyEvent.iModifiers & EModifierLeftCtrl) ||
(aKeyEvent.iModifiers & EModifierRightCtrl);
if(isCtrl)
return KErrNone;
#endif
CPtiCoreLanguage* lang = static_cast<CPtiCoreLanguage*>(iPtiEngine->GetLanguage(
settingsCache.InputLanguage()));
#ifdef RD_INTELLIGENT_TEXT_INPUT
// Qwerty Keyboard layout
TInt keyboardLayout = 0;
RProperty::Get(KCRUidAvkon, KAknKeyBoardLayout, keyboardLayout);
TPtiKeyboardType keyboardType = (TPtiKeyboardType) keyboardLayout ;
#endif
if (lang)
{
#ifdef RD_INTELLIGENT_TEXT_INPUT
CPtiQwertyKeyMappings* maps;
if(keyboardType != EPtiKeyboardHalfQwerty)
maps = static_cast<CPtiQwertyKeyMappings*>(lang->GetQwertyKeymappings());
else
maps = static_cast<CPtiQwertyKeyMappings*>(lang->GetHalfQwertyKeymappings());
#else
CPtiQwertyKeyMappings* maps =
static_cast<CPtiQwertyKeyMappings*>(lang->GetQwertyKeymappings());
#endif
if (maps)
{
#ifdef RD_INTELLIGENT_TEXT_INPUT
maps->SetKeyboardType(keyboardType);
if(functionized)
{
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseFnLower);
if( !(keys.Length() && IsCharacterCategoryNumber(keys[0])))
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseFnUpper);
if(!keys.Length())
{
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseFnLower);
}
}
else if(shifted)
{
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseUpper);
}
else
{
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseFnLower);
if( !(keys.Length() && IsCharacterCategoryNumber(keys[0])))
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseFnUpper);
if( !(keys.Length() && IsCharacterCategoryNumber(keys[0])))
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseLower);
if( !(keys.Length() && IsCharacterCategoryNumber(keys[0])))
maps->GetDataForKey((TPtiKey)keyEventLocal.iScanCode, keys, EPtiCaseUpper);
if( !(keys.Length() && IsCharacterCategoryNumber(keys[0])))
keys.SetLength(0);
}
#else
if (shifted)
{
maps->GetDataForKey((TPtiKey)aKeyEvent.iScanCode, keys, EPtiCaseUpper);
}
else
{
maps->GetDataForKey((TPtiKey)aKeyEvent.iScanCode, keys, EPtiCaseLower);
}
#endif
}
}
if ( keys.Length() > 0 )
{
switch (keys[0])
{
case KPtiPinyinMarker:
case KPtiStrokeMarker:
case KPtiZhuyinMarker:
case KPtiCangjieMarker:
case KPtiGetAllMarker:
if (keys.Length() > 1)
{
aCode = keys[1];
}
break;
default:
aCode = keys[0];
}
}
}
return KErrNone;
}
void CAknCapAppServerAppUi::ForwardKeyToPhoneAppL(const TKeyEvent& aKeyEvent)
{
if (iScanCodeCaptureHandle)
{
return;
}
iPhoneKey = aKeyEvent; // reset
iScanCodeCaptureHandle = CCoeEnv::Static()->RootWin().CaptureKeyUpAndDowns(
aKeyEvent.iScanCode,0,0 );
if (!iIdler)
{
iIdler = CIdle::NewL(CActive::EPriorityStandard);
}
iIdler->Start(TCallBack(AknPhoneKeyForwarder::ForwardKeyToPhoneApp, &iPhoneKey));
iUpReceived = EFalse;
}
void CAknCapAppServerAppUi::PhoneKeyUpReceived()
{
if (iScanCodeCaptureHandle)
{
CCoeEnv::Static()->RootWin().CancelCaptureKeyUpAndDowns(iScanCodeCaptureHandle);
}
iScanCodeCaptureHandle = 0;
iUpReceived = ETrue;
if (!iIdler->IsActive()) // callback already triggered
{ // direct call
AknPhoneKeyForwarder::ForwardUpEventToPhoneApp(&iPhoneKey);
}
}
void CAknCapAppServerAppUi::SetFgSpDataSubscriberIdL(TInt aId)
{
CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
if (statusPane)
{
CEikServStatusPane* ssp = static_cast<CEikServStatusPane*>(statusPane);
CAknStatusPaneDataPublisher* publisher = ssp->iDataPublisher;
if (publisher)
{
publisher->SetForegroundSubscriberId(aId);
publisher->PublishDataL();
}
}
}
void CAknCapAppServerAppUi::CloseFSW()
{
if (iFSControl)
{
iFSControl->CloseFastSwap();
}
}
void CAknCapAppServerAppUi::SetIdleActive( TBool bActive )
{
iIdleActive = bActive;
}
TBool CAknCapAppServerAppUi::IsIdelActive( )
{
return iIdleActive;
}
void CAknCapAppServerAppUi::PublishInstalledLanguagesL()
{
User::LeaveIfError( RProperty::Define(
KPSUidUikon,
KUikInstalledLanguages,
RProperty::EText,
KReadPolicy, // None
KWriteDDPolicy ) ); // WriteDeviceData
CArrayFixFlat<TInt>* installedLanguages = 0;
User::LeaveIfError( SysLangUtil::GetInstalledLanguages( installedLanguages ) );
CleanupStack::PushL( installedLanguages );
TInt nbrOfLanguages = installedLanguages->Count();
// This is a bit more than enough buffer in most cases
// Add one just for the space at the beginning of the data.
TInt bufferLength = nbrOfLanguages * KMaxLanguageCodeLength + 1;
HBufC8* languages = HBufC8::NewLC( bufferLength );
TPtr8 ptr( languages->Des() );
if ( nbrOfLanguages > 0 )
{
ptr.Append( KSeparator ); // Add space at the beginning of the data
}
for ( TInt i = 0; i < nbrOfLanguages; i++ )
{
ptr.AppendNum( installedLanguages->At(i) ); // Add language ID to data
ptr.Append( KSeparator );// Space is also added as the last character
}
RProperty::Set( KPSUidUikon, KUikInstalledLanguages, ptr );
CleanupStack::PopAndDestroy( 2, installedLanguages );
}
TInt CAknCapAppServerAppUi::GlobalNotesAllowedCallBack(TAny* aPtr)
{
CAknCapAppServerAppUi* self = static_cast<CAknCapAppServerAppUi*>(aPtr);
if (self)
{
self->HandlePropertyChange(KUikGlobalNotesAllowed);
}
return KErrNone;
}
TInt CAknCapAppServerAppUi::TelephonyIdleUidCallBack(TAny* aPtr)
{
CAknCapAppServerAppUi* self = static_cast<CAknCapAppServerAppUi*>(aPtr);
if (self)
{
self->HandlePropertyChange(KActiveIdleUid);
}
return KErrNone;
}
void CAknCapAppServerAppUi::HandlePropertyChange(const TInt aProperty)
{
switch(aProperty)
{
case KUikGlobalNotesAllowed:
{
TInt globalNotesAllowed = 0;
TInt err = iTelephonyIdleUidProperty.Get(globalNotesAllowed);
if(!err && globalNotesAllowed)
{
// Global notes allowed, so the boot is finished. Now the idle app uid and its
// window group id can be fetched.
HandlePropertyChange(KActiveIdleUid);
}
}
break;
case KActiveIdleUid:
{
TInt idleAppUid = 0;
TInt err = iTelephonyIdleUidProperty.Get(idleAppUid);
if(!err)
{
// Fetch the Idle application window group id.
TApaTaskList taskList(CEikonEnv::Static()->WsSession());
TApaTask task = taskList.FindApp(TUid::Uid(idleAppUid));
TInt wgId = task.WgId();
// Save the window group id to PubSub.
RProperty::Set(KPSUidAvkonInternal, KAknIdleAppWindowGroupId, wgId);
}
}
break;
default:
break;
};
}
// -----------------------------------------------------------------------------
// C++ constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CPropertySubscriber::CPropertySubscriber(TCallBack aCallBack, RProperty& aProperty)
: CActive(EPriorityNormal), iCallBack(aCallBack), iProperty(aProperty)
{
CActiveScheduler::Add(this);
}
// -----------------------------------------------------------------------------
// Destructor.
// -----------------------------------------------------------------------------
//
CPropertySubscriber::~CPropertySubscriber()
{
Cancel();
}
// -----------------------------------------------------------------------------
// Starts to listen for changes.
// -----------------------------------------------------------------------------
//
void CPropertySubscriber::Subscribe()
{
if (!IsActive())
{
iProperty.Subscribe(iStatus);
SetActive();
}
}
// -----------------------------------------------------------------------------
// Stops listening for changes.
// -----------------------------------------------------------------------------
//
void CPropertySubscriber::StopSubscribe()
{
Cancel();
}
// -----------------------------------------------------------------------------
// When active object fires, call callback and continue listening.
// -----------------------------------------------------------------------------
//
void CPropertySubscriber::RunL()
{
if (iStatus.Int() == KErrNone)
{
iCallBack.CallBack();
Subscribe();
}
}
// -----------------------------------------------------------------------------
// Cancel.
// -----------------------------------------------------------------------------
//
void CPropertySubscriber::DoCancel()
{
iProperty.Cancel();
}
// Actual entry point.
LOCAL_C CApaApplication* NewApplication()
{
return new CAknCapServerApplication();
}
GLDEF_C TInt E32Main()
{
return EikStart::RunApplication(NewApplication);
}
// End of file