startupservices/SplashScreen/src/SplashScreen.cpp
changeset 0 2e3d3ce01487
child 19 924385140d98
--- /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 <w32std.h>
+#include <coedef.h>
+#include <data_caging_path_literals.hrh>
+#include <splashscreen.mbg>
+#include <AknIconSrvClient.h>
+#include <startupdomainpskeys.h>
+
+// 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");
+	}
+