windowing/windowserver/nga/SERVER/openwfc/WINBASE.CPP
changeset 0 5d03bc08d59c
child 122 5fabdb30d001
child 136 62bb7c97884c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/openwfc/WINBASE.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,797 @@
+// 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 virtual base class, windows and window groups are derived from this
+// 
+//
+
+#include <e32std.h>
+#include "server.h"
+#include "winbase.h"
+#include "rootwin.h"
+#include "windowgroup.h"
+#include "walkwindowtree.h"
+#include "wstop.h"
+#include "EVQUEUE.H"
+#include "EVENT.H"
+#include "panics.h"
+#include "pointer.h"
+#include "windowelementset.h"
+
+CWsWindowBase::CWsWindowBase(CWsClient* aOwner,WH_HANDLES aType, CScreen* aScreen) : CWsScreenObject(aOwner,aType,aScreen)		
+	{
+	}
+
+void CWsWindowBase::ConstructL(CWsWindowBase *aParent)
+	{
+	iParent=aParent;
+	iSibling=aParent->iChild;
+	aParent->iChild=this;
+	CScreen* screen = aParent->Screen();
+	WS_ASSERT_DEBUG(screen,EWsPanicNoScreen);
+	MWsWindowTreeObserver* const windowTreeObserver = screen->WindowTreeObserver();
+	if (windowTreeObserver)
+		{
+		windowTreeObserver->NodeCreated(*this, ParentNode());
+		iBaseWinFlags |= EBaseWinNodeCreated;
+		}
+	SetOrdinalPosition(0);
+	iFadeCount = iParent->iFadeCount;
+	}
+
+CWsWindowBase *CWsWindowBase::GetPrevSibling() const
+	{
+	if(iParent == NULL) //RootWindow
+		return(NULL);
+	
+	CWsWindowBase* prev=iParent->iChild;
+	CWsWindowBase *ret=NULL;
+	while (prev!=this)
+		{
+		ret=prev;
+		prev=prev->iSibling;
+		}
+	return(ret);
+	}
+
+CWsWindowBase *CWsWindowBase::LastSibling() const
+	{
+	const CWsWindowBase *win;
+	for(win=this;win->iSibling;win=win->iSibling)
+		{}
+	return (CWsWindowBase*)win;
+	}
+
+CWsWindowBase *CWsWindowBase::PrevSiblingMultiParent() const
+	{
+	CWsWindowBase *win=GetPrevSibling();
+	if (win)
+		return(win);
+	for(CWsWindowBase *parent=iParent->GetPrevSibling();parent;parent=parent->GetPrevSibling())
+		if ((win=parent->iChild)!=NULL)
+			return(win->LastSibling());
+	return(NULL);
+	}
+
+CWsWindowBase *CWsWindowBase::NextSiblingMultiParent() const
+	{
+	if (iSibling)
+		return(iSibling);
+	for(CWsWindowBase *parent=iParent->iSibling;parent;parent=parent->iSibling)
+		{
+		if (parent->iChild!=NULL)
+			return(parent->iChild);
+		}
+	return(NULL);
+	}
+
+TInt CWsWindowBase::OrdinalPosition(TBool aFull) const
+	{
+	if (!iParent)
+		{
+		OwnerPanic(EWservPanicParentDeleted);
+		}
+	CWsWindowBase *win=iParent->iChild;
+	if (!aFull)
+		while(iOrdinalPriority<win->iOrdinalPriority)
+			win=win->iSibling;
+	TInt count;
+	for(count=0;win!=this;count++)
+		win=win->iSibling;
+	return(count);
+	}
+
+/** Removes a window from the list of siblings maintained by its parent window.
+
+The iSibling stored inside the window we remove is kept unchanged as it may be needed later.
+
+@internalComponent
+@released
+*/
+void CWsWindowBase::RemoveFromSiblingList()
+	{
+	if (iParent!=NULL)
+		{
+		CWsWindowBase **prev= &iParent->iChild;
+		while ((*prev)!=this)
+			prev= &(*prev)->iSibling;
+		*prev=iSibling;
+		}
+	}
+
+CWsWindowGroup *CWsWindowBase::WinGroup() const
+	{
+	if (iWinType==EWinTypeClient)
+		return(((CWsClientWindow *)this)->TopClientWindow()->Parent());
+	if (iWinType==EWinTypeGroup)
+		return((CWsWindowGroup *)this);
+	return(NULL);
+	}
+
+TBool CWsWindowBase::CheckOrdinalPositionChange(TInt aPos)
+//
+// This routine checks to see whether the specified new ordinal position
+// will causes a change, if so returns ETrue else EFalse.
+//
+	{
+	CWsWindowBase *win= iParent->iChild;
+	CWsWindowBase *prev= NULL;
+	while(win==this || (win!=NULL && iOrdinalPriority<win->iOrdinalPriority))
+		{
+		prev=win;
+		win=win->iSibling;
+		}
+	if (prev==this)
+		win=this;
+	else if (win==NULL || (win->iSibling==this && iOrdinalPriority>win->iOrdinalPriority))
+		return ETrue;
+	while(aPos--!=0 && win->iSibling!=NULL && iOrdinalPriority==win->iSibling->iOrdinalPriority)
+		win=win->iSibling;
+	return(win!=this);
+	}
+
+void CWsWindowBase::ChangeWindowPosition(TInt aPos,CWsWindowBase* aNewParent)
+	{
+	TBool changedWindowGroup = EFalse;
+	WS_ASSERT_DEBUG(aNewParent,EWsPanicWindowNull);
+	if (aNewParent != iParent)
+		{
+		iScreen->ScheduleRegionUpdate(NULL);		
+		TWalkWindowTreeScheduleRedraws wwt;
+		WalkWindowTree(wwt, EWalkChildren);
+		changedWindowGroup = ETrue;
+		}
+	else if (WinType() == EWinTypeClient)
+		{
+		CWsClientWindow * cliwin = static_cast<CWsClientWindow*>(this);
+		if (cliwin->IsVisible())
+			{
+			iScreen->ScheduleRegionUpdate(NULL);
+			if (cliwin->IsTranslucent())
+				{
+				// There is still room for optimization here.  These redraws are only required if the window
+				// moved through another window and BOTH of them were transparent, otherwise the visible
+				// region change will sort out the redraws required.
+				TWalkWindowTreeScheduleRedraws wwt;
+				WalkWindowTree(wwt, EWalkChildren);
+				}
+			}
+		}
+	else if (WinType() == EWinTypeGroup)
+		{
+		iScreen->ScheduleRegionUpdate(NULL);
+		if (static_cast<CWsWindowGroup*>(this)->HasVisibleTranslucentChild())
+			{
+			TWalkWindowTreeScheduleRedraws wwt;
+			WalkWindowTree(wwt, EWalkChildren);				
+			}
+		}
+
+	RemoveFromSiblingList();
+	CWsWindowBase **prevWinPtr= &aNewParent->iChild;
+	while((*prevWinPtr)!=NULL && iOrdinalPriority<(*prevWinPtr)->iOrdinalPriority)
+		{
+		prevWinPtr= &(*prevWinPtr)->iSibling;
+		}
+	while(aPos--!=0 && *prevWinPtr!=NULL && iOrdinalPriority==(*prevWinPtr)->iOrdinalPriority)
+		{
+		prevWinPtr= &(*prevWinPtr)->iSibling;
+		}
+	iSibling=*prevWinPtr;
+	iParent=aNewParent;
+	*prevWinPtr=this;
+
+	Screen()->WindowElements().SortByZOrder();
+
+	MWsWindowTreeObserver* const windowTreeObserver = Screen()->WindowTreeObserver();
+	if (windowTreeObserver)
+		{
+		if(changedWindowGroup && (WinType() == EWinTypeClient))
+			{
+			windowTreeObserver->MovedToWindowGroup(*this, *(this->WinGroup()));
+			}
+		else if(!changedWindowGroup)
+			{
+			windowTreeObserver->SiblingOrderChanged(*this, OrdinalPosition(ETrue));
+			}
+		else if(changedWindowGroup)
+			{
+			OwnerPanic(EWservPanicInvalidParameter); //Should be impossible to end up here as only WinType() EWinTypeClient 
+			}										 //and EWinTypeGroup can be moved to another windowgroup.
+		}											 //@see RWindowBase::MoveToGroup
+	}
+
+void CWsWindowBase::SetOrdinalPosition(TInt aPos)
+	{
+	if (CheckOrdinalPositionChange(aPos))
+		ChangeWindowPosition(aPos,iParent);
+	}
+
+TEventQueueWalkRet EventPurgeFunc(TAny *aPtr, TWsEvent *aEvent)
+//
+// Callback function for event queue walk
+//
+	{
+	return(((CWsWindowBase *)aPtr)->EventPurgeCheck(aEvent));
+	}
+
+TEventQueueWalkRet CWsWindowBase::EventPurgeCheck(TWsEvent *aEvent)
+	{
+	if (aEvent->Handle()==ClientHandle())
+		return(EEventQueueWalkDeleteEvent);
+	return(EEventQueueWalkOk);
+	}
+
+void CWsWindowBase::PurgeEvents()
+	{
+	iWsOwner->EventQueue()->WalkEventQueue(&EventPurgeFunc,this);
+	}
+
+void CWsWindowBase::Shutdown()
+//
+// Destroy a window, disconnects from the window tree and destroys all it's child windows
+//
+	{
+	if (iWsOwner!=NULL)
+		PurgeEvents();
+	if (iParent!=NULL)	// Check it's connected to something
+		{
+		CWsWindowBase *win;
+		for(win=this;win && win->iParent!=(CWsWindowBase *)RootWindow();win=win->iParent)
+			{}
+		RemoveFromSiblingList();
+		TWalkWindowTreeDisconnect wwt2(win ? ((CWsWindowGroup *)win)->TextCursor() : NULL);
+		WalkWindowTree(wwt2,EWalkChildren); // Disconnect all child windows
+		iChild=NULL;
+		}
+	TWindowServerEvent::RemoveFromSwitchOnEventList(*this);
+	TWindowServerEvent::RemoveFromErrorMessageList(*this);
+	TWindowServerEvent::RemoveFromGroupChangeEventEventList(*this);
+	TWindowServerEvent::RemoveFromFocusChangeEventEventList(*this);
+	TWindowServerEvent::RemoveFromGroupListChangeEventEventList(*this);
+	TWindowServerEvent::RemoveFromModifierChangedEventList(*this);
+	TWindowServerEvent::RemoveFromScreenDeviceChangeEventList(*this);
+	CWsTop::StopWindowGettingOffEvents(this);
+	}
+
+TBool CWsWindowBase::CommandL(TInt aOpcode, TWsWinCmdUnion &aCmd)
+//
+// If the command is supported by the window base class process it and return ETrue
+// if it is not supported return EFalse
+//
+	{
+	switch(aOpcode)
+		{
+		case EWsWinOpFree:
+			{
+			delete this;
+			break;
+			}
+		case EWsWinOpSetOrdinalPosition:
+			SetOrdinalPosition(*aCmd.Int);
+			break;
+		case EWsWinOpOrdinalPriority:
+			SetReply(iOrdinalPriority);
+			break;
+		case EWsWinOpOrdinalPosition:
+			SetReply(OrdinalPosition(EFalse));
+			break;
+		case EWsWinOpFullOrdinalPosition:
+			SetReply(OrdinalPosition(ETrue));
+			break;
+		case EWsWinOpClientHandle:
+			SetReply(iClientHandle);
+			break;
+		case EWsWinOpParent:
+			if (!iParent)
+				{
+				OwnerPanic(EWservPanicParentDeleted);
+				}
+			SetReply(iParent->iClientHandle);
+			break;
+		case EWsWinOpPrevSibling:
+			{
+			if (!iParent)
+				{
+				OwnerPanic(EWservPanicParentDeleted);
+				}
+			TUint32 reply=NULL;
+			for(CWsWindowBase *win=this->GetPrevSibling();win;win=win->GetPrevSibling())
+				{
+				if (win->iWsOwner==iWsOwner)
+					{
+					reply=win->iClientHandle;
+					break;
+					}
+				}
+			SetReply(reply);
+			}
+			break;
+		case EWsWinOpNextSibling:
+			{
+			TUint32 reply=NULL;
+			for(CWsWindowBase *win=this->iSibling;win;win=win->iSibling)
+				{
+				if (win->iWsOwner==iWsOwner)
+					{
+					reply=win->iClientHandle;
+					break;
+					}
+				}
+			SetReply(reply);
+			}
+			break;
+		case EWsWinOpChild:
+			SetReply(iChild==NULL ? NULL : iChild->iClientHandle);
+			break;
+		case EWsWinOpScreenNumber:
+			SetReply(Screen()->ScreenNumber());
+			break;
+		case EWsWinOpWindowGroupId:
+			{
+			TUint32 reply=NULL;
+			CWsWindowGroup *wg=WinGroup();
+			if (wg)
+				{
+				reply=wg->Identifier();
+				}
+			SetReply(reply);
+			}
+			break;
+		case EWsWinOpEnableOnEvents:
+			{
+			const TEventControl circumstances = *aCmd.EventControl;
+			TWindowServerEvent::AddToSwitchOnEventListL(*this, circumstances);
+			if (iScreen->ChangeTracking())
+				{
+				if(circumstances & EEventControlOnlyWhenVisible)
+					{
+					TWalkWindowTreeSetupVisibleRegionTracking wwt(ETrue);
+					WalkWindowTree(wwt, EWalkChildren);
+					}
+				}
+			break;
+			}
+		case EWsWinOpDisableOnEvents:
+			{
+			TWindowServerEvent::RemoveFromSwitchOnEventList(*this);
+			if (iScreen->ChangeTracking())
+				{
+				TWalkWindowTreeSetupVisibleRegionTracking wwt(EFalse);
+				WalkWindowTree(wwt, EWalkChildren);
+				}
+			break;
+			}
+		case EWsWinOpEnableErrorMessages:
+			{
+			const TEventControl circumstances = *aCmd.EventControl;
+			TWindowServerEvent::AddToErrorMessageListL(*this, circumstances);
+			if (iScreen->ChangeTracking())
+				{
+				if(circumstances & EEventControlOnlyWhenVisible)
+					{
+					TWalkWindowTreeSetupVisibleRegionTracking wwt(ETrue);
+					WalkWindowTree(wwt, EWalkChildren);
+					}
+				}
+			break;
+			}
+		case EWsWinOpDisableErrorMessages:
+			{
+			TWindowServerEvent::RemoveFromErrorMessageList(*this);
+			if (iScreen->ChangeTracking())
+				{
+				TWalkWindowTreeSetupVisibleRegionTracking wwt(EFalse);
+				WalkWindowTree(wwt, EWalkChildren);
+				}
+			break;
+			}
+		case EWsWinOpEnableModifierChangedEvents:
+			{
+			const TInt modifierMask = aCmd.EnableModifierChangedEvents->modifierMask;
+			const TEventControl circumstances = aCmd.EnableModifierChangedEvents->circumstances;
+			TWindowServerEvent::AddToModifierChangedEventListL(*this, modifierMask, circumstances);
+			if (iScreen->ChangeTracking())
+				{
+				if(circumstances & EEventControlOnlyWhenVisible)
+					{
+					TWalkWindowTreeSetupVisibleRegionTracking wwt(ETrue);
+					WalkWindowTree(wwt, EWalkChildren);
+					}
+				}
+			break;
+			}
+		case EWsWinOpDisableModifierChangedEvents:
+			{
+			TWindowServerEvent::RemoveFromModifierChangedEventList(*this);
+			if (iScreen->ChangeTracking())
+				{
+				TWalkWindowTreeSetupVisibleRegionTracking wwt(EFalse);
+				WalkWindowTree(wwt, EWalkChildren);
+				}
+			break;
+			}
+		case EWsWinOpEnableGroupChangeEvents:
+			TWindowServerEvent::AddToGroupChangeEventListL(*this);
+			break;
+		case EWsWinOpDisableGroupChangeEvents:
+			TWindowServerEvent::RemoveFromGroupChangeEventEventList(*this);
+			break;
+		case EWsWinOpEnableFocusChangeEvents:
+			TWindowServerEvent::AddToFocusChangeEventListL(*this);
+			break;
+		case EWsWinOpDisableFocusChangeEvents:
+			TWindowServerEvent::RemoveFromFocusChangeEventEventList(*this);
+			break;
+		case EWsWinOpEnableGroupListChangeEvents:
+			TWindowServerEvent::AddToGroupListChangeEventListL(*this);
+			break;
+		case EWsWinOpDisableGroupListChangeEvents:
+			TWindowServerEvent::RemoveFromGroupListChangeEventEventList(*this);
+			break;
+		case EWsWinOpSetCustomPointerCursor:
+			CWsObject *pointercursor;
+			if ((pointercursor=iWsOwner->HandleToObj(*aCmd.Int, WS_HANDLE_POINTER_CURSOR))==NULL)
+				OwnerPanic(EWservPanicSprite);
+			SetPointerCursor((CWsPointerCursor *)pointercursor);
+			break;
+		case EWsWinOpSetPointerCursor:
+			SetPointerCursorByIndex(*aCmd.UInt);
+			break;
+		case EWsWinOpClearPointerCursor:
+			SetPointerCursor(NULL);
+			break;
+		case EWsWinOpSetNonFading:
+			{
+			WS_ASSERT_DEBUG(iScreen, EWsPanicNoScreen);
+			// No fading will occur from a graphical perspective, but the fade counts
+			// are maintained for BC reasons.
+			TWalkWindowTreeSetNonFading wwt(*aCmd.Bool);
+			WalkWindowTree(wwt,EWalkChildren);
+			}
+			break;
+		case EWsWinOpSetFade:
+			{
+			WS_ASSERT_DEBUG(iScreen, EWsPanicNoScreen);
+			
+			TUint8 blackMap;
+			TUint8 whiteMap;
+			if (aCmd.SetFaded->UseDefaultMap())
+				{
+				iScreen->GetFadingParams(blackMap,whiteMap);
+				}
+			else
+				{
+				aCmd.SetFaded->GetFadingParams(blackMap,whiteMap);
+				}
+			
+			if (aCmd.SetFaded->IncludeChildren())
+				{
+				TWalkWindowTreeSetFaded wwt(aCmd.SetFaded->Faded(),this,blackMap,whiteMap);
+				WalkWindowTree(wwt,EWalkChildren);
+				}
+			else
+				{
+				if (iWinType==EWinTypeGroup)
+					OwnerPanic(EWservPanicOpcode);
+				
+				const TBool KNotifyObserver = ETrue; //yes please
+				const TBool KFaded = aCmd.SetFaded->Faded();
+				static_cast<CWsClientWindow*>(this)->SetFaded(KFaded, blackMap, whiteMap, KNotifyObserver); 
+				}
+			}
+			break;
+			case EWsWinOpEnableAdvancedPointers:
+				User::LeaveIfError(IsActivated()?KErrInUse:KErrNone);
+				iBaseWinFlags |= EBaseWinAdvancedPointersEnabled;
+				break;
+		default:
+			return(EFalse);
+		}
+	return(ETrue);
+	}
+
+/** @see MWsWindowTreeNode */
+MWsWindowTreeNode::TType CWsWindowBase::NodeType() const
+	{
+	return static_cast<MWsWindowTreeNode::TType>(iWinType); //TWinType is a subset of MWsWindowTreeNode::TType
+	}
+
+/** @see MWsWindowTreeNode */
+const MWsWindow* CWsWindowBase::Window() const
+	{
+	return (iWinType!=EWinTypeGroup) ? (static_cast<const CWsWindow*>(this)) : NULL;
+	}
+
+/** @see MWsWindowTreeNode */
+const MWsSprite* CWsWindowBase::Sprite() const
+	{
+	return NULL;
+	}
+
+/** @see MWsWindowTreeNode */
+const MWsStandardTextCursor* CWsWindowBase::StandardTextCursor() const
+	{
+	return NULL;
+	}
+
+/** @see MWsWindowTreeNode */
+const MWsWindowGroup* CWsWindowBase::WindowGroup() const
+	{
+	return static_cast<MWsWindowGroup*>(WinGroup()); 
+	}
+
+/** @see MWsWindowTreeNode */
+const MWsWindowTreeNode* CWsWindowBase::ParentNode() const
+	{
+	return iParent;
+	}
+
+TBool CWsWindowBase::QueueEvent(TInt aEvent, TInt aIntVal) const
+	{
+	if (WsOwner())
+		return(WsOwner()->EventQueue()->QueueEvent(iClientHandle, aEvent, aIntVal));
+	return(EFalse);
+	}
+
+void CWsWindowBase::SetPointerCursorByIndex(TInt aIndex)
+	{
+	SetPointerCursor(CWsClient::SystemPointerCursor(aIndex));
+	}
+
+void CWsWindowBase::SetPointerCursor(CWsPointerCursor *aCursor)
+	{
+	CWsPointerCursor *old=iPointerCursor;
+	iPointerCursor=aCursor;
+	if (iPointerCursor)
+		iPointerCursor->Open();
+	TWsPointer::UpdatePointerCursor();
+	if (old)
+		old->Close();
+	}
+
+TBool CWsWindowBase::TreeIsObscured() const
+	{
+	TBool result;
+	TWalkWindowTreeIsObscured wwt(result);
+	CONST_CAST(CWsWindowBase *,this)->WalkWindowTree(wwt,EWalkChildren);
+	return(result);
+	}
+
+CEventQueue *CWsWindowBase::EventQueue() const
+	{
+	CEventQueue* eventQueue = NULL;
+	if (iWsOwner)
+		eventQueue = iWsOwner->EventQueue();
+	return eventQueue;
+	}
+
+TInt CWsWindowBase::Depth() const
+	{
+	TInt count=0;
+	const CWsWindowBase *win=this;
+	while (win->WinType()!=EWinTypeRoot)
+		{
+		++count;
+		win=win->iParent;
+		}
+	return(count);
+	}
+
+void CWsWindowBase::WalkWindowTree(TWalkWindowTreeBase &aWalkClass,TWalkMode aMode)
+//
+// Walks windows in a front to back order
+//
+// If mode is EWalkBehind
+//	call DoIt for all windows that are behind 'this'
+// else if mode is EWalkChildren
+//  call DoIt for all descendents
+// else if mode is EWalkChildrenAndBehind
+//  call DoIt for for all descendents and windows behind
+//
+	{
+	if (this!=NULL)
+		{
+		CWsWindowBase *win=this;
+		CWsWindowBase *end=RootWindow();
+		CWsWindowBase *sibling=win->iSibling;
+		CWsWindowBase *parent=win->iParent;
+		if (aMode!=EWalkBehind)
+			{
+			if (aMode==EWalkChildren)
+				end=win;
+			goto start;
+			}
+		do
+			{
+			if (sibling!=NULL)
+				{
+				win=sibling;
+start:			while(win->iChild!=NULL)
+					win=win->iChild;
+				}
+			else
+				win=parent;
+			sibling=win->iSibling;	// De-reference win so it can be destroyed by 'DoIt'
+			parent=win->iParent;
+			if (win->iWinType!=EWinTypeGroup && aWalkClass.DoIt((CWsWindow *)win))
+				return;
+			} while(win!=end);
+		}
+	}
+
+/* Walks windows in a front to back order
+
+ If aResume is EFalse the walk is identical to above.
+ Otherwise iWin is taken as the restart point, (any child windows will have been
+ walked previously).
+ */
+void CWsWindowBase::WalkWindowTree(TResumableWalkWindowTreeBase& aWalkClass, TWalkMode aMode, TBool aResume)
+	{
+	if (this != NULL)
+		{ // init
+		if (!aResume)
+			{
+			aWalkClass.iWin = this;
+			aWalkClass.iEnd = (aMode == EWalkChildren) ? this : RootWindow();
+			aWalkClass.iParent = aWalkClass.iWin->iParent;
+			if (aMode == EWalkBehind)
+				{
+				aWalkClass.iNextChild = aWalkClass.iWin->iSibling;
+				}
+			else
+				{ // ensure walk includes this and its child windows
+				aWalkClass.iNextChild = this;
+				}
+			}
+		else if (aWalkClass.iWin == aWalkClass.iEnd)
+			{
+			return; // walk had already reached end
+			}
+
+		do
+			{
+			if (aWalkClass.iNextChild != NULL)
+				{ // walk down tree to a leaf window
+				aWalkClass.iWin = aWalkClass.iNextChild;
+				while (aWalkClass.iWin->iChild != NULL)
+					{
+					aWalkClass.iWin = aWalkClass.iWin->iChild;
+					}
+				}
+			else
+				{ // walk up tree
+				aWalkClass.iWin = aWalkClass.iParent;
+				}
+			// De-reference iWin so it can be destroyed by 'DoIt'
+			aWalkClass.iNextChild = aWalkClass.iWin->iSibling;
+			aWalkClass.iParent = aWalkClass.iWin->iParent;
+			if ( ( aWalkClass.iWin->iWinType != EWinTypeGroup ) && aWalkClass.DoIt(static_cast<CWsWindow *>(aWalkClass.iWin)) )
+				{
+				return;
+				}
+			}
+		while (aWalkClass.iWin != aWalkClass.iEnd);
+		}
+	}
+
+void CWsWindowBase::WalkWindowTreeBackToFront(TWalkWindowTreeBase &aWalkClass, TWalkModeBackToFront aMode)
+	{
+	// Walks windows in a back to front order
+	//
+	// If mode is EVisitParentNodesFirst
+	// call DoIt() on each node before walking their child windows.	
+	
+	if(iSibling)
+		iSibling->WalkWindowTreeBackToFront(aWalkClass,aMode);
+	
+	if(aMode == EVisitParentNodesFirst)
+		aWalkClass.DoIt(static_cast<CWsWindow *>(this));
+	
+	if(iChild)
+		iChild->WalkWindowTreeBackToFront(aWalkClass,aMode);
+	
+	}
+
+TBool CWsWindowBase::IsDSAHost() const
+	{
+	return EFalse;
+	}
+
+TBool CWsWindowBase::IsActivated() const
+	{
+	return EFalse;
+	}
+
+void CWsWindowBase::AddSprite(CWsSpriteBase * aSprite)
+	{
+	aSprite->SetNext(iSpriteList);
+	iSpriteList = aSprite;
+	}
+	
+void CWsWindowBase::RemoveSprite(CWsSpriteBase * aSprite)
+	{
+	if (aSprite == iSpriteList)
+		{
+		iSpriteList = aSprite->Next();
+		}
+	else
+		{
+		for (CWsSpriteBase * sprite = iSpriteList; sprite; sprite = sprite->Next())
+			{
+			if (sprite->Next() == aSprite)
+				{
+				sprite->SetNext(aSprite->Next());
+				}
+			}
+		}
+	aSprite->SetNext(0);
+	}
+
+void CWsWindowBase::SendState(MWsWindowTreeObserver& aWindowTreeObserver) const
+	{
+	//Sprites
+	if(iSpriteList)
+		iSpriteList->SendState(aWindowTreeObserver);
+	}
+
+#if defined(_DEBUG)
+
+void CWsWindowBase::CheckTree()
+	{
+	TWalkWindowTreeCheck wwt1;
+	WalkWindowTree(wwt1,EWalkChildren);
+	}
+
+enum {ENullWsHandle=0xFFFFFFFF};	// Events delivered to this handle are thrown away
+TBool CWsWindowBase::IsClientHandleInUse(TUint32 aHandle)
+	{
+	if (aHandle==static_cast<TUint>(ENullWsHandle))		//This value has a special meaning in test code
+		return EFalse;
+	CWsObjectIx* index=iWsOwner->ObjectIndex();
+	const CWsObject* obj;
+	TInt length=index->Length();
+	TInt ii;
+	for (ii=0;ii<length;++ii)
+		{
+		obj=index->At(ii);
+		if (obj && (obj->Type()==WS_HANDLE_WINDOW || obj->Type()==WS_HANDLE_GROUP_WINDOW))
+			{
+			if (STATIC_CAST(const CWsWindowBase*,obj)->ClientHandle()==aHandle)
+				return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+#endif