|
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 } |