// 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(®ion);
}
}
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(®ion);
}
}
}
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);
}
}