diff -r 000000000000 -r 2e3d3ce01487 startupservices/SplashScreen/src/SplashScreen.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/startupservices/SplashScreen/src/SplashScreen.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,612 @@ +/* +* Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Displays single startup screen. Animation not supported. +* +*/ + + +// SYSTEM INCLUDES +#include +#include +#include +#include +#include +#include + +// USER INCLUDES +#include "SplashScreen.h" +#include "SplashScreenDefines.h" + + +// ==================== LOCAL FUNCTIONS ==================== +LOCAL_C void DoItL(); + +GLDEF_C TInt E32Main() + { + TRACES("E32Main(): Start"); + + __UHEAP_MARK; + CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack + + TRAPD(error,DoItL()); // more initialization, then do Splash + __ASSERT_ALWAYS(!error,User::Panic(KPanicMsg,error)); + delete cleanup; // destroy clean-up stack + __UHEAP_MARKEND; // check no memory leak + TRACES("E32Main(): End"); + return KErrNone; + } + +// 120 seconds (the splash should have been killed +// by the Starter before this runs out) +const TInt KSplashTimeout=(2* 60 * 1000000); + + +/////////////////////////////////////////////////////////////////////////////// +////////////////////////// CWindow implementation ///////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +CWindow::CWindow(CWsClient* aClient) +: iClient(aClient) + { + TRACES("CWindow::CWindow()"); + } + +void CWindow::ConstructL (const TRect& aRect, CWindow* aParent) + { + TRACES("CWindow::ConstructL(): Start"); + + // If a parent window was specified, use it; if not, use the window group + // (aParent defaults to 0). + RWindowTreeNode* parent= aParent ? (RWindowTreeNode*) &(aParent->Window()) : &(iClient->iGroup); + iWindow=RWindow(iClient->iWs); // use app's session to window server + User::LeaveIfError(iWindow.Construct(*parent,(TUint32)this)); + TRACES1("CWindow::ConstructL(): Start - window handle is: 0x%08x", this); + iRect = aRect; + iWindow.SetExtent(iRect.iTl, iRect.Size()); // set extent relative to group coords + iWindow.Activate(); // window is now active + TRACES("CWindow::ConstructL(): End"); + } + + +CWindow::~CWindow() + { + TRACES("CWindow::~CWindow(): Start"); + iWindow.Close(); // close our window + TRACES("CWindow::~CWindow(): End"); + } + +RWindow& CWindow::Window() + { + TRACES("CWindow::Window()"); + return iWindow; + } + +CWindowGc* CWindow::SystemGc() + { + TRACES("CWindow::SystemGc()"); + return iClient->iGc; + } + + +/////////////////////////////////////////////////////////////////////////////// +////////////////////////// CWsRedrawer implementation ///////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +CWsRedrawer::CWsRedrawer() +: CActive(CActive::EPriorityLow) + { + TRACES("CWsRedrawer::CWsRedrawer()"); + } + +void CWsRedrawer::ConstructL(CWsClient* aClient) + { + TRACES("CWsRedrawer::ConstructL(): Start"); + iClient=aClient; // remember WsClient that owns us + CActiveScheduler::Add(this); // add ourselves to the scheduler + IssueRequest(); // issue request to draw + TRACES("CWsRedrawer::ConstructL(): End"); + } + +CWsRedrawer::~CWsRedrawer() + { + TRACES("CWsRedrawer::~CWsRedrawer(): Start"); + Cancel(); + TRACES("CWsRedrawer::~CWsRedrawer(): End"); + } + +void CWsRedrawer::IssueRequest() + { + TRACES("CWsRedrawer::IssueRequest(): Start"); + iClient->iWs.RedrawReady(&iStatus); + SetActive(); + TRACES("CWsRedrawer::IssueRequest(): End"); + } + +void CWsRedrawer::DoCancel() + { + TRACES("CWsRedrawer::DoCancel(): Start"); + iClient->iWs.RedrawReadyCancel(); + TRACES("CWsRedrawer::DoCancel(): End"); + } + +void CWsRedrawer::RunL() + { + TRACES("CWsRedrawer::RunL(): Start"); + + // find out what must be done + TWsRedrawEvent redrawEvent; + iClient->iWs.GetRedraw(redrawEvent); // get event + CWindow* window=(CWindow*)(redrawEvent.Handle()); // get window + if (window) + { + TRACES1("CWsRedrawer::RunL(): window - 0x%08x", window); + TRect rect=redrawEvent.Rect(); // and rectangle that needs redrawing + // now do drawing + iClient->iGc->Activate(window->Window()); + window->Window().BeginRedraw(rect); + window->Draw(rect); + window->Window().EndRedraw(); + iClient->iGc->Deactivate(); + } + // maintain outstanding request + IssueRequest(); + TRACES("CWsRedrawer::RunL(): End"); + } + +CTimeout::CTimeout() +: CTimer(0) + { + TRACES("CTimeout::CTimeout()"); + CActiveScheduler::Add(this); + } + +void CTimeout::ConstructL(CMainWindow* aWindow) + { + TRACES("CTimeout::ConstructL(): Start"); + CTimer::ConstructL(); + SetMainWindow( aWindow ); + TRACES("CTimeout::ConstructL(): End"); + } + +void CTimeout::SetMainWindow( CMainWindow* aWindow ) + { + iWindow = aWindow; + } + +void CTimeout::RunL() + { + TRACES("CTimeout::RunL(): Start"); + CActiveScheduler::Stop(); + if ( iWindow ) + { + iWindow ->Client()->Group().SetOrdinalPosition(0,ECoeWinPriorityNeverAtFront); // Background - so it's no more visible + } + TRACES("CTimeout::RunL(): End"); + } + + +///////////////////////////////////////////////////////////////////////////////////// +/////////////////////////// CWsClient implementation //////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CWsClient::CWsClient() +: CActive(CActive::EPriorityStandard), + iPSRemoveSplashState( ESplashRunning ) + { + TRACES("CWsClient::CWsClient()"); + } + +void CWsClient::ConstructL() + { + TRACES("CWsClient::ConstructL(): Start"); + + RProperty::Define(KPSUidStartup, + KPSSplashShutdown, + RProperty::EInt, + KReadPolicy, + KWritePolicy ); + RProperty::Set( KPSUidStartup, KPSSplashShutdown, iPSRemoveSplashState ); + CActiveScheduler::Install(new (ELeave) CActiveScheduler); + CActiveScheduler::Add(this); + iProperty.Attach( KPSUidStartup, KPSSplashShutdown ); + iProperty.Subscribe( iStatus ); + + // get a session going + User::LeaveIfError(iWs.Connect()); + + // construct screen device and graphics context + iScreen=new (ELeave) CWsScreenDevice(iWs); // make device for this session + User::LeaveIfError(iScreen->Construct( 0 )); // and complete its construction + User::LeaveIfError(iScreen->CreateContext(iGc)); // create graphics context + iLastScreenMode = iScreen->CurrentScreenMode(); + TRACES1("CWsClient::ConstructL() - iLastScreenMode: %d", iLastScreenMode); + + // construct our one and only window group + iGroup=RWindowGroup(iWs); + User::LeaveIfError(iGroup.Construct( (TInt) this,ETrue)); // meaningless handle; enable focus + // Set our name for sending commands via key-events + iGroup.SetName(KSplashScreenWindowGroup); + + TInt error = iGroup.EnableScreenChangeEvents(); + TRACES1("CWsClient::ConstructL() - enable screen change events: %d", error); + + // construct redrawer + iRedrawer=new (ELeave) CWsRedrawer; + iRedrawer->ConstructL(this); + User::LeaveIfError( RAknIconSrvClient::Connect() ); + // construct main window + ConstructMainWindowL(); + + iWs.EventReady(&iStatus); // request an event + SetActive(); // so we're now active + // request first event and start scheduler + + TRACES("CWsClient::ConstructL(): About to start CActiveScheduler"); + + CActiveScheduler::Start(); // start the active scheduler + + TRACES("CWsClient::CWsClient(): End"); + } + +CWsClient::~CWsClient() + { + TRACES("CWsClient::~CWsClient(): Start"); + RAknIconSrvClient::Disconnect(); + // neutralize us as an active object + Deque(); // cancels and removes from scheduler + // get rid of scheduler and all attached objects + delete CActiveScheduler::Current(); // delete the scheduler + // get rid of everything we allocated + delete iGc; + delete iScreen; + delete iRedrawer; + // destroy window group + iGroup.Close(); + // finish with window server + Cancel(); + iProperty.Close(); + iWs.Close(); + TRACES("CWsClient::~CWsClient(): End"); + } + +void CWsClient::Exit() + { + TRACES("CWsClient::Exit(): Start"); + CActiveScheduler::Stop(); + TRACES("CWsClient::Exit(): End"); + } + +void CWsClient::IssueRequest() + { + TRACES("CWsClient::IssueRequest(): Start"); + iWs.EventReady(&iStatus); // request an event + SetActive(); // so we're now active + TRACES("CWsClient::IssueRequest(): End"); + } + +void CWsClient::DoCancel() + { + TRACES("CWsClient::DoCancel(): Start"); + iWs.EventReadyCancel(); // cancel event request + TRACES("CWsClient::DoCancel(): End"); + } + +void CWsClient::ConstructMainWindowL() + { + TRACES("CWsClient::ConstructMainWindowL()"); + } + + + +////////////////////////////////////////////////////////////////////////////// +// Implementation for derived window classes +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// CMainWindow implementation // +////////////////////////////////////////////////////////////////////////////// + +/****************************************************************************\ +| Function: Constructor/Destructor for CMainWindow +| Doesn't do much, as most initialisation is done by the +| CWindow base class. +| Input: aClient Client application that owns the window +\****************************************************************************/ +CMainWindow::CMainWindow (CWsClient* aClient) +: CWindow (aClient) + { + TRACES("CMainWindow::CMainWindow()"); + } + + +CMainWindow::~CMainWindow () + { + TRACES("CMainWindow::~CMainWindow(): Start"); + delete iBitmap; + TRACES("CMainWindow::~CMainWindow(): End"); + } + +void CMainWindow::ConstructL (const TRect& aRect, CWindow* aParent) + { + TRACES("CMainWindow::ConstructL(): Start"); + + TInt err( KErrNone ); + + CWindow::ConstructL(aRect, aParent); + + TParse* fp = new(ELeave) TParse(); + fp->Set(KSplashBitmapName, &KDC_APP_BITMAP_DIR, NULL); + TRACES1("CMainWindow::ConstructL(): Load Bitmap from %S", &fp->FullName()); + + RFs fs; + TInt thisTry = 0; + while ( ( err = fs.Connect() ) != KErrNone && ( thisTry++ ) <= KTriesToConnectServer ) + { + User::After( KTimeBeforeRetryingServerConnection ); + } + + TFindFile findFile( fs ); + err = findFile.FindByPath( fp->FullName(), NULL ); + fs.Close(); + if ( !err ) + { + TRACES("CMainWindow::ConstructL(): Image found"); + iBitmap = AknIconUtils::CreateIconL( fp->FullName(), EMbmSplashscreenQgn_startup_screen ); + AknIconUtils::ExcludeFromCache(iBitmap); + AknIconUtils::SetSize( iBitmap, iRect.Size(), EAspectRatioPreservedAndUnusedSpaceRemoved ); + } + else + { + TRACES("CMainWindow::ConstructL(): Image not found"); + } + + delete fp; + + TRACES("CMainWindow::ConstructL(): End"); + } + + +/****************************************************************************\ +| Function: CMainWindow::Draw +| Purpose: Redraws the contents of CMainWindow within a given +| rectangle. As CMainWindow has no contents, it simply +| clears the redraw area. A blank window could be used here +| instead. The Clear() is needed because a redraw should +| always draw to every pixel in the redraw rectangle. +| Input: aRect Rectangle that needs redrawing +| Output: None +\****************************************************************************/ +void CMainWindow::Draw(const TRect& aRect) + { + TRACES("CMainWindow::Draw(): Start"); + + CWindowGc* gc=SystemGc(); // get a gc + gc->SetClippingRect(aRect); // clip outside this rect + TRACES2("CMainWindow::Draw(): Rect: X0=%d Y0=%d", aRect.iTl.iX, aRect.iTl.iY); + TRACES2("CMainWindow::Draw(): Rect: X1=%d Y1=%d", aRect.iBr.iX, aRect.iBr.iY); + + TRACES1("CMainWindow::Draw(): iBitmap = %d", iBitmap); + if (iBitmap) + { + TSize bmpSizeInPixels = iBitmap->SizeInPixels(); + //center image to the center of the screen + TInt xDelta = ( aRect.Width() - bmpSizeInPixels.iWidth ) / 2; + TInt yDelta = ( aRect.Height() - bmpSizeInPixels.iHeight ) / 2; + TPoint pos = TPoint( xDelta , yDelta ); // displacement vector + TRACES2("CMainWindow::Draw(): Image top left corner: X=%d Y=%d", pos.iX, pos.iY); + gc->Clear(); + gc->BitBlt(pos, iBitmap); + } + else + { + TRACES("CMainWindow::Draw(): Image not available. Draw lines from corner to corner"); + TRect rect(Window().Position(), Window().Size()); + gc->DrawLine(rect.iTl, rect.iBr); + gc->DrawLine(TPoint(rect.iTl.iX, rect.iBr.iY), TPoint(rect.iBr.iX, rect.iTl.iY)); + } + TRACES("CMainWindow::Draw(): End"); + } + +/****************************************************************************\ +| Function: CMainWindow::HandlePointerEvent +| Purpose: Handles pointer events for CMainWindow. Doesn't do +| anything except get the co-ordinates where the pointer +| event occurred. +| Input: aPointerEvent The pointer event +| Output: None +\****************************************************************************/ +void CMainWindow::HandlePointerEvent (TPointerEvent& /*aPointerEvent*/) + { + TRACES("CMainWindow::HandlePointerEvent(): Start"); +// TPoint point = aPointerEvent.iPosition; +// (void)point; + TRACES("CMainWindow::HandlePointerEvent(): End"); + } + +////////////////////////////////////////////////////////////////////////////// +// CSplashWsClient implementation // +////////////////////////////////////////////////////////////////////////////// + +/****************************************************************************\ +| Function: Constructor/Destructor for CSplashWsClient +| Destructor deletes everything that was allocated by +| ConstructMainWindowL() +\****************************************************************************/ +CSplashWsClient::CSplashWsClient() + { + TRACES("CSplashWsClient::CSplashWsClient()"); + } + +CSplashWsClient::~CSplashWsClient () + { + TRACES("CSplashWsClient::~CSplashWsClient(): Start"); + if ( iMainWindow ) + { + TRACES("CSplashWsClient::~CSplashWsClient(): To background"); + iMainWindow->Client()->Group().SetOrdinalPosition(-1,ECoeWinPriorityNormal); // Back to the normal position + iWs.Flush(); + } + delete iMainWindow; + delete iTimeout; + TRACES("CSplashWsClient::~CSplashWsClient(): End"); + } + +/****************************************************************************\ +| Function: CSplashWsClient::ConstructMainWindowL() +| Called by base class's ConstructL +| Purpose: Allocates and creates all the windows owned by this client +| (See list of windows in CSplashWsCLient declaration). +\****************************************************************************/ + +void CSplashWsClient::ConstructMainWindowL() + { + TRACES("CSplashWsClient::ConstructMainWindowL(): Start"); + + TSize windowSize=iScreen->SizeInPixels(); + + CMainWindow* window = new (ELeave) CMainWindow(this); + CleanupStack::PushL( window ); + window->ConstructL(TRect(TPoint(0,0), windowSize)); + window->Client()->Group().SetOrdinalPosition(0,ECoeWinPriorityAlwaysAtFront + 1); // in front of the Status Bar + delete iMainWindow; + iMainWindow = window; + CleanupStack::Pop( window ); + + if ( iTimeout == NULL ) + { + iTimeout = new (ELeave) CTimeout; + iTimeout->ConstructL(iMainWindow); + iTimeout->After(KSplashTimeout); + } + else + { + iTimeout->SetMainWindow( window ); + } + + TRACES("CSplashWsClient::ConstructMainWindowL(): End"); + } + + +/****************************************************************************\ +| Function: CSplashWsClient::RunL() +| Called by active scheduler when an even occurs +| Purpose: Processes events according to their type +| For key events: calls HandleKeyEventL() (global to client) +| For pointer event: calls HandlePointerEvent() for window +| event occurred in. +\****************************************************************************/ +void CSplashWsClient::RunL() + { + TRACES("CSplashWsClient::RunL(): Start"); + + TInt state; + RProperty::Get( KPSUidStartup, KPSSplashShutdown, state ); + TRACES1("CSplashWsClient::RunL(): KPSSplashShutdown state = %d", state); + + if ( state != iPSRemoveSplashState ) + { + TRACES("CSplashWsClient::RunL(): KPSSplashShutdown state has changed -> PS event"); + if ( state == ESplashShutdown ) + { + TRACES("CSplashWsClient::RunL(): Exit requested"); + Exit(); + } + } + else + { + TRACES("CSplashWsClient::RunL(): WS event"); + + // get the event + iWs.GetEvent(iWsEvent); + const TInt eventType = iWsEvent.Type(); + + // take action on it + switch (eventType) + { + // window-group related event types + case EEventKey: + { + TRACES("CSplashWsClient::RunL(): EEventKey"); + TKeyEvent& keyEvent=*iWsEvent.Key(); // get key event + HandleKeyEventL (keyEvent); + break; + } + // window related events + case EEventPointer: + { + TRACES("CSplashWsClient::RunL(): EEventPointer"); + CWindow* window=(CWindow*)(iWsEvent.Handle()); // get window + TPointerEvent& pointerEvent=*iWsEvent.Pointer(); + window->HandlePointerEvent (pointerEvent); + break; + } + case EEventScreenDeviceChanged: + { + const TInt currentScreenMode = iScreen->CurrentScreenMode(); + TRACES2("CSplashWsClient::RunL() - EEventScreenDeviceChanged - iLastScreenMode: %d, currentScreenMode: %d", iLastScreenMode, currentScreenMode); + if ( iLastScreenMode != currentScreenMode ) + { + RDebug::Printf("[SS] CSplashWsClient::RunL() - EEventScreenDeviceChanged - real screen mode change detected!!!!"); + iScreen->SetAppScreenMode( currentScreenMode ); + TPixelsTwipsAndRotation currentRot; + iScreen->GetScreenModeSizeAndRotation( currentScreenMode, currentRot ); + iMainWindow->Window().SetExtent( TPoint(0, 0), currentRot.iPixelSize ); + iMainWindow->Client()->Group().SetOrdinalPosition(0, ECoeWinPriorityAlwaysAtFront + 10000); // in front of the Status Bar + iMainWindow->Window().Invalidate(); + + iLastScreenMode = currentScreenMode; + } + TRACES("CSplashWsClient::RunL() - EEventScreenDeviceChanged - done"); + } + break; + default: + TRACES("CSplashWsClient::RunL(): default"); + break; + } + IssueRequest(); // maintain outstanding request + } + TRACES("CSplashWsClient::RunL(): End"); + } + + +/****************************************************************************\ +| Function: CSplashWsClient::HandleKeyEventL() +| +| Purpose: Processes key events for CSplashWsClient +| Gets the key code from the key event. Exits on 'Escape' +\****************************************************************************/ +void CSplashWsClient::HandleKeyEventL (TKeyEvent& /*aKeyEvent*/) + { + TRACES("CSplashWsClient::HandleKeyEventL(): Start"); + TRACES("CSplashWsClient::HandleKeyEventL(): End"); + } + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +// Main program starts here // +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +LOCAL_C void DoItL() + { + // make new client + TRACES("DoItL(): Start"); + + CSplashWsClient* client=new (ELeave) CSplashWsClient; // allocate new client + CleanupStack::PushL(client); // push, just in case + client->ConstructL(); // construct and run + CleanupStack::PopAndDestroy(); // destruct + + TRACES("DoItL(): End"); + } +