--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/openwfc/WINDOW.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1088 @@
+// Copyright (c) 1994-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 functions
+//
+//
+
+#include "server.h"
+#include "rootwin.h"
+#include "window.h"
+#include "walkwindowtree.h"
+#include "wstop.h"
+#include "ScrDev.H"
+#include "EVENT.H"
+#include "ANIM.H"
+#include "Direct.H"
+#include "panics.h"
+#include "backedupwindow.h"
+#include "wstypes.h"
+#include "windowelementset.h"
+
+CWsWindow* CWsWindow::iAccessListRecentEnd = 0;
+CWsWindow* CWsWindow::iAccessListOldestEnd = 0;
+
+#ifndef _DEBUG
+
+#define LOG_WINDOW_REDRAW_START(wswin)
+#define LOG_WINDOW_REDRAW_END(wswin)
+#define LOG_WINDOW_ANIM_REDRAW_START(wswin)
+#define LOG_WINDOW_ANIM_REDRAW_END(wswin)
+#define LOG_WINDOW_SPRITE_REDRAW_START(aWsWin)
+#define LOG_WINDOW_SPRITE_REDRAW_END(aWsWin)
+
+#else
+
+#define LOG_WINDOW_REDRAW_START(wswin) LogWindowRedrawStart(wswin)
+#define LOG_WINDOW_REDRAW_END(wswin) LogWindowRedrawEnd(wswin)
+#define LOG_WINDOW_ANIM_REDRAW_START(wswin) LogWindowAnimRedrawStart(wswin)
+#define LOG_WINDOW_ANIM_REDRAW_END(wswin) LogWindowAnimRedrawEnd(wswin)
+#define LOG_WINDOW_SPRITE_REDRAW_START(wswin) LogWindowSpriteRedrawStart(wswin)
+#define LOG_WINDOW_SPRITE_REDRAW_END(wswin) LogWindowSpriteRedrawEnd(wswin)
+
+#include "../debuglog/DEBUGLOG.H"
+extern CDebugLogBase *wsDebugLog;
+
+extern void LogRegion(const TRegion* aRegion)
+ {
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ TInt rectCount = (aRegion == NULL ? 0 : aRegion->Count());
+ log.AppendFormat(_L("Fading region: [%d,"), &overflow, rectCount);
+ if (rectCount > 0)
+ {
+ const TRect* rectangles = aRegion->RectangleList();
+ TBuf<1> comma;
+ for (TInt ii = 0; ii < rectCount; ii++)
+ {
+ TRect current = rectangles[ii];
+ log.AppendFormat(_L("%S{{%d,%d},{%d,%d}}"), &overflow, &comma,
+ current.iTl.iX,current.iTl.iY,current.iBr.iX,current.iBr.iY);
+ comma = _L(",");
+ }
+ }
+ else
+ {
+ log.AppendFormat(_L("NULL"), &overflow);
+ }
+ log.AppendFormat(_L("]"), &overflow);
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+
+extern void LogFadeStart(const CWsWindow* aWsWin)
+ {
+ if (wsDebugLog && aWsWin->WsOwner())
+ {
+ _LIT(KLogDrawCommandsStart, ">> CWsRedrawMsgWindow::Fade() [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin->WsOwner()->Client().FullName();
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ log.AppendFormat(KLogDrawCommandsStart, &overflow, &clientName, aWsWin->WsOwner()->ConnectionHandle(), aWsWin->LogHandle());
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+extern void LogFadeRegion(const TRegion* aRegion)
+ {
+ if (wsDebugLog)
+ {
+ LogRegion(aRegion);
+ }
+ }
+
+extern void LogFadeEnd(const CWsWindow* aWsWin)
+ {
+ if (wsDebugLog && aWsWin->WsOwner())
+ {
+ _LIT(KLogDrawCommandsEnd, "<< CWsRedrawMsgWindow::Fade() [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin->WsOwner()->Client().FullName();
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ log.AppendFormat(KLogDrawCommandsEnd, &overflow, &clientName, aWsWin->WsOwner()->ConnectionHandle(), aWsWin->LogHandle());
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+static void LogWindowRedrawStart(const CWsWindow& aWsWin)
+ {
+ if (wsDebugLog)
+ {
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ if(aWsWin.Type() == WS_HANDLE_ROOT_WINDOW)
+ {
+ _LIT(KAnnotateWindowRedrawStart, ">> MWsDrawAnnotationObserver::WindowRedrawStart RootWindow for screen:%d");
+ log.AppendFormat(KAnnotateWindowRedrawStart, &overflow, aWsWin.Screen()->ScreenNumber());
+ }
+ else
+ {
+ _LIT(KAnnotateWindowRedrawStart, ">> MWsDrawAnnotationObserver::WindowRedrawStart [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin.WsOwner()->Client().FullName();
+ log.AppendFormat(KAnnotateWindowRedrawStart, &overflow, &clientName, aWsWin.WsOwner()->ConnectionHandle(), aWsWin.LogHandle());
+ }
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+static void LogWindowRedrawEnd(const CWsWindow& aWsWin)
+ {
+ if (wsDebugLog)
+ {
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ if(aWsWin.Type() == WS_HANDLE_ROOT_WINDOW)
+ {
+ _LIT(KAnnotateWindowRedrawEnd, "<< MWsDrawAnnotationObserver::WindowRedrawEnd RootWindow for screen:%d");
+ log.AppendFormat(KAnnotateWindowRedrawEnd, &overflow, aWsWin.Screen()->ScreenNumber());
+ }
+ else
+ {
+ _LIT(KAnnotateWindowRedrawEnd, "<< MWsDrawAnnotationObserver::WindowRedrawEnd [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin.WsOwner()->Client().FullName();
+ log.AppendFormat(KAnnotateWindowRedrawEnd, &overflow, &clientName, aWsWin.WsOwner()->ConnectionHandle(), aWsWin.LogHandle());
+ }
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+static void LogWindowAnimRedrawStart(const CWsWindow& aWsWin)
+ {
+ if (wsDebugLog)
+ {
+ _LIT(KAnnotateWindowAnimRedrawStart, " >> MWsDrawAnnotationObserver::WindowAnimRedrawStart [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin.WsOwner()->Client().FullName();
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ log.AppendFormat(KAnnotateWindowAnimRedrawStart, &overflow, &clientName, aWsWin.WsOwner()->ConnectionHandle(), aWsWin.LogHandle());
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+static void LogWindowAnimRedrawEnd(const CWsWindow& aWsWin)
+ {
+ if (wsDebugLog)
+ {
+ _LIT(KAnnotateWindowAnimRedrawEnd, " << MWsDrawAnnotationObserver::WindowAnimRedrawEnd [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin.WsOwner()->Client().FullName();
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ log.AppendFormat(KAnnotateWindowAnimRedrawEnd, &overflow, &clientName, aWsWin.WsOwner()->ConnectionHandle(), aWsWin.LogHandle());
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+static void LogWindowSpriteRedrawStart(const CWsWindow& aWsWin)
+ {
+ if (wsDebugLog)
+ {
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ if(aWsWin.Type() == WS_HANDLE_ROOT_WINDOW)
+ {
+ _LIT(KAnnotateSpriteRedrawStart, "<< MWsDrawAnnotationObserver::WindowSpriteRedrawStart RootWindow for screen:%d");
+ log.AppendFormat(KAnnotateSpriteRedrawStart, &overflow, aWsWin.Screen()->ScreenNumber());
+ }
+ else
+ {
+ _LIT(KAnnotateSpriteRedrawStart, " >> MWsDrawAnnotationObserver::WindowSpriteRedrawStart [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin.WsOwner()->Client().FullName();
+ log.AppendFormat(KAnnotateSpriteRedrawStart, &overflow, &clientName, aWsWin.WsOwner()->ConnectionHandle(), aWsWin.LogHandle());
+ }
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+static void LogWindowSpriteRedrawEnd(const CWsWindow& aWsWin)
+ {
+ if (wsDebugLog)
+ {
+ TBuf<LogTBufSize> log;
+ TTruncateOverflow overflow;
+ if(aWsWin.Type() == WS_HANDLE_ROOT_WINDOW)
+ {
+ _LIT(KAnnotateSpriteRedrawEnd, " << MWsDrawAnnotationObserver::WindowSpriteRedrawEnd RootWindow for screen:%d");
+ log.AppendFormat(KAnnotateSpriteRedrawEnd, &overflow, aWsWin.Screen()->ScreenNumber());
+ }
+ else
+ {
+ _LIT(KAnnotateSpriteRedrawEnd, " << MWsDrawAnnotationObserver::WindowSpriteRedrawEnd [%S][app %d] RWindow[%d]");
+ const TDesC& clientName = aWsWin.WsOwner()->Client().FullName();
+ log.AppendFormat(KAnnotateSpriteRedrawEnd, &overflow, &clientName, aWsWin.WsOwner()->ConnectionHandle(), aWsWin.LogHandle());
+ }
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, log);
+ }
+ }
+
+#endif
+
+extern void AnnotateWindowRedrawStart(const CWsWindow& aWsWin, const TRegion& aRegion)
+ {
+ LOG_WINDOW_REDRAW_START(aWsWin);
+ MWsDrawAnnotationObserver* annoObs = aWsWin.Screen()->DrawAnnotationObserver();
+ if(annoObs)
+ {
+ annoObs->WindowRedrawStart(aWsWin, aRegion);
+ }
+ }
+
+extern void AnnotateWindowRedrawEnd(const CWsWindow& aWsWin)
+ {
+ LOG_WINDOW_REDRAW_END(aWsWin);
+ MWsDrawAnnotationObserver* annoObs = aWsWin.Screen()->DrawAnnotationObserver();
+ if(annoObs)
+ {
+ annoObs->WindowRedrawEnd(aWsWin);
+ }
+ }
+
+extern void AnnotateWindowAnimRedrawStart(const CWsWindow& aWsWin, const CWsAnim& aAnim, const TRegion& aRegion)
+ {
+ LOG_WINDOW_ANIM_REDRAW_START(aWsWin);
+ MWsDrawAnnotationObserver* annoObs = aWsWin.Screen()->DrawAnnotationObserver();
+ if(annoObs)
+ {
+ annoObs->WindowAnimRedrawStart(aAnim, aRegion);
+ }
+ }
+
+extern void AnnotateWindowAnimRedrawEnd(const CWsWindow& aWsWin, const CWsAnim& aAnim)
+ {
+ LOG_WINDOW_ANIM_REDRAW_END(aWsWin);
+ MWsDrawAnnotationObserver* annoObs = aWsWin.Screen()->DrawAnnotationObserver();
+ if(annoObs)
+ {
+ annoObs->WindowAnimRedrawEnd(aAnim);
+ }
+ }
+
+extern void AnnotateSpriteRedrawStart(const CWsWindow& aWsWin, const CWsSpriteBase& aSprite, const TRegion& aRegion)
+ {
+ LOG_WINDOW_SPRITE_REDRAW_START(aWsWin);
+ MWsDrawAnnotationObserver* annoObs = aWsWin.Screen()->DrawAnnotationObserver();
+ if(annoObs)
+ {
+ annoObs->SpriteRedrawStart(aSprite, aRegion);
+ }
+ }
+
+extern void AnnotateSpriteRedrawEnd(const CWsWindow& aWsWin, const CWsSpriteBase& aSprite)
+ {
+ LOG_WINDOW_SPRITE_REDRAW_END(aWsWin);
+ MWsDrawAnnotationObserver* annoObs = aWsWin.Screen()->DrawAnnotationObserver();
+ if(annoObs)
+ {
+ annoObs->SpriteRedrawEnd(aSprite);
+ }
+ }
+
+CWsWindow::CWsWindow(CWsClient* aOwner,WH_HANDLES aType, CScreen* aScreen) : CWsWindowBase(aOwner,aType,aScreen),
+ iFlags(EFlagHidden),
+ iDSAs(_FOFF(CWsDirectScreenAccess,iMultipleDSALink))
+ {
+ }
+
+CWsWindow::~CWsWindow()
+ {
+ //2-phase destruction, Shutdown() is called before destructor
+ iFadableRegion.Reset();
+ iQuickFadeRegion.Reset();
+ }
+
+void CWsWindow::Fade(MWsGraphicsContext * aGc, const TRegion& aRegion)
+ {
+ if ( NULL != iRedraw )
+ {
+ iRedraw->Fade( aGc, aRegion );
+ }
+ }
+
+void CWsWindow::Construct()
+ {
+ InsertIntoAccessListOldestEnd();
+ }
+
+void CWsWindow::Shutdown()
+ {
+ TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EWindowClosing, 0, 0, this));
+ RemoveFromAccessList();
+ CWsAnim::WindowClosing(iAnimList); // Destroy any animated objects attached to this window
+ iVisibleRegion.Reset();
+ iScheduledRegion.Reset();
+ iScheduledSpriteRegion.Reset();
+ iDirtyWindowRegion.Reset();
+ iDirtySpriteRegion.Reset();
+ AbortAllDSAs();
+ CWsWindowBase::Shutdown();
+ SetPointerCursor(NULL);
+ delete iRedraw;
+ iRedraw=NULL;
+ Screen()->RemoveFromScheduledList(this);
+ Screen()->RemoveFromTimedDrawList(this);
+ Screen()->RemoveFromQuickFadeList(this);
+ }
+
+//
+// Region and invalid area functions //
+//
+
+TRect CWsWindow::FullRect() const
+ {
+ return(TRect(iOrigin,iRel.Size()));
+ }
+
+//
+// Normal regions //
+//
+
+void CWsWindow::AreaCovered(TRegion &aRegion)
+ {
+ aRegion.Copy(WindowArea());
+ }
+
+void CWsWindow::SetNonFading(TBool aNonFade)
+ {
+ const TUint oldFlags = iFlags;
+
+ if (aNonFade)
+ iFlags|=EFlagNonFadingWindow;
+ else
+ iFlags&=(~EFlagNonFadingWindow);
+
+ //Schedule window for quickfade if non-fading flag is changed
+ if (!Screen()->ChangeTracking() && CWsTop::IsFadeEnabled() && (oldFlags != iFlags) )
+ {
+ Screen()->AcceptFadeRequest(this, !aNonFade);
+ }
+
+ MWsWindowTreeObserver* const windowTreeObserver = Screen()->WindowTreeObserver();
+ if (windowTreeObserver && oldFlags!=iFlags)
+ windowTreeObserver->FlagChanged(*this, MWsWindowTreeObserver::ENonFading, aNonFade);
+ }
+
+TPoint CWsWindow::InquireOffset(TUint32 aHandle) const
+ {
+ CWsWindowBase *win2;
+ iWsOwner->HandleToWindow(aHandle,&win2);
+ return(iOrigin-win2->Origin());
+ }
+
+TDisplayMode CWsWindow::SetRequiredDisplayModeL(TDisplayMode)
+ {
+ return DisplayMode();
+ }
+
+TDisplayMode CWsWindow::DisplayMode() const
+ {
+ return iScreen->DisplayMode();
+ }
+
+void CWsWindow::StatusDump(TDes &aBuf)
+ {
+ _LIT(KStatusString1,"CWsWindow[0x%x]RWindow[0x%x,%d],Pos(%d,%d),Size(%d,%d)");
+ _LIT(KStatusString3,",Mode=%d");
+ _LIT(KStatusInvisible,",Inv");
+ aBuf.AppendFormat(KStatusString1,this,iClientHandle,LogHandle(),iRel.iTl.iX,iRel.iTl.iY,Size().iWidth,Size().iHeight);
+ TDisplayMode displayMode = DisplayMode();
+ aBuf.AppendFormat(KStatusString3,(TInt&)displayMode);
+ if (!IsVisible())
+ aBuf.Append(KStatusInvisible);
+ }
+
+TDblQue<TPointerKeyList> *CWsWindow::PointerKeyList() const
+ {
+ return(NULL);
+ }
+
+TInt CWsWindow::AddDSA(CWsDirectScreenAccess& aDirect)
+ {
+ TInt error = KErrNone;
+
+ if (iDSAs.IsEmpty() && !aDirect.IsRegionTrackingOnly())
+ {
+ TRAP(error,iRedraw->SetDsaElementL());
+ }
+
+ if (!error)
+ {
+ iDSAs.AddLast(aDirect);
+ }
+
+ return error;
+ }
+
+void CWsWindow::RemoveDSA(CWsDirectScreenAccess& aDirect)
+ {
+ iDSAs.Remove(aDirect);
+ }
+
+void CWsWindow::AbortAllDSAs()
+ {
+ iScreen->AbortDSAs(RDirectScreenAccess::ETerminateRegion,iDSAs);
+ }
+
+void CWsWindow::PossibleVisibilityChangedEvent(TBool aForceSend)
+ {
+ // notify plugin
+ //
+ // coverity[unchecked_value]
+ TWservCrEvent crEvent(TWservCrEvent::EWindowVisibilityChanged, HasBeenDrawnToScreen(), IsVisible()? &iVisibleRegion : NULL, this);
+ TWindowServerEvent::NotifyDrawer(crEvent);
+
+ if (!(iFlags & EFlagGeneratesVisibilityEvents))
+ return;
+
+ if (!IsVisible())
+ {
+ goto notvisible;
+ }
+
+ if (iVisibleRegion.Count() == 0)
+ {
+ goto notvisible;
+ }
+
+ {// braces here to avoid gccxml error
+ TInt visibleArea = 0;
+ TInt count = iVisibleRegion.Count();
+ TInt ii;
+ for (ii = 0; ii < count; ii++)
+ {
+ visibleArea+= iVisibleRegion[ii].Width() * iVisibleRegion[ii].Height();
+ }
+
+ const TRegion* baseRegion = (static_cast<CWsClientWindow*>(this))->BaseArea();
+ TInt baseArea = 0;
+ count = baseRegion->Count();
+ for (ii = 0; ii < count; ii++)
+ {
+ const TRect& rect = (*baseRegion)[ii];
+ baseArea+= rect.Width() * rect.Height();
+ }
+
+ if (visibleArea == baseArea)
+ {
+ goto fullyvisible;
+ }
+ else
+ {
+ goto partiallyvisible;
+ }
+ }
+
+fullyvisible:
+ if (aForceSend || !(iFlags & EFlagNotCantBeSeen) || !(iFlags & EFlagCanBeSeen))
+ {
+ iFlags |= (EFlagCanBeSeen | EFlagNotCantBeSeen);
+ TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::EPartiallyVisible | TWsVisibilityChangedEvent::EFullyVisible);
+ // we have to set EPartiallyVisible too for compatibility reasons
+ }
+ return;
+
+partiallyvisible:
+ if (aForceSend || !(iFlags & EFlagCanBeSeen) || (iFlags & EFlagNotCantBeSeen))
+ {
+ iFlags |= EFlagCanBeSeen;
+ iFlags &= ~EFlagNotCantBeSeen;
+ TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::EPartiallyVisible);
+ }
+ return;
+
+notvisible:
+ if (aForceSend || (iFlags & EFlagCanBeSeen) || (iFlags & EFlagNotCantBeSeen))
+ {
+ iFlags &= ~(EFlagCanBeSeen | EFlagNotCantBeSeen);
+ TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::ENotVisible);
+ }
+ return;
+ }
+
+TPoint CWsWindow::Origin() const
+ {
+ return iOrigin;
+ }
+
+TRect CWsWindow::AbsRect() const
+ {
+ return iAbs;
+ }
+
+TSize CWsWindow::Size() const
+ {
+ return iRel.Size();
+ }
+
+TBool CWsWindow::SetScheduledRegion(const TRegion& aRegion)
+ {
+ iScheduledRegion.Copy(aRegion);
+ return !iScheduledRegion.CheckError();
+ }
+
+void CWsWindow::ClearScheduledRegion()
+ {
+ iScheduledRegion.Reset();
+ }
+
+void CWsWindow::SetFadeBehind(TBool aFade)
+ {
+ if (aFade != ((iFlags & EFlagFadeBehind) != 0))
+ {
+ iFlags ^= EFlagFadeBehind;
+ }
+ }
+
+void CWsWindow::FocusChanged(TBool aNewFocusState)
+ {
+ TRAPD(err,FocusChangedL(aNewFocusState));
+ if (err!=KErrNone)
+ OwnerPanic(EWservPanicAnimLeave);
+ }
+
+void CWsWindow::FocusChangedL(TBool aNewFocusState)
+ {
+ for (CWsAnim * anim = iAnimList; anim; anim = anim->Next())
+ {
+ anim->FocusChanged(aNewFocusState);
+ }
+ }
+
+// Moves a window to the recent end of the accessed list
+void CWsWindow::Accessed()
+ {
+ WS_ASSERT_DEBUG(iAccessListRecentEnd && iAccessListOldestEnd, EWsPanicAccessList);
+
+ RemoveFromAccessList();
+ InsertIntoAccessListRecentEnd();
+ }
+
+void CWsWindow::InsertIntoAccessListOldestEnd()
+ {
+ iAccessListPrev = 0;
+ iAccessListNext = iAccessListOldestEnd;
+ if (iAccessListNext)
+ iAccessListNext->iAccessListPrev = this;
+ iAccessListOldestEnd = this;
+ if (!iAccessListRecentEnd)
+ iAccessListRecentEnd = this;
+ }
+
+void CWsWindow::InsertIntoAccessListRecentEnd()
+ {
+ iAccessListNext = 0;
+ iAccessListPrev = iAccessListRecentEnd;
+ if (iAccessListPrev)
+ iAccessListPrev->iAccessListNext = this;
+ iAccessListRecentEnd = this;
+ if (!iAccessListOldestEnd)
+ iAccessListOldestEnd = this;
+ }
+
+void CWsWindow::RemoveFromAccessList()
+ {
+ if (iAccessListOldestEnd == this)
+ iAccessListOldestEnd = iAccessListNext;
+ if (iAccessListRecentEnd == this)
+ iAccessListRecentEnd = iAccessListPrev;
+ if (iAccessListPrev)
+ iAccessListPrev->iAccessListNext = iAccessListNext;
+ if (iAccessListNext)
+ iAccessListNext->iAccessListPrev = iAccessListPrev;
+ }
+
+TBool CWsWindow::ReleaseMemory(MWsMemoryRelease::TMemoryReleaseLevel aLevel)
+ {
+ for (CWsWindow * access = iAccessListOldestEnd; access; access = access->iAccessListNext)
+ {
+ if(access->Redraw())
+ {
+ if (access->Redraw()->ReleaseMemory(aLevel))
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+const TRegion& CWsWindow::VisibleRegion() const
+ {
+ return(iVisibleRegion);
+ }
+
+const TRegion& CWsWindow::QuickFadeRegion() const
+ {
+ return iQuickFadeRegion;
+ }
+
+const TRegion& CWsWindow::FadableRegion() const
+ {
+ return iFadableRegion;
+ }
+
+TBool CWsWindow::IsDSAHost() const
+ {
+ TBool res = EFalse;
+ if ( !iDSAs.IsEmpty() )
+ {
+ TSglQueIter<CWsDirectScreenAccess> iter( (TSglQueBase&)iDSAs );
+ iter.SetToFirst();
+ CWsDirectScreenAccess* dsa;
+ while ( (dsa = iter++) != NULL && !res )
+ {
+ res = dsa->IsVisible();
+ }
+ }
+ return res;
+ }
+
+void CWsWindow::SendState(MWsWindowTreeObserver& aWindowTreeObserver) const
+ {
+ aWindowTreeObserver.NodeCreated(*this, ParentNode());
+
+ if(iFlags & EFlagActive)
+ {
+ aWindowTreeObserver.NodeExtentChanged(*this, FullRect());
+ aWindowTreeObserver.NodeActivated(*this);
+ }
+
+ if(!IsVisible())
+ {
+ aWindowTreeObserver.FlagChanged(*this, MWsWindowTreeObserver::EVisible, EFalse);
+ }
+
+ if(IsTrackingVisibleRegion())
+ {
+ MWsWindowVisibilityNotifier* windowVisibilityNotifier = Screen()->WindowVisibilityNotifier();
+ if(windowVisibilityNotifier)
+ windowVisibilityNotifier->RegisterWindow(*this);
+ }
+
+ if(HasAlpha())
+ {
+ aWindowTreeObserver.FlagChanged(*this, MWsWindowTreeObserver::EAlphaChannelTransparencyEnabled, ETrue);
+ }
+
+ if(IsNonFading())
+ {
+ aWindowTreeObserver.FlagChanged(*this, MWsWindowTreeObserver::ENonFading, ETrue);
+ }
+
+ if(iAnimList)
+ iAnimList->SendState(aWindowTreeObserver);
+
+ CWsWindowBase::SendState(aWindowTreeObserver);
+ }
+
+void CWsWindow::ResetVisibleRegion()
+ {
+ if (!iVisibleRegion.IsEmpty())
+ {
+ iVisibleRegion.Reset();
+ }
+ iFadableRegion.Reset();
+ iQuickFadeRegion.Reset();
+ }
+
+void CWsWindow::SetVisibleRegion(const TRegion& aNewRegion, const TRegion* aTop)
+ {
+ WS_ASSERT_DEBUG(iScreen, EWsPanicNoScreen);
+ STACK_REGION difference;
+ TBool diffs = EFalse;
+
+ difference.Copy(iVisibleRegion);
+ difference.SubRegion(aNewRegion);
+ if (!difference.IsEmpty())
+ {
+ diffs = ETrue;
+ if (IsTranslucent())
+ {
+ iScreen->AddRedrawRegion(difference, EFalse);
+ }
+ }
+
+ difference.Copy(aNewRegion);
+ if (HasBeenDrawnToScreen())
+ {
+ difference.SubRegion(iVisibleRegion);
+ }
+ if (!difference.IsEmpty())
+ {
+ diffs = ETrue;
+ if(!iScreen->ChangeTracking())
+ {
+ //the following code will restart animations
+ STACK_REGION topDiff;
+ topDiff.Copy(difference);
+ WS_ASSERT_DEBUG(aTop,EWsPanicRegion);
+ topDiff.Intersect(*aTop);
+ difference.SubRegion(topDiff);
+ iScreen->AddRedrawRegion(topDiff, EFalse, ERedrawTopOnly);
+ iScreen->AddRedrawRegion(difference, EFalse, ERedrawAll);
+ topDiff.Close();
+ }
+ else if(IsVisible())
+ {
+ RestartAnimations(aNewRegion);
+ }
+ }
+
+ difference.Close();
+
+ AbortDsaIfRequired(aNewRegion, aTop);
+
+ if (diffs)
+ {
+ ResetVisibleRegion();
+ iVisibleRegion.Copy(aNewRegion);
+ PossibleVisibilityChangedEvent(EFalse);
+
+ if (Redraw()->HasElement())
+ {
+ WS_ASSERT_DEBUG(WinType()==EWinTypeClient,EWsPanicWindowType);
+
+ if (WinType()==EWinTypeClient)
+ {
+ iScreen->WindowElements().SetVisibleRegion(*static_cast<CWsClientWindow*>(this));
+ }
+ }
+ }
+
+ // Just because the visible region (screen coordinates) didn't change doesn't
+ // mean the invalid region (window coordinates) didn't change, so we always call this.
+ iRedraw->VisibleRegionChange();
+ }
+
+//This function sets up the quick fadable region.
+//It removes anything that cannot be quick faded, and schedules it to be drawn in the normal fashion.
+void CWsWindow::SetFadeableRegion(const TRegion& aNewFadableRegion, const TRegion& aTop)
+ {
+ WS_ASSERT_DEBUG(iScreen, EWsPanicNoScreen);
+ iFadableRegion.Copy(aNewFadableRegion);
+
+ //Try to figure out if any part of iFadableRegion can be quick faded (i.e. fading applied to
+ //the screen without first having to redraw all visible windows intersecting the region).
+ if ( !iFadableRegion.IsEmpty() && iScreen->IsQuickFadeScheduled(this) )
+ {
+ if (IsTranslucent())
+ {
+ //If a window is semitransparent, then we cannot apply a quickfade to it if
+ //the window below is faded too.
+ iScreen->AddRedrawRegion(iVisibleRegion, EFalse, ERedrawAll);
+ iScreen->RemoveFromQuickFadeList(this);
+ }
+ else
+ {
+ iQuickFadeRegion.Intersection(iFadableRegion, aTop);
+
+ //Remove any regions not possible to quick fade from iQuickFadeRegion and
+ //schedule these regions for full back-front rendering instead.
+ STACK_REGION nonQuickFadableRegion;
+
+ for(CWsSpriteBase * sprite = iSpriteList; sprite; sprite = sprite->Next())
+ {
+ nonQuickFadableRegion.AddRect(sprite->Rect());
+ }
+
+ for(CWsAnim * anim = iAnimList; anim; anim = anim->Next())
+ {
+ nonQuickFadableRegion.AddRect(anim->BestRect());
+ }
+
+ RWsTextCursor* const cursor = CWsTop::CurrentTextCursor();
+ if( cursor && (cursor->Window()==this) && cursor->IsStandardCursorActive() )
+ {
+ nonQuickFadableRegion.AddRect(cursor->Rect());
+ }
+
+ //Any regions scheduled for fading but partly or fully covered by transparent windows above them
+ STACK_REGION coveredFadableRegion;
+ coveredFadableRegion.Copy(iFadableRegion);
+ coveredFadableRegion.SubRegion(iQuickFadeRegion);
+ nonQuickFadableRegion.Union(coveredFadableRegion);
+ coveredFadableRegion.Close();
+
+ nonQuickFadableRegion.Tidy();
+
+ //Remove any regions not possible to quick fade from iQuickFadeRegion
+ iQuickFadeRegion.SubRegion(nonQuickFadableRegion);
+
+ if (!nonQuickFadableRegion.CheckError())
+ {
+ //Schedule normal drawing (full back to front rendering) for the region not possible to quick fade
+ if (!nonQuickFadableRegion.IsEmpty())
+ {
+ iScreen->AddRedrawRegion(nonQuickFadableRegion, EFalse, ERedrawAll);
+ }
+ }
+ else
+ {
+ //Schedule normal drawing for the whole iVisibleRegion if the calculations are broken
+ iScreen->AddRedrawRegion(iVisibleRegion, EFalse, ERedrawAll);
+ }
+ nonQuickFadableRegion.Close();
+ }
+ }
+ else
+ {
+ iQuickFadeRegion.Reset();
+ }
+ }
+
+void CWsWindow::RestartAnimations(const TRegion& aNewRegion)
+ {
+ //When not ChangeTracking, restarting is handled by AddRedrawRegion (called from CWsWindow::SetVisibleRegion) and TWalkWindowTreeScheduleRegions
+ WS_ASSERT_DEBUG(iScreen->ChangeTracking(),EWsPanicNoChangetracking);
+
+ //Restart uncovered window animations
+ for (CWsAnim* anim = iAnimList; anim; anim = anim->Next())
+ {
+ if(!iScreen->IsScheduled(EWindowAnim, anim->BestRect(), this) && aNewRegion.Intersects(anim->BestRect()))
+ {
+ iScreen->ScheduleAnimation(EWindowAnim, anim->BestRect(), 0, 0, 0, this);
+ }
+ }
+ //Restart uncovered sprite animations
+ for (CWsSpriteBase* sprite = iSpriteList; sprite; sprite = sprite->Next())
+ {
+ if(!iScreen->IsScheduled(ESpriteAnim, sprite->Rect(), sprite->Win()) && aNewRegion.Intersects(sprite->Rect()))
+ {
+ iScreen->ScheduleAnimation(ESpriteAnim, sprite->Rect(), 0, 0, 0, sprite->Win());
+ }
+ }
+ }
+
+void CWsWindow::ClearVisibleRegion()
+ {
+ AbortAllDSAs();
+ iScreen->AddRedrawRegion(VisibleRegion(), EFalse);
+ ResetVisibleRegion();
+ PossibleVisibilityChangedEvent(EFalse);
+ if (Redraw()->HasElement())
+ {
+ WS_ASSERT_DEBUG(WinType()==EWinTypeClient,EWsPanicWindowType);
+
+ if (WinType()==EWinTypeClient)
+ {
+ iScreen->WindowElements().SetVisibleRegion(*static_cast<CWsClientWindow*>(this));
+ }
+ }
+ iFlags &= ~EFlagDrawnToScreen;
+ }
+
+void CWsWindow::AbortDsaIfRequired(const TRegion& aNewRegion, const TRegion* aTop)
+ {
+ if (!iDSAs.IsEmpty())
+ {
+ // If the top visible region of this window has changed, DSA clients may need
+ // to be sent a DSA abort, as they may be drawing to a different region
+ STACK_REGION newTopVisible;
+ newTopVisible.Copy(aNewRegion); // new visible region
+ if (aTop!=NULL)
+ {
+ newTopVisible.Intersect(*aTop); // area of new visible region not obscured by any other opaque or translucent windows
+ }
+ // Build a list of DSA clients that need to be sent a DSA abort
+ TSglQue<CWsDirectScreenAccess> dsaList(_FOFF(CWsDirectScreenAccess,iAbortLink));
+ TSglQueIter<CWsDirectScreenAccess> iter(iDSAs);
+ CWsDirectScreenAccess* dsa;
+ while ((dsa=iter++)!=NULL)
+ {
+ if (dsa->IsAbortRequired(newTopVisible))
+ {
+ dsaList.AddLast(*dsa);
+ }
+ }
+ if (!dsaList.IsEmpty())
+ {
+ iScreen->AbortDSAs(RDirectScreenAccess::ETerminateRegion, dsaList);
+ }
+ newTopVisible.Close();
+ }
+ }
+
+const TRegion* CWsWindow::VisibleRegionIfValid() const
+ {
+ return iVisibleRegion.CheckError() ? NULL : &iVisibleRegion;
+ }
+
+TBool CWsWindow::ReadyToDraw() const
+ {
+ return iRedraw->ReadyToDraw();
+ }
+
+/**
+This function draws the region specified
+*/
+void CWsWindow::Render(MWsGraphicsContext& aGc, const TRegion& aWindowRegion, const TRegion& aWindowChildNodeRegion)
+ {
+ WS_ASSERT_DEBUG(IsVisible() || (WinType() == EWinTypeRoot), EWsPanicScheduledRedraw);
+
+ AnnotateWindowRedrawStart(*this, aWindowRegion);
+
+ Accessed();
+ iFlags |= EFlagDrawnToScreen;
+
+ aGc.Reset();
+ iRedraw->PreDrawWindow(&aGc, aWindowRegion);
+ iRedraw->DrawWindow();
+ iRedraw->PostDrawWindow(&aGc, aWindowChildNodeRegion);
+ }
+
+void CWsWindow::SetNextScheduled(CWsWindow * aWin)
+ {
+ iNextScheduled = aWin;
+ }
+
+CWsWindow * CWsWindow::NextScheduled() const
+ {
+ return iNextScheduled;
+ }
+
+void CWsWindow::DeactivateAllSprites()
+ {
+ CWsSpriteBase * current = iSpriteList;
+ while (current)
+ {
+ CWsSpriteBase * next = current->Next();
+ current->Deactivate();
+ current = next;
+ }
+ }
+
+void CWsWindow::ClipRectToViewport(TRect& aRect) const
+ {
+ const CWsWindowBase * win = this;
+ while (win)
+ {
+ if (win->WinType() != EWinTypeGroup)
+ {
+ aRect.Intersection(win->AbsRect());
+ }
+ win = win->BaseParent();
+ }
+ }
+
+void CWsWindow::AddDirtyWindowRegion(const TRegion& aRegion)
+ {
+ iDirtyWindowRegion.Union(aRegion);
+ if (iDirtyWindowRegion.CheckError())
+ {
+ iDirtyWindowRegion.Reset();
+ iDirtyWindowRegion.AddRect(AbsRect()); // fallback to potentially visible part of window
+ }
+ }
+
+const TRegion& CWsWindow::DirtyWindowRegion() const
+ {
+ return iDirtyWindowRegion;
+ }
+
+void CWsWindow::ScheduleDirtyWindowRegion()
+ {
+ iDirtyWindowRegion.Tidy();
+ iDirtyWindowRegion.Offset(iOrigin); //convert to screen coords
+ iScheduledRegion.Copy(iDirtyWindowRegion);
+ iDirtyWindowRegion.Reset();
+ if (iScheduledRegion.CheckError())
+ {
+ iScheduledRegion.Reset();
+ iScheduledRegion.AddRect(AbsRect()); // fallback to potentially visible part of window
+ }
+ }
+
+void CWsWindow::AddDirtySpriteRegion(const TRegion& aRegion)
+ {
+ iDirtySpriteRegion.Union(aRegion);
+ if (iDirtySpriteRegion.CheckError())
+ {
+ iDirtySpriteRegion.Reset();
+ iDirtySpriteRegion.AddRect(AbsRect()); // fallback to potentially visible part of window
+ }
+ }
+
+const TRegion& CWsWindow::DirtySpriteRegion() const
+ {
+ return iDirtySpriteRegion;
+ }
+
+void CWsWindow::ScheduleDirtySpriteRegion()
+ {
+ iDirtySpriteRegion.Tidy();
+ iDirtySpriteRegion.Offset(iOrigin); //convert to screen coords
+ iScheduledSpriteRegion.Copy(iDirtySpriteRegion);
+ iDirtySpriteRegion.Reset();
+ if (iScheduledSpriteRegion.CheckError())
+ {
+ iScheduledSpriteRegion.Reset();
+ iScheduledSpriteRegion.AddRect(AbsRect()); // fallback to potentially visible part of window
+ }
+ }
+
+void CWsWindow::ClearScheduledSpriteRegion()
+ {
+ iScheduledSpriteRegion.Reset();
+ }
+
+/**
+In ChangeTracking mode, wserv is not maintaining the visible region of windows.
+Windows that need to keep track of their visible region in ChangeTracking mode
+should call this function.
+
+@param aRegister ETrue if iVisibleRegion should be maintained with accurate information,
+ EFalse if not.
+
+@internalComponent
+*/
+void CWsWindow::SetupVisibleRegionTracking(TBool aRegister)
+ {
+ if (aRegister)
+ {
+ ++iVisibleRegionTrackingCounter;
+ if (iVisibleRegionTrackingCounter==1)
+ {
+ //If visible region tracking has not been setup, let's do it now.
+ iScreen->SetupVisibleRegionTracking(*this, ETrue);
+ }
+ }
+ else if (iVisibleRegionTrackingCounter>0)
+ {
+ --iVisibleRegionTrackingCounter;
+ if (iVisibleRegionTrackingCounter==0)
+ {
+ //If aReason was the last reason to track visibility, disable further notifications.
+ iScreen->SetupVisibleRegionTracking(*this, EFalse);
+ }
+ }
+ }
+
+/**
+MWsWindow
+*/
+MWsWindow * CWsWindow::FindChildByHandle(TUint32 aHandle)
+ {
+ TWalkWindowTreeFindByHandle wwt(aHandle);
+ WalkWindowTree(wwt, EWalkChildren);
+ return wwt.Found();
+ }
+
+TUint32 CWsWindow::Handle() const
+ {
+ return ClientHandle();
+ }
+
+MWsScreen * CWsWindow::WsScreen() const
+ {
+ return iScreen;
+ }
+
+TInt CWsWindow::OrdinalPriority() const
+ {
+ return iOrdinalPriority;
+ }