windowing/windowserver/nonnga/SERVER/REDRAWQ.CPP
author Faisal Memon <faisal.memon@nokia.com>
Thu, 06 May 2010 11:31:11 +0100
branchNewGraphicsArchitecture
changeset 47 48b924ae7197
parent 0 5d03bc08d59c
permissions -rw-r--r--
Applied patch 1, to provide a syborg specific minigui oby file. Need to compare this with the "stripped" version currently in the tree. This supplied version applies for Nokia builds, but need to repeat the test for SF builds to see if pruning is needed, or if the file needs to be device-specific.

// Copyright (c) 1996-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 server redraw queue handling
//
#include <e32std.h>
#include "server.h"
#include "rootwin.h"
#include "windowgroup.h"
#include "walkwindowtree.h"
#include "EVQUEUE.H"
#include "panics.h"
#include "wstop.h"
#include "wstraces.h"

const TInt KGranularity = 10;

void TWsRedrawEvent::SetHandle(TUint aHandle)
	{
	iHandle=aHandle;
	}

void TWsRedrawEvent::SetRect(TRect aRect)
	{
	iRect=aRect;
	}

TWsRedrawEvent CRedrawQueue::iNullRedrawEvent;

CRedrawQueue::CRedrawQueue(CWsClient *aOwner) : CEventBase(aOwner)
	{
	__DECLARE_NAME(_S("CRedrawQueue"));
	}

void CRedrawQueue::ConstructL()
	{
	iRedrawTrigger=EFalse;
	iRedraws=new(ELeave) CArrayFixSeg<TRedraw>(KGranularity);
	iKeyPriority=new(ELeave) TKeyArrayFix(_FOFF(TRedraw,iPriority),ECmpTUint32);
	iKeyWindow=new(ELeave) TKeyArrayFix(_FOFF(TRedraw,iRedraw),ECmpTUint32);
	Mem::FillZ(&iNullRedrawEvent,sizeof(iNullRedrawEvent));
	}

CRedrawQueue::~CRedrawQueue()
	{
	delete iRedraws;
	delete iKeyPriority;
	delete iKeyWindow;
	}

void CRedrawQueue::ReCalcOrder()
	{
	const TInt redrawsCount=iRedraws->Count();
	for(TInt index=0;index<redrawsCount;index++)
		{
		TRedraw *redraw=&iRedraws->At(index);
		redraw->iPriority=static_cast<CWsClientWindow*>(redraw->iRedraw->WsWin())->RedrawPriority();
		}
	iRedraws->Sort(*iKeyPriority);
	}

void CRedrawQueue::AddInvalid(CWsWindowRedraw *aRedrawWin) 
//
// Add a window to the update list.
//
	{
	TInt index;
	TRedraw redraw;

	redraw.iRedraw=aRedrawWin;
	if (iRedraws->Find(redraw,*iKeyWindow,index)!=0)
		{
		redraw.iPriority=static_cast<CWsClientWindow*>(aRedrawWin->WsWin())->RedrawPriority();
		TRAPD(err,iRedraws->InsertIsqAllowDuplicatesL(redraw,*iKeyPriority));
		if (err!=KErrNone)
			{
			WS_ASSERT_DEBUG(err==KErrNoMemory,EWsPanicRedrawQueueError);
			iAllocError=ETrue;
			}
		iRedrawTrigger=ETrue;
		}
	}

void CRedrawQueue::DeleteFromQueue(TInt aIndex)
	{
	iRedraws->Delete(aIndex,1);
	
	//We are certain we will need iRedraws again, so it would be silly to compress away the last KGranularity slots.
	const TInt count = iRedraws->Count();
	if((count >= KGranularity) && (count % KGranularity == 0))
		{
		iRedraws->Compress();
		}
	}

void CRedrawQueue::RemoveInvalid(CWsWindowRedraw *aRedrawWin)
//
// remove the window from the invalid window list.
// harmless to call if the window is not in the list.
//
	{
	TInt index;
	TRedraw redraw;

	redraw.iRedraw=aRedrawWin;
	redraw.iPriority=0;
	if ((iRedraws->Find(redraw,*iKeyWindow,index))==KErrNone)
		DeleteFromQueue(index);
	}

TBool CRedrawQueue::TriggerRedraw()
//
// Trigger any pending redraw messages in the queue
// Returns ETrue if a redraw was sent, EFalse if not.
//
	{
	WS_TRACE_SERVER_TRIGGERREDRAW();	
	TBool ret=EFalse;
	if (iRedrawTrigger)
		{
		iRedrawTrigger=EFalse;
		if (!iEventMsg.IsNull() && (iRedraws->Count()>0 || iAllocError))
			{
			SignalEvent();
			ret=ETrue;
			}
		}
	return(ret);
	}

void CRedrawQueue::EventReady(const RMessagePtr2& aEventMsg)
//
// Queue a read of an event from the queue
//
	{
	CEventBase::EventReady(aEventMsg);
	iRedrawTrigger=ETrue;
	TriggerRedraw();
	}

TBool CRedrawQueue::FindOutstandingRedrawEvent(CWsWindowRedraw& aRedraw, TWsRedrawEvent& aEvent)
	{
	TRect rect;
	if (aRedraw.GetRedrawRect(rect))
		{
		aEvent.SetRect(rect);
		aEvent.SetHandle(aRedraw.WsWin()->ClientHandle());
		CEventBase::GetData(&aEvent,sizeof(aEvent));
		return ETrue;
		}
	return EFalse;
	}

TBool CRedrawQueue::FindWindowNeedingRedrawEvent(TWsRedrawEvent& aEvent)
	{
#if defined(_DEBUG)
	CWsWindowRedraw* previousRedraw = NULL;
#endif
	// search all screens
	TInt invalidWindows = 0;
	for (TInt screenNo = 0; screenNo < CWsTop::NumberOfScreens(); ++screenNo)
		{
		CWsRootWindow* rootWindow = CWsTop::Screen(screenNo)->RootWindow();
		for (CWsWindowGroup *groupWin = rootWindow->Child(); groupWin; groupWin = groupWin->NextSibling())
			{
			if (groupWin->WsOwner() == iWsOwner)
				{
				CWsWindowRedraw* redrawWin = NULL;
				// use a window tree walk that can be resumed to find windows with an invalid region
				TResumableWalkWindowTreeFindInvalid wwt(&redrawWin);
				groupWin->WalkWindowTree(wwt, EWalkChildren, EFalse);
				while (redrawWin != NULL)
					{
					WS_ASSERT_DEBUG(redrawWin != previousRedraw, EWsPanicRedrawQueueError);
					// (the window may not actually need the client to redraw it, e.g. a CWsBlankWindow can redraw itself)
					if (FindOutstandingRedrawEvent(*redrawWin, aEvent))
						{
						return ETrue;
						}
					else
						{ // continue the Tree Walk
#if defined(_DEBUG)
						previousRedraw = redrawWin;
#endif
						if (redrawWin->NeedsRedraw())
							{ // needs to be redrawn later?
							++invalidWindows;
							}
						redrawWin = NULL;
						groupWin->WalkWindowTree(wwt, EWalkChildren, ETrue);
						}
					}
				}
			}
		}

	if (invalidWindows == 0)
		{ // error recovery is complete
		iAllocError = 0;
		}
	return EFalse;
	}

void CRedrawQueue::GetData()
//
// If there is an outstanding redraw event in the queue, reply with it's data
//
	{
	CWsWindowRedraw *redraw;
	TWsRedrawEvent event;

	while (iRedraws->Count()>0)
		{
		redraw=(*iRedraws)[0].iRedraw;
		if (FindOutstandingRedrawEvent(*redraw,event))
			{
			return;
			}
		TInt toDelete=0;
		if (redraw!=(*iRedraws)[0].iRedraw)
			{		//In low memory conditions calls to FindOutstandingRedrawEvent can cause extra entries to be added to the array
			TRedraw redrawFind;
			redrawFind.iRedraw=redraw;
			iRedraws->Find(redrawFind,*iKeyWindow,toDelete);
			}
		DeleteFromQueue(toDelete);
		}

	if (iAllocError && FindWindowNeedingRedrawEvent(event))
		{
		return;
		}

	CEventBase::GetData(&iNullRedrawEvent,sizeof(iNullRedrawEvent));
	}

TUint CRedrawQueue::RedrawPriority(CWsWindowRedraw *aRedrawWin)
	{
	TInt index;
	TRedraw redraw;
	TUint priority=0;
	redraw.iRedraw=aRedrawWin;

	if ((iRedraws->Find(redraw,*iKeyWindow,index))==KErrNone)
		{
		priority=iRedraws->At(index).iPriority;
		}
	return priority;
	}