diff -r 000000000000 -r bde4ae8d615e os/graphics/windowing/windowserver/nonnga/SERVER/REDRAWQ.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/windowing/windowserver/nonnga/SERVER/REDRAWQ.CPP Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,261 @@ +// 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 +#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(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;indexAt(index); + redraw->iPriority=static_cast(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(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; + }