--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/openwfc/wnredraw.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,953 @@
+// 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())
+ {
+ STACK_REGION redrawRegion;
+ sprite->CalcRedrawRegion(aRegion, redrawRegion);
+ if(redrawRegion.CheckError() || !redrawRegion.IsEmpty())
+ {
+ if (sprite->IsFlashingEnabled() || sprite->IsDirty() || sprite->HasAnimation())
+ {
+ AnnotateSpriteRedrawStart(*iWsWin, *sprite, redrawRegion);
+
+ 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
+ aGc->Reset();
+ sprite->Redraw(aGc, redrawRegion);
+
+ 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);
+ }
+ }