windowing/windowserver/nga/SERVER/openwfc/windowelementset.cpp
changeset 0 5d03bc08d59c
child 11 fed1595b188e
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2006-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 #include <e32std.h>
       
    17 #include "cliwin.h"
       
    18 #include "server.h"
       
    19 #include "windowelementset.h"
       
    20 #include "regionextend.h"
       
    21 #include <graphics/wsscene.h>
       
    22 #include <graphics/wsgraphicdrawer.h>
       
    23 #include "panics.h"
       
    24 #include "wstop.h"
       
    25 
       
    26 #include "EVENT.H"
       
    27 
       
    28 #ifndef KCacheListGranularity
       
    29 	enum	{KCacheListGranularity = 8};
       
    30 #endif
       
    31 #ifndef KCacheExtensionReserve
       
    32 	enum	{KCacheExtensionReserve = 1};
       
    33 #endif
       
    34 	
       
    35 
       
    36 
       
    37 /** Element to gc rotation function
       
    38 */
       
    39 LOCAL_C inline CFbsBitGc::TGraphicsOrientation ElementToGcRotation(MWsElement::TElementRotation aElementRotation)
       
    40 	{
       
    41 	CFbsBitGc::TGraphicsOrientation gcRotation = CFbsBitGc::EGraphicsOrientationNormal;
       
    42 
       
    43 	switch (aElementRotation)
       
    44 		{
       
    45 		case MWsElement::EElementAntiClockwise90:
       
    46 			gcRotation = CFbsBitGc::EGraphicsOrientationRotated90;
       
    47 			break;
       
    48 		case MWsElement::EElementAntiClockwise180:
       
    49 			gcRotation = CFbsBitGc::EGraphicsOrientationRotated180;
       
    50 			break;
       
    51 		case MWsElement::EElementAntiClockwise270:
       
    52 			gcRotation = CFbsBitGc::EGraphicsOrientationRotated270;
       
    53 			break;
       
    54 		default:
       
    55 			break;
       
    56 		}
       
    57 	return gcRotation;
       
    58 	}
       
    59 
       
    60 //
       
    61 // CWindowElement
       
    62 //
       
    63 
       
    64 CWindowElement::CWindowElement(const CWsClientWindow& aWindow) :
       
    65 	iWindow(aWindow), iCache(KCacheListGranularity), iHighestReusedIndex(-1)
       
    66 	{}
       
    67 
       
    68 
       
    69 /** Finds all elements within the window that overlap with the region and 
       
    70 marks them as unassigned.
       
    71 If any part of these unassigned elements are outside the region, they are also 
       
    72 marked overlapping and locked config.
       
    73 
       
    74 @param aRegion The region that is being redrawn.
       
    75 @return KErrNone on success or KErrNoMemory if critical calculations could not be made.
       
    76 
       
    77 @see CWindowElementSet::UnassignPlacedElements
       
    78 **/
       
    79 TInt CWindowElement::UnassignPlacedElements(const TRegion& aRegion,TInt aGcDrawingCount)
       
    80 	{
       
    81 	iFlags = 0;	//reset flags
       
    82 	iStartGcDrawingCount = aGcDrawingCount;	//Detect any drawing between calls
       
    83 	iBackgroundElement.SetDrawnOverLast(iBackgroundElement.DrawnOver());
       
    84 	iNonRedrawVisibleRegion.Clear();
       
    85 	iNonRedrawVisibleRegion.Copy(const_cast<CWsClientWindow&>(iWindow).VisibleRegion());
       
    86 	iNonRedrawVisibleRegion.SubRegion(aRegion);
       
    87 	if (iNonRedrawVisibleRegion.CheckError())
       
    88 		{	//memory error. Still needs to cope if whole window is being redrawn
       
    89 		iNonRedrawVisibleRegion.Clear();
       
    90 		TInt fullWindowRedraw = TRegionExtend::Cast(aRegion).TestDifference(const_cast<CWsClientWindow&>(iWindow).VisibleRegion());
       
    91 		if (fullWindowRedraw != 0)
       
    92 			{	//not a full window redraw, return immediately
       
    93 			return KErrNoMemory;
       
    94 			}
       
    95 		}	
       
    96 	TInt placedElements = iPlacedElements.Count();
       
    97 	TInt unassignedCount = 0;
       
    98 	TInt ii;
       
    99 	TBool cacheError = EFalse;
       
   100 
       
   101 	STACK_REGION tempSurfaceBaseArea;
       
   102 	if (iCache.Reserve(placedElements + KCacheExtensionReserve) < KErrNone)	//quite often there may need to be room for more
       
   103 		{	//failed to reserve space
       
   104 		cacheError = ETrue;
       
   105 		}
       
   106 	TRect tempExtent;
       
   107 	TRect tempIntersect;
       
   108 	
       
   109 	for (ii=0; ii<placedElements; ii++)
       
   110 		{
       
   111 		if (!cacheError)
       
   112 			{	//cache is ok up to this point but does not contain cache for this element yet
       
   113 			RRegion newRegion;
       
   114 			if (iCache.Append(newRegion) < KErrNone)
       
   115 				{
       
   116 				cacheError = ETrue;
       
   117 				}
       
   118 			newRegion.Close();
       
   119 			}
       
   120 
       
   121 		iPlacedElements[ii].iElement->GetDestinationRectangle(tempExtent);
       
   122 		TInt regionReturn = TRegionExtend::Cast(aRegion).TestDifference(tempExtent);
       
   123 		iPlacedElements[ii].SetDrawnOverLast(iPlacedElements[ii].DrawnOver());	//allows detection of change of state
       
   124 		if (!(regionReturn&TRegionExtend::ENoIntersect))
       
   125 			{	//redraw region intersects with element
       
   126 			iPlacedElements[ii].SetUnassigned();
       
   127 			iPlacedElements[ii].SetDrawnOver(EFalse);
       
   128 			unassignedCount++;
       
   129 			
       
   130 			if (!(regionReturn&TRegionExtend::EAdd))
       
   131 				{	//surface is entirely within the redraw region
       
   132 				iPlacedElements[ii].SetOverlapping(EFalse);
       
   133 				iPlacedElements[ii].SetLockedConfig(EFalse);
       
   134 				if(!cacheError)
       
   135 					{
       
   136 					TRect destinationRect;
       
   137 					tempSurfaceBaseArea.Clear();
       
   138                     iPlacedElements[ii].iElement->GetDestinationRectangle(destinationRect);
       
   139 					tempSurfaceBaseArea.AddRect(destinationRect);
       
   140 					if (!tempSurfaceBaseArea.CheckError())
       
   141 						{
       
   142 						tempSurfaceBaseArea.Offset(tempExtent.iTl);	//cache needs to be in absolute coords
       
   143 						iCache[ii].Copy(tempSurfaceBaseArea);
       
   144 						}
       
   145 					if (tempSurfaceBaseArea.CheckError() || iCache[ii].CheckError())
       
   146 						{	//cache is no good from this point onwards
       
   147 						iCache[ii].Close();
       
   148 						iCache.Remove(ii);
       
   149 						cacheError = ETrue;
       
   150 						}
       
   151 					}
       
   152 				}
       
   153 			else
       
   154 				{
       
   155                 TRect destinationRect;
       
   156                 tempSurfaceBaseArea.Clear();
       
   157                 iPlacedElements[ii].iElement->GetDestinationRectangle(destinationRect);
       
   158                 tempSurfaceBaseArea.AddRect(destinationRect);
       
   159 				if (tempSurfaceBaseArea.CheckError())
       
   160 					{	//critical failure, clear cache and return error
       
   161 					for (ii=iCache.Count(); ii>0; ii--)
       
   162 						{
       
   163 						iCache[ii-1].Close();
       
   164 						iCache.Remove(ii-1);
       
   165 						}
       
   166 					iCache.Reset();
       
   167 					iNonRedrawVisibleRegion.Close();
       
   168 					tempSurfaceBaseArea.Close();
       
   169 					return KErrNoMemory;
       
   170 					}
       
   171 				else
       
   172 					{
       
   173 					tempSurfaceBaseArea.Offset(tempExtent.iTl);	//change to absolute coordinates
       
   174 					regionReturn = TRegionExtend::Cast(iNonRedrawVisibleRegion ).TestDifference(tempSurfaceBaseArea);
       
   175 					if (regionReturn&TRegionExtend::ENoIntersect)
       
   176 						{	//element base area entirely inside redraw region
       
   177 						iPlacedElements[ii].SetOverlapping(EFalse);
       
   178 						iPlacedElements[ii].SetLockedConfig(EFalse);
       
   179 						}
       
   180 					else
       
   181 						{	//element base area is at least partly within non redraw visible region
       
   182 						iPlacedElements[ii].SetOverlapping(ETrue);
       
   183 						iPlacedElements[ii].SetLockedConfig(ETrue);
       
   184 						}
       
   185 					if(!cacheError)
       
   186 						{
       
   187 						iCache[ii].Copy(tempSurfaceBaseArea);
       
   188 						if (iCache[ii].CheckError())
       
   189 							{	//cache is no good from this point onwards
       
   190 							iCache[ii].Close();
       
   191 							iCache.Remove(ii);
       
   192 							cacheError = ETrue;
       
   193 							}
       
   194 						}
       
   195 					}
       
   196 				}
       
   197 			}
       
   198 		else
       
   199 			{	//element does not intersect with redraw region
       
   200 			iPlacedElements[ii].SetUnassigned(EFalse);
       
   201 			}
       
   202 		}
       
   203 	tempSurfaceBaseArea.Close();
       
   204 	
       
   205 	if (iRemovedSurfaces.Reserve(unassignedCount) == KErrNone)
       
   206 		{
       
   207 		iRemovedSurfacesValid = ETrue;
       
   208 		}
       
   209 	else
       
   210 		{
       
   211 		iRemovedSurfacesValid = EFalse;
       
   212 		}
       
   213 	return KErrNone;
       
   214 	}
       
   215 
       
   216 /** Marks all elements that have been assigned since the unassign as drawn over.
       
   217 
       
   218 @see CWindowElementSet::FlagAssignedElementsDrawnOver
       
   219 **/
       
   220 void CWindowElement::FlagAssignedElementsDrawnOver(TInt aGcDrawingCount)
       
   221 	{
       
   222 	iStartGcDrawingCount = aGcDrawingCount;
       
   223 	if (iBackgroundElement.iElement)
       
   224 		{
       
   225 		iBackgroundElement.SetDrawnOver();
       
   226 		}
       
   227 	TInt placedElementCount = iPlacedElements.Count();
       
   228 	for (TInt ii = 0; ii < placedElementCount; ii++)
       
   229 		{
       
   230 		if(!iPlacedElements[ii].Unassigned() && iPlacedElements[ii].LockedConfig())
       
   231 			{
       
   232 			iPlacedElements[ii].SetDrawnOver();
       
   233 			}
       
   234 		else if(iPlacedElements[ii].Unassigned() && iPlacedElements[ii].LockedConfig() &&
       
   235 				!iPlacedElements[ii].ChangedClip() && iPlacedElements[ii].Overlapping())
       
   236 			{
       
   237 			iPlacedElements[ii].SetDrawnOver();
       
   238 			}
       
   239 		}
       
   240 	}
       
   241 
       
   242 /** Checks whether a elements configuration is the same as that of the surface configuration, taking
       
   243 into account the stateflags (TPlacedAttributes) passed in.
       
   244 It must match surfaceId and extent.
       
   245 If it is a locked config it will need to match viewport and orientation as well.
       
   246 
       
   247 @param aElement Element to compare against.
       
   248 @param aSurfaceConfiguration Configuration to compare.
       
   249 @param aStateFlags The TPlacedAttributes flags for the element.
       
   250 @return ETrue if a match, otherwise EFalse.
       
   251 */
       
   252 TBool CWindowElement::IsElementAMatch(MWsElement& aElement, const TSurfaceConfiguration& aSurfaceConfiguration,
       
   253 		TInt aStateFlags)
       
   254 	{
       
   255 	TBool match = EFalse;
       
   256 	
       
   257 	TRect tempElementExtent;
       
   258 	TRect tempCRPExtent;
       
   259 	aElement.GetDestinationRectangle(tempElementExtent);
       
   260 	aSurfaceConfiguration.GetExtent(tempCRPExtent);
       
   261 	if (tempElementExtent == tempCRPExtent)
       
   262 		{
       
   263 		TSurfaceId tempElementSurfaceId;
       
   264 		TSurfaceId tempCRPSurfaceId;
       
   265 		aSurfaceConfiguration.GetSurfaceId(tempElementSurfaceId);
       
   266 		tempCRPSurfaceId = aElement.ConnectedSurface();
       
   267 		if (tempElementSurfaceId == tempCRPSurfaceId)
       
   268 			{
       
   269 			match = ETrue;
       
   270 			if (aStateFlags&TPlacedAttributes::ELockedConfig)
       
   271 				{
       
   272 				match = EFalse;
       
   273 				TBool orientationOK = EFalse;
       
   274 				TRect tempCRPViewport;
       
   275 				aSurfaceConfiguration.GetViewport(tempCRPViewport);
       
   276 				//if explicit viewport flagged
       
   277 				TRect tempElementViewport;
       
   278 				aElement.GetSourceRectangle(tempElementViewport);
       
   279 				if (tempElementViewport == tempCRPViewport)
       
   280 					{
       
   281 					CFbsBitGc::TGraphicsOrientation tempElementOrientation;
       
   282 					MWsElement::TElementRotation tempCRPRotation;
       
   283 					CFbsBitGc::TGraphicsOrientation tempCRPOrientation;
       
   284 					tempElementOrientation = aSurfaceConfiguration.Orientation();
       
   285 					tempCRPRotation = aElement.SourceRotation();
       
   286 					tempCRPOrientation = ElementToGcRotation(tempCRPRotation);	//convert to common type
       
   287 					if (tempElementOrientation == tempCRPOrientation)
       
   288 						{
       
   289 						orientationOK = ETrue;
       
   290 						}
       
   291 					}
       
   292 				if(orientationOK)
       
   293 				    {
       
   294 				    TBool tempElementFlip = aSurfaceConfiguration.Flip();
       
   295 				    TBool tempCRPFlip = aElement.SourceFlipping();
       
   296 				    if(tempElementFlip == tempCRPFlip)
       
   297 				        {
       
   298 				        match = ETrue;
       
   299 				        }
       
   300 				    }
       
   301 				}
       
   302 			}
       
   303 		}
       
   304 	return match;
       
   305 	}
       
   306 
       
   307 /** Sets the surfaceconfiguration to the element.
       
   308 
       
   309 @param aElement The element to set.
       
   310 @param aSurfaceConfiguration The configuration to set to the element.
       
   311 @param aLimitedSet Set all values if EFalse, otherwise only set viewport and orientation.
       
   312 @return KErrNone on success, error from compositor if it could not set the surface id.
       
   313 */
       
   314 TInt CWindowElement::SetElement(MWsElement& aElement, const TSurfaceConfiguration& aSurfaceConfiguration, TBool aLimitedSet)
       
   315 	{	//aLimitedSet - EFalse = set all . ETrue = set viewport and orientation only
       
   316 	if (!aLimitedSet)
       
   317 		{
       
   318 		//set surface id
       
   319 		TSurfaceId newSurfaceId;
       
   320 		aSurfaceConfiguration.GetSurfaceId(newSurfaceId);
       
   321 		TInt error = aElement.ConnectSurface(newSurfaceId);
       
   322 		if (error != KErrNone)
       
   323 			{
       
   324 			return error;
       
   325 			}
       
   326 		
       
   327 		//set extent
       
   328 		TRect newExtent;
       
   329 		aSurfaceConfiguration.GetExtent(newExtent);
       
   330 		aElement.SetDestinationRectangle(newExtent);
       
   331 		}
       
   332 	
       
   333 	//set viewport
       
   334 	TRect newViewport;
       
   335 	aSurfaceConfiguration.GetViewport(newViewport);
       
   336 	if (newViewport.iTl.iX < 0 || newViewport.iTl.iY < 0)
       
   337 		{
       
   338 		return KErrArgument;
       
   339 		}
       
   340 	
       
   341 	if (!newViewport.IsEmpty())
       
   342 		{	//need to check if viewport is valid size
       
   343 		TInt error = aElement.SetSourceRectangle(newViewport);
       
   344         if (error != KErrNone)
       
   345             {
       
   346             return error;
       
   347             }
       
   348 		}
       
   349 
       
   350 	//set orientation
       
   351 	//Note for compatibility with Oghma:
       
   352 	//This method does not properly error check or return KErrArgument,
       
   353 	//as that would propagate a client panic in SetBackgroundSurface which did not previously occur.
       
   354 	aElement.SetSourceRotation(GcToElementRotation(aSurfaceConfiguration.Orientation()));
       
   355 	// Set or clear flip if the element flags are changing
       
   356 	if (aSurfaceConfiguration.Flip() != aElement.SourceFlipping()) 
       
   357 	    {
       
   358         aElement.SetSourceFlipping(!aElement.SourceFlipping());
       
   359 	    }
       
   360 	return KErrNone;
       
   361 	}
       
   362 
       
   363 /** Attempts to insert a region cache in to the the windows iCache.
       
   364 If it fails, it will remove all cache beyond its index as it is now out of step.
       
   365 
       
   366 @param aIndexToInsert The index of where to insert the cache.
       
   367 @return ETrue on success, else EFalse.
       
   368 */
       
   369 
       
   370 TBool CWindowElement::InsertCache(TInt aIndexToInsert)
       
   371 	{
       
   372 	RRegion newRegion;
       
   373 	TInt cacheInsertError = iCache.Insert(newRegion, aIndexToInsert);
       
   374 	if (cacheInsertError == KErrNone)
       
   375 		{
       
   376 		newRegion.Close(); 
       
   377 		return ETrue;	//inserted cache
       
   378 		}
       
   379 	if (iCache.Count() > aIndexToInsert)
       
   380 		{	//if insert failed and there is more cache above where its trying to insert
       
   381 		iCache.Remove(iCache.Count()-1);
       
   382 		cacheInsertError = iCache.Insert(newRegion, aIndexToInsert);
       
   383 		
       
   384 		if (cacheInsertError == KErrNone)
       
   385 			{
       
   386 			newRegion.Close();
       
   387 			return ETrue;	//inserted cache
       
   388 			}
       
   389 		}
       
   390 	
       
   391 	//cant insert this cache, there may be invalid cache to destroy
       
   392 	TInt count = iCache.Count();
       
   393 	while(count > aIndexToInsert)
       
   394 		{	//if there is cache where we wished to insert, it and everything above is now invalid
       
   395 		iCache[count-1].Close();
       
   396 		iCache.Remove(count-1);
       
   397 		count--;
       
   398 		};
       
   399 	newRegion.Close();
       
   400 	return EFalse;	//failed to insert
       
   401 	}
       
   402 
       
   403 /** Will send a notification that a surface being unreferenced if it is not
       
   404 found in any WindowElementSet
       
   405 
       
   406 @pre Make sure the element being removed has already had its surfaceid set to NULL.
       
   407 @param aSurfaceId The surface being removed
       
   408 */
       
   409 void CWindowElement::NotifyReleasingSurface(TSurfaceId aSurfaceId)
       
   410 	{
       
   411 	if (CWsTop::SearchDuplicateSurfaceId(aSurfaceId) == EFalse)
       
   412 		{	//NOT found other instance of surface id, send notification now
       
   413 		TWservCrEvent crEvent(TWservCrEvent::ESurfaceUnreferenced, sizeof(aSurfaceId), &aSurfaceId);
       
   414 		TWindowServerEvent::NotifyDrawer(crEvent);
       
   415 		}
       
   416 	}
       
   417 
       
   418 /** Called to place a element within the window.
       
   419 It will either create a new element, recycle a element, or extend a element .
       
   420 
       
   421 @pre UnassignPlacedElements has already been called.
       
   422 @param aPlacedAttributes Returns the attributes of the surface placed.
       
   423 @param aSurfaceConfiguration The surface configuration for the surface to place.
       
   424 @param aUserDefinedRegion The user defined clipping of the window.
       
   425 @param aScene Access to the scene.
       
   426 @return Serious error, otherwise flags to describe what extra work needs doing.
       
   427 
       
   428 @see CWindowElementSet::AssignPlacedElement
       
   429 */
       
   430 TInt CWindowElement::AssignPlacedElement(
       
   431 		TPlacedAttributes*& aPlacedAttributes,
       
   432 		const TSurfaceConfiguration& aSurfaceConfiguration,
       
   433 		const TRegion& aUserDefinedRegion,
       
   434 		MWsScene& aScene,
       
   435 		TInt	aGcDrawingCount
       
   436 		)
       
   437 	{	
       
   438 	if (iStartGcDrawingCount!=aGcDrawingCount)
       
   439 		{
       
   440 		FlagAssignedElementsDrawnOver(aGcDrawingCount);
       
   441 		}
       
   442 
       
   443 	if (iNonRedrawVisibleRegion.CheckError())
       
   444 		{
       
   445 		//CANNOT DO ANYTHING, LEAVE
       
   446 		return KErrNotReady;	//error
       
   447 		}
       
   448 
       
   449 	TRect surfaceExtent;
       
   450 	aSurfaceConfiguration.GetExtent(surfaceExtent);
       
   451 	if (!aUserDefinedRegion.Intersects(surfaceExtent))
       
   452 		{
       
   453 		//clippedRegion.Close();
       
   454 		return KErrCancel;	//no intersection, so nothing to do
       
   455 		}
       
   456 
       
   457 	TInt matchFound = -1;
       
   458 	
       
   459 	//check 'current' (last placed element) to see if it is a match
       
   460 	if (iHighestReusedIndex != -1)
       
   461 		{
       
   462 		if (IsElementAMatch(*(iPlacedElements[iHighestReusedIndex].iElement),aSurfaceConfiguration,iPlacedElements[iHighestReusedIndex].Flags()) )
       
   463 			{
       
   464 			matchFound = iHighestReusedIndex;
       
   465 			}
       
   466 		}
       
   467 
       
   468 	if (matchFound == -1)
       
   469 		{
       
   470 		//check current unassigned elements to see if there is a match
       
   471 		for (TInt ii = (iHighestReusedIndex == -1)?0:iHighestReusedIndex+1; ii < iPlacedElements.Count(); ii++)
       
   472 			{
       
   473 			if (IsElementAMatch(*(iPlacedElements[ii].iElement),aSurfaceConfiguration,iPlacedElements[ii].Flags()))
       
   474 				{
       
   475 				matchFound = ii;
       
   476 				break;
       
   477 				}
       
   478 			}
       
   479 		}
       
   480 	TInt returnValue = 0;
       
   481 	if (matchFound == -1)
       
   482 		{	//not found a element to extend
       
   483 		//iResort = ETrue;
       
   484 		matchFound = 0;
       
   485 		while(1)
       
   486 			{
       
   487 			if (iPlacedElements.Count() == 0 || iHighestReusedIndex == -1 || matchFound == iHighestReusedIndex)	//reached last re assigned element, so cannot reuse one
       
   488 				{
       
   489 				matchFound = -1;
       
   490 				break;
       
   491 				}
       
   492 			if (iPlacedElements[matchFound].Unassigned() && !iPlacedElements[matchFound].LockedConfig())	//found a element to reuse
       
   493 				{
       
   494 				break;
       
   495 				}
       
   496 			matchFound++;
       
   497 			};
       
   498 
       
   499 		if (matchFound != -1)
       
   500 			{	//found a element to recycle
       
   501 			returnValue = AssignRecycleElement(matchFound,aSurfaceConfiguration,aUserDefinedRegion,aScene);
       
   502 			}
       
   503 		else
       
   504 			{	//need to create a new element
       
   505 			returnValue = AssignCreateElement(aSurfaceConfiguration,aUserDefinedRegion,aScene);
       
   506 			}
       
   507 		}
       
   508 	else
       
   509 		{	//found a candidate to extend
       
   510 		returnValue = AssignExtendElement(matchFound,aSurfaceConfiguration,aUserDefinedRegion,aScene);
       
   511 		}
       
   512 	if (returnValue < KErrNone)
       
   513 		{	//failed with error
       
   514 			return returnValue;
       
   515 		}
       
   516 	aPlacedAttributes = &iPlacedElements[iHighestReusedIndex];
       
   517 	iFlags|=returnValue;	//update window wide flags
       
   518 	return returnValue;
       
   519 	}
       
   520 
       
   521 /** Recycle a element assigned to the window.
       
   522 
       
   523 @param aIndex The index of the placed element to recycle.
       
   524 @param aSurfaceConfiguration The surface configuration for the surface to place.
       
   525 @param aUserDefinedRegion The user defined clipping of the window.
       
   526 @param aScene Access to the scene.
       
   527 @return Serious error, otherwise flags to describe what extra work needs doing.
       
   528 
       
   529 @see CWindowElement::AssignPlacedElement
       
   530 */
       
   531 TInt CWindowElement::AssignRecycleElement(const TInt aIndex, const TSurfaceConfiguration& aSurfaceConfiguration, const TRegion& aUserDefinedRegion, MWsScene& aScene)
       
   532 	{
       
   533 	TInt returnValue = 0;
       
   534 	TInt error = KErrNone;
       
   535 	STACK_REGION clippedRegion;
       
   536 	TRect surfaceExtent;
       
   537 	aSurfaceConfiguration.GetExtent(surfaceExtent);
       
   538 	clippedRegion.AddRect(surfaceExtent);
       
   539 	clippedRegion.Intersect(aUserDefinedRegion);
       
   540 	if (clippedRegion.CheckError())
       
   541 		{	//failed crucial calculation, leave while nothing has been changed!
       
   542 		clippedRegion.Close();
       
   543 		return KErrNoMemory;
       
   544 		}
       
   545 	WS_ASSERT_DEBUG(!clippedRegion.IsEmpty(),EWsPanicRegion);
       
   546 	if (clippedRegion.IsEmpty())
       
   547 		{
       
   548 		return KErrArgument;
       
   549 		}
       
   550 	
       
   551 	//keep note of surface being removed
       
   552 	TSurfaceId oldSurfaceId = iPlacedElements[aIndex].iElement->ConnectedSurface();
       
   553 	
       
   554 	//set element with new attributes
       
   555 	error = SetElement(*(iPlacedElements[aIndex].iElement),aSurfaceConfiguration,EFalse);
       
   556 	
       
   557 	if (error < KErrNone)
       
   558 		{	//must be a bad surface id or bad viewport, leave while nothing has been changed!
       
   559 		clippedRegion.Close();
       
   560 		return error;
       
   561 		}
       
   562 	
       
   563 	returnValue|=EFastPath;
       
   564 	returnValue|=EPauseComposition;
       
   565 	//element has been altered, must make sure old surface unreferenced notify will be called
       
   566 	if (!iRemovedSurfacesValid)
       
   567 		{	//didnt reserve space for surface ids, do search immediately
       
   568 		NotifyReleasingSurface(oldSurfaceId);
       
   569 		}
       
   570 	else
       
   571 		{	//keep memory of surface id - search will be done during cleanup. Space already been reserved
       
   572 		iRemovedSurfaces.Append(oldSurfaceId);
       
   573 		}
       
   574 
       
   575 	//order placed element correctly in iPlacedElements
       
   576 	TPlacedAttributes tempAttributes = iPlacedElements[aIndex];
       
   577 	iPlacedElements.Remove(aIndex);
       
   578 	//keep cache up to date
       
   579 	if (iCache.Count() > aIndex)
       
   580 		{
       
   581 		iCache[aIndex].Close();
       
   582 		iCache.Remove(aIndex);
       
   583 		}
       
   584 
       
   585 	WS_ASSERT_DEBUG(iHighestReusedIndex != -1,EWsPanicRecycleElement);
       
   586 	if (iHighestReusedIndex == -1)
       
   587 		{
       
   588 		return KErrArgument;
       
   589 		}
       
   590 	
       
   591 	error = iPlacedElements.Insert(tempAttributes, iHighestReusedIndex);
       
   592 	if (error < KErrNone)
       
   593 		{	//must destroy the element and leave.  Old elements surface unregistration already dealt with
       
   594 		aScene.DestroySceneElement(tempAttributes.iElement);
       
   595 		clippedRegion.Close();
       
   596 		return KErrNoMemory;
       
   597 		}
       
   598 	returnValue|=EResort;	//element has been moved, will need a resort
       
   599 	//set placed element attributes
       
   600 	iPlacedElements[iHighestReusedIndex].SetUnassigned(EFalse);
       
   601 	iPlacedElements[iHighestReusedIndex].SetLockedConfig(ETrue);
       
   602 	iPlacedElements[iHighestReusedIndex].SetChangedClip(ETrue);
       
   603 	
       
   604 	TRect tempViewport;
       
   605 	aSurfaceConfiguration.GetViewport(tempViewport);
       
   606 
       
   607 	TBool cacheSaved = EFalse;
       
   608 	if (iCache.Count() >= iHighestReusedIndex)
       
   609 		{	//need to update cache with visible region of element
       
   610 		TBool insertSuccess = InsertCache(iHighestReusedIndex);
       
   611 		if (insertSuccess != EFalse)
       
   612 			{
       
   613 			iCache[iHighestReusedIndex].Copy(clippedRegion);
       
   614 			if (!iCache[iHighestReusedIndex].CheckError())
       
   615 				{
       
   616 				cacheSaved = ETrue;
       
   617 				}
       
   618 			}
       
   619 		}
       
   620 	if (cacheSaved == EFalse)
       
   621 		{	//need to set clipping to element immediately
       
   622 		TInt count = iCache.Count();
       
   623 		while(count > iHighestReusedIndex)
       
   624 			{	//if there is cache where we wished to insert, it and everything above is now invalid
       
   625 			iCache[count-1].Close();
       
   626 			iCache.Remove(count-1);
       
   627 			count--;
       
   628 			};
       
   629 		}
       
   630 	clippedRegion.Close();
       
   631 	return returnValue;
       
   632 	}
       
   633 
       
   634 /** Create a new element for the placed surface.
       
   635 
       
   636 @param aSurfaceConfiguration The surface configuration for the surface to place.
       
   637 @param aUserDefinedRegion The user defined clipping of the window.
       
   638 @param aScene Access to the scene.
       
   639 @return Serious error, otherwise flags to describe what extra work needs doing.
       
   640 
       
   641 @see CWindowElement::AssignPlacedElement
       
   642 */
       
   643 TInt CWindowElement::AssignCreateElement(const TSurfaceConfiguration& aSurfaceConfiguration, const TRegion& aUserDefinedRegion, MWsScene& aScene)
       
   644 	{
       
   645 	TInt returnValue = 0;
       
   646 	TInt error = KErrNone;
       
   647 	STACK_REGION clippedRegion;
       
   648 	TRect surfaceExtent;
       
   649 	aSurfaceConfiguration.GetExtent(surfaceExtent);
       
   650 	//calculate region
       
   651 	clippedRegion.AddRect(surfaceExtent);
       
   652 	clippedRegion.Intersect(aUserDefinedRegion);
       
   653 	if (clippedRegion.CheckError())
       
   654 		{	//failed, return KErrNoMemory
       
   655 		clippedRegion.Close();
       
   656 		return KErrNoMemory;
       
   657 		}
       
   658 	
       
   659 	TPlacedAttributes newElement;
       
   660 	if (iHighestReusedIndex == -1)
       
   661 		{
       
   662 		error = iPlacedElements.Insert(newElement,0);
       
   663 		}
       
   664 	else
       
   665 		{	//insert above current highest reused element
       
   666 		error = iPlacedElements.Insert(newElement,iHighestReusedIndex+1);
       
   667 		}
       
   668 	if (error >= KErrNone)
       
   669 		{
       
   670 		iHighestReusedIndex++;
       
   671 		}
       
   672 	else
       
   673 		{
       
   674 		//FAILED! LEAVE FUNCTION. nothing has been changed
       
   675 		clippedRegion.Close();
       
   676 		return KErrNoMemory;
       
   677 		}
       
   678 
       
   679 	//create new element with new configuration
       
   680 	MWsElement* element = NULL;
       
   681 	TRAP(error,element = aScene.CreateSceneElementL());
       
   682 	if (error != KErrNone)
       
   683 		{
       
   684 		//FAILED! LEAVE FUNCTION. nothing has been changed
       
   685 		clippedRegion.Close();
       
   686 		return error;
       
   687 		}
       
   688 
       
   689 	element->SetGlobalAlpha( 0xFF );
       
   690 
       
   691 	iPlacedElements[iHighestReusedIndex].iElement = element;
       
   692 	error = SetElement(*element,aSurfaceConfiguration,EFalse);
       
   693 	if (error < KErrNone)
       
   694 		{
       
   695 		//must be a bad surface id or viewport. Leave now.
       
   696 		aScene.DestroySceneElement(element);
       
   697 		clippedRegion.Close();
       
   698 		iPlacedElements.Remove(iHighestReusedIndex);
       
   699 		iHighestReusedIndex--;
       
   700 		return error;
       
   701 		}
       
   702 	
       
   703 	//Now certain that these must be flagged
       
   704 	returnValue|=EFastPath;
       
   705 	returnValue|=EPauseComposition;
       
   706 	returnValue|=EResort;
       
   707 
       
   708 	//set placed element attributes
       
   709 	iPlacedElements[iHighestReusedIndex].SetUnassigned(EFalse);
       
   710 	iPlacedElements[iHighestReusedIndex].SetChangedClip(ETrue);
       
   711 	iPlacedElements[iHighestReusedIndex].SetLockedConfig(ETrue);
       
   712 	
       
   713 	TRect tempViewport;
       
   714 	aSurfaceConfiguration.GetViewport(tempViewport);
       
   715 
       
   716 	TBool cacheSaved = EFalse;
       
   717 	if (iCache.Count() >= iHighestReusedIndex)
       
   718 		{	//should try to add new elements region to cache
       
   719 		TBool insertSuccess = InsertCache(iHighestReusedIndex);
       
   720 		if (insertSuccess != EFalse)
       
   721 			{
       
   722 			iCache[iHighestReusedIndex].Copy(clippedRegion);
       
   723 			if (!iCache[iHighestReusedIndex].CheckError())
       
   724 				{
       
   725 				cacheSaved = ETrue;
       
   726 				}
       
   727 			}
       
   728 		}
       
   729 	if (cacheSaved == EFalse)
       
   730 		{	//need to clear cache from this point onward, and set clipping to element immediately
       
   731 		TInt count = iCache.Count();
       
   732 		while(count > iHighestReusedIndex)
       
   733 			{	//if there is cache where we wished to insert, it and everything above is now invalid
       
   734 			iCache[count-1].Close();
       
   735 			iCache.Remove(count-1);
       
   736 			count--;
       
   737 			};
       
   738 		}
       
   739 	//add the new element to the scene
       
   740     error = aScene.InsertSceneElement(element, NULL);    //place at the back. will get ordered correctly later
       
   741 	WS_ASSERT_DEBUG(error == KErrNone,EWsPanicSceneErrorIgnored);
       
   742 	clippedRegion.Close();
       
   743 	return returnValue;
       
   744 	}
       
   745 
       
   746 /** Extend an existing placed surface element.
       
   747 
       
   748 @param The index of the element to extend.
       
   749 @param aSurfaceConfiguration The surface configuration for the surface to place.
       
   750 @param aUserDefinedRegion The user defined clipping of the window.
       
   751 @param aScene Access to the scene.
       
   752 @return Serious error, otherwise flags to describe what extra work needs doing.
       
   753 
       
   754 @see CWindowElement::AssignPlacedElement
       
   755 */
       
   756 TInt CWindowElement::AssignExtendElement(const TInt aIndex, const TSurfaceConfiguration& aSurfaceConfiguration, const TRegion& aUserDefinedRegion, MWsScene& /*aScene*/)
       
   757 	{
       
   758 	TInt returnValue = 0;
       
   759 	TInt error = KErrNone;
       
   760 	STACK_REGION backupRegionAgainstFail;
       
   761 	STACK_REGION clippedRegion;
       
   762 	TRect surfaceExtent;
       
   763 	aSurfaceConfiguration.GetExtent(surfaceExtent);
       
   764 	TRect surfaceViewport;
       
   765 	aSurfaceConfiguration.GetViewport(surfaceViewport);
       
   766 	
       
   767 	if (!iPlacedElements[aIndex].LockedConfig())
       
   768 		{	//set element now. If viewport is invalid its ok to fail now
       
   769 		error = SetElement(*iPlacedElements[aIndex].iElement,aSurfaceConfiguration,ETrue);
       
   770 		if (error < KErrNone)
       
   771 			{
       
   772 			backupRegionAgainstFail.Close();
       
   773 			clippedRegion.Close();
       
   774 			return error;
       
   775 			}
       
   776 		}
       
   777 
       
   778 	if(iPlacedElements[aIndex].Unassigned() && !iPlacedElements[aIndex].Overlapping())
       
   779 		{
       
   780 		//backup stays clear
       
   781 		clippedRegion.Copy(aUserDefinedRegion);
       
   782 		}
       
   783 	else
       
   784 		{
       
   785 		clippedRegion.Copy(iNonRedrawVisibleRegion);
       
   786 		if (iCache.Count() > aIndex)	//if cache is ok
       
   787 			{
       
   788 			clippedRegion.Intersect(iCache[aIndex]);
       
   789 			clippedRegion.Union(iCache[aIndex]);	//previously added regions should be kept
       
   790 			}
       
   791 		else
       
   792 			{
       
   793 			STACK_REGION tempSurfaceBaseArea;
       
   794             TRect destinationRect;
       
   795             iPlacedElements[aIndex].iElement->GetDestinationRectangle(destinationRect);
       
   796             tempSurfaceBaseArea.AddRect(destinationRect);
       
   797 			tempSurfaceBaseArea.Offset(surfaceExtent.iTl);
       
   798 			clippedRegion.Intersect(tempSurfaceBaseArea);
       
   799 			clippedRegion.Union(tempSurfaceBaseArea);
       
   800 			tempSurfaceBaseArea.Close();
       
   801 			}
       
   802 		backupRegionAgainstFail.Copy(clippedRegion);
       
   803 		//clipped region should contain something
       
   804 		clippedRegion.Union(aUserDefinedRegion);
       
   805 		}
       
   806 	clippedRegion.ClipRect(surfaceExtent);
       
   807 	
       
   808 	if (backupRegionAgainstFail.CheckError() || clippedRegion.CheckError())
       
   809 		{	//failed critical calculations, leave now before anything has been changed
       
   810 		clippedRegion.Close();
       
   811 		backupRegionAgainstFail.Close();
       
   812 		return KErrNoMemory;
       
   813 		}
       
   814 
       
   815 	TBool setCache = EFalse;
       
   816 	if (iCache.Count() > aIndex)	//if Cache is ok
       
   817 		{
       
   818 		//compare
       
   819 		TInt compareReturn;
       
   820 		compareReturn = TRegionExtend::Cast(iCache[aIndex]).TestDifference(clippedRegion);
       
   821 
       
   822 		if (compareReturn&TRegionExtend::EDiffers)	//element has changed
       
   823 			{
       
   824 			iPlacedElements[aIndex].SetChangedClip(ETrue);
       
   825 			if (compareReturn&TRegionExtend::EAdd)	//element has become revealed on the screen
       
   826 				{
       
   827 				returnValue|=EPauseComposition;	//need to pause before the end of assign placed element
       
   828 				}
       
   829 			else
       
   830 				{
       
   831 				returnValue|=EFastPath;	//fastpath and pause will be called during cleanup
       
   832 				}
       
   833 			}
       
   834 		
       
   835 		//copy clipped region to cache
       
   836 		iCache[aIndex].Copy(clippedRegion);	//can fail
       
   837 		setCache = ETrue;
       
   838 		if (iCache[aIndex].CheckError())
       
   839 			{	//copy failed, remove cache from this element onwards
       
   840 			TInt count = iCache.Count();
       
   841 			while(count > aIndex)
       
   842 				{	//if there is cache where we wished to insert, it and everything above is now invalid
       
   843 				iCache[count-1].Close();
       
   844 				iCache.Remove(count-1);
       
   845 				count--;
       
   846 				};
       
   847 			setCache = EFalse;
       
   848 			}
       
   849 		}
       
   850 	if (setCache == EFalse)
       
   851 		{	//need to pause composition and update element immediately
       
   852 		returnValue|=EPauseComposition;
       
   853 		}
       
   854 	iPlacedElements[aIndex].SetUnassigned(EFalse);
       
   855 	iPlacedElements[aIndex].SetLockedConfig(ETrue);
       
   856 	iHighestReusedIndex = aIndex;
       
   857 	backupRegionAgainstFail.Close();
       
   858 	clippedRegion.Close();
       
   859 	return returnValue;
       
   860 	}
       
   861 
       
   862 /** Called at the end of a redraw to set cached changed to elements, and
       
   863 removed elements that are still unassigned.
       
   864 
       
   865 @param aScene Access to the scene.
       
   866 @return Flags to describe what extra work needs doing.
       
   867 @see CWindowElementSet::CleanUpPlacedElements
       
   868 */
       
   869 TInt CWindowElement::CleanUpPlacedElements(MWsScene& aScene, TInt aGcDrawingCount)
       
   870 	{
       
   871 	if (iStartGcDrawingCount!=aGcDrawingCount)
       
   872 		{
       
   873 		FlagAssignedElementsDrawnOver(aGcDrawingCount);
       
   874 		}
       
   875 	TInt returnFlags = iFlags;
       
   876 	if (iFlags > 0)
       
   877 		{	//copy flags to return, and ensure pause is flagged
       
   878 		returnFlags|=EPauseComposition;
       
   879 		}
       
   880 	TInt ii;
       
   881 	TBool removeElements = EFalse;
       
   882 	//destroy placed element reference
       
   883 	for (ii=0; ii<iPlacedElements.Count(); ii++)
       
   884 		{
       
   885 		if (iPlacedElements[ii].Unassigned() && !iPlacedElements[ii].Overlapping())
       
   886 			{
       
   887 			returnFlags|=EFastPath;	//need to invoke 1108
       
   888 			if (iRemovedSurfacesValid)
       
   889 				{
       
   890 				iRemovedSurfaces.Append(iPlacedElements[ii].iElement->ConnectedSurface());
       
   891 				iPlacedElements[ii].iElement->ConnectSurface(TSurfaceId::CreateNullId());
       
   892 				}
       
   893 			else
       
   894 				{
       
   895 				TSurfaceId tempId = iPlacedElements[ii].iElement->ConnectedSurface();
       
   896 				iPlacedElements[ii].iElement->ConnectSurface(TSurfaceId::CreateNullId());
       
   897 				NotifyReleasingSurface(tempId);
       
   898 				}
       
   899 			removeElements = ETrue;
       
   900 			}
       
   901 		}
       
   902 
       
   903 	if (removeElements)
       
   904 		{	//there will be elements to remove
       
   905 		for (ii=0; ii<iPlacedElements.Count(); ii++)
       
   906 			{
       
   907 			if (iPlacedElements[ii].iElement->ConnectedSurface().IsNull())
       
   908 				{
       
   909 				aScene.DestroySceneElement(iPlacedElements[ii].iElement);
       
   910 				iPlacedElements.Remove(ii);
       
   911 				if (iCache.Count() > ii)
       
   912 					{	//there is cache for this element, remove it
       
   913 					iCache[ii].Close();
       
   914 					iCache.Remove(ii);
       
   915 					}
       
   916 				ii--;
       
   917 				}
       
   918 			}
       
   919 		}
       
   920 
       
   921 	if (iRemovedSurfaces.Count() > 1)
       
   922 		{	//remove duplicates of surface id from removal list
       
   923 		for (ii = 0; ii < iRemovedSurfaces.Count() - 1; ii++)
       
   924 			{
       
   925 			for (TInt jj = ii+1; jj < iRemovedSurfaces.Count(); jj++)
       
   926 				{
       
   927 				if (iRemovedSurfaces[ii] == iRemovedSurfaces[jj])
       
   928 					{
       
   929 					iRemovedSurfaces.Remove(jj);
       
   930 					jj--;
       
   931 					}
       
   932 				}
       
   933 			}
       
   934 		}
       
   935 	
       
   936 	//do global search for surface ids
       
   937 	while (iRemovedSurfaces.Count()>0)
       
   938 		{
       
   939 		TInt tempRemoval = iRemovedSurfaces.Count() - 1;
       
   940 		NotifyReleasingSurface(iRemovedSurfaces[tempRemoval]);
       
   941 		iRemovedSurfaces.Remove(tempRemoval);
       
   942 		};
       
   943 
       
   944 	iRemovedSurfaces.Reset();
       
   945 
       
   946 	//clip unassigned overlapping entries, mark as changedclip if region changed
       
   947 	for (ii=0; ii<iPlacedElements.Count(); ii++)
       
   948 		{
       
   949 		if (iPlacedElements[ii].Unassigned())	//non overlapping unassigned have already been destroyed
       
   950 			{	//these must overlap
       
   951 			TBool failureOccured = EFalse;
       
   952 			if (iCache.Count() > ii)
       
   953 				{
       
   954 				//if cache region is entirely inside non redraw vis region, nothing to update!
       
   955 				TInt changed = 
       
   956 						TRegionExtend::Cast(iCache[ii]).TestDifference(iNonRedrawVisibleRegion);
       
   957 				if (changed&TRegionExtend::ESub)
       
   958 					{	//the clipping will change
       
   959 					iCache[ii].Intersect(iNonRedrawVisibleRegion);
       
   960 					if (iCache[ii].CheckError())
       
   961 						{
       
   962 						failureOccured = ETrue;
       
   963 						iCache[ii].Close();
       
   964 						iCache.Remove(ii);
       
   965 						}
       
   966 					else
       
   967 						{
       
   968 						iPlacedElements[ii].SetChangedClip(ETrue);	//changed clipping
       
   969 						}
       
   970 					}
       
   971 				}
       
   972 			else
       
   973 				{	//attempt getting element region to perform calculation and update element directly
       
   974 				STACK_REGION elementRegion;
       
   975 	            TRect destinationRect;
       
   976 	            iPlacedElements[ii].iElement->GetDestinationRectangle(destinationRect);
       
   977 	            elementRegion.AddRect(destinationRect);
       
   978 				if (elementRegion.CheckError())
       
   979 					{
       
   980 					failureOccured = ETrue;
       
   981 					}
       
   982 				else
       
   983 					{
       
   984 					TRect elementExtent;
       
   985 					iPlacedElements[ii].iElement->GetDestinationRectangle(elementExtent);
       
   986 					elementRegion.Offset(elementExtent.iTl);	//get element region into absolute coordinates
       
   987 					TInt changed =
       
   988 						TRegionExtend::Cast(elementRegion).TestDifference(iNonRedrawVisibleRegion);
       
   989 					if (changed&TRegionExtend::ESub)
       
   990 						{	//need to clip element back
       
   991 						elementRegion.Intersect(iNonRedrawVisibleRegion);
       
   992 						if (!elementRegion.CheckError())
       
   993 							{
       
   994 							elementRegion.Offset(-elementExtent.iTl);	//put element region back into relative coords
       
   995 							returnFlags|=EFastPath;
       
   996 							}
       
   997 						else
       
   998 							{
       
   999 							failureOccured = ETrue;
       
  1000 							}
       
  1001 						}
       
  1002 					}
       
  1003 				elementRegion.Close();
       
  1004 				}
       
  1005 			if (failureOccured)
       
  1006 				{	//need to release element
       
  1007 				TSurfaceId tempId = iPlacedElements[ii].iElement->ConnectedSurface();
       
  1008 				iPlacedElements[ii].iElement->ConnectSurface(TSurfaceId::CreateNullId());
       
  1009 				NotifyReleasingSurface(tempId);
       
  1010 				aScene.DestroySceneElement(iPlacedElements[ii].iElement);
       
  1011 				returnFlags|=EFailed;
       
  1012 				iPlacedElements.Remove(ii);	//remove placed element entry, cache is already removed
       
  1013 				ii--;
       
  1014 				}
       
  1015 			}
       
  1016 		}
       
  1017 
       
  1018 	//update any elements marked as changedclip , clear all cache, clear flags
       
  1019 	for (ii=0; ii<iPlacedElements.Count(); ii++)
       
  1020 		{
       
  1021 		if (iPlacedElements[ii].ChangedClip())
       
  1022 			{
       
  1023 			returnFlags|=EFastPath;	//need to invoke 1108
       
  1024 			}
       
  1025 		else
       
  1026 			if (	!(returnFlags&EFastPath)
       
  1027 				&&	iPlacedElements[ii].LockedConfig() && !iPlacedElements[ii].Unassigned()
       
  1028 				&&	iPlacedElements[ii].DrawnOver()!=iPlacedElements[ii].DrawnOverLast()	)
       
  1029 						{
       
  1030 						returnFlags|=EFastPath;
       
  1031 						}
       
  1032 		iPlacedElements[ii].ClearRedrawFlags();
       
  1033 		if (iCache.Count() > ii)
       
  1034 			{
       
  1035 			iCache[ii].Clear();
       
  1036 			}
       
  1037 		}
       
  1038 	iCache.Reset();
       
  1039 	iNonRedrawVisibleRegion.Clear();
       
  1040 	iHighestReusedIndex = -1;
       
  1041 	return returnFlags;
       
  1042 	}
       
  1043 
       
  1044 /** Move all elements in this windowelement to above the supplied element in the scene
       
  1045 
       
  1046 @param aScene Access to the scene.
       
  1047 @param aElement The element to set all this windows elements above.
       
  1048 */
       
  1049 
       
  1050 void CWindowElement::MoveToAboveGivenElement(MWsScene& aScene, MWsElement* aElement)
       
  1051 	{
       
  1052 	MWsElement* newAboveElement = iBackgroundElement.iElement;
       
  1053 	MWsElement* previousAboveElement = aElement;
       
  1054 	if (newAboveElement)
       
  1055 		{
       
  1056 		aScene.InsertSceneElement(newAboveElement, previousAboveElement);	//background element is put on first
       
  1057 		previousAboveElement = newAboveElement;		
       
  1058 		}
       
  1059 	TInt placedElements = iPlacedElements.Count();
       
  1060 	if (placedElements != 0)
       
  1061 		{
       
  1062 		for (TInt ii = 0; ii < placedElements; ii++)
       
  1063 			{
       
  1064 			newAboveElement = iPlacedElements[ii].iElement;
       
  1065 			aScene.InsertSceneElement(newAboveElement, previousAboveElement);	//place element above previous above element
       
  1066 			previousAboveElement = newAboveElement;	
       
  1067 			}
       
  1068 		}
       
  1069 	}
       
  1070 
       
  1071 /** Updates the elements extent, whether from a window movement or a change in window size
       
  1072 
       
  1073 @param aOffset The movement of the window.  If NULL then the window has changed size.
       
  1074 @see CWindowElementSet::UpdateElementExtent
       
  1075 */
       
  1076 void CWindowElement::UpdateElementExtent(const TPoint* aOffset)
       
  1077 	{
       
  1078 	if (aOffset)	//window moved
       
  1079 		{
       
  1080 		TRect tempExtent;
       
  1081 		MWsElement* element = iBackgroundElement.iElement;
       
  1082 		TBool complete = EFalse;
       
  1083 		TInt placedElementDone = -1;
       
  1084 		while (!complete)
       
  1085 			{
       
  1086 			if (!element && placedElementDone < iPlacedElements.Count()-1)
       
  1087 				{
       
  1088 				placedElementDone++;
       
  1089 				element = iPlacedElements[placedElementDone].iElement;
       
  1090 				}
       
  1091 			if (!element)
       
  1092 				{
       
  1093 				complete = ETrue;
       
  1094 				}
       
  1095 			else
       
  1096 				{
       
  1097 				tempExtent = const_cast<CWsClientWindow&>(iWindow).GetOriginalDestElementRect();
       
  1098 				tempExtent.Move(*aOffset);
       
  1099 				element->SetDestinationRectangle(tempExtent);
       
  1100 				const_cast<CWsClientWindow&>(iWindow).SetOriginalDestElementRect(tempExtent);
       
  1101 				}
       
  1102 			element = NULL;
       
  1103 			}
       
  1104 		}
       
  1105 	else			//window changed size
       
  1106 		{
       
  1107 		if (!iBackgroundElement.ExplicitExtent() && iBackgroundElement.iElement)
       
  1108 			{
       
  1109 			iBackgroundElement.iElement->SetDestinationRectangle(iWindow.FullRect());
       
  1110 			const_cast<CWsClientWindow&>(iWindow).SetOriginalDestElementRect(iWindow.FullRect());
       
  1111 			}
       
  1112 		}
       
  1113 	}
       
  1114 
       
  1115 /** Checks the windows placed elements when the windows visibility is changed.
       
  1116 If the placed elements are no longer visible, they are removed.
       
  1117 
       
  1118 @param aRegion The new visible region of the window.
       
  1119 @param aScene Access to the scene.
       
  1120 @return ETrue if any elements have been removed, otherwise EFalse.
       
  1121 @see CWindowElementSet::SetVisibleRegion
       
  1122 */
       
  1123 TBool CWindowElement::SetVisibleRegion(const TRegion& aRegion, MWsScene& aScene)
       
  1124 	{
       
  1125 	TBool retcode=EFalse;
       
  1126 	if (iPlacedElements.Count() == 0)
       
  1127 		{
       
  1128 		return EFalse;	//there is noting to do
       
  1129 		}
       
  1130 	
       
  1131 	STACK_REGION tempRegion;
       
  1132 	for (TInt ii = 0; ii < iPlacedElements.Count(); ii++)
       
  1133 		{
       
  1134 		TRect tempExtent;
       
  1135         tempRegion.Clear();
       
  1136         iPlacedElements[ii].iElement->GetDestinationRectangle(tempExtent);
       
  1137         tempRegion.AddRect(tempExtent);
       
  1138 		if (tempRegion.CheckError())	//if there was error getting region
       
  1139 			{
       
  1140 			tempRegion.Clear();
       
  1141 			tempRegion.AddRect(tempExtent);
       
  1142 			}
       
  1143 		else
       
  1144 			{	//offset basearea of element
       
  1145 			tempRegion.Offset(tempExtent.iTl);
       
  1146 			}
       
  1147 		TInt regionReturn = TRegionExtend::Cast(aRegion).TestDifference(tempRegion);
       
  1148 		if (regionReturn&TRegionExtend::ENoIntersect)
       
  1149 			{	//placed surface needs to be removed
       
  1150 			TSurfaceId tempId = iPlacedElements[ii].iElement->ConnectedSurface();
       
  1151 			iPlacedElements[ii].iElement->ConnectSurface(TSurfaceId::CreateNullId());
       
  1152 			NotifyReleasingSurface(tempId);
       
  1153 			aScene.DestroySceneElement(iPlacedElements[ii].iElement);
       
  1154 			retcode = ETrue;	//a element has been removed
       
  1155 			iPlacedElements.Remove(ii);
       
  1156 			if (iCache.Count() > ii)
       
  1157 				{	//keep cache up to date
       
  1158 				iCache[ii].Close();
       
  1159 				iCache.Remove(ii);
       
  1160 				}
       
  1161 			ii--;
       
  1162 			}
       
  1163 		}
       
  1164 	tempRegion.Close();
       
  1165 	return retcode;
       
  1166 	}
       
  1167 
       
  1168 /** Checks if any of the windows element ids match the one in question.
       
  1169 
       
  1170 @param aSurfaceId The surface id to match against.
       
  1171 @return ETrue if a match is found, otherwise EFalse.
       
  1172 
       
  1173 @see CWindowElementSet::SearchDuplicateSurfaceId
       
  1174 */
       
  1175 TBool CWindowElement::SearchDuplicateSurfaceId(const TSurfaceId& aSurfaceId)
       
  1176 	{
       
  1177 	if (iBackgroundElement.iElement)
       
  1178 		{
       
  1179 		if (iBackgroundElement.iElement->ConnectedSurface() == aSurfaceId)
       
  1180 			{
       
  1181 			return ETrue;
       
  1182 			}
       
  1183 		}
       
  1184 	if (iPlacedElements.Count() > 0)
       
  1185 		{
       
  1186 		for (TInt ii = 0; ii < iPlacedElements.Count(); ii++)
       
  1187 			{
       
  1188 			if (iPlacedElements[ii].iElement)	//if removed without reserved space for ids, could be a null element
       
  1189 				{
       
  1190 				if (iPlacedElements[ii].iElement->ConnectedSurface() == aSurfaceId)
       
  1191 					{
       
  1192 					return ETrue;
       
  1193 					}
       
  1194 				}
       
  1195 			}
       
  1196 		}
       
  1197 	return EFalse;
       
  1198 	}
       
  1199 
       
  1200 /** Sets the opacity for the background surface and if setting to 0 removes placed surfaces.
       
  1201 
       
  1202 @param aOpacity The opacity to set.
       
  1203 @param aScene Access to the scene.
       
  1204 @see CWindowElementSet::SetElementOpacity
       
  1205 */
       
  1206 void CWindowElement::SetElementOpacity(TInt aOpacity, MWsScene& aScene)
       
  1207 	{
       
  1208 	if (iBackgroundElement.iElement)
       
  1209 		{
       
  1210 	    TUint32 flags = 0;
       
  1211 	    iBackgroundElement.iElement->GetTargetRendererFlags(flags);
       
  1212 	    flags |= MWsElement::EElementTransparencyGlobalAlpha;
       
  1213 		iBackgroundElement.iElement->SetTargetRendererFlags(MWsElement::EElementTransparencyGlobalAlpha);
       
  1214 		iBackgroundElement.iElement->SetGlobalAlpha(aOpacity);
       
  1215 		iBackgroundElement.SetConcealed(aOpacity==0);
       
  1216 		}
       
  1217 	if (aOpacity == 0)
       
  1218 		{
       
  1219 		while (iPlacedElements.Count() > 0)
       
  1220 			{	//remove any placed elements
       
  1221 			TInt placedElement = iPlacedElements.Count()-1;
       
  1222 			TSurfaceId tempId = iPlacedElements[placedElement].iElement->ConnectedSurface();
       
  1223 			iPlacedElements[placedElement].iElement->ConnectSurface(TSurfaceId::CreateNullId());
       
  1224 			NotifyReleasingSurface(tempId);
       
  1225 			aScene.DestroySceneElement(iPlacedElements[placedElement].iElement);
       
  1226 			iPlacedElements.Remove(placedElement);
       
  1227 			};
       
  1228 		}
       
  1229 	}
       
  1230 
       
  1231 MWsElement* CWindowElement::Element() const
       
  1232     {
       
  1233     return iBackgroundElement.iElement;
       
  1234     }
       
  1235 
       
  1236 //
       
  1237 // CWindowElementSet
       
  1238 //
       
  1239 
       
  1240 /** Destroys the set of window-element pairs.
       
  1241 */
       
  1242 CWindowElementSet::~CWindowElementSet()
       
  1243 	{
       
  1244 	ASSERT(iElements.Count() == 0);
       
  1245 	iElements.Close();
       
  1246 	}
       
  1247 
       
  1248 /** Basic NewL constructor
       
  1249 @param aScene To allow access to the scene.
       
  1250 @param aComposer To allow access to the composer.
       
  1251 */
       
  1252 CWindowElementSet* CWindowElementSet::NewL(MWsScene& aScene)
       
  1253 	{
       
  1254 	CWindowElementSet* wls = new (ELeave) CWindowElementSet(aScene);
       
  1255 	return wls;
       
  1256 	}
       
  1257 
       
  1258 /** Sets a new background surface on the window supplied.
       
  1259 Will remove any previous background surface.
       
  1260 
       
  1261 @param aWindow The window to place a background surface on.
       
  1262 @return A reference to the new background surface attributes.
       
  1263 */
       
  1264 TBackgroundAttributes& CWindowElementSet::AcquireBackgroundElementL(CWsClientWindow& aWindow)
       
  1265 	{
       
  1266 	// Find the matching element.
       
  1267 	TInt index;
       
  1268 	TInt result = FindEntry(aWindow, index);
       
  1269 	MWsElement* element;
       
  1270 
       
  1271 	// If a background element is already associated with the window, then unregister
       
  1272 	// the surface. Create and add a new element to scene.
       
  1273 	// This will ensure that the element has default values.
       
  1274 	if (result != KErrNotFound && iElements[index]->iBackgroundElement.iElement)
       
  1275 	    {
       
  1276 	    element = iElements[index]->iBackgroundElement.iElement;
       
  1277 		TSurfaceId surface = element->ConnectedSurface();
       
  1278 		element->ConnectSurface(TSurfaceId::CreateNullId());
       
  1279 		UnregisterSurface(surface);
       
  1280 		iScene.DestroySceneElement(element);
       
  1281 	    }
       
  1282 	if (index < 0)
       
  1283 		{
       
  1284 		index = 0;
       
  1285 		}
       
  1286 
       
  1287 	// Allocate a new element and add it to the set and the scene
       
  1288 	element = iScene.CreateSceneElementL();
       
  1289 	
       
  1290 	TInt returnCode;
       
  1291 	if (result == KErrNotFound)
       
  1292 		{
       
  1293 		CWindowElement* winelement = new CWindowElement(aWindow);
       
  1294 		if (!winelement)
       
  1295 			{
       
  1296 			iScene.DestroySceneElement(element);
       
  1297 			User::Leave(KErrNoMemory);
       
  1298 			}
       
  1299 		returnCode = iElements.Insert(winelement, index);
       
  1300 		if(returnCode != KErrNone)
       
  1301 		    {
       
  1302 		    delete winelement;
       
  1303 		    iScene.DestroySceneElement(element);
       
  1304 		    User::Leave(returnCode);
       
  1305 		    }
       
  1306 		}
       
  1307 
       
  1308 	// Use the element below the insertion point to decide where the element
       
  1309 	// goes in the scene
       
  1310 	returnCode = KErrNone;
       
  1311 	if (index == 0)
       
  1312 		{
       
  1313 		returnCode = iScene.InsertSceneElement(element, NULL);
       
  1314 		}
       
  1315 	else
       
  1316 		{
       
  1317 		//Find highest element in window below
       
  1318 		MWsElement* below;
       
  1319 		TInt placedCount = iElements[index-1]->iPlacedElements.Count();
       
  1320 		if (placedCount > 0)
       
  1321 			{
       
  1322 			below = iElements[index-1]->iPlacedElements[placedCount-1].iElement;
       
  1323 			}
       
  1324 		else
       
  1325 			{	//below = above = background surface
       
  1326 			below = iElements[index-1]->iBackgroundElement.iElement;
       
  1327 			}
       
  1328 		returnCode = iScene.InsertSceneElement(element, below);
       
  1329 		}
       
  1330 	
       
  1331 	__ASSERT_DEBUG(returnCode == KErrNone, Panic(EWsPanicSceneErrorIgnored));
       
  1332 
       
  1333 	iElements[index]->iBackgroundElement.iElement = element;
       
  1334 	return iElements[index]->iBackgroundElement;
       
  1335 	}
       
  1336 
       
  1337 /** Removes the background element of the specified window.
       
  1338 
       
  1339 @param aWindow The window to remove the background element from.
       
  1340 @param aWindowClosing ETrue if aWindow is in between closing state.
       
  1341 @return KErrNone on success or a system-wide error code.
       
  1342 */
       
  1343 TInt CWindowElementSet::ReleaseBackgroundElement(const CWsClientWindow& aWindow, TBool aWindowClosing /*= EFalse*/)
       
  1344 	{
       
  1345 	TInt index;
       
  1346 
       
  1347 	TInt err = FindEntry(aWindow, index, aWindowClosing);
       
  1348 	__ASSERT_DEBUG(err != KErrNotFound, Panic(EWsPanicNoWindowElement));
       
  1349 
       
  1350 	if (err==KErrNone)
       
  1351 		{
       
  1352 		CWindowElement* winElement=iElements[index];
       
  1353 		if (winElement->iPlacedElements.Count() == 0)
       
  1354 			{	//destroy the window entry
       
  1355 			DestroyWindowElementEntry(index);
       
  1356 			}
       
  1357 		else
       
  1358 			{	// just destroy the background
       
  1359 			if (winElement->iBackgroundElement.iElement)
       
  1360 				{
       
  1361 				winElement->iBackgroundElement.Destroy(iScene, ETrue);
       
  1362 				}
       
  1363 			}
       
  1364 		}
       
  1365 	return err;
       
  1366 	}
       
  1367 
       
  1368 /** Destroys the element associated with this set of attributes
       
  1369 
       
  1370 @param aScene To allow access to the scene.
       
  1371 @param aUnregister Whether to call unregister on the surface id.
       
  1372 @return ETrue if a element existed to be destroyed, otherwise EFalse.
       
  1373 */
       
  1374 TBool TAttributes::Destroy(MWsScene& aScene, TBool aUnregister)
       
  1375 	{
       
  1376 	MWsElement* element = iElement;
       
  1377 	if (element)
       
  1378 		{
       
  1379 		TSurfaceId surface = element->ConnectedSurface();
       
  1380 		element->ConnectSurface(TSurfaceId::CreateNullId());
       
  1381         if (aUnregister)
       
  1382             {
       
  1383             aScene.UnregisterSurface(surface);
       
  1384             }
       
  1385 		aScene.DestroySceneElement(element);
       
  1386 		iElement = NULL;
       
  1387 		}
       
  1388 	return element!=NULL;
       
  1389 	}
       
  1390 
       
  1391 /** Destroys all elements associated with the window and removes the window from the element set
       
  1392 
       
  1393 @param aWinElementIndex The index of the window in the element set
       
  1394 */
       
  1395 void CWindowElementSet::DestroyWindowElementEntry(const TInt aWinElementIndex)
       
  1396 	{
       
  1397 	CWindowElement* winElement=iElements[aWinElementIndex];
       
  1398 	const CWsClientWindow& window = winElement->iWindow;
       
  1399 	winElement->iBackgroundElement.Destroy(iScene, ETrue);
       
  1400 	for (TInt placedIndex=0,maxindex=winElement->iPlacedElements.Count();placedIndex<maxindex;placedIndex++)
       
  1401 		{
       
  1402 		winElement->iPlacedElements[placedIndex].Destroy(iScene, EFalse);
       
  1403 		}
       
  1404 	winElement->iPlacedElements.Close();
       
  1405 	delete winElement;
       
  1406 	iElements.Remove(aWinElementIndex);
       
  1407 	window.Redraw()->SetHasElement(EFalse);
       
  1408 	window.Screen()->ElementRemoved();
       
  1409 	}
       
  1410 
       
  1411 /** Removes all elements in the associated window.
       
  1412 
       
  1413 @param aWindow The window to remove the elements for.
       
  1414 @param aWindowClosing ETrue if aWindow is in between closing state.
       
  1415 @return KErrNone on success, KErrNotFound if there was no windowelement entry.
       
  1416 */
       
  1417 TInt CWindowElementSet::ReleaseAllElements(const CWsClientWindow& aWindow, TBool aWindowClosing /*= EFalse*/)
       
  1418 	{
       
  1419 	TInt index;
       
  1420 
       
  1421 	TInt err = FindEntry(aWindow, index, aWindowClosing);
       
  1422 	__ASSERT_DEBUG(err != KErrNotFound, Panic(EWsPanicNoWindowElement));
       
  1423 	if (err==KErrNone)
       
  1424 		{
       
  1425 		DestroyWindowElementEntry(index);
       
  1426 		}
       
  1427 	return err;
       
  1428 	}
       
  1429 
       
  1430 /** For every window element, checks if any of the windows element ids match the one in question.
       
  1431 
       
  1432 @param aSurfaceId The surface id to match against.
       
  1433 @return ETrue if a match is found, otherwise EFalse.
       
  1434 
       
  1435 @see CWindowElement::SearchDuplicateSurfaceId
       
  1436 */
       
  1437 TBool CWindowElementSet::SearchDuplicateSurfaceId(const TSurfaceId& aSurfaceId)
       
  1438 	{
       
  1439 	TInt windowElements = iElements.Count();
       
  1440 	for (TInt ii = 0; ii < windowElements; ii++)
       
  1441 		{
       
  1442 		if (iElements[ii]->SearchDuplicateSurfaceId(aSurfaceId))
       
  1443 			{
       
  1444 			return ETrue;
       
  1445 			}
       
  1446 		}
       
  1447 	return EFalse;
       
  1448 	}
       
  1449 
       
  1450 /** For a window, sets the opacity for the background surface and if setting to 
       
  1451 0 removes placed surfaces.
       
  1452 
       
  1453 @param aWindow The window to perform the function on.
       
  1454 @param aOpacity The opacity to set.
       
  1455 @see CWindowElement::SetElementOpacity
       
  1456 */
       
  1457 void CWindowElementSet::SetElementOpacity(CWsClientWindow& aWindow, TInt aOpacity)
       
  1458 	{
       
  1459 	WS_ASSERT_DEBUG(aOpacity == 0 || aOpacity == 255,EWsPanicUnexpectedOpacity);
       
  1460 	return FindElement(aWindow)->SetElementOpacity(aOpacity, iScene);
       
  1461 	}
       
  1462 
       
  1463 /** Finds all elements within the window that overlap with the region and 
       
  1464 marks them as unassigned.
       
  1465 If any part of these unassigned elements are outside the region, they are also 
       
  1466 marked overlapping and locked config.
       
  1467 
       
  1468 @param aRedrawRegion The region in which elements will be unassigned
       
  1469 @param aWindow The window to perform the function on.
       
  1470 @return KErrNone on success or KErrNoMemory if critical calculations could not be made.
       
  1471 @see CWindowElement::UnassignPlacedElements
       
  1472 */
       
  1473 TInt CWindowElementSet::UnassignPlacedElements(const TRegion& aRedrawRegion, const CWsClientWindow& aWindow, TInt aGcDrawingCount)
       
  1474 	{
       
  1475 	return FindElement(aWindow)->UnassignPlacedElements(aRedrawRegion, aGcDrawingCount);
       
  1476 	}
       
  1477 
       
  1478 /** Called to place a element within the window.
       
  1479 It will either create a new element, recycle a element, or extend a element .
       
  1480 
       
  1481 @param aPlacedAttributes Returns the attributes of the surface placed.
       
  1482 @param aSurfaceConfiguration The surface configuration for the surface to place.
       
  1483 @param aUserDefinedRegion The user defined clipping of the window.
       
  1484 @param aWindow The window to perform the function on.
       
  1485 @return KErrNone on success or a system-wide error code.
       
  1486 @see CWindowElement::AssignPlacedElement
       
  1487 */
       
  1488 TInt CWindowElementSet::AssignPlacedElement(
       
  1489 		TPlacedAttributes*& aPlacedAttributes,
       
  1490 		const TSurfaceConfiguration& aSurfaceConfiguration,
       
  1491 		const TRegion& aUserDefinedRegion,
       
  1492 		const CWsClientWindow& aWindow,
       
  1493 		TInt aGcDrawingCount	)
       
  1494 	{
       
  1495 	TInt index;
       
  1496 	TInt error = KErrNone;
       
  1497 	TInt result = FindEntry(aWindow, index);
       
  1498 	TBool insertedElement = EFalse;
       
  1499 	if (result == KErrNotFound)
       
  1500 		{
       
  1501 		CWindowElement* winelement = new CWindowElement(aWindow);
       
  1502 		if (!winelement)
       
  1503 			{
       
  1504 			return KErrNoMemory;		//memory error
       
  1505 			}
       
  1506 		error = iElements.Insert(winelement, index);
       
  1507 		if (error == KErrNone)
       
  1508 			{
       
  1509 			insertedElement = ETrue;
       
  1510 			aWindow.Redraw()->SetHasElement(ETrue);
       
  1511 			STACK_REGION windowRegion = aWindow.Abs();
       
  1512 			if (!windowRegion.CheckError())
       
  1513 				{
       
  1514 				error = iElements[index]->UnassignPlacedElements(windowRegion, aGcDrawingCount);
       
  1515 				}
       
  1516 			else
       
  1517 				{
       
  1518 				error = KErrNoMemory;
       
  1519 				}
       
  1520 			windowRegion.Close();
       
  1521 			}
       
  1522 		else
       
  1523 			{
       
  1524 			delete winelement;
       
  1525 			}
       
  1526 		}
       
  1527 	if (error == KErrNone)
       
  1528 		{
       
  1529 		
       
  1530 		TInt assignReturn = iElements[index]->AssignPlacedElement(aPlacedAttributes, aSurfaceConfiguration,
       
  1531 				aUserDefinedRegion, iScene, aGcDrawingCount);
       
  1532 		error = assignReturn;	//return assign flags
       
  1533 		}
       
  1534 	if (error < KErrNone && insertedElement)
       
  1535 		{	//remove this element that has just been created
       
  1536 		aWindow.Redraw()->SetHasElement(EFalse);
       
  1537 		iElements.Remove(index);
       
  1538 		}
       
  1539 	return error;
       
  1540 	}
       
  1541 
       
  1542 /** Marks all elements that have been assigned since the unassign as drawn over.
       
  1543 
       
  1544 @param aWindow The window to perform the function on.
       
  1545 @see CWindowElement::FlagAssignedElementsDrawnOver
       
  1546 **/
       
  1547 //void CWindowElementSet::FlagAssignedElementsDrawnOver(const CWsClientWindow& aWindow)
       
  1548 //	{
       
  1549 //	FindElement(aWindow)->FlagAssignedElementsDrawnOver();
       
  1550 //	}
       
  1551 
       
  1552 /** Called at the end of a redraw to set cached changed to elements, and
       
  1553 removed elements that are still unassigned.
       
  1554 
       
  1555 @param aWindow The window to perform the function on.
       
  1556 @return Flags to describe what extra work needed doing.
       
  1557 @see CWindowElement::CleanUpPlacedElements
       
  1558 */
       
  1559 TInt CWindowElementSet::CleanUpPlacedElements(const CWsClientWindow& aWindow, TInt aGcDrawingCount)
       
  1560 	{
       
  1561 	TInt index;
       
  1562 	TInt error = FindEntry(aWindow,index);
       
  1563 	if (error < 0)
       
  1564 		{
       
  1565 		WS_ASSERT_DEBUG(0,EWsPanicNoWindowElement);
       
  1566 		return error;
       
  1567 		}
       
  1568 	TInt returnFlags = iElements[index]->CleanUpPlacedElements(iScene, aGcDrawingCount);
       
  1569 
       
  1570 	if (!iElements[index]->iBackgroundElement.iElement && iElements[index]->iPlacedElements.Count() == 0)
       
  1571 		{	//remove window entry
       
  1572 		DestroyWindowElementEntry(index);
       
  1573 		}
       
  1574 	else
       
  1575 		{
       
  1576 		if (returnFlags&CWindowElement::EResort)
       
  1577 			{	//need to sort elements
       
  1578 			//find front most visible element in window behind, invoke sort by z order
       
  1579 			if (index == 0)
       
  1580 				{	//this element is backmost window
       
  1581 				iElements[index]->MoveToAboveGivenElement(iScene,NULL);
       
  1582 				}
       
  1583 			else
       
  1584 				{	//place infront of highest element behind
       
  1585 				if (iElements[index-1]->iPlacedElements.Count() == 0)
       
  1586 					{	//top element of element behind must be the background element
       
  1587 					iElements[index]->MoveToAboveGivenElement(iScene,iElements[index-1]->iBackgroundElement.iElement);				
       
  1588 					}
       
  1589 				else
       
  1590 					{	//top element of element behind must be highest placed element
       
  1591 					TInt placedCount = iElements[index-1]->iPlacedElements.Count();
       
  1592 					iElements[index]->MoveToAboveGivenElement(iScene,iElements[index-1]->iPlacedElements[placedCount-1].iElement);
       
  1593 					}
       
  1594 				}
       
  1595 			}
       
  1596 		}
       
  1597 	if (returnFlags&CWindowElement::EFailed)
       
  1598 		{	//visible elements may have been deleted, error to suggest a full window redraw
       
  1599 		return KErrGeneral;
       
  1600 		}
       
  1601 	return returnFlags;
       
  1602 	}
       
  1603 
       
  1604 /** Counts how many elements there are in the set.
       
  1605 
       
  1606 @return The number of elements in the set.
       
  1607 */
       
  1608 TInt CWindowElementSet::Count() const
       
  1609 	{
       
  1610 	return iElements.Count();
       
  1611 	}
       
  1612 
       
  1613 /** Returns the background attributes for the specified window
       
  1614 
       
  1615 @param aWindow The window to perform the function on.
       
  1616 @return The background surface attributes.  If the window has no elementset entry, returns NULL.
       
  1617 */
       
  1618 TBackgroundAttributes* CWindowElementSet::FindBackgroundElement(const CWsClientWindow& aWindow)
       
  1619 	{
       
  1620 	TInt index;
       
  1621 	TInt err = FindEntry(aWindow, index);
       
  1622 
       
  1623 	if (err != KErrNotFound)
       
  1624 		{
       
  1625 		return &(iElements[index]->iBackgroundElement);
       
  1626 		}
       
  1627 	return NULL;
       
  1628 	}
       
  1629 
       
  1630 /**	Returns the contents of the element data associated with the input window.
       
  1631 If this method is successful, then neither pointer will be NULL.
       
  1632 
       
  1633 @return standard symbian error code.
       
  1634 @param	aWindow	window to find
       
  1635 @param	aBackAttr	backgroud surface attributes associated with the window
       
  1636 @param	aPlacedAttr	array of placed surface attributes associated with the window.
       
  1637 */
       
  1638 TInt CWindowElementSet::FindElements(	CWsClientWindow const &aWindow, 
       
  1639 									TBackgroundAttributes const * & aBackAttr, 
       
  1640 									RArray<class TPlacedAttributes> const * &	aPlacedAttr	)
       
  1641 	{
       
  1642 	TInt index;
       
  1643 
       
  1644 	TInt err = FindEntry(aWindow, index);
       
  1645 //	__ASSERT_DEBUG(err != KErrNotFound, Panic(EWsPanicNoWindowElement));
       
  1646 
       
  1647 //	return *iElements[index].iElement;
       
  1648 	if (err >= KErrNone)
       
  1649 		{
       
  1650 		aBackAttr=&iElements[index]->iBackgroundElement;
       
  1651 		aPlacedAttr=&iElements[index]->iPlacedElements;
       
  1652 		}
       
  1653 	else
       
  1654 		{
       
  1655 		aBackAttr=NULL;
       
  1656 		aPlacedAttr=NULL;
       
  1657 		}
       
  1658 	return err;
       
  1659 	
       
  1660 	}
       
  1661 
       
  1662 /** Registers the surface with the compositor.
       
  1663 @param aSurface The surface id to register.
       
  1664 @return  KErrNone if successful, KErrNoMemory if registration fails due to low
       
  1665 memory, KErrNotSupported if the surface is not compatible with
       
  1666 this compositor or KErrBadHandle if the given surface ID does not
       
  1667 represent a valid surface. KErrArgument is returned if the
       
  1668 surface does not have both dimensions less than 32 767 pixels.
       
  1669 */
       
  1670 TInt CWindowElementSet::RegisterSurface(const TSurfaceId& aSurface)
       
  1671     {
       
  1672     
       
  1673     return iScene.RegisterSurface(aSurface);
       
  1674     }
       
  1675 
       
  1676 /** Unregisters the surface with the compositor.
       
  1677 
       
  1678 @param aSurface The surface id to register.
       
  1679 @return  KErrNone if successful. KErrInUse if the surface is
       
  1680 used by a layer or layers. KErrBadHandle if the surface
       
  1681 is not currently registered. KErrArgument if
       
  1682 the surface ID is a NULL ID.
       
  1683 */
       
  1684 
       
  1685 void CWindowElementSet::UnregisterSurface(const TSurfaceId& aSurface)
       
  1686     {
       
  1687     
       
  1688     TInt returnCode = iScene.UnregisterSurface(aSurface);
       
  1689     __ASSERT_DEBUG((returnCode==KErrNone || returnCode==KErrInUse || returnCode==KErrBadHandle), Panic(EWsPanicSceneErrorIgnored));
       
  1690     }
       
  1691 
       
  1692 /** Sorts the array elements into the same order as the windows are in the
       
  1693 hierarchy. Use after window hierarchy has been modified, to update the scene
       
  1694 order to match.
       
  1695 @return EFalse if element order unchanged, ETrue if order may have changed.
       
  1696 */
       
  1697 TBool CWindowElementSet::SortByZOrder()
       
  1698 	{
       
  1699 	if (iElements.Count() < 2)
       
  1700 		{
       
  1701 		// Early out for the very common cases where there are zero or one
       
  1702 		// elements, which cannot therefore be out of order.
       
  1703 		return EFalse;
       
  1704 		}
       
  1705 
       
  1706 	// The approach being used is to first just sort the array, then update the 
       
  1707 	// scene order afterwards. This is simple to code and since there are not
       
  1708 	// expected to be many elements, it should be perfectly good enough.
       
  1709 
       
  1710 	TLinearOrder<CWindowElement> order(WindowOrder);
       
  1711 	iElements.Sort(order);
       
  1712 
       
  1713 	TBool orderChanged = EFalse;
       
  1714 	MWsElement* below;
       
  1715 	TInt elementCount = iElements.Count();
       
  1716 	for (TInt index = 0; index < elementCount; index++)
       
  1717 		{
       
  1718 		if (index == 0)
       
  1719 			{
       
  1720 			below = NULL;
       
  1721 			}
       
  1722 		else
       
  1723 			{
       
  1724 			//Find highest element in window below
       
  1725 			TInt placedCount = iElements[index-1]->iPlacedElements.Count();
       
  1726 			if (placedCount > 0)
       
  1727 				{
       
  1728 				below = iElements[index-1]->iPlacedElements[placedCount-1].iElement;
       
  1729 				}
       
  1730 			else
       
  1731 				{	//below = above = background surface
       
  1732 				below = iElements[index-1]->iBackgroundElement.iElement;
       
  1733 				}
       
  1734 			}
       
  1735 		//Find lowest element in above window element
       
  1736 		MWsElement* above;
       
  1737 		if (iElements[index]->iBackgroundElement.iElement != NULL)
       
  1738 			{	//use background element
       
  1739 			above = iElements[index]->iBackgroundElement.iElement;	//background element will be bottom
       
  1740 			}
       
  1741 		else	//use bottom element of placed surfaces
       
  1742 			{
       
  1743 			//above = iElements[index]->iPlacedElements[iElements[index]->iPlacedElements.Count()-1].iElement;	//first or last placed element is bottom?
       
  1744 			above = iElements[index]->iPlacedElements[0].iElement;
       
  1745 			}
       
  1746 		if (above->ElementBelow() != below)
       
  1747 			{
       
  1748 			//CALL below window element function to move all elements above 'below'
       
  1749 			iElements[index]->MoveToAboveGivenElement(iScene, below);
       
  1750 	        orderChanged = ETrue;
       
  1751 			}
       
  1752 		}
       
  1753 	return orderChanged;
       
  1754 	}
       
  1755 
       
  1756 /** Processes the specified windows placed elements, for when windows visibility is changed.
       
  1757 If the placed elements are no longer visible, they are removed.
       
  1758 
       
  1759 @param aWindow The window to call the function on.
       
  1760 @return Positive if any elements have been removed, zero if not, or errorcode. 
       
  1761 @see CWindowElement::SetVisibleRegion
       
  1762 */
       
  1763 TInt CWindowElementSet::SetVisibleRegion(CWsClientWindow& aWindow)
       
  1764 	{
       
  1765 	TInt index;
       
  1766 	TInt find = FindEntry(aWindow,index);
       
  1767 	WS_ASSERT_DEBUG(find>=KErrNone,EWsPanicNoWindowElement);
       
  1768 	TBool ret = iElements[index]->SetVisibleRegion(aWindow.VisibleRegion(), iScene);
       
  1769 
       
  1770 	if (!iElements[index]->iBackgroundElement.iElement && iElements[index]->iPlacedElements.Count() == 0)
       
  1771 		{
       
  1772 		DestroyWindowElementEntry(index);
       
  1773 		}
       
  1774 	return ret;
       
  1775 	}
       
  1776 
       
  1777 /** Updates the specified windows elements extent, either from a window movement or a change in window size
       
  1778 
       
  1779 @param aWindow The window to call the function on.
       
  1780 @param aOffset The movement of the window.  If NULL then the window has changed size.
       
  1781 @see CWindowElement::UpdateElementExtent
       
  1782 */
       
  1783 void CWindowElementSet::UpdateElementExtent(const CWsClientWindow& aWindow, const TPoint* aOffset)
       
  1784 	{
       
  1785 	FindElement(aWindow)->UpdateElementExtent(aOffset);
       
  1786 	}
       
  1787 
       
  1788 /** Method to fill in a TSurfaceConfiguration from a scene element.
       
  1789 
       
  1790 @param aConfiguration Surface configuration to fill in.
       
  1791 @param aElement Element to get information from.
       
  1792 @return Once multiple versions of TSurfaceConfiguration are available, KErrNotSupported if configuration supplied is too small.
       
  1793 */
       
  1794 TInt CWindowElementSet::GetConfiguration(TSurfaceConfiguration& aConfiguration,MWsElement& aElement)
       
  1795 	{
       
  1796 	TSurfaceId tempSurfaceId = aElement.ConnectedSurface();
       
  1797 	aConfiguration.SetSurfaceId(tempSurfaceId);
       
  1798 	
       
  1799 	//Convert and copy orientation
       
  1800 	aConfiguration.SetOrientation(ElementToGcRotation(aElement.SourceRotation()));
       
  1801 	
       
  1802 	//Convert and copy flip
       
  1803 	TBool flip = aElement.SourceFlipping();
       
  1804 	aConfiguration.SetFlip(flip);
       
  1805 
       
  1806 	//Convert and copy viewport
       
  1807 	TRect tempViewport;
       
  1808 	aElement.GetSourceRectangle(tempViewport);
       
  1809 	aConfiguration.SetViewport(tempViewport);
       
  1810 	TRect tempExtent;
       
  1811 	aElement.GetDestinationRectangle(tempExtent);
       
  1812 	aConfiguration.SetExtent(tempExtent);
       
  1813 	return KErrNone;	//Could fail if there are multiple versions of TSurfaceConfiguration
       
  1814 	}
       
  1815 
       
  1816 /** Returns the window element entry for the specified window.
       
  1817 
       
  1818 @param aWindow The window to call the function on.
       
  1819 */
       
  1820 CWindowElement* CWindowElementSet::FindElement(const CWsClientWindow& aWindow) const
       
  1821 	{
       
  1822 	TInt index;
       
  1823 	TInt error = FindEntry(aWindow,index);
       
  1824 	if (error == KErrNone)
       
  1825 		return iElements[index];
       
  1826 	WS_ASSERT_DEBUG(EFalse,EWsPanicNoWindowElement);
       
  1827 	return NULL;
       
  1828 	}
       
  1829 
       
  1830 /** Creates a set of window-element pairs for this scene.
       
  1831 
       
  1832 @param aScene To allow access to the scene.
       
  1833 @param aComposer To allow access to the composer.
       
  1834 */
       
  1835 CWindowElementSet::CWindowElementSet(MWsScene& aScene) :
       
  1836 	iScene(aScene)
       
  1837 	{}
       
  1838 
       
  1839 /** Searches for the entry in iElements with the given window
       
  1840 
       
  1841 @param aWindow The window to find the entry of / where it should be inserted.
       
  1842 @param aIndex aIndex is set to entry found or the insertion point, respectively.
       
  1843 @param aLinearSearch ETrue if a linear search of the window element set is required.
       
  1844 @return KErrNone if found or KErrNotFound.
       
  1845 */
       
  1846 TInt CWindowElementSet::FindEntry(const CWsClientWindow& aWindow, TInt& aIndex, TBool aLinearSearch /*= EFalse*/) const
       
  1847 	{
       
  1848 	CWindowElement winelement(aWindow);
       
  1849 	
       
  1850 	// The array order makes use of the parent pointer, which gets reset during
       
  1851 	// window shutdown, so if it is clear fall back to a linear search.
       
  1852 	if (!aWindow.BaseParent() || aLinearSearch)
       
  1853 		{
       
  1854 		TIdentityRelation<CWindowElement> match(WindowMatch);
       
  1855 		
       
  1856 		aIndex = iElements.Find(&winelement, match);
       
  1857 		return (aIndex == KErrNotFound) ? KErrNotFound : KErrNone;
       
  1858 		}
       
  1859 	else
       
  1860 		{
       
  1861 		TLinearOrder<CWindowElement> order(WindowOrder);
       
  1862 		return iElements.FindInOrder(&winelement, aIndex, order);
       
  1863 		}
       
  1864 	}
       
  1865 
       
  1866 /** Used to find an entry in the set when order cannot be used. 
       
  1867 
       
  1868 @param aFirst First windowelement to compare.
       
  1869 @param aSecond Second windowelement to compare.
       
  1870 @return ETrue if the entries are the same, and EFalse if they are not.
       
  1871 */
       
  1872 TBool CWindowElementSet::WindowMatch(const CWindowElement& aFirst, const CWindowElement& aSecond)
       
  1873 	{
       
  1874 	return (&aFirst.iWindow == &aSecond.iWindow);
       
  1875 	}
       
  1876 
       
  1877 
       
  1878 /** Used to determine the order of entries in the set.
       
  1879 
       
  1880 @param aFirst First windowelement to compare.
       
  1881 @param aSecond Second windowelement to compare.
       
  1882 @return zero if the entries are the same, a negative value if 
       
  1883 aFirst is behind aSecond or a positive value if aFirst is in front of aSecond.
       
  1884 */
       
  1885 TInt CWindowElementSet::WindowOrder(const CWindowElement& aFirst, const CWindowElement& aSecond)
       
  1886 	{
       
  1887 	TInt result = 0;
       
  1888 
       
  1889 	if (&aFirst.iWindow != &aSecond.iWindow)
       
  1890 		{
       
  1891 		result = aFirst.iWindow.IsInfrontOf(&aSecond.iWindow) ? 1 : -1;
       
  1892 		}
       
  1893 
       
  1894 	return result;
       
  1895 	}
       
  1896 
       
  1897 
       
  1898 /**	Re-sends the extents for all the elements (in this window) to the scene  	
       
  1899  * 	This allows the renderstage to re-scale those element extents
       
  1900  * 
       
  1901  * 
       
  1902  **/
       
  1903 void CWindowElement::ResubmitAllElementExtents()
       
  1904 	{
       
  1905 	if (MWsElement* element=iBackgroundElement.iElement)
       
  1906 		{
       
  1907 		TRect extent(TRect::EUninitialized);
       
  1908 		element->GetDestinationRectangle(extent);
       
  1909 		element->SetDestinationRectangle(extent);
       
  1910 		}
       
  1911 	TInt elementCount = iPlacedElements.Count();
       
  1912 	for (TInt index = 0; index < elementCount; index++)
       
  1913 		{
       
  1914 		if (MWsElement* element=iPlacedElements[index].iElement)
       
  1915 			{
       
  1916 			TRect extent(TRect::EUninitialized);
       
  1917 			element->GetDestinationRectangle(extent);
       
  1918 			element->SetDestinationRectangle(extent);
       
  1919 			}
       
  1920 		}
       
  1921 	}
       
  1922 
       
  1923 /**	Re-sends the extents for all the elements (in all the windows) to the scene  	
       
  1924  * 	This allows the renderstage to re-scale those element extents
       
  1925  * 
       
  1926  * 
       
  1927  **/
       
  1928 void CWindowElementSet::ResubmitAllElementExtents()
       
  1929 	{
       
  1930 	TInt elementCount = iElements.Count();
       
  1931 	for (TInt index = 0; index < elementCount; index++)
       
  1932 		{
       
  1933 		iElements[index]->ResubmitAllElementExtents();
       
  1934 		}
       
  1935 	}
       
  1936 
       
  1937 //
       
  1938 // Debug functions
       
  1939 //
       
  1940 
       
  1941 /** Returns background attributes for the specified window index.
       
  1942 For use with debug client interface.
       
  1943 
       
  1944 @param aWin Window index to get the surface attributes from.
       
  1945 @return Background attributes for the specified window.  NULL if the window index is invalid.
       
  1946 */
       
  1947 const TBackgroundAttributes* CWindowElementSet::DebugBackgroundAt(TUint aWin)const
       
  1948 	{
       
  1949 	if (aWin>=Count())
       
  1950 		return NULL;
       
  1951 	return &iElements[aWin]->iBackgroundElement;
       
  1952 	}
       
  1953 
       
  1954 /** Returns the client window for the specified window index.
       
  1955 For use with debug client interface.
       
  1956 
       
  1957 @param aWin Window index to get the client window from.
       
  1958 @return Client window for the specified window.  NULL if the window index is invalid.
       
  1959 */
       
  1960 const CWsClientWindow* CWindowElementSet::DebugWindowAt(TUint aWin)const
       
  1961 	{
       
  1962 	if (aWin>=Count())
       
  1963 		return NULL;
       
  1964 	return &iElements[aWin]->iWindow;
       
  1965 	}
       
  1966 
       
  1967 /** Returns how many placed surfaces are on the specified window
       
  1968 For use with debug client interface.
       
  1969 
       
  1970 @param aWin Window index to get the client window from.
       
  1971 @return Amount of placed surfaces for the specified window index
       
  1972 */
       
  1973 TInt CWindowElementSet::DebugPlacedCountAt(TUint aWin)const
       
  1974 	{
       
  1975 	if (aWin>=Count())
       
  1976 		return -1;
       
  1977 	return iElements[aWin]->iPlacedElements.Count();
       
  1978 	}
       
  1979 
       
  1980 /** Returns the placed attributes for the specified placed surface index in the
       
  1981 specified window index.
       
  1982 For use with debug client interface.
       
  1983 
       
  1984 @param aWin Window index to get the client window from.
       
  1985 @param aPlace Placed surface index to get the placed surface attributes
       
  1986 @return Placed surface attributes.  NULL if either index was invalid.
       
  1987 */
       
  1988 const TPlacedAttributes* CWindowElementSet::DebugPlacedAt(TUint aWin,TUint aPlace)const
       
  1989 	{
       
  1990 	if (aWin>=Count())
       
  1991 		return NULL;
       
  1992 	if (aPlace>=iElements[aWin]->iPlacedElements.Count())
       
  1993 		return NULL;
       
  1994 	return &iElements[aWin]->iPlacedElements[aPlace];
       
  1995 	}
       
  1996 
       
  1997 MWsElement* CWindowElementSet::GetElementFromWindow(const CWsClientWindow& aWindow) const
       
  1998     {
       
  1999     CWindowElement* windowElement = FindElement(aWindow);
       
  2000     if (windowElement)
       
  2001         return windowElement->Element();
       
  2002     else 
       
  2003         return NULL; 
       
  2004     }