windowing/windowserver/nga/SERVER/openwfc/wnredraw.cpp
author William Roberts <williamr@symbian.org>
Thu, 03 Jun 2010 17:39:46 +0100
branchNewGraphicsArchitecture
changeset 87 0709f76d91e5
parent 19 ac96196b945c
child 163 bbf46f59e123
permissions -rw-r--r--
Add MMP files to build libOpenVG_sw.lib which uses LINKAS to redirect to libOpenVG.dll (and the same for libEGL_sw.lib and libOpenVGU_sw.lib). Only the libEGL_sw.lib redirection isn't activated - this can't happen until there is a merged libEGL.dll which supports the OpenWF synchronisation and also implements the graphical support functions. The overall aim is to eliminate the *_sw.dll implementations, at least as a compile-time way of choosing a software-only implementation.The correct way to choose is to put the right set of libraries into a ROM with suitable renaming, and in the emulator to use the "switching DLL" technique to pick the right set. As the Symbian Foundation doesn't have any alternative implementations, we don't need the switching DLLs and we can build directly to the correct name.

// Copyright (c) 1995-2009 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:
// Window redraw code, three sorts of redrawing are supported
// Sending a redraw message to the client (see redrawmsgwindow.cpp)
// Drawing from backup bitmap
// Simply clearing the window
// 
//

#include "wnredraw.h"
#include "server.h"
#include "playbackgc.h"
#include "wstop.h"
#include "ANIM.H"
#include "EVQUEUE.H"
#include <s32mem.h>
#include <gdi.h>
#include "panics.h"
#include "inifile.h"
#include "rootwin.h"
#include "EVENT.H"
#include "wstypes.h"
#include <graphics/surface.h>
#include <graphics/wselement.h>
#include <graphics/wsscreendevice.h>
#include "windowelementset.h"

struct TFadingParams
	{
	TUint8 blackMap;
	TUint8 whiteMap;
	};

CWsWindowRedraw::CWsWindowRedraw(CWsWindow *aWin) : iWsWin(aWin)
	{
	}

CWsWindowRedraw::~CWsWindowRedraw()
	{
	if (iWsWin->WsOwner())
		{
		iWsWin->WsOwner()->RedrawQueue()->RemoveInvalid(this);
		}
	if (HasElement())
		{
		iWsWin->Screen()->WindowElements().ReleaseAllElements(*CliWin());
		}
	}

void CWsWindowRedraw::ConstructL()
	{
	}

const TRegion& CWsWindowRedraw::InvalidArea() const
	{
	return(nullRegion);
	}

const TRegion &CWsWindowRedraw::BaseDrawRegion() const
	{
	return(iWsWin->VisibleRegion());
	}

void CWsWindowRedraw::ClipInvalidRegion(const TRect &)
	{
	}

void CWsWindowRedraw::Resize(const TSize &, const TSize &)
	{
	}

void CWsWindowRedraw::SetReply(TInt aReply)
	{
	iWsWin->WsOwner()->SetReply(aReply);
	}

void CWsWindowRedraw::OwnerPanic(TClientPanic aPanic)
	{
	iWsWin->OwnerPanic(aPanic);
	}

CWsBackedUpWindow *CWsWindowRedraw::Backup() const
	{
	return(NULL);
	}

void CWsWindowRedraw::Scroll(const TRect &, const TPoint &,const TRect &)
	{
	}

void CWsWindowRedraw::UpdateAnimArea()
	{
	}

void CWsWindowRedraw::PrepareForResizeL(const TSize& /* aNewSize */, TSize& /* aOldSize */)
	{
	}

TBool CWsWindowRedraw::DrawCommand(CWsGc*,const TAny*)
	{
	return ETrue;
	}

void CWsWindowRedraw::GcAttributeChange(CWsGc*,const TAny*)
	{
	}

void CWsWindowRedraw::GcDeactivate(CWsGc*)
	{
	}

CFbsDevice* CWsWindowRedraw::OutputDevice() const
	{
	return NULL;
	}

void CWsWindowRedraw::ClientExposing()
	{
	}

void CWsWindowRedraw::ClearRedrawStore(TBool)
	{}

void CWsWindowRedraw::PreDrawWindow(MWsGraphicsContext* aGc, const TRegion& aWindowRegion)
	{
	WS_ASSERT_DEBUG(iRedrawRegion == NULL, EWsPanicScheduledRedraw);
	iRedrawRegion = &aWindowRegion;
	CPlaybackGc::Instance()->SetTargetRegion(iRedrawRegion);
	CWsClient::iCurrentCommand.iOpcode=0;
	CPlaybackGc::Instance()->Activate(CliWin(), aGc, iRedrawRegion);
	}

void CWsWindowRedraw::PostDrawWindow(MWsGraphicsContext* aGc, const TRegion& aWindowChildNodeRegion)
	{
	WS_ASSERT_DEBUG(iRedrawRegion, EWsPanicScheduledRedraw);
	CPlaybackGc::Instance()->Deactivate();
	CPlaybackGc::Instance()->SetTargetRegion(NULL);
	
	if(!Screen()->ChangeTracking())
		{
		DoFade(*iRedrawRegion);
		}

	AnnotateWindowRedrawEnd(*iWsWin);	
	
	DrawWindowAnims(aGc, aWindowChildNodeRegion);
	DrawCursorAndSprites(aGc, aWindowChildNodeRegion);
	iRedrawRegion = 0;
	}

void CWsWindowRedraw::Fade(MWsGraphicsContext * aGc, const TRegion& aRegion)
	{
	LOG_WINDOW_FADE_START(WsWin());	
	AnnotateWindowRedrawStart(*iWsWin, aRegion);
	
	aGc->Reset();
	DoFade(aRegion);
	
	AnnotateWindowRedrawEnd(*iWsWin);		
	LOG_WINDOW_FADE_END(WsWin());	
	}

void CWsWindowRedraw::DoFade(const TRegion& aRegion)
	{
	if( CWsTop::IsFadeEnabled() && iWsWin && iWsWin->FadeCount()>0 && !(iWsWin->IsNonFading()) && !(iWsWin->FadableRegion().IsEmpty()) && !(iWsWin->IsDSAHost()) )
		{
		MWsFader* fader = static_cast<MWsFader*>(iWsWin->Screen()->ResolveObjectInterface(KMWsFader));
		if(fader)
			{
		  	TFadingParams parameters;
	  		iWsWin->GetFadingParams(parameters.blackMap,parameters.whiteMap);
	      	TPckgBuf<TFadingParams> buf(parameters);
	      	fader->SetFadingParameters(buf);
		  	// Only fade the region that hasn't been faded before
	  		STACK_REGION fdRgn;
	  		fdRgn.Copy( aRegion );
			fdRgn.Intersect( iWsWin->FadableRegion() );
			if(!fdRgn.CheckError())
				{
				fader->FadeArea( fdRgn );
				LOG_WINDOW_FADE_REGION(&fdRgn);
				}
	  		fdRgn.Close();
	      	}
		}
	}

void CWsWindowRedraw::DrawWindowAnims(MWsGraphicsContext * aGc, const TRegion& aRegion)
	{
	if (iWsWin->iAnimList)
		{
		// If an anim panics, it will leave and set the panic flag on the client
		// The client itself won't actually panic yet, and we don't want to leave from here.
		TRAP_IGNORE(DrawWindowAnimsL(aGc, aRegion));
		}
	}

void CWsWindowRedraw::DrawWindowAnimsL(MWsGraphicsContext * aGc, const TRegion& aRegion)
	{
	for (CWsAnim * anim = iWsWin->iAnimList; anim; anim = anim->Next())
		{
		AnnotateWindowAnimRedrawStart(*iWsWin, *anim, aRegion);
		
		//Animate and redraw
		TRAPD(err,anim->RedrawWindowAnimL(Screen()->Now(), aGc, &aRegion));
		if(err!=KErrNone)
			{
			AnnotateWindowAnimRedrawEnd(*iWsWin, *anim);
			anim->Panic(EWservPanicAnimLeave);
			return;
			}
		
		AnnotateWindowAnimRedrawEnd(*iWsWin, *anim);
		}
	}

void CWsWindowRedraw::DrawCursorAndSprites(MWsGraphicsContext * aGc, const TRegion& aRegion)
	{	
	// Draw standard text cursor if required
	RWsTextCursor* const cursor = CWsTop::CurrentTextCursor();
	if (!iWsWin->Screen()->ChangeTracking() && cursor && cursor->Win() == iWsWin && cursor->IsStandardCursorActive())
		{
		// Standard text cursor is active on this window
		const TBool flashing = cursor->IsFlashing();
		TFlashState flashState = EFlashOn;
		if (flashing)
			{
			flashState = cursor->CurrentCursorFlashState();
			}
		if (flashState == EFlashOn)
			{
			// Cursor should be visible, so draw it
			cursor->Draw(aRegion);
			}
		if (flashing)
			{
			// Reschedule to flash the standard cursor on or off
			Screen()->ScheduleAnimation(ETextCursor, cursor->RectRelativeToScreen(), Screen()->SpriteManager()->NextCursorFlashStateChange(), 0, 0, iWsWin);
			}
		}

	for (CWsSpriteBase * sprite = iWsWin->iSpriteList; sprite; sprite = sprite->Next())
		{
        TBool hasRedrawBegun = EFalse;
		STACK_REGION redrawRegion;
		sprite->CalcRedrawRegion(aRegion, redrawRegion);
		if(redrawRegion.CheckError() || !redrawRegion.IsEmpty())
			{
			if (sprite->IsFlashingEnabled() || sprite->IsDirty() || sprite->HasAnimation())
				{
                if (sprite->IsDirty() || sprite->HasAnimation())
                    {
                    AnnotateSpriteRedrawStart(*iWsWin, *sprite, redrawRegion);
                    hasRedrawBegun = ETrue;
                    }
				
				if(sprite->HasAnimation())
					{
					CWsAnim* anim = static_cast<CWsSprite*>(sprite)->iAnim;
					WS_ASSERT_DEBUG(anim,EWsPanicAnim);
					
					//Animate and...
					TRAPD(err, anim->AnimateSpriteAnimL(Screen()->Now()));
					if(err!=KErrNone)
						{
						AnnotateSpriteRedrawEnd(*iWsWin, *sprite);
						anim->Panic(EWservPanicAnimLeave);
						return;
						}
					}
				
				//...call Redraw on the sprite
				if (hasRedrawBegun)
				    {
                    aGc->Reset();
				    }
				sprite->Redraw(aGc, redrawRegion);
				
				if (hasRedrawBegun)
				    {
                    AnnotateSpriteRedrawEnd(*iWsWin, *sprite);
				    }
				}
			}
		redrawRegion.Close();
		}
	}

TBool CWsWindowRedraw::Contains(const TArray<TGraphicDrawerId>& /*aDrawers*/,const TRegion& aRegion) const
	{
	// if in doubt, assume we do
	return !aRegion.IsEmpty();
	}

TInt CWsWindowRedraw::DrawBackgroundColor(const TRegion& aRegion, TBool	aDoFillColor)
	{
	if (BackColor().Alpha() == 0 && !HasElement())
		return KErrNone;
	
	if(aRegion.IsEmpty())
		return KErrNone;
	
	TRect winAbs(CliWin()->AbsRect());	//fill size for background color fill
	TRect surfaceAbs(0,0,0,0);			//fill size for background surface fill - initially disabled
	
	if (HasElement())
		{
		TBackgroundAttributes* backgroundAttributes = CliWin()->Screen()->WindowElements().FindBackgroundElement(*CliWin());
		WS_ASSERT_DEBUG(backgroundAttributes,EWsPanicNoWindowElement);
		
		if (backgroundAttributes->iElement)
			{
			if (backgroundAttributes->ExplicitExtent())
				{
				backgroundAttributes->iElement->GetDestinationRectangle(surfaceAbs);
				surfaceAbs.Intersection(winAbs);
				if (surfaceAbs==winAbs)
					{
					winAbs.iBr.iX=winAbs.iTl.iX;	//disable background color fill
					}
				}
			else
				{
				surfaceAbs=winAbs;
				winAbs.iBr.iX=winAbs.iTl.iX;	//disable background color fill
				}
			}
		if (!aDoFillColor)
			{
			winAbs.iBr.iX=winAbs.iTl.iX;	//disable background color fill
			}
		}
	
	CPlaybackGc* playback = CPlaybackGc::Instance();
	MWsGraphicsContext* gc = static_cast<MWsGraphicsContext*>(playback->ResolveObjectInterface(KMWsGraphicsContext));
	gc->SetClippingRegion(aRegion);
	gc->SetBrushStyle(MWsGraphicsContext::ESolidBrush);
	gc->SetPenStyle(MWsGraphicsContext::ENullPen);
	TInt err = KErrNone;
	if (!winAbs.IsEmpty())
		{
		gc->SetBrushColor(BackColor());
		gc->DrawRect(winAbs);
		}
	if (!surfaceAbs.IsEmpty())
		{
		gc->SetDrawMode(MWsGraphicsContext::EDrawModeWriteAlpha);
		gc->SetBrushColor(TRgb(0,0,0,0));
		gc->DrawRect(surfaceAbs);
		gc->SetBrushColor(BackColor());		//leave in a sensible state
		gc->SetDrawMode(MWsGraphicsContext::EDrawModePEN);
		}
	gc->ResetClippingRegion();
	return err;
	}

TBool CWsWindowRedraw::ReleaseMemory(MWsMemoryRelease::TMemoryReleaseLevel)
	{
	return EFalse;
	}

void CWsWindowRedraw::VisibleRegionChange()
	{
	}

TBool CWsWindowRedraw::ReadyToDraw() const
	{
	return ETrue;
	}

TBool CWsWindowRedraw::RedrawingInProgress() const
	{
	return EFalse;	
	}

void CWsWindowRedraw::WindowClosing()
	{
	ReleaseBackgroundElement();
	}

TBool CWsWindowRedraw::HasDsaElement() const
	{
	TBool hasDsaElement = EFalse;

	if (HasElement())
		{
		CWsClientWindow* cliWin = CliWin();
		CWindowElementSet& set = cliWin->Screen()->WindowElements();
		TBackgroundAttributes* backgroundAttributes = set.FindBackgroundElement(*cliWin);
		WS_ASSERT_DEBUG(backgroundAttributes,EWsPanicNoWindowElement);

		if (backgroundAttributes->iElement)
			{
			MWsElement& element = *(backgroundAttributes->iElement);
			hasDsaElement = (element.ConnectedSurface() == cliWin->Screen()->DsaSurface());
			}
		}

	return hasDsaElement;
	}

void CWsWindowRedraw::SetDsaElementL()
	{
	TRect extent(TPoint(0,0), WsWin()->Screen()->DSASizeInPixels());
	MWsDisplayMapping *dispMap = WsWin()->Screen()->DisplayMapping();
	TRect extentOut;
	TRect extentInDSA;
	if(dispMap)
		{
		dispMap->MapCoordinates(EDirectScreenAccessSpace,extent,EApplicationSpace,extentOut);
		//DSA extent in application space intersects window extent in application space
		extentOut.Intersection(WsWin()->FullRect());		
		if(extentOut.IsEmpty())
			{
			extentOut.SetRect(0,0,0,0);
			}
		//use DSA coordinates to determine the viewport
		dispMap->MapCoordinates(EApplicationSpace, extentOut, EDirectScreenAccessSpace, extentInDSA);
		}
	else
		{
		extentOut = extent;
		extentInDSA = extent;
		extentOut.Intersection(WsWin()->FullRect());
		}
	if (!HasDsaElement())
		{
		WsWin()->Screen()->ClearDsaSurface(extent, BackColor());
		}

	TSurfaceConfiguration sc;
	sc.SetSurfaceId(WsWin()->Screen()->DsaSurface());
	sc.SetExtent(extentOut.Size());
	sc.SetViewport(extentInDSA);

	SetBackgroundSurfaceL(sc, ETrue, ETrue);
	}

TBackgroundAttributes& CWsWindowRedraw::AcquireBackgroundElementL()
	{
	// Only client windows can have elements set
	WS_ASSERT_DEBUG(iWsWin->WinType() == EWinTypeClient,EWsPanicWindowType);
	CWsClientWindow* cliWin = static_cast<CWsClientWindow*>(iWsWin);
	CScreen* screen = cliWin->Screen();
	WS_ASSERT_DEBUG(screen,EWsPanicNoScreen);

	CWindowElementSet& set = screen->WindowElements();
	SetHasElement(EFalse);
	TBackgroundAttributes& backgroundAttributes = set.AcquireBackgroundElementL(*cliWin);
	MWsElement& element = *(backgroundAttributes.iElement);
	element.SetGlobalAlpha(cliWin->IsVisible() ? 0xFF : 0);
	SetHasElement(ETrue);
	screen->ElementAdded();
	
	return backgroundAttributes;
	}

void CWsWindowRedraw::SetBackgroundSurfaceL(const TSurfaceId& aSurface)
	{
	if (aSurface.Type() == TSurfaceId::EScreenSurface || aSurface.IsNull())
		{
		OwnerPanic(EWservPanicInvalidSurface);
		}

	CWsClientWindow* cliWin = CliWin();
	CScreen* screen = cliWin->Screen();
	CWindowElementSet& set = screen->WindowElements();
	TBackgroundAttributes& backgroundAttributes = AcquireBackgroundElementL();
	MWsElement& element = *(backgroundAttributes.iElement);
    TInt err = set.RegisterSurface(aSurface);
    if (err != KErrNone)
        {
        ReleaseBackgroundElement();
        User::Leave(err);
        }
	err = element.ConnectSurface(aSurface); 
	if (err != KErrNone)
		{
		set.UnregisterSurface(aSurface);
		ReleaseBackgroundElement();
		User::Leave(err);
		}

	TRect winExtent = cliWin->FullRect();
	element.SetDestinationRectangle(winExtent);
	
	// By default Element's source rectangle is set to its surface rectangle
	TRect srcRect;
	element.GetSourceRectangle(srcRect);
	cliWin->SetOriginalSrcElementRect(srcRect);
	cliWin->SetOriginalDestElementRect(winExtent);

	SetMayContainElementFlags();
	
	MWsWindowTreeObserver* windowTreeObserver = Screen()->WindowTreeObserver();
	if (windowTreeObserver)
		{
		windowTreeObserver->ElementAdded(*iWsWin, element);
		}
	}

void CWsWindowRedraw::SetBackgroundSurfaceL(const TSurfaceConfiguration& aConfiguration, TBool aTriggerRedraw, TBool aAllowScreenSurface)
	{
	if (aConfiguration.Size() < sizeof(TSurfaceConfiguration))
		{
		__ASSERT_COMPILE(sizeof(TSurfaceConfiguration2)==sizeof(TSurfaceConfiguration));
		if (aConfiguration.Size() != sizeof(TSurfaceConfiguration1))
			{
			OwnerPanic(EWservPanicInvalidSurfaceConfiguration);
			}
		}

	TSurfaceId surfaceId;
	aConfiguration.GetSurfaceId(surfaceId);
	if ((surfaceId.Type() == TSurfaceId::EScreenSurface && !aAllowScreenSurface) || surfaceId.IsNull())
		{
		OwnerPanic(EWservPanicInvalidSurface);
		}

	CFbsBitGc::TGraphicsOrientation tempOrientation = aConfiguration.Orientation();
	__ASSERT_COMPILE(CFbsBitGc::EGraphicsOrientationNormal==0 && 
			CFbsBitGc::EGraphicsOrientationRotated270 == 3);
	if(tempOrientation < CFbsBitGc::EGraphicsOrientationNormal || 
			tempOrientation > CFbsBitGc::EGraphicsOrientationRotated270)
		{
		OwnerPanic(EWservPanicInvalidSurfaceConfiguration);
		}

	CWsClientWindow* cliWin = CliWin();
	CScreen* screen = cliWin->Screen();
	__ASSERT_DEBUG(screen, Panic(EWsPanicNoScreen));
	
	CWindowElementSet& set = screen->WindowElements();
	TBool mustRegister = ETrue;
	TRect oldExtent(0,0,0,0);
	MWsElement::TElementRotation oldRotation = MWsElement::EElementAntiClockwise0;
	TBool oldFlip = EFalse;
	TRect oldViewport(0,0,0,0);
	TSurfaceId oldSurfaceId = TSurfaceId::CreateNullId();

	// If a element has already been set
	if (HasElement())
		{
		TBackgroundAttributes* backgroundAttributes = set.FindBackgroundElement(*cliWin);
		WS_ASSERT_DEBUG(backgroundAttributes,EWsPanicNoWindowElement);
		
		if (backgroundAttributes->iElement)
			{
			MWsElement& element = *(backgroundAttributes->iElement);
			element.GetDestinationRectangle(oldExtent);
			element.GetSourceRectangle(oldViewport);
			oldRotation = element.SourceRotation();
			oldFlip = element.SourceFlipping();
			oldSurfaceId = element.ConnectedSurface();
			mustRegister = EFalse;
			// If it is a different surface, flag to register the new surface
			if (element.ConnectedSurface() != surfaceId)
				{
				mustRegister = ETrue;
				}
			}
		}
	
	//the call to AcquireBackgroundElementL() will remove any existing background element
	TBackgroundAttributes& backgroundAttributes = mustRegister ? 
			AcquireBackgroundElementL() : *(set.FindBackgroundElement(*cliWin));
	MWsElement& element = *(backgroundAttributes.iElement);
	TInt err = KErrNone;
	if (mustRegister)
		{
        err = set.RegisterSurface(surfaceId);
        switch(err)
            {
        case KErrBadHandle:
            // Invalid surface IDs have to return KErrArgument
            err = KErrArgument;
            // drop through
        case KErrNoMemory:
        case KErrArgument:
            ReleaseBackgroundElement();
            User::Leave(err);
        case KErrNone:
            break;
        default:
            // No need to release layer here since session closure will do it
            // automatically when the client thread is panicked.
            OwnerPanic(EWservPanicInvalidSurface);
            }

		err = element.ConnectSurface(surfaceId);
		if (err != KErrNone)
			{
			set.UnregisterSurface(surfaceId);
			ReleaseBackgroundElement();	//Releasing new empty element
			User::Leave(err);
			}

		if (screen->DsaSurface() == surfaceId)
			{
	         TUint32 flags; 
	         element.GetRenderStageFlags(flags);
	         flags |= MWsElement::EElementIsDirectlyRenderedUserInterface;
	         element.SetRenderStageFlags(flags);
			}
		}

	SetHasElement(ETrue);		//set element flag
	SetMayContainElementFlags();
	
	err = CWindowElement::SetElement(element,aConfiguration,ETrue);	//set viewport and orientation
	if (err == KErrArgument)
		{
		OwnerPanic(EWservPanicInvalidSurfaceConfiguration);
		}
    TRect srcRect;
    aConfiguration.GetViewport(srcRect);
    if (!srcRect.IsEmpty())
        backgroundAttributes.SetExplicitViewPort();
    element.GetSourceRectangle(srcRect);
    cliWin->SetOriginalSrcElementRect(srcRect);

	//Set Extent
	TRect newExtent;
	aConfiguration.GetExtent(newExtent);
	SetElementExtentL(newExtent, backgroundAttributes);
	cliWin->SetOriginalDestElementRect(newExtent);
	
	MWsWindowTreeObserver* windowTreeObserver = Screen()->WindowTreeObserver();
	if (windowTreeObserver && mustRegister)
		{
		windowTreeObserver->ElementAdded(*iWsWin, element);
		}
	
	//If set, redraw
	if (aTriggerRedraw)
		{
		TRect newViewport;
		aConfiguration.GetViewport(newViewport);
		CFbsBitGc::TGraphicsOrientation orientation = aConfiguration.Orientation();
		MWsElement::TElementRotation newRotation = GcToElementRotation(orientation);
		TBool newFlip = aConfiguration.Flip();
		
		//The following parameter guarantees that update will be scheduled. 
		//This will trigger the composition.
		TBool alwaysScheduleUpdate = (oldSurfaceId != surfaceId) || 
									(oldExtent != newExtent) ||
									(oldViewport != newViewport) ||
									(oldRotation != newRotation)||
									(oldFlip != newFlip);
									
		ElementRedraw(oldExtent,newExtent,alwaysScheduleUpdate);
		}
	}

/**
Sets the EMayContainElement flag for parent window.
Sets the flag for all ancestor windows.
**/
void CWsWindowRedraw::SetMayContainElementFlags()
	{
	CWsWindowBase* parent = CliWin()->BaseParent();
	TInt type = parent->WinType();
	while(type ==EWinTypeClient)
			{
			CWsClientWindow* win = static_cast<CWsClientWindow*>(parent);
			win->Redraw()->iStateFlags |= EMayContainElement;
			parent=parent->BaseParent();
			type = parent->WinType();
			}
	}

void CWsWindowRedraw::SetElementExtentL(TRect& aNewExtent, TBackgroundAttributes& aAttributes)
	{
	CWsClientWindow* cliWin = CliWin();
	MWsElement& element = *(aAttributes.iElement);
	if (aNewExtent.IsEmpty())
		{
		aNewExtent = cliWin->FullRect();
		aAttributes.SetExplicitExtent(EFalse);
		}
	else
		{
		TRect tempWindowPosition = cliWin->FullRect();		//get window absolute coordinates
		aNewExtent.Move(tempWindowPosition.iTl);				//shift user defined extent to absolute coordinates
		aAttributes.SetExplicitExtent(ETrue);
		}
	element.SetDestinationRectangle(aNewExtent);
	}

void CWsWindowRedraw::ElementRedraw(const TRect& aOldExtent, const TRect& aNewExtent, TBool aAlwaysScheduleUpdate)
	{
	if (!aOldExtent.IsEmpty())
		{
		//If the previous extent was different
		if (aOldExtent != aNewExtent)
			{
			STACK_REGION tempRegion;
			tempRegion.AddRect(aOldExtent);
			tempRegion.AddRect(aNewExtent);

			//Calculate the difference between
			TRect tempRect = aOldExtent;
			tempRect.Intersection(aNewExtent);			//intersect both regions
			tempRegion.SubRect(tempRect);		//cut unaltered region
			Screen()->ScheduleRegionUpdate(&tempRegion);

			tempRegion.Close();
			}
		else
			{
			if(aAlwaysScheduleUpdate)
				{
				TTimeIntervalMicroSeconds interval(0);
				Screen()->ScheduleRender(interval);
				}
			}
		}
	else
		{
		TRegionFix<1> region(aNewExtent);
		Screen()->ScheduleRegionUpdate(&region);
		}
	}

void CWsWindowRedraw::RemoveBackgroundSurface(TBool aTriggerRedraw)
	{
	if (HasElement())
		{
		TBackgroundAttributes* backgroundAttributes = CliWin()->Screen()->
				WindowElements().FindBackgroundElement(*CliWin());
		WS_ASSERT_DEBUG(backgroundAttributes,EWsPanicNoWindowElement);
		if (backgroundAttributes->iElement)
			{
			RemoveBackgroundElement(aTriggerRedraw);
			}
		}
	}

void CWsWindowRedraw::RemoveBackgroundElement(TBool aTriggerRedraw)
	{
	CWsClientWindow* cliWin = CliWin();
	CScreen* screen = cliWin->Screen();
	TRect tempRect;
	if (aTriggerRedraw)
		{
		TBackgroundAttributes* backgroundAttributes = screen->WindowElements().FindBackgroundElement(*CliWin());
		WS_ASSERT_DEBUG(backgroundAttributes,EWsPanicNoWindowElement);
		if (backgroundAttributes->ExplicitExtent())
			{
			backgroundAttributes->iElement->GetDestinationRectangle(tempRect);
			backgroundAttributes->SetExplicitExtent(EFalse);
			}
		else
			{
			tempRect = cliWin->FullRect();
			}
		}
	ReleaseBackgroundElement();
    if (aTriggerRedraw)
        {
        if (screen->ChangeTracking())
            {
            TTimeIntervalMicroSeconds interval(0);
            screen->ScheduleRender(interval);
            }
        else
            {
            TRegionFix<1> region(tempRect);
            screen->ScheduleRegionUpdate(&region);
            }
        }
	}

void CWsWindowRedraw::GetBackgroundSurfaceL(TSurfaceConfiguration& aConfiguration)
	{
	if (aConfiguration.Size() < sizeof(TSurfaceConfiguration))
		{
		__ASSERT_COMPILE(sizeof(TSurfaceConfiguration2)==sizeof(TSurfaceConfiguration));
		if (aConfiguration.Size() != sizeof(TSurfaceConfiguration1))
			{
			OwnerPanic(EWservPanicInvalidSurfaceConfiguration);
			}
		}
	
	CWsClientWindow* cliWin = CliWin();
	TBackgroundAttributes* backgroundAttributes = NULL;

	if (HasElement())
		{
		backgroundAttributes = cliWin->Screen()->WindowElements().FindBackgroundElement(*cliWin);
		WS_ASSERT_DEBUG(backgroundAttributes,EWsPanicNoWindowElement);
		if (!backgroundAttributes->iElement)
			{
			User::Leave(KErrNotFound);
			}
		}
	else
		{
		User::Leave(KErrNotFound);
		}

	MWsElement& element = *(backgroundAttributes->iElement);

	TInt errCode=CWindowElementSet::GetConfiguration(aConfiguration,element);

	// Get source rect
	if (errCode>=KErrNone)
	    {
	    if (!backgroundAttributes->ExplicitViewPort())
	        {
	        aConfiguration.SetViewport(TRect());
	        }
	    else
	        {
	        TRect tempExtent = cliWin->GetOriginalSrcElementRect();
	        aConfiguration.SetViewport(tempExtent);
	        }
	    }

	//Convert and copy extent
	if (errCode>=KErrNone)
		{
		if (!backgroundAttributes->ExplicitExtent())
			{
			aConfiguration.SetExtent(TRect());
			}
		else	//translate to window coordinates
			{
			TRect tempExtent = cliWin->GetOriginalDestElementRect();
			tempExtent.Move(-cliWin->Origin());
			aConfiguration.SetExtent(tempExtent);
			}
		}
	}

void CWsWindowRedraw::ReleaseBackgroundElement()
	{
	if (HasElement())
		{
		CWsClientWindow* cliWin = CliWin();
		CScreen* screen = cliWin->Screen();
		screen->WindowElements().ReleaseBackgroundElement(*cliWin, ETrue);
		screen->ElementRemoved();
		}
	}

//
// Blank window //
//

CWsBlankWindow::CWsBlankWindow(CWsWindow *aWin) : CWsWindowRedraw(aWin), iColor(iWsWin->RootWindow()->DefaultBackgroundColor()), iNoColor(EFalse)
	{
	}

CWsBlankWindow::~CWsBlankWindow()
	{
	}

void CWsBlankWindow::ConstructL()
	{
	CWsWindowRedraw::ConstructL();
	if (Screen()->ChangeTracking())
		{
		STACK_REGION dirtyRegion;
		dirtyRegion.Copy(iWsWin->WindowArea());
		dirtyRegion.Offset(-iWsWin->Origin());
		iWsWin->AddDirtyWindowRegion(dirtyRegion);
		dirtyRegion.Close();
		}
	}

void CWsBlankWindow::SetColor(TRgb aColor)
	{
	iColor=aColor;
	iNoColor=EFalse;
	if (Screen()->ChangeTracking())
		{
		STACK_REGION dirtyRegion;
		dirtyRegion.Copy(iWsWin->WindowArea());
		dirtyRegion.Offset(-iWsWin->Origin());
		iWsWin->AddDirtyWindowRegion(dirtyRegion);
		dirtyRegion.Close();

		if (iWsWin->IsActive() && iWsWin->IsVisible())
			{
			Screen()->ScheduleWindow(iWsWin);
			}
		}
	else
		{
		Screen()->AddRedrawRegion(iWsWin->VisibleRegion());
		}
	}

TBool CWsBlankWindow::CommandL(TInt aOpcode, TWsWinCmdUnion &aCmd)
	{
	switch(aOpcode)
		{
		case EWsWinOpSetBackgroundSurface:
			SetBackgroundSurfaceL(*aCmd.Surface);
			break;
		case EWsWinOpSetBackgroundSurfaceConfig:
			SetBackgroundSurfaceL(aCmd.SurfaceConfigurationAndTrigger->surfaceConfig, aCmd.SurfaceConfigurationAndTrigger->triggerRedraw, EFalse);
			break;
		case EWsWinOpRemoveBackgroundSurface:
			RemoveBackgroundSurface(*aCmd.Bool);
			break;
		case EWsWinOpGetBackgroundSurfaceConfig:
			{
			TSurfaceConfiguration tempConfiguration = *aCmd.SurfaceConfiguration;
			GetBackgroundSurfaceL(tempConfiguration);
			TInt tempSize = aCmd.SurfaceConfiguration->Size();
			if (sizeof(TSurfaceConfiguration)<tempSize)
				tempSize = sizeof(TSurfaceConfiguration);
			CWsClient::ReplyBuf(&tempConfiguration,tempSize);
			}
			break;
		case EWsWinOpSetColor:
			SetColor(*aCmd.rgb);
			break;
		case EWsWinOpSetNoBackgroundColor:
			SetBackgroundClear();
			break;
		default:
			return(EFalse);
		}
	return(ETrue);
	}

TRgb CWsBlankWindow::BackColor() const
	{
	return(iColor);
	}

TBool CWsBlankWindow::GetRedrawRect(TRect &) const
	{
	if (!iNoColor || iWsWin->iAnimList)
		iWsWin->Screen()->AddRedrawRegion(iWsWin->VisibleRegion());
	return(EFalse);
	}

TBool CWsBlankWindow::NeedsRedraw() const
	{
	return(EFalse);
	}

void CWsBlankWindow::DrawWindow()
	{
	if ((!iNoColor)||HasElement())
		{
		DrawBackgroundColor(*iRedrawRegion,!iNoColor);
		}
	}