uifw/EikStd/srvuisrc/EIKSRVUI.CPP
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
child 14 3320e4e6e8bb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/EikStd/srvuisrc/EIKSRVUI.CPP	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1971 @@
+/*
+* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <uikon/eiknotifyalert.h>
+#include <viewclipartner.h>
+#include <uiklaf/private/pluginuid.hrh>
+#endif
+#include <hal.h>
+#include <hal_data.h>
+#include <s32file.h>
+#include <basched.h>
+#include <bautils.h>
+#include <eikdll.h>
+#include <eikenv.h>
+#include <eikkeys.h>
+#include "eikkwin.h"
+#include <eikmover.h>
+#include <eikon.rsg>
+
+#include <uikon/eiksrvui.h>
+#include <eiksvdef.h>
+#include <Eikalmct.h>
+
+#define __ASSHDBITFLAGS_H__
+
+#include <uikon/eikalsup.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <uikon/eikenvinterface.h>
+#endif
+#include <eikunder.h>
+#include <uikon/eikalsrv.h>
+#include <uikon/eiknfysv.h>
+#include "EIKNFYUI.H"
+#include <eiksrvui.rsg>
+#include <viewcli.h>
+
+/*
+* Following resources used from Symbian's eikpriv.rss file:
+* 
+* r_eik_system_default_view_id
+* r_eik_system_view_server_event_time_out
+* r_eik_system_view_server_client_request_time_out
+*/
+#include <eikpriv.rsg>
+#include "EIKSRV.HRH"
+
+#include <aknPopup.h>
+#include <avkon.rsg>
+#include <eiktxlbx.h>
+#include <eiktxlbm.h>
+#include "eikkeysoundserver.h"
+#include <aknsoundsystem.h>
+#include <eikapp.h>
+#include <aknenv.h>
+
+#include <AknLayout.lag>
+#include <AknUtils.h>
+#include <AknsUtils.h>
+#include <featmgr.h>
+
+#include <e32property.h>
+#include <UikonInternalPSKeys.h>    // KUikLayoutState
+
+#include <aknpriv.rsg>
+#include <AknDef.h>
+
+#include <AknIconUtils.h>
+#include <avkon.mbg>
+#include <aknlayout.cdl.h>
+
+#include <asclisession.h>
+#include <asclidefinitions.h>
+#include <ascliclientutils.h>
+#include <c32comm.h>
+
+#include <apasvst.h>
+#include <apgcli.h>
+#include <apgwgnam.h>
+#include <viewcli.h>
+#include <vwsappst.h> 
+
+#include "e32uid.h"
+
+#include <eiksrvsp.h>
+#include <eiksrvs.h>
+#include <akneiksrvs.h>
+
+#include <uiklaf/private/lafenv.h>
+#include <uiklaf/private/lafsrv.h>
+
+#include <eikrutil.h>
+#include <AknSgcc.h>
+#include <aknconsts.h>
+
+#include "EikLafShutStarter.h"
+#include "EikLafShutScheduler.h"
+
+#include <AknWsEventObserver.h>
+#include <aknappui.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknFontSpecification.h>
+#include <AknTextDecorationMetrics.h>
+#include <e32capability.h>
+
+#include <AknCapServerDefs.h>
+#include <akndialogcontroller.h>
+
+#include "AknNotifierControllerPlugin.h"
+#include <AknCustomCursorSupport.h>
+#include "AknEikSrv.pan"
+
+#if defined(__WINS__)
+const TInt KEikServSideBarWidth = 35;
+const TInt KEikServAppbarHeight = 50;
+#endif
+
+#if defined (__WINS__)
+_LIT(COMMS_PDD_NAME, "ECDRV");
+_LIT(COMMS_LDD_NAME, "ECOMM");
+#else
+_LIT(COMMS_PDD_NAME, "EUART1");
+_LIT(COMMS_LDD_NAME, "ECOMM");
+#endif
+
+const TInt KEikServServerRestartDelay = 500000; // .5 sec
+const TInt KEikServServerRestartInterval = 3000000; // 3 sec
+
+_LIT(KResFileName, "z:\\resource\\eiksrvui.rsc");
+_LIT(KAnimDllFileName, "AknAnimDll.Dll");
+_LIT(KWatcherThreadName, "UikonWatchers");
+
+const TInt KEikServPanicTextBufferSize = 512;
+
+GLDEF_C void Panic(TEikServPanic aPanic)
+    {
+    _LIT(KPanicCat,"EIKON-SERVER");
+    User::Panic(KPanicCat,aPanic);
+    }
+
+#define iAknCapServerClient (*(CAknSgcClient::AknSrv()))
+
+class CFbsBitmap;
+
+// =====================
+// RKeySoundServerCloser
+// =====================
+
+class RKeySoundServerCloser : public RSessionBase
+    {
+public:
+    void CloseServer();
+    };
+
+void RKeySoundServerCloser::CloseServer()
+    {
+    if (CreateSession(__KEYSOUND_SERVER_NAME, TVersion(KKeySoundServMajorVN, KKeySoundServMinorVN, 
+        KKeySoundServBuildVN), 0) == KErrNone)
+        {
+        SendReceive(EKeySoundServerCloseServer, TIpcArgs());
+        Close();
+        }
+    }
+
+// ==================
+// CEikServAppStarter
+// ==================
+
+class CEikServAppStarter : public CBase, public MVwsAppStarter
+    {
+public:
+    static CEikServAppStarter* NewL();
+    ~CEikServAppStarter();
+public: // From MVwsAppStarter.
+    void StartAppL(TUid aAppUid, TThreadId& aThreadId);
+private:
+    CEikServAppStarter();
+    void ConstructL();
+private:
+    };
+
+CEikServAppStarter* CEikServAppStarter::NewL()
+    {
+    CEikServAppStarter* self=new(ELeave) CEikServAppStarter;
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+CEikServAppStarter::~CEikServAppStarter()
+    {
+    }
+
+CEikServAppStarter::CEikServAppStarter()
+    {
+    }
+
+void CEikServAppStarter::ConstructL()
+    {
+    }
+
+void CEikServAppStarter::StartAppL(TUid aAppUid, TThreadId& aThreadId)
+    {
+    RApaLsSession ls;
+    CleanupClosePushL(ls);
+    User::LeaveIfError(ls.Connect());
+    TApaAppInfo info;
+    TInt err = ls.GetAppInfo(info,aAppUid);
+
+    User::LeaveIfError(err);
+    
+    // LeaveIfError does not trigger to positive values, but GetAppInfo does not return valid 
+    // data unless server returns KErrNone.
+    if ( err > 0 ) 
+        {         
+        User::Leave(KErrNotReady);
+        }
+
+    CApaCommandLine* cmdLine = CApaCommandLine::NewLC();  
+    cmdLine->SetExecutableNameL(info.iFullName);
+    cmdLine->SetCommandL(EApaCommandViewActivate);
+    
+    // Using apparc client-server to do this "internal" launch.
+    ls.StartApp(*cmdLine, aThreadId); 
+    CleanupStack::PopAndDestroy(); // cmdLine
+    CleanupStack::PopAndDestroy(); // ls
+    }
+
+// Thread function for OOD watcher.
+GLDEF_C TInt WatcherThreadFunction(TAny* /*aParameters*/)
+    {
+    TInt err(KErrNone);
+
+    CTrapCleanup* cleanup = CTrapCleanup::New();
+    CActiveScheduler* scheduler = new CEikLafShutScheduler();
+    CEikLafShutStarter* lafShut = NULL;
+
+    if (!cleanup || !scheduler)
+        {
+        err = KErrNoMemory;
+        }
+
+    else
+        {
+        CActiveScheduler::Install(scheduler);
+        TRAP(err, 
+            {
+            RThread me;
+            me.SetPriority(EPriorityLess);
+            lafShut = CEikLafShutStarter::NewL();
+            })
+
+        if (err == KErrNone)
+            {
+            // start the watchers
+            CActiveScheduler::Start();
+            }
+        }
+
+    delete cleanup;
+    delete scheduler;
+    delete lafShut;
+    
+    return err;
+    }
+
+// Creates thread for OOM & OOD watchers.
+GLDEF_C void CreateWatcherThreadL()
+    {
+    RThread thread;
+
+    TInt ret = thread.Create( 
+        KWatcherThreadName, 
+        WatcherThreadFunction,
+        0x2000,                 // stack size
+        NULL,                   // uses caller thread's heap
+        (TAny*)NULL );
+
+    if (ret == KErrNone)
+        {
+        thread.Resume();
+        thread.Close();
+        }
+
+    User::LeaveIfError(ret);
+    }
+
+// ==================
+// CEikSrvAppShutdown
+// ==================
+
+NONSHARABLE_CLASS(CEikSrvAppShutdown) : public CActive
+    {
+public:
+    static void StartL(
+        const TUid aRequesterUID, 
+        const RMessage2& aShutdownMessage, 
+        const TInt aTimeoutInMicroseconds);
+private:
+    CEikSrvAppShutdown(const RMessage2& aShutdownMessage);
+    ~CEikSrvAppShutdown();
+    void DoCancel();
+    void RunL();
+private:
+    RMessagePtr2 iMessage;
+    };
+
+void CEikSrvAppShutdown::StartL(const TUid aRequesterUID, const RMessage2& aShutdownMessage,
+    const TInt aTimeoutInMicroseconds)
+    {
+    if (iAknCapServerClient.Handle())
+        {
+        CEikSrvAppShutdown* self = new(ELeave) CEikSrvAppShutdown(aShutdownMessage);
+        iAknCapServerClient.ShutdownApps(aRequesterUID, aTimeoutInMicroseconds, self->iStatus);
+        self->SetActive();
+        }
+    else
+        aShutdownMessage.Complete(KErrNone);
+    }
+
+CEikSrvAppShutdown::CEikSrvAppShutdown(const RMessage2& aShutdownMessage)
+: CActive(CActive::EPriorityStandard), iMessage(aShutdownMessage)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+CEikSrvAppShutdown::~CEikSrvAppShutdown()
+    {
+    Cancel();
+    }
+
+void CEikSrvAppShutdown::DoCancel()
+    {
+    }
+
+void CEikSrvAppShutdown::RunL()
+    {
+    iMessage.Complete(KErrNone);
+    delete this;
+    }
+
+// =============
+// CEikServExtra
+// =============
+
+class CEikServExtra : public CBase
+    {
+public:
+    CPeriodic* iServerRestarter;
+    CArrayPtr<RWsPointerCursor>* iPointerCursors;
+    CIdle* iNotifierServerStarter;
+    };
+
+const TInt KEiksrvUiDllValue = 0x100053D0;
+
+
+EXPORT_C CEikServAppUiBase* CEikServAppUiBase::NewLC()
+    {
+    if (CEikonEnv::Static()->WsSession().FindWindowGroupIdentifier(
+        0, __EIKON_SERVER_NAME, 0) > KErrNotFound)
+        {
+        return NULL; // Already an Eikon server running.
+        }
+
+    // This code duplicates what is in EikSrv.cpp in CEikServAppUiServer::CreateAppUiL().
+    _LIT(KRomPath, "\\System\\Libs\\");
+    _LIT(KEiksrvUiDllName, "EiksrvUi.dll");
+    TFileName path;
+    Dll::FileName(path);
+    const TUint16& drv = path[0];
+    if (drv == 'z' || drv == 'Z')
+        {
+        path.Append(KRomPath);
+        }
+    else
+        {
+        TParse parse;
+        User::LeaveIfError(parse.Set(path, NULL, NULL));
+        path = parse.DriveAndPath();
+        }
+    TUidType uidType(KDynamicLibraryUid, KSharedLibraryUid, TUid::Uid(KEiksrvUiDllValue));
+    RLibrary lib;
+    User::LeaveIfError(lib.Load(KEiksrvUiDllName, path, uidType));
+    CleanupClosePushL(lib);
+    TLibraryFunction appui = lib.Lookup(1);
+    CEikServAppUiBase* self = REINTERPRET_CAST(CEikServAppUiBase*, (*appui)());
+    User::LeaveIfNull(self);
+    STATIC_CAST(CEikServEnv*, CEikonEnv::Static())->SetUiDll(lib);
+    CleanupStack::Pop(); // lib
+    CleanupStack::PushL(self);
+    STATIC_CAST(CEikAppUi*, self)->ConstructL();
+
+    return self;
+    }
+
+EXPORT_C void CEikServAppUiBase::NotifyAlarmServerOfTaskChangeL()
+    {
+    if (iAlarmAlertServer)
+        {
+        iAlarmAlertServer->TaskKeyPressedL();
+        }
+    }
+
+EXPORT_C void CEikServAppUiBase::EnableTaskListL()
+    {
+    User::Leave(KErrNotSupported);
+    }
+
+EXPORT_C void CEikServAppUiBase::LaunchTaskListL()
+    {
+    User::Leave(KErrNotSupported);
+    }
+
+EXPORT_C void CEikServAppUiBase::CycleTasksL(enum TTaskCycleDirection aDirection) 
+    {
+    TApaTaskList taskList(iCoeEnv->WsSession());
+    if (aDirection == EBackwards)
+        {
+        TApaTask task = taskList.FindByPos(-1);
+        task.BringToForeground();
+        }
+    else
+        {
+        TApaTask task = taskList.FindByPos(0);
+        task.SendToBackground();
+        }
+    
+    // Will also task away from alarm when only 1 task!! Correct?        
+    NotifyAlarmServerOfTaskChangeL(); 
+    }
+
+EXPORT_C CEikServAppUiBase::CEikServAppUiBase()
+    {
+    SetFullScreenApp(EFalse);
+    }
+
+LOCAL_C void ReleaseFactories(TAny* aPtr)
+    {
+    TEikServCtrlFactories& factory = *(TEikServCtrlFactories*)aPtr;
+    if (factory.iAlert)
+        {
+        factory.iAlert->Release();
+        }
+    }
+
+LOCAL_C void PointerCleanup(TAny* aPtr)
+    {
+    RWsPointerCursor* ptr = REINTERPRET_CAST(RWsPointerCursor*, aPtr);
+    ptr->Close();
+    delete ptr;
+    }
+
+EXPORT_C void CEikServAppUiBase::ConstructL() 
+    {
+    RWindowGroup& groupWin = iCoeEnv->RootWin();
+    RWsSession& wsSession = iCoeEnv->WsSession();
+    iEikonEnv->SetAutoForwarding(ETrue);
+    iEikonEnv->SetSystem(ETrue);
+    iEikonEnv->FsSession().SetNotifyUser(EFalse);
+
+    // Must call BaseConstructL to get Avkon classes called.
+#ifdef _DEBUG
+    RDebug::Print(_L("CAknAppUiBase::BaseConstructL() in "));
+#endif
+    CAknAppUiBase::BaseConstructL(ENonStandardResourceFile|ENoScreenFurniture|
+        EAknEnableMSK|EAknSingleClickCompatible);
+#ifdef _DEBUG
+    RDebug::Print(_L("CAknAppUiBase::BaseConstructL() out"));
+#endif
+
+    groupWin.SetName(__EIKON_SERVER_NAME);
+    groupWin.EnableErrorMessages(EEventControlAlways);
+    groupWin.EnableOnEvents(EEventControlAlways);
+    wsSession.ComputeMode(RWsSession::EPriorityControlDisabled);
+    iCoeEnv->RootWin().EnableScreenChangeEvents();
+    RThread thread;
+    
+#if defined(__EPOC32__)
+    thread.SetProcessPriority(EPriorityHigh);
+#else
+    thread.SetPriority(EPriorityAbsoluteForeground);
+#endif
+
+    // Create a window group for the password and alarm screens.
+    iAlertGroupWin = RWindowGroup(wsSession);
+    
+    // EFalse disables key events - they will be enabled again as soon as the ordinal position is 
+    // set such that iAlertGroupWin is not the foreground window-group.
+    User::LeaveIfError(iAlertGroupWin.Construct((TUint32)this, EFalse)); 
+    
+    iAlertGroupWin.SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront);
+    
+    // Enable key events, now that iAlertGroupWin is not in the foreground.
+    iAlertGroupWin.EnableReceiptOfFocus(ETrue); 
+
+    iEikServExtra = new(ELeave) CEikServExtra();
+    
+    TInt numCursors = LafServAppUiBase::NumberOfCursorsInSystemCursorList();
+    if(numCursors != 0 && LafServAppUiBase::ClaimPointerCursorListIfNeeded(*iEikonEnv) == KErrNone)
+        {
+        iEikServExtra->iPointerCursors = new(ELeave) CArrayPtrFlat<RWsPointerCursor>(4);
+        TSpriteMember member;
+        for(TInt ii = 0; ii < numCursors; ii++)
+            {
+            RWsPointerCursor* cursor = LafServAppUiBase::ConstructPointerCursorL(ii, member, 
+                *iEikonEnv);
+                
+            CleanupStack::PushL(TCleanupItem(PointerCleanup, cursor));
+            iEikServExtra->iPointerCursors->AppendL(cursor);
+            CleanupStack::Pop(); // cursor - handle & ptr
+            }
+        }
+    }
+
+EXPORT_C void CEikServAppUiBase::InitializeL(TEikServCtrlFactories& aCtrlFactories)
+    {
+    RWindowGroup& rootWin = iCoeEnv->RootWin();
+
+    CleanupStack::PushL(TCleanupItem(&ReleaseFactories,&aCtrlFactories));
+    RFs& fsSession = iCoeEnv->FsSession();
+    _LIT(KAppDirName, "C:\\System\\Apps\\");
+    fsSession.MkDirAll(KAppDirName); // !! prevent app arch crash
+
+    // Initialize some system settings.
+    SetSystemTime();
+    rootWin.EnableOnEvents(EEventControlAlways);
+
+    TPasswordMode mode = EPasswordNone;
+
+    TRAP_IGNORE(
+        CEikPasswordModeCategory* pcategory = CEikPasswordModeCategory::NewLC(fsSession);
+        if( pcategory )
+            {
+            pcategory->GetPasswordModeL(mode);
+            if (mode == EPasswordNone) // prevent overwriting once per day
+                {
+                mode = EPasswordAlways;    
+                }
+            // Initialise (write to system.ini) here so that it won't fail in the future due to OOM.
+            pcategory->SetPasswordModeL(mode);
+            CleanupStack::PopAndDestroy(); // pcategory
+            }
+        );
+
+    // Create separate thread for OOD watchers.
+    CreateWatcherThreadL();
+
+    // Start View Server.
+    iAppStarter = CEikServAppStarter::NewL();
+    User::LeaveIfError(CVwsSessionWrapper::StartViewServer(*iAppStarter));
+    iVwsSession = CVwsSessionWrapper::NewL();
+    
+    TResourceReader reader;
+    iEikonEnv->CreateResourceReaderLC(reader, R_EIK_SYSTEM_DEFAULT_VIEW_ID);
+    TVwsViewId viewId;
+    viewId.iAppUid.iUid = reader.ReadInt32();
+    viewId.iViewUid.iUid = reader.ReadInt32();
+    CleanupStack::PopAndDestroy(); // reader
+    iVwsSession->SetSystemDefaultView(viewId);
+
+    TInt serverEventTimeOutDuration = EikResourceUtils::ReadTInt32L(    
+        R_EIK_SYSTEM_VIEW_SERVER_EVENT_TIME_OUT, iEikonEnv);
+        
+    iVwsSession->SetServerEventTimeOut( TTimeIntervalMicroSeconds32(serverEventTimeOutDuration) );
+    
+    TInt clientRequestTimeOutDuration = EikResourceUtils::ReadTInt32L(
+        R_EIK_SYSTEM_VIEW_SERVER_CLIENT_REQUEST_TIME_OUT, iEikonEnv);
+        
+    iVwsSession->SetClientRequestTimeOut( TTimeIntervalMicroSeconds32(clientRequestTimeOutDuration) );
+
+    iVwsSession->EnableServerBlankScreen(EFalse);
+    
+    // Start Comms
+    TInt err = StartC32();
+    if (err != KErrNone && err != KErrAlreadyExists)
+        {
+        User::Leave(err);
+        }
+    
+    err = User::LoadPhysicalDevice(COMMS_PDD_NAME);
+    if (err != KErrNone && err != KErrAlreadyExists && err != KErrNotFound)
+        {
+        User::Leave(err);
+        }
+        
+    err = User::LoadLogicalDevice(COMMS_LDD_NAME);
+    if (err != KErrNone && err != KErrAlreadyExists && err != KErrNotFound)
+        {
+        User::Leave(err);
+        }
+
+    // Start notifier server last as these may have plug-ins that rely on the other servers 
+    // started here being up and running.
+    iNotifyServer = CEikServNotifyServer::NewL(aCtrlFactories.iAlert);
+
+    CleanupStack::Pop(); // aCtrlFactories
+
+    iEikServExtra->iNotifierServerStarter = CIdle::NewL(CActive::EPriorityLow);
+    iEikServExtra->iNotifierServerStarter->Start(TCallBack(StartNotifierServerCallBackL, this));
+
+    rootWin.EnableGroupListChangeEvents();
+
+    // Create undertaker active object.
+    iUndertaker = CEikUndertaker::NewL(*this);
+
+    // Create an active object to restart servers. 
+    iEikServExtra->iServerRestarter = CPeriodic::NewL(CActive::EPriorityStandard);
+    }
+
+EXPORT_C void CEikServAppUiBase::HandleThreadExitL(RThread& aThread)
+    {
+    if (aThread.Name() == ASCliDefinitions::ServerAndThreadName()) // alarm server died
+        {
+        aThread.Close(); // need to Close() before restarting with same name
+        iServerToRestart |= EAlwlSvr; // restarted under active object
+        }
+    else if (aThread.Name()==NameApaServServerThread()) // AppArc server died
+        {
+        aThread.Close();
+        iServerToRestart|=EApaSvr;
+        }
+        
+    if (iServerToRestart && !iEikServExtra->iServerRestarter->IsActive())
+        {
+        iEikServExtra->iServerRestarter->Start(
+            KEikServServerRestartDelay, 
+            KEikServServerRestartInterval, 
+            TCallBack(RestartServerCallback, this));
+        }
+    }
+
+EXPORT_C void CEikServAppUiBase::HandleForegroundEventL(TBool aForeground)
+    {
+    CAknAppUiBase::HandleForegroundEventL(aForeground);
+    }
+
+TInt CEikServAppUiBase::RestartServerCallback(TAny* aObj)
+    {
+    STATIC_CAST(CEikServAppUiBase*, aObj)->RestartServer();
+    return KErrNone;
+    }
+
+TInt CEikServAppUiBase::StartNotifierServerCallBackL(TAny* aPtr)
+    { // static
+    CEikServAppUiBase* self = static_cast<CEikServAppUiBase*>(aPtr);
+    self->iNotifyServer->StartL();
+    delete self->iEikServExtra->iNotifierServerStarter;
+    self->iEikServExtra->iNotifierServerStarter=NULL;
+    return KErrNone;
+    }
+
+// Kick dead servers back to life, if we can connect then stop kicking.
+void CEikServAppUiBase::RestartServer()
+    {
+    if (iServerToRestart & EAlwlSvr)
+        {
+        // Start AlarmServer
+        TInt err = AlarmClientUtils::StartAlarmServer();
+        if (err == KErrNone)
+            {
+            iServerToRestart&=(~EAlwlSvr);
+            }
+        }
+        
+    if (iServerToRestart&EApaSvr)
+        {
+        AknStartupApaServerProcess();
+
+        // try to connect to the server
+        RApaLsSession ls;
+        TInt err = ls.Connect();
+        if (err == KErrNone)
+            {
+            ls.Close();
+            iServerToRestart&=(~EApaSvr);
+            }
+        }
+        
+    if (!iServerToRestart)
+        {
+        iEikServExtra->iServerRestarter->Cancel();
+        }
+    }
+
+EXPORT_C TKeyResponse CEikServAppUiBase::HandleKeyEventL(const TKeyEvent& aKeyEvent, 
+    TEventCode /*aType*/)
+    {
+    if (aKeyEvent.iCode == CTRL('e'))
+        {
+        CBaActiveScheduler::Exit();
+        }
+    return EKeyWasConsumed;
+    }
+
+// Check the battery states and update any alarm snooze time.
+EXPORT_C void CEikServAppUiBase::HandleSwitchOnEventL(CCoeControl* /*aDestination*/)
+    {
+    // Could just expose alarm alert server to UI dll!!
+    if (iAlarmAlertServer)
+        {
+        iAlarmAlertServer->HandleSwitchOnEvent();
+        }
+    }
+
+EXPORT_C void CEikServAppUiBase::HandleSystemEventL(const TWsEvent& aEvent)
+    {
+    TInt event = *((TInt*)aEvent.EventData());
+    switch (event)
+        {
+#ifdef _DEBUG
+        case EEikServExit:
+            CBaActiveScheduler::Exit();
+            break;
+#endif
+        default:
+            break;
+        }
+    }
+
+EXPORT_C void CEikServAppUiBase::HandleApplicationSpecificEventL(TInt aType, const TWsEvent& aEvent)
+    {
+    // Check command/number or whatever first!!
+    CAknAppUiBase::HandleApplicationSpecificEventL(aType, aEvent);
+    }
+
+
+EXPORT_C CEikServAppUiBase::~CEikServAppUiBase()
+    {
+    delete iUndertaker;
+    
+    if (iEikServExtra)
+        {
+        delete iEikServExtra->iServerRestarter;
+        
+        if (iEikServExtra->iPointerCursors)
+            {
+            const TInt count = iEikServExtra->iPointerCursors->Count();
+            
+            for (TInt ii = 0; ii < count; ii++)
+                {
+                (*(iEikServExtra->iPointerCursors))[ii]->Close();
+                }
+                
+            iEikServExtra->iPointerCursors->ResetAndDestroy();
+            delete iEikServExtra->iPointerCursors;
+            }
+            
+        delete iEikServExtra->iNotifierServerStarter;
+        delete iEikServExtra;
+        }
+        
+    LafServAppUiBase::FreePointerCursorListIfNeeded(*iEikonEnv);
+    RWindowGroup& groupWin = iEikonEnv->RootWin();
+    groupWin.DisableErrorMessages();
+    groupWin.DisableOnEvents();
+    iAlertGroupWin.Close();
+    delete iNotifyServer;
+    delete iAlarmAlertServer;
+    delete iAppStarter;
+    
+    if (iVwsSession)
+        {
+        iVwsSession->ShutdownViewServer();
+        delete iVwsSession;
+        }
+    }
+
+void CEikServAppUiBase::SetSystemTime() const
+    {
+    // Deprecated, we don't have capability to set system time.
+    }
+
+// Bring to foreground or send to background appropriately.
+EXPORT_C void CEikServAppUiBase::BringAlertGroupWinForwards(TBool aForwards)
+    {
+    if (aForwards)
+        {
+        if (!iAlertGroupForwardsCount++)
+            {
+            iAlertGroupWin.SetOrdinalPosition(0, KMaxTInt); 
+            }
+        }
+    else if (--iAlertGroupForwardsCount == 0)
+        {
+        iAlertGroupWin.SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront); 
+        }
+    }
+
+EXPORT_C void CEikServAppUiBase::SetStatusPaneFlags(TInt /*aFlags*/)
+    {
+    User::Leave(KErrNotSupported);
+    }
+
+EXPORT_C void CEikServAppUiBase::SetStatusPaneLayoutL(TInt /*aLayoutResId*/)
+    {
+    User::Leave(KErrNotSupported);
+    }
+
+EXPORT_C void CEikServAppUiBase::BlankScreenL()
+    {
+    User::Leave(KErrNotSupported);
+    }
+
+EXPORT_C void CEikServAppUiBase::UnblankScreen()
+    {
+    User::Leave(KErrNotSupported);
+    }
+
+EXPORT_C void CEikServAppUiBase::ShutdownAppsL(const TUid aRequesterUID, 
+    const RMessage2& aShutdownMessage, const TInt aTimeoutInMicroseconds)
+    {
+    CEikSrvAppShutdown::StartL(aRequesterUID, aShutdownMessage, aTimeoutInMicroseconds);
+    }
+
+EXPORT_C void CEikServAppUiBase::HandleResourceChangeL(TInt aType)
+    {
+    CAknAppUiBase::HandleResourceChangeL(aType);
+    }
+
+void CEikServAppUiBase::Extension(TUid /*aExtensionUid*/, const TDesC8& /*aBuffer*/, 
+    RMessagePtr2 /*aMessage*/)
+    {
+    // Not implemented
+    }
+
+EXPORT_C void CEikServAppUiBase::HandleWsEventL(const TWsEvent& aEvent,CCoeControl* aDestination)
+    {
+    CAknAppUiBase::HandleWsEventL(aEvent, aDestination);
+    }
+
+void CEikServAppUiBase::SetSgcParamsL(TInt /*aWgId*/, TBitFlags /*aAppFlags*/, TInt /*aSpLayout*/, 
+    TInt /*aSpFlags*/)
+    {
+    }
+
+void CEikServAppUiBase::PrepareForAppExitL(TInt /*aWgId*/)
+    {
+    }
+
+
+// =============
+// CEikServAppUi
+// =============
+
+void CEikServAppUi::SetStatusPaneFlags(TInt aFlags)
+    {
+    if (iAknCapServerClient.Handle())
+        {
+        iAknCapServerClient.SetStatusPaneFlags(aFlags);
+        }
+    }
+
+void CEikServAppUi::SetStatusPaneLayoutL(TInt aLayoutResId)
+    {
+    if (iAknCapServerClient.Handle())
+        {
+        iAknCapServerClient.SetStatusPaneLayout(aLayoutResId);
+        }
+    }
+
+void CEikServAppUi::BlankScreenL()
+    {
+    if (iAknCapServerClient.Handle())
+        {
+        iAknCapServerClient.BlankScreen();
+        }
+    }
+
+void CEikServAppUi::UnblankScreen()
+    {
+    if (iAknCapServerClient.Handle())
+        {
+        iAknCapServerClient.UnblankScreen();
+        }
+    }
+
+void CEikServAppUi::EnableTaskListL()
+    {
+    User::LeaveIfError(iAknCapServerClient.EnableTaskList(ETrue));
+    }
+
+void CEikServAppUi::LaunchTaskListL() //const
+    {
+    User::LeaveIfError(iAknCapServerClient.MakeTaskListVisible(ETrue));
+    }
+
+void CEikServAppUi::CloseTaskList() //const
+    {
+    // Ignore possible error.
+    iAknCapServerClient.MakeTaskListVisible(EFalse);
+    }
+
+CEikServAppUi::CEikServAppUi()
+    {
+    }
+
+void CEikServAppUi::ConstructL()
+    {
+    // Create stub to allow device boot up with old notifier controller dependencies.
+    iNotifierDialogController = CNotifierDialogController::NewL(0);
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL() in"));
+#endif
+
+    AknsUtils::InitSkinSupportL();
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL() init skins ok"));
+#endif
+
+    CEikServAppUiBase::ConstructL();
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL() CEikServAppUiBase constructed"));
+#endif
+
+    AknsUtils::SetAvkonSkinEnabledL( ETrue );
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), CEikServAppUiBase::ConstructL() succeed"));
+#endif
+
+    AknsUtils::SetAvkonSkinEnabledL( ETrue );
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUiBase::ConstructL(), Skins enabled"));
+#endif
+
+    TFileName fileName(KResFileName);
+    BaflUtils::NearestLanguageFile(iEikonEnv->FsSession(), fileName);
+    iResourceFileOffset = iCoeEnv->AddResourceFileL(fileName);
+
+    // Create notifier controller before Notfier server is started.
+    iNotifierController = CAknNotifierController::NewL();
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), initializing Alert"));
+#endif
+
+    CEikServNotifyAlert* alert=new(ELeave) CEikServNotifyAlert;
+    CleanupStack::PushL(alert);
+    alert->ConstructL();
+    TEikServCtrlFactories fctry;
+    fctry.iAlert = alert;
+    fctry.iAlarmAlert = this;
+    CleanupStack::Pop();
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), Alert created"));
+#endif
+
+    CEikServAppUiBase::InitializeL(fctry);
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUiBase::InitializeL(fctry) succeed"));
+#endif
+
+    RWsSession& wsSession = iCoeEnv->WsSession();
+
+    // Initialize some system settings.
+    TRAP_IGNORE(EnsureExternalKeyHandlerAppStreamExistsL());
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), Creating WG for status pane"));
+#endif
+
+    // Create high priority windows for app bar and side bar.
+    iOffScreenGroupWin = RWindowGroup(wsSession);
+    User::LeaveIfError(iOffScreenGroupWin.Construct((TUint32)&iOffScreenGroupWin, 
+        EFalse)); // EFalse disables key events
+    iOffScreenGroupWin.SetOrdinalPosition(0,ECoeWinPriorityHigh);
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), Starting sound server"));
+#endif
+
+    // Launch the Avkon KeySound Server
+    User::LeaveIfError(CEikKeySoundServer::LaunchServer(iKeySoundThreadId));
+    
+    // Start the Avkon Anim Dll - required for keysounds
+    iAknAnimDll = new(ELeave)RAnimDll(wsSession);
+    iAknAnimDll->Load(KAnimDllFileName);
+    iAknAnimKeySound = new(ELeave)RAknAnimKeySound(*iAknAnimDll);
+    iAknAnimKeySound->ConstructL(&iOffScreenGroupWin);
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), Keysounds and plugin initialized"));
+#endif
+
+    // Create default keysounds - pass in UID.
+    ReplaceKeySoundsL(0x100053D0);
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), Default client and context for keysound created "));
+#endif
+
+    // Window server buffer size.
+    RWsSession &ws = iEikonEnv->WsSession();
+    TInt bufSize = 6400;
+    ws.SetMaxBufferSizeL(bufSize);
+
+    // Load bitmap cursors.
+    LoadBitmapCursorsL();
+
+    STATIC_CAST(CEikServEnv*,CEikonEnv::Static())->SetEikServAppUiSessionFactory( this );
+
+#ifdef _DEBUG
+    RDebug::Print(_L("CEikServAppUi::ConstructL(), over and out"));
+#endif
+    }
+
+
+void CEikServAppUi::RestartKeySoundThreadL()
+    {
+    // Restart keysound server.
+    TInt err = CEikKeySoundServer::LaunchServer(iKeySoundThreadId);
+    if (err != KErrNone)
+        {
+        // Server cannot be restarted, so leave existing animation dll.
+        // No sounds will be played, but machine will still operate.
+        return;
+        }
+        
+    // Restart the animation dll
+    if (iAknAnimKeySound)
+        {
+        iAknAnimKeySound->Close();
+        delete iAknAnimKeySound;
+        iAknAnimKeySound = NULL;
+        }
+        
+    if (iAknAnimDll)
+        {
+        iAknAnimDll->Close();
+        delete iAknAnimDll;
+        iAknAnimDll = NULL;
+        }
+
+    // Restart the animation dll.
+    iAknAnimDll = new(ELeave)RAnimDll(iCoeEnv->WsSession());
+    iAknAnimDll->Load(KAnimDllFileName);
+    iAknAnimKeySound = new(ELeave)RAknAnimKeySound(*iAknAnimDll);
+    iAknAnimKeySound->ConstructL(&iOffScreenGroupWin);
+
+    // Invented new API.
+    ReplaceKeySoundsL(0x100053D0);
+    KeySounds()->BringToForeground();
+    }
+
+
+void CEikServAppUi::HandleThreadExitL(RThread& aThread)
+    {
+    if(aThread.Name().CompareF(_L("aknnfysrv")) == 0)
+        {
+        StartNewServerApplicationL(KCommonNotifierAppSrvUid);
+        return;
+        }
+
+    TThreadId id = aThread.Id();
+    TExitType exitType = aThread.ExitType();
+    if (id == iExternalKeyHandlerThreadId)
+        {
+        iExternalKeyHandlerRunning = EFalse;
+        }
+    else if (id == iHelpAppThreadId)
+        {
+        iHelpAppRunning = EFalse;
+        }
+    else if (id == iKeySoundThreadId)
+        {
+        RestartKeySoundThreadL();
+        // Don't tell the user about it.
+        return;
+        }
+
+    TBool rdSupport = BaflUtils::FileExists( iEikonEnv->FsSession(), KRDSupport );
+
+    // Show panic notes only if that feature is enabled.
+    if ( exitType == EExitPanic && ( rdSupport || FeatureManager::FeatureSupported( 
+        KFeatureIdShowPanics )) )
+        {
+        // Construct text for a panic note.
+        HBufC* panicText = ConstructPanicTextLC( aThread, rdSupport );
+        
+        iAknCapServerClient.ShowGlobalNoteL(panicText->Des(), EAknGlobalErrorNote);
+        CleanupStack::PopAndDestroy(); // panicText
+        }
+        
+    CEikServAppUiBase::HandleThreadExitL(aThread);
+    }
+
+void CEikServAppUi::UpdateTaskListL()
+    {
+    iAknCapServerClient.UpdateTaskList();
+    }
+
+TKeyResponse CEikServAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode /*aType*/)
+    {
+    if (aKeyEvent.iCode == CTRL('e')) // Exit
+        {
+        CBaActiveScheduler::Exit();
+        }
+    return EKeyWasConsumed;
+    }
+
+void CEikServAppUi::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination)
+    {
+    switch (aEvent.Type())
+        {
+        case EEventPassword:
+            {
+            // No action in Avkon.
+            break;
+            }
+        case EEventErrorMessage:
+            HandleErrorMessageEvent(*(aEvent.ErrorMessage()));
+            break;
+        case KUidValueAknsSkinChangeEvent:
+            {
+            HandleResourceChangeL(KAknsMessageSkinChange);
+            HandleStackedControlsResourceChange(KAknsMessageSkinChange);
+            break;
+            }
+        default:
+            CEikServAppUiBase::HandleWsEventL(aEvent, aDestination);
+            break;
+        }
+    }
+
+// Handle an error message from the window server.
+void CEikServAppUi::HandleErrorMessageEvent(const TWsErrorMessage& aErrorMessage)
+    {
+    TUint err = aErrorMessage.iError;
+    
+    switch (aErrorMessage.iErrorCategory)
+        {
+        case TWsErrorMessage::EDrawingRegion:
+            HandleOomEvent();
+            break;
+        case TWsErrorMessage::EBackLight:
+            HandleBacklightError(err);
+            break;
+        case TWsErrorMessage::ELogging:
+            HandleWservLoggingError(err);
+            break;
+        default:
+            break; // intentionally ignored
+        }
+    }
+
+void CEikServAppUi::HandleResourceChangeL(TInt aType)
+    {
+    CEikServAppUiBase::HandleResourceChangeL(aType);
+    if ( aType == KEikDynamicLayoutVariantSwitch )
+        {
+        UpdateCursorsL();
+        }
+    }
+
+// Check the battery states and update any alarm snooze time.
+void CEikServAppUi::HandleSwitchOnEventL(CCoeControl* /*aDestination*/)
+    {
+    if (iAlarmAlertServer)
+        {
+        iAlarmAlertServer->HandleSwitchOnEvent();
+        }
+    }
+
+void CEikServAppUi::HandleSystemEventL(const TWsEvent& aEvent)
+    {
+    TInt event = *((TInt*)aEvent.EventData());
+    switch (event)
+        {
+#ifdef _DEBUG
+        case EEikServExit:
+            CBaActiveScheduler::Exit();
+            break;
+#endif
+        case EEikServChangePasswordMode:
+            // No action in Avkon
+            break;
+        case EEikServShowTaskList:
+            LaunchTaskListL();
+            break;
+        case EEikServHideTaskList:
+            CloseTaskList();
+            break;
+        default:
+            break;
+        }
+    }
+
+CEikServAppUi::~CEikServAppUi()
+    {
+    if (iAknAnimKeySound)
+        {
+        iAknAnimKeySound->Close();
+        }
+    delete iAknAnimKeySound;
+    
+    if (iAknAnimDll)
+        {
+        iAknAnimDll->Close();
+        }
+    delete iAknAnimDll;
+
+    // Shut down the key sound server.
+    RKeySoundServerCloser ksCloserSession;
+    ksCloserSession.CloseServer();
+
+    iOffScreenGroupWin.Close();
+    delete iAppbarWindow;
+    delete iSidebarWindow;
+    
+    if (iCoeEnv)
+        {
+        iCoeEnv->DeleteResourceFile(iResourceFileOffset);
+        }
+
+    delete iIdler;
+    iNotifServerAppQueue.Close();
+
+    delete iNotifierController;
+    delete iNotifierDialogController;
+    }
+
+MEikServAlarm* CEikServAppUi::NewAlarmL(CEikAlmControlSupervisor& aSupervisor)
+    {
+    CEikAlarmControl* alarm = new(ELeave) CEikAlarmControl(&aSupervisor,this);
+    CleanupStack::PushL(alarm);
+    alarm->ConstructL();
+    CleanupStack::Pop(); // alarm
+    return alarm;
+    }
+
+void CEikServAppUi::EnsureExternalKeyHandlerAppStreamExistsL()
+    {
+    }
+
+// Respond to an out of memory event from the window server.
+void CEikServAppUi::HandleOomEvent()
+    {
+    TBuf<80> msg1;
+    TBuf<80> msg2;
+    iEikonEnv->ReadResource(msg1, R_EIKSRV_OOM_EVENT_TOP);
+    iEikonEnv->ReadResource(msg2, R_EIKSRV_OOM_EVENT_BOT);
+    MEikAlertWin* mAlert = CONST_CAST(MEikAlertWin*, iEikonEnv->Alert());
+    CEikDialog* alert = mAlert->AsEikDialog();
+    
+    CEikMover* title = NULL;
+    if ( alert )
+        {
+        title = &( alert->Title() );
+        alert->SetGloballyCapturing(ETrue);
+        title->SetActive(EFalse);
+        }
+    iEikonEnv->AlertWin(msg1, msg2);
+    if ( alert )
+        {
+        title->SetActive(ETrue);
+        alert->SetGloballyCapturing(EFalse);
+        }
+    }
+
+// Respond to an error from the backlight (battery too low).
+void CEikServAppUi::HandleBacklightError(TInt /*aError*/)
+    {
+    }
+
+// Respond to a logging error from wserv (for use by developers)
+void CEikServAppUi::HandleWservLoggingError(TInt aError)
+    {
+    TBuf<80> temp;
+    iEikonEnv->ReadResource(temp, R_EIKSRV_WSERV_LOGGING_ERROR);
+    TBuf<80> msg;
+    msg.Format(temp, aError);
+    iEikonEnv->AlertWin(msg);
+    }
+
+EXPORT_C void CEikServAppUi::SuppressAppSwitching(TBool aSuppress)
+    {
+    // Ignore error as there is nothing to do if failing.
+    iAknCapServerClient.ConnectAndSendAppsKeySuppress(aSuppress);
+    }
+
+HBufC* CEikServAppUi::ConstructPanicTextLC( RThread& aThread, TBool aRDSupport ) const
+    {
+    HBufC* panicText = HBufC::NewLC( KEikServPanicTextBufferSize );
+    TPtr ptr = panicText->Des();
+
+    iEikonEnv->ReadResource( ptr, R_PROGRAM_CLOSED );
+
+    ptr.Append( '\n' );
+
+    HBufC* buffer = aThread.Name().AllocL();
+    TPtr name = buffer->Des();
+
+    // Here we truncate the thread name to fit in the second and third lines of the note.
+
+    TRect mainPane;
+    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EPopupParent, mainPane );
+    TAknLayoutRect popupNoteWindow;
+    
+    AknLayoutUtils::TAknCbaLocation cbaLocation( AknLayoutUtils::CbaLocation() );
+    TInt variety( 0 );
+    if ( cbaLocation == AknLayoutUtils::EAknCbaLocationRight )
+        {
+        variety = 3;
+        }
+    else if ( cbaLocation == AknLayoutUtils::EAknCbaLocationLeft )
+        {
+        variety = 6;
+        }
+    else
+        {
+        variety = 0;
+        }
+        
+    popupNoteWindow.LayoutRect(mainPane, AknLayoutScalable_Avkon::popup_note_window( variety ) );
+        
+    TAknLayoutText textRectTwoLines;
+    
+    textRectTwoLines.LayoutText(
+        popupNoteWindow.Rect(), 
+        AKN_LAYOUT_TEXT_Note_pop_up_window_texts_Line_1(1));
+
+    // First determine how much fits in the 2. line of the note this can't return NULL.
+    const CFont* font = textRectTwoLines.Font();
+
+    TInt characters( font->TextCount( name, textRectTwoLines.TextRect().Width() ) );
+
+    // 'characters' is now the amount of characters that fit in the second line.
+
+    ptr.Append( name.Left( characters ) );
+    ptr.Append( '\n' );
+
+    // If the name was cut, clip the rest in the third line.
+    TInt charactersLeft( name.Length() - characters );
+
+    if ( charactersLeft > 0 )
+        {
+        TPtr line3( 
+            (TText*)&name[characters],
+            charactersLeft,
+            charactersLeft );
+
+        popupNoteWindow.LayoutRect(
+            mainPane, 
+            AknLayoutScalable_Avkon::popup_note_window( variety + 1) );
+            
+        TAknLayoutText textRectThreeLines;
+        
+        textRectThreeLines.LayoutText(
+            popupNoteWindow.Rect(), 
+            AKN_LAYOUT_TEXT_Note_pop_up_window_texts_Line_1(2));
+            
+        // No bidirectional text support for rendering the thread name. This is intentional.
+
+        AknTextUtils::ClipToFit(
+            line3,
+            *font,
+            textRectThreeLines.TextRect().Width() );
+
+        ptr.Append( line3 );
+        ptr.Append( '\n' );
+        }
+
+    delete buffer;
+
+    // Append panic category and reason only if RD-support file exists.
+
+    if ( aRDSupport )
+        {
+        ptr.Append( aThread.ExitCategory() );
+        ptr.Append( ' ' );
+        ptr.AppendNum( aThread.ExitReason() );
+        }
+
+    return panicText;
+    }
+
+void CEikServAppUi::LoadBitmapCursorsL()
+    {
+    RWsSession& ws = iEikonEnv->WsSession();
+
+    // Create the array containing one sprite member.
+    TFixedArray<TSpriteMember, 1> spriteMemberArray;
+    TSpriteMember& spriteMember = spriteMemberArray[0];
+    spriteMember.iInterval = TTimeIntervalMicroSeconds32(0);
+
+    // This resource is of type AVKON_CUSTOM_TEXT_CURSORS defined in eiksrvui.rss.
+    TResourceReader reader;
+    iEikonEnv->CreateResourceReaderLC(reader, R_AKN_CUSTOM_TEXT_CURSORS);
+
+    HBufC* bmpFile = reader.ReadHBufCL();
+    CleanupStack::PushL(bmpFile);
+
+
+    TInt count = reader.ReadInt16();
+    for (TInt ii = 0; ii < count; ii++)
+        {
+        // id
+        TInt id = reader.ReadInt32();
+
+        // bmpId and maskId
+        TInt bmpId = reader.ReadInt32();
+        TInt maskId = reader.ReadInt32();
+        spriteMember.iBitmap = NULL;
+        spriteMember.iMaskBitmap = NULL;
+
+        if (maskId != -1)
+            {
+            AknIconUtils::CreateIconLC( 
+                spriteMember.iBitmap,
+                spriteMember.iMaskBitmap,
+                *bmpFile,
+                bmpId,
+                maskId );
+            }
+        else
+            {
+            spriteMember.iBitmap = AknIconUtils::CreateIconL( *bmpFile, bmpId );
+            CleanupStack::PushL( spriteMember.iBitmap );
+            }
+         
+        TAknWindowLineLayout l;
+
+        switch( id )
+            {
+            case KAknCustomTextCursorIdLeftToRight:
+            case KAknCustomTextCursorIdRightToLeft:
+                l = AknLayoutScalable_Avkon::cursor_primary_pane().LayoutLine();
+                break;
+            case KAknCustomTextCursorIdLeftToRightThin:
+            case KAknCustomTextCursorIdRightToLeftThin:
+            default:
+                l = AknLayoutScalable_Avkon::cursor_primary_small_pane().LayoutLine();                   
+                break;
+            }
+
+        TRect rectParent = ApplicationRect();
+        TAknLayoutRect layoutRect;
+        layoutRect.LayoutRect( rectParent, l );
+        TRect rectCursorBitmap( layoutRect.Rect() );
+        TSize scaledSize(rectCursorBitmap.Width(),  rectCursorBitmap.Height() );
+        
+        // Perform the scaling
+        AknIconUtils::SetSize( 
+            spriteMember.iBitmap, 
+            scaledSize, 
+            EAspectRatioPreservedAndUnusedSpaceRemoved);
+            
+        if ( spriteMember.iMaskBitmap )
+            {
+            AknIconUtils::SetSize( 
+                spriteMember.iMaskBitmap, 
+                scaledSize, 
+                EAspectRatioPreservedAndUnusedSpaceRemoved);
+            }
+        
+        // Flags.
+        TUint flags = reader.ReadUint16();
+        spriteMember.iInvertMask = flags|EAknCustomTextCursorFlagInvertMask;
+
+        // Draw mode.
+        spriteMember.iDrawMode = (CGraphicsContext::TDrawMode)reader.ReadInt16();
+
+        // Offset. Use actual scalings used. Do not read inside TPoint constructor for compiler 
+        // independence.
+        TInt offsetX = reader.ReadInt16(); 
+        TInt offsetY = reader.ReadInt16(); 
+        spriteMember.iOffset = TPoint(offsetX, offsetY);
+
+        // Alignment.
+        TInt align = reader.ReadInt16();
+
+        // Decode the "vehicle ids" into features:
+        TAknFontCategory category(EAknFontCategoryPrimary);
+        TBool isRightToLeft(EFalse);
+
+        switch( id )
+            {
+            case KAknCustomTextCursorIdLeftToRight:
+                break;
+            case KAknCustomTextCursorIdRightToLeft:
+                isRightToLeft = ETrue;
+                break;
+            case KAknCustomTextCursorIdLeftToRightThin:
+                category = EAknFontCategoryPrimarySmall;
+                break;
+            case KAknCustomTextCursorIdRightToLeftThin:
+                category = EAknFontCategoryPrimarySmall;
+                isRightToLeft = ETrue;
+                break;
+            default:
+                // Should not get here if the resource is correct. Already initialized defaults 
+                // get used.
+                break;
+            }
+
+        id = AknCustomCursorSupport::CustomBidiTextCursorId( 
+            category, 
+            rectCursorBitmap, 
+            isRightToLeft );
+
+        // Return code is ignored since we will regularly be setting a bitmap twice
+        (void)ws.SetCustomTextCursor(
+            id, 
+            spriteMemberArray.Array(), 
+            ESpriteFlash, 
+            (RWsSession::TCustomTextCursorAlignment)align);
+
+        if (maskId != -1)
+            {
+            CleanupStack::PopAndDestroy(spriteMember.iMaskBitmap);
+            }
+        CleanupStack::PopAndDestroy(spriteMember.iBitmap);
+        }
+
+    CleanupStack::PopAndDestroy(bmpFile);
+    CleanupStack::PopAndDestroy();        // reader
+    }
+
+//
+// First export
+//
+
+EXPORT_C CEikServAppUi* CreateAppUi()
+    {
+    return new CEikServAppUi;
+    }
+
+EXPORT_C void CEikServAppUi::ActivateDisplayIfNeeded()
+    {
+#ifndef __WINS__
+
+    // Check if screen saver active.
+    TApaTaskList list(iCoeEnv->WsSession());
+    TApaTask task = list.FindByPos(0); // topmost application
+    CApaWindowGroupName* name = 0;
+    TRAPD( err, name = CApaWindowGroupName::NewL(iCoeEnv->WsSession(), task.WgId()));
+    if ( !err && name->AppUid() == TUid::Uid(0x100056CF) ) // Screen saver Uid
+        {
+        User::ResetInactivityTime();
+        }
+    delete name;
+#endif
+    }
+
+EXPORT_C CEikServAppUiSession* CEikServAppUi::CreateSessionL( /*RThread aClient*/ )
+    {
+    return CAknEikServAppUiSession::NewL( /*aClient,*/ this, *this);
+    }
+
+void CEikServAppUi::Extension(TUid aExtensionUid, const TDesC8& aBuffer, RMessagePtr2 aMessage)
+    {
+    TBool hasCap = aMessage.HasCapability(ECapabilityWriteDeviceData); // Write Dev D required here
+
+    if (!hasCap)
+        {
+        aMessage.Complete(KErrPermissionDenied);
+        return;
+        }
+
+    switch(aExtensionUid.iUid)
+        {
+        case EAknCommonNotifierServerRunning:
+            {
+            aMessage.Complete(KErrNone);
+            TRAP_IGNORE(
+                // Do not clear the list, it can be used when common notifier server is being
+                // restarted due crash.
+                for (TInt i = iNotifierController->iPreloadList.Count() - 1; i >= 0; i--)
+                    {
+                    iNotifierController->iPreloadList[i]->PreLoadLibraryL();
+                    }
+                );
+            break;   
+            }
+        case EAknNotifierControllerCmd: 
+            {
+            TInt cmd = static_cast<TInt>(*(aBuffer.Ptr()));
+#ifdef _DEBUG
+            RThread thread;
+            aMessage.ClientL(thread); // ok to leave in debug mode
+            TName threadName( thread.Name() );
+#endif        
+            if(cmd == CAknNotifierControllerUtility::EDoAllow)
+                {
+#ifdef _DEBUG
+                
+                RDebug::Print(_L("Allow all notifications: thread %S"), &threadName);      
+#endif
+                NotifierController()->DoAllowNotifications();
+                }
+            else if(cmd == CAknNotifierControllerUtility::EDoStop)
+                {
+#ifdef _DEBUG
+                RDebug::Print(_L("Stop all notifications: thread %S"), &threadName);
+#endif
+                NotifierController()->DoStopNotifications();
+                }
+            else if(cmd == CAknNotifierControllerUtility::DoCancelAll)
+                {
+#ifdef _DEBUG
+                RDebug::Print(_L("Cancel all notifications: thread %S"), &threadName);      
+#endif
+                CloseTaskList();
+                NotifierController()->DoCancelAllNotificatons();
+                }
+            else    
+                {
+                if (!aMessage.IsNull())
+                    {
+                    aMessage.Complete(KErrNotSupported);
+                    }
+                return; 
+                } 
+    
+            if (!aMessage.IsNull())
+                { 
+                // Release caller before forwarding to app servers.                    
+                aMessage.Complete(KErrNone); 
+                }
+            
+            NotifierController()->NotifyAppServers(cmd);
+            break;
+            }
+        case EAknCapServerStartupComplete:
+            {
+            aMessage.Complete(KErrNone); // No one is listening this return value.
+            TRAP_IGNORE(DoAknCapServerStartupCompleteL());
+            break;  
+            }
+        case EAknSignalAknCapServerReady:
+            {
+            DoSignalWhenAknServerReady(aMessage); // Completes message when akncapserver is ready.
+            break;
+            }
+        default:
+            aMessage.Complete(KErrNotSupported);
+        }
+    }
+
+/// Session within avkon code:
+
+CAknEikServAppUiSession::CAknEikServAppUiSession(
+    /* RThread aClient, */
+    MEikServAppUiSessionHandler* aHandler, 
+    CEikServAppUi& aAppUi )
+: CEikServAppUiSession( aHandler), iAppUi(aAppUi)
+    {
+    }
+
+CAknEikServAppUiSession* CAknEikServAppUiSession::NewL(
+    /*RThread aClient, */
+    MEikServAppUiSessionHandler* aHandler, 
+    CEikServAppUi& aAppUi )
+    {
+    CAknEikServAppUiSession* session = new(ELeave) CAknEikServAppUiSession( 
+        /*aClient,*/ 
+        aHandler, 
+        aAppUi);
+        
+    CleanupStack::PushL(session);
+    session->ConstructL();
+    CleanupStack::Pop();
+    return session;
+    }
+
+CAknEikServAppUiSession::~CAknEikServAppUiSession()
+    {
+    }
+
+void CAknEikServAppUiSession::ConstructL()
+    {
+    }
+
+void CAknEikServAppUiSession::ServiceL(const RMessage2 &aMessage)
+    {
+    switch (aMessage.Function())
+        {
+        case EEikAppUiNotifyAlarmServerOfTaskChange:
+            SessionHandler()->NotifyAlarmServerOfTaskChangeL();
+            aMessage.Complete(KErrNone); 
+            break;
+        case EEikAppUiEnableTaskList:
+            SessionHandler()->EnableTaskListL();
+            aMessage.Complete(KErrNone);
+            break;
+        case EEikAppUiLaunchTaskList:
+            SessionHandler()->LaunchTaskListL();
+            aMessage.Complete(KErrNone);
+            break;
+        case EEikAppUiCycleTasks:
+            {
+            aMessage.Complete(KErrNone); 
+            }
+            break;
+        case EAknEikAppUiAddToStack:
+            {
+            CCoeControl*temp = REINTERPRET_CAST(CCoeControl*, CONST_CAST(TAny*, aMessage.Ptr0()) );
+            iAppUi.AddToStackL(temp, aMessage.Int1(), aMessage.Int2());
+            aMessage.Complete(KErrNone);
+            }
+            break;
+        case EAknEikAppUiRemoveFromStack:
+            {
+            CCoeControl*temp = REINTERPRET_CAST(CCoeControl*, CONST_CAST(TAny*, aMessage.Ptr0()) );
+            iAppUi.RemoveFromStack(temp);
+            aMessage.Complete(KErrNone);
+            }
+            break;
+        case EAknEikAppUiShutdownApps:
+            {
+            aMessage.HasCapabilityL(ECapabilityPowerMgmt); // PowerMgmt required here
+            TUid uid;
+            uid.iUid = (REINTERPRET_CAST(TInt, CONST_CAST(TAny*, aMessage.Ptr0()) ));
+            TInt timeout = REINTERPRET_CAST(TInt, CONST_CAST(TAny*, aMessage.Ptr1()) );
+            
+            //ShutdownAppsL must complete message.
+            TRAPD(err, iAppUi.ShutdownAppsL(uid, aMessage, timeout)); 
+            if (err != KErrNone)
+                { 
+                // Message wasn't completed.
+                aMessage.Complete(err);
+                }
+            }
+            break;
+         
+        default:
+            {
+            // It is the base class' responsibility to complete.
+            // This will pick up any new opcodes added by Symbian that are
+            // not yet handled here.
+            CEikServAppUiSession::ServiceL(aMessage);
+            break;    
+            }
+        }
+    }
+void CAknEikServAppUiSession::Write(const RMessage2& aMessage, const TAny* aPtr, const TDesC8& aDes,
+    TInt anOffset)
+    {
+    TRAPD(ret, aMessage.WriteL( (TInt)aPtr, aDes, anOffset);)
+    if (ret != KErrNone)
+        {
+        RThread clientThread;
+        (void)aMessage.Client( clientThread); 
+        clientThread.Panic(_L("CEikServAppUi server"), KErrGeneral);
+        }
+    }
+
+//
+// Main
+//
+
+GLDEF_C TInt PanicNoteThreadFunction( TAny* /*aParameters*/ )
+    {
+    return KErrNone;
+    }
+    
+// Probably obsolete, but just in case, Fix Me !!
+EXPORT_C void CEikServAppUi::HideApplicationFromFswL(TInt aUid,TBool aDisable)
+    {
+    iAknCapServerClient.HideApplicationFromFsw(aDisable, aUid);
+    }
+
+// Start new notifier server plugin using fixed server differentiator.
+void StartNotifierAppServerL(TUid aAppServerUid)
+    {
+    RApaLsSession apa;
+    User::LeaveIfError(apa.Connect());
+    CleanupClosePushL(apa);
+
+    TApaAppInfo info;
+    
+    TInt err(0);
+    for(TInt i = 20;
+        ((err = apa.GetAppInfo(info, aAppServerUid)) == RApaLsSession::EAppListInvalid) && i > 0;
+        i--)
+        {
+        User::After(500000);    
+        }
+
+    User::LeaveIfError(err);
+
+    CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
+    cmdLine->SetExecutableNameL(info.iFullName);
+    cmdLine->SetServerRequiredL(KUikonUidPluginInterfaceNotifiers);
+    cmdLine->SetCommandL(EApaCommandBackground);
+    TThreadId dummy;
+    User::LeaveIfError(apa.StartApp(*cmdLine, dummy));
+
+    CleanupStack::PopAndDestroy(2, &apa);   // cmdLine and apa
+    }
+
+TBool StartNotifierAppServer(TAny* aAny)
+    {
+    // Resolve uid.
+    CEikServAppUi* appUI = (CEikServAppUi*)aAny;
+    TUid serverUid = appUI->NextNotifierServerUid();  
+
+    // Check if the aknnfysrv.exe is running, perventing for dropping into
+    // an infinite loop of launching aknnfysrv.exe
+    if (serverUid == KCommonNotifierAppSrvUid)
+        {
+        TFullName serverName;
+        serverName.Format(_L("%08x_%08x_AppServer"), KUikonUidPluginInterfaceNotifiers, KCommonNotifierAppSrvUid);
+        TFindServer find(serverName);
+        TFullName fullName;
+        if (find.Next(fullName) == KErrNone)
+            {
+            // Aknnfysrv.exe is already running, so just return.
+            return EFalse;
+            }    
+        }
+
+    if (serverUid != KNullUid)
+        {
+        TRAP_IGNORE(StartNotifierAppServerL(serverUid))
+        }
+
+    return EFalse; // do not call back again 
+    }
+
+EXPORT_C void CEikServAppUi::StartNewServerApplicationL(TUid aAppServerUid)
+    {
+    // Add to queue.   
+    if (iNotifServerAppQueue.Find(aAppServerUid.iUid) == KErrNotFound)
+        {
+        iNotifServerAppQueue.AppendL(aAppServerUid.iUid);    
+        }
+
+    // Start idler if does not exist (if only akncapserver is already running).
+    if (!iIdler && iAknCapServerClient.Handle() != 0)
+        {
+        iIdler = CIdle::NewL(CActive::EPriorityHigh);
+        iIdler->Start(TCallBack(StartNotifierAppServer, this));
+        }
+    }
+    
+TUid CEikServAppUi::NextNotifierServerUid()
+    {
+    TInt uid = 0;
+
+    delete iIdler;
+    iIdler = 0;
+
+    if (iNotifServerAppQueue.Count()) 
+        {
+        uid = iNotifServerAppQueue[0];
+        iNotifServerAppQueue.Remove(0);
+        }    
+
+    // Activate idler for next uid.
+    if (iNotifServerAppQueue.Count()) 
+        {
+        // We must trap this call, if creating a new CIdle fails, no applications will be started 
+        // from queue until new request comes.
+        TRAPD(err, iIdler = CIdle::NewL(CActive::EPriorityHigh))
+        if (!err)
+            {
+            iIdler->Start(TCallBack(StartNotifierAppServer, this));
+            }
+        }
+     else
+        { 
+        // Last notifier app server is being launched, free starter.
+        if (!iAknCapServerMessage.IsNull())
+            {
+            iAknCapServerMessage.Complete(KErrNone);
+            }
+        }
+        
+    // Return uid of topmost.
+    return TUid::Uid(uid);  
+    }
+    
+void CEikServAppUi::UpdateCursorsL() 
+    {
+    LoadBitmapCursorsL();
+    }
+
+TInt DoPollCapServer(TAny* appui)
+    {
+    _LIT(KServerNameFormat, "%08x_%08x_AppServer");
+    TFullName serverName;
+    serverName.Format(KServerNameFormat, KUikonUidPluginInterfaceNotifiers, KAknCapServerUid.iUid);
+    TFindServer find(serverName);
+    TFullName fullName;
+    ((CEikServAppUi*)appui)->AknCapServerStartupComplete(find.Next(fullName) == KErrNone);
+    return KErrNone;
+    }
+
+// We are doing this on startup when there is always enough memory, so methods with L really 
+// can't leave.
+void CEikServAppUi::AknCapServerStartupComplete(TBool aComplete)
+    {
+    delete iIdler;
+    iIdler = 0;
+
+    if (aComplete)
+        {
+        // In this phase of boot, create real connection to akncapserver.
+        iAknCapServerClient.DoEikonServerConnect();           
+        
+        // Create alarm server as we have capserver running.
+        TRAPD(err, DoAlarmServerStartupL());
+        
+        // No use to startup phone if this fails.
+        __ASSERT_ALWAYS(!err, User::Invariant()); 
+        
+        iIdler = CIdle::NewL(CActive::EPriorityHigh);
+        iIdler->Start(TCallBack(StartNotifierAppServer, this));
+        }
+    else
+        {
+        const TInt waitDelay = 200000;  // 0.2 seconds
+        User::After(waitDelay);
+        DoAknCapServerStartupCompleteL();
+        }
+    }
+
+void CEikServAppUi::DoAknCapServerStartupCompleteL()
+    {
+    __ASSERT_DEBUG(iIdler == 0, User::Invariant());
+
+    iIdler = CIdle::NewL(CActive::EPriorityIdle);
+    iIdler->Start(TCallBack(DoPollCapServer, this));
+    }
+    
+void CEikServAppUi::DoSignalWhenAknServerReady(const RMessagePtr2& aMessage)
+    {
+    if (iAknCapServerClient.Handle() != 0)
+        {
+        aMessage.Complete(KErrNone);
+        }
+        
+    // This should be used as single shot.
+    __ASSERT_DEBUG(iAknCapServerMessage.IsNull(), User::Invariant());   
+    iAknCapServerMessage = aMessage;
+    }
+
+void CEikServAppUi::DoAlarmServerStartupL()
+    {
+    // Stupid naming, perhaps.
+    iAlarmAlertServer = CEikServAlarmAlertServer::NewL(this);
+
+    // Start AlarmServer.
+    TInt err = AlarmClientUtils::StartAlarmServer();
+    if (err != KErrNone && err != KErrAlreadyExists)
+        {
+        User::Leave(err);
+        }
+
+    HandleSwitchOnEventL( NULL );    
+    }
+
+// End of file