windowing/windowserver/nonnga/SERVER/REDRAWQ.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 // Window server redraw queue handling
       
    17 //
       
    18 #include <e32std.h>
       
    19 #include "server.h"
       
    20 #include "rootwin.h"
       
    21 #include "windowgroup.h"
       
    22 #include "walkwindowtree.h"
       
    23 #include "EVQUEUE.H"
       
    24 #include "panics.h"
       
    25 #include "wstop.h"
       
    26 #include "wstraces.h"
       
    27 
       
    28 const TInt KGranularity = 10;
       
    29 
       
    30 void TWsRedrawEvent::SetHandle(TUint aHandle)
       
    31 	{
       
    32 	iHandle=aHandle;
       
    33 	}
       
    34 
       
    35 void TWsRedrawEvent::SetRect(TRect aRect)
       
    36 	{
       
    37 	iRect=aRect;
       
    38 	}
       
    39 
       
    40 TWsRedrawEvent CRedrawQueue::iNullRedrawEvent;
       
    41 
       
    42 CRedrawQueue::CRedrawQueue(CWsClient *aOwner) : CEventBase(aOwner)
       
    43 	{
       
    44 	__DECLARE_NAME(_S("CRedrawQueue"));
       
    45 	}
       
    46 
       
    47 void CRedrawQueue::ConstructL()
       
    48 	{
       
    49 	iRedrawTrigger=EFalse;
       
    50 	iRedraws=new(ELeave) CArrayFixSeg<TRedraw>(KGranularity);
       
    51 	iKeyPriority=new(ELeave) TKeyArrayFix(_FOFF(TRedraw,iPriority),ECmpTUint32);
       
    52 	iKeyWindow=new(ELeave) TKeyArrayFix(_FOFF(TRedraw,iRedraw),ECmpTUint32);
       
    53 	Mem::FillZ(&iNullRedrawEvent,sizeof(iNullRedrawEvent));
       
    54 	}
       
    55 
       
    56 CRedrawQueue::~CRedrawQueue()
       
    57 	{
       
    58 	delete iRedraws;
       
    59 	delete iKeyPriority;
       
    60 	delete iKeyWindow;
       
    61 	}
       
    62 
       
    63 void CRedrawQueue::ReCalcOrder()
       
    64 	{
       
    65 	const TInt redrawsCount=iRedraws->Count();
       
    66 	for(TInt index=0;index<redrawsCount;index++)
       
    67 		{
       
    68 		TRedraw *redraw=&iRedraws->At(index);
       
    69 		redraw->iPriority=static_cast<CWsClientWindow*>(redraw->iRedraw->WsWin())->RedrawPriority();
       
    70 		}
       
    71 	iRedraws->Sort(*iKeyPriority);
       
    72 	}
       
    73 
       
    74 void CRedrawQueue::AddInvalid(CWsWindowRedraw *aRedrawWin) 
       
    75 //
       
    76 // Add a window to the update list.
       
    77 //
       
    78 	{
       
    79 	TInt index;
       
    80 	TRedraw redraw;
       
    81 
       
    82 	redraw.iRedraw=aRedrawWin;
       
    83 	if (iRedraws->Find(redraw,*iKeyWindow,index)!=0)
       
    84 		{
       
    85 		redraw.iPriority=static_cast<CWsClientWindow*>(aRedrawWin->WsWin())->RedrawPriority();
       
    86 		TRAPD(err,iRedraws->InsertIsqAllowDuplicatesL(redraw,*iKeyPriority));
       
    87 		if (err!=KErrNone)
       
    88 			{
       
    89 			WS_ASSERT_DEBUG(err==KErrNoMemory,EWsPanicRedrawQueueError);
       
    90 			iAllocError=ETrue;
       
    91 			}
       
    92 		iRedrawTrigger=ETrue;
       
    93 		}
       
    94 	}
       
    95 
       
    96 void CRedrawQueue::DeleteFromQueue(TInt aIndex)
       
    97 	{
       
    98 	iRedraws->Delete(aIndex,1);
       
    99 	
       
   100 	//We are certain we will need iRedraws again, so it would be silly to compress away the last KGranularity slots.
       
   101 	const TInt count = iRedraws->Count();
       
   102 	if((count >= KGranularity) && (count % KGranularity == 0))
       
   103 		{
       
   104 		iRedraws->Compress();
       
   105 		}
       
   106 	}
       
   107 
       
   108 void CRedrawQueue::RemoveInvalid(CWsWindowRedraw *aRedrawWin)
       
   109 //
       
   110 // remove the window from the invalid window list.
       
   111 // harmless to call if the window is not in the list.
       
   112 //
       
   113 	{
       
   114 	TInt index;
       
   115 	TRedraw redraw;
       
   116 
       
   117 	redraw.iRedraw=aRedrawWin;
       
   118 	redraw.iPriority=0;
       
   119 	if ((iRedraws->Find(redraw,*iKeyWindow,index))==KErrNone)
       
   120 		DeleteFromQueue(index);
       
   121 	}
       
   122 
       
   123 TBool CRedrawQueue::TriggerRedraw()
       
   124 //
       
   125 // Trigger any pending redraw messages in the queue
       
   126 // Returns ETrue if a redraw was sent, EFalse if not.
       
   127 //
       
   128 	{
       
   129 	WS_TRACE_SERVER_TRIGGERREDRAW();	
       
   130 	TBool ret=EFalse;
       
   131 	if (iRedrawTrigger)
       
   132 		{
       
   133 		iRedrawTrigger=EFalse;
       
   134 		if (!iEventMsg.IsNull() && (iRedraws->Count()>0 || iAllocError))
       
   135 			{
       
   136 			SignalEvent();
       
   137 			ret=ETrue;
       
   138 			}
       
   139 		}
       
   140 	return(ret);
       
   141 	}
       
   142 
       
   143 void CRedrawQueue::EventReady(const RMessagePtr2& aEventMsg)
       
   144 //
       
   145 // Queue a read of an event from the queue
       
   146 //
       
   147 	{
       
   148 	CEventBase::EventReady(aEventMsg);
       
   149 	iRedrawTrigger=ETrue;
       
   150 	TriggerRedraw();
       
   151 	}
       
   152 
       
   153 TBool CRedrawQueue::FindOutstandingRedrawEvent(CWsWindowRedraw& aRedraw, TWsRedrawEvent& aEvent)
       
   154 	{
       
   155 	TRect rect;
       
   156 	if (aRedraw.GetRedrawRect(rect))
       
   157 		{
       
   158 		aEvent.SetRect(rect);
       
   159 		aEvent.SetHandle(aRedraw.WsWin()->ClientHandle());
       
   160 		CEventBase::GetData(&aEvent,sizeof(aEvent));
       
   161 		return ETrue;
       
   162 		}
       
   163 	return EFalse;
       
   164 	}
       
   165 
       
   166 TBool CRedrawQueue::FindWindowNeedingRedrawEvent(TWsRedrawEvent& aEvent)
       
   167 	{
       
   168 #if defined(_DEBUG)
       
   169 	CWsWindowRedraw* previousRedraw = NULL;
       
   170 #endif
       
   171 	// search all screens
       
   172 	TInt invalidWindows = 0;
       
   173 	for (TInt screenNo = 0; screenNo < CWsTop::NumberOfScreens(); ++screenNo)
       
   174 		{
       
   175 		CWsRootWindow* rootWindow = CWsTop::Screen(screenNo)->RootWindow();
       
   176 		for (CWsWindowGroup *groupWin = rootWindow->Child(); groupWin; groupWin = groupWin->NextSibling())
       
   177 			{
       
   178 			if (groupWin->WsOwner() == iWsOwner)
       
   179 				{
       
   180 				CWsWindowRedraw* redrawWin = NULL;
       
   181 				// use a window tree walk that can be resumed to find windows with an invalid region
       
   182 				TResumableWalkWindowTreeFindInvalid wwt(&redrawWin);
       
   183 				groupWin->WalkWindowTree(wwt, EWalkChildren, EFalse);
       
   184 				while (redrawWin != NULL)
       
   185 					{
       
   186 					WS_ASSERT_DEBUG(redrawWin != previousRedraw, EWsPanicRedrawQueueError);
       
   187 					// (the window may not actually need the client to redraw it, e.g. a CWsBlankWindow can redraw itself)
       
   188 					if (FindOutstandingRedrawEvent(*redrawWin, aEvent))
       
   189 						{
       
   190 						return ETrue;
       
   191 						}
       
   192 					else
       
   193 						{ // continue the Tree Walk
       
   194 #if defined(_DEBUG)
       
   195 						previousRedraw = redrawWin;
       
   196 #endif
       
   197 						if (redrawWin->NeedsRedraw())
       
   198 							{ // needs to be redrawn later?
       
   199 							++invalidWindows;
       
   200 							}
       
   201 						redrawWin = NULL;
       
   202 						groupWin->WalkWindowTree(wwt, EWalkChildren, ETrue);
       
   203 						}
       
   204 					}
       
   205 				}
       
   206 			}
       
   207 		}
       
   208 
       
   209 	if (invalidWindows == 0)
       
   210 		{ // error recovery is complete
       
   211 		iAllocError = 0;
       
   212 		}
       
   213 	return EFalse;
       
   214 	}
       
   215 
       
   216 void CRedrawQueue::GetData()
       
   217 //
       
   218 // If there is an outstanding redraw event in the queue, reply with it's data
       
   219 //
       
   220 	{
       
   221 	CWsWindowRedraw *redraw;
       
   222 	TWsRedrawEvent event;
       
   223 
       
   224 	while (iRedraws->Count()>0)
       
   225 		{
       
   226 		redraw=(*iRedraws)[0].iRedraw;
       
   227 		if (FindOutstandingRedrawEvent(*redraw,event))
       
   228 			{
       
   229 			return;
       
   230 			}
       
   231 		TInt toDelete=0;
       
   232 		if (redraw!=(*iRedraws)[0].iRedraw)
       
   233 			{		//In low memory conditions calls to FindOutstandingRedrawEvent can cause extra entries to be added to the array
       
   234 			TRedraw redrawFind;
       
   235 			redrawFind.iRedraw=redraw;
       
   236 			iRedraws->Find(redrawFind,*iKeyWindow,toDelete);
       
   237 			}
       
   238 		DeleteFromQueue(toDelete);
       
   239 		}
       
   240 
       
   241 	if (iAllocError && FindWindowNeedingRedrawEvent(event))
       
   242 		{
       
   243 		return;
       
   244 		}
       
   245 
       
   246 	CEventBase::GetData(&iNullRedrawEvent,sizeof(iNullRedrawEvent));
       
   247 	}
       
   248 
       
   249 TUint CRedrawQueue::RedrawPriority(CWsWindowRedraw *aRedrawWin)
       
   250 	{
       
   251 	TInt index;
       
   252 	TRedraw redraw;
       
   253 	TUint priority=0;
       
   254 	redraw.iRedraw=aRedrawWin;
       
   255 
       
   256 	if ((iRedraws->Find(redraw,*iKeyWindow,index))==KErrNone)
       
   257 		{
       
   258 		priority=iRedraws->At(index).iPriority;
       
   259 		}
       
   260 	return priority;
       
   261 	}