windowing/windowserver/nonnga/SERVER/WINDOW.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nonnga/SERVER/WINDOW.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,535 @@
+// 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 "offscreenbitmap.h"
+
+CWsWindow* CWsWindow::iAccessListRecentEnd = 0;
+CWsWindow* CWsWindow::iAccessListOldestEnd = 0;
+
+CWsWindow::CWsWindow(CWsClient* aOwner,WH_HANDLES aType, CScreen* aScreen) : CWsWindowBase(aOwner,aType,aScreen),
+	iFlags(EFlagHidden),
+	 iDSAs(_FOFF(CWsDirectScreenAccess,iMultipleDSALink))
+	{
+	}
+
+CWsWindow::~CWsWindow()
+	{
+	iFadableRegion.Close();
+	}
+
+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.Close();
+	iScheduledRegion.Close();
+	AbortAllDSAs();
+	CWsWindowBase::Shutdown();
+	SetPointerCursor(NULL);
+	delete iRedraw;
+	}
+
+//
+// Region and invalid area functions //
+//
+
+TRect CWsWindow::FullRect() const
+	{
+	return(TRect(iOrigin,iRel.Size()));
+	}
+
+//
+// Normal regions //
+//
+
+void CWsWindow::SetNonFading(TBool aNonFade)
+	{
+	if (aNonFade)
+		iFlags|=EFlagNonFadingWindow;
+	else
+		iFlags&=(~EFlagNonFadingWindow);
+	}
+
+TPoint CWsWindow::InquireOffset(TUint32 aHandle) const
+	{
+	CWsWindowBase *win2;
+	iWsOwner->HandleToWindow(aHandle,&win2);
+	return(iOrigin-win2->Origin());
+	}
+
+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);
+	aBuf.AppendFormat(KStatusString3,(TInt)iScreen->DisplayMode());
+	if (!IsVisible())
+		aBuf.Append(KStatusInvisible);
+	}
+
+TDblQue<TPointerKeyList> *CWsWindow::PointerKeyList() const
+	{
+	return(NULL);
+	}
+
+void CWsWindow::AbortAllDSAs()
+	{
+	iScreen->AbortDSAs(RDirectScreenAccess::ETerminateRegion,iDSAs);
+	}
+
+void CWsWindow::PossibleVisibilityChangedEvent(TBool aForceSend)
+	{
+	// notify plugin
+	//
+	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 RWsRegion& aRegion)
+	{
+	iScheduledRegion.Copy(aRegion);
+	return !iScheduledRegion.CheckError();
+	}
+
+void CWsWindow::ClearScheduledRegion()
+	{
+	iScheduledRegion.Clear();
+	}
+
+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);
+	}
+
+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() || dsa->IsSyncTimeoutPending();
+			}
+		}
+	return res;
+	}
+
+void CWsWindow::ResetVisibleRegion()
+	{
+	if (!iVisibleRegion.IsEmpty())
+		{
+		iVisibleRegion.Clear();
+		}
+	iFadableRegion.Clear();
+	}
+
+void CWsWindow::SetVisibleRegion(const TRegion& aNewRegion, const TRegion* aTop, TRegion& aNewFadableRegion)
+	{
+	STACK_REGION difference;
+	TBool diffs = EFalse;
+
+	difference.Copy(iVisibleRegion);
+	difference.SubRegion(aNewRegion);
+	if (!difference.IsEmpty())
+		{
+		diffs = ETrue;
+		if (IsTranslucent())
+			{
+			// Andy - If this is a client window (what else could it be) we can also subtract the
+			// user defined opaque region before doing this:
+			iScreen->AddRedrawRegion(difference, EFalse);
+			}
+		}
+
+	difference.Copy(aNewRegion);
+	if (HasBeenDrawnToScreen())
+		{
+		difference.SubRegion(iVisibleRegion);
+		}
+	if (!difference.IsEmpty())
+		{
+		diffs = ETrue;
+		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();
+		}
+
+	difference.Close();
+
+	AbortDsaIfRequired(aNewRegion, aTop);
+
+	if (diffs)
+		{
+		ResetVisibleRegion();
+		iVisibleRegion.Copy(aNewRegion);
+		PossibleVisibilityChangedEvent(EFalse);
+		}
+
+	iFadableRegion.Copy( aNewFadableRegion );
+	
+	// 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();
+	}
+	
+void CWsWindow::ClearVisibleRegion()
+	{
+	AbortAllDSAs();         
+	iScreen->AddRedrawRegion(VisibleRegion(), EFalse);
+	ResetVisibleRegion();
+	PossibleVisibilityChangedEvent(EFalse);
+	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
+Andy - I would be happier if no region was specified here - the GC should incorporate that information
+*/
+void CWsWindow::Render(CFbsBitGc * aGc, const TRegion& aRegion)
+	{
+	WS_ASSERT_DEBUG(IsVisible() || (WinType() == EWinTypeRoot), EWsPanicScheduledRedraw);
+	
+	Accessed();
+	iFlags |= EFlagDrawnToScreen;
+	
+	iRedraw->PreDrawWindow(aGc, aRegion);
+	iRedraw->DrawWindow();
+	iRedraw->PostDrawWindow(aGc);
+	}
+
+void CWsWindow::SetNextScheduled(CWsWindow * aWin)
+	{
+	iNextScheduled = aWin;
+	}
+	
+CWsWindow * CWsWindow::NextScheduled()  const
+	{
+	return iNextScheduled;
+	}
+
+void CWsWindow::AddSprite(CWsSpriteBase * aSprite)
+	{
+	aSprite->SetNext(iSpriteList);
+	iSpriteList = aSprite;
+	}
+	
+void CWsWindow::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 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();
+		}
+	}
+
+const TRegion& CWsWindow::FadableRegion() const
+	{
+	return iFadableRegion;
+	}
+
+/**
+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;
+	}