--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nonnga/SERVER/REDRAWQ.CPP Tue Feb 02 01:47:50 2010 +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 <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;
+ }