|
1 // Copyright (c) 2008-2010 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 /** |
|
17 @file |
|
18 */ |
|
19 |
|
20 |
|
21 #include <e32std.h> |
|
22 #include <e32math.h> |
|
23 #include <w32std.h> |
|
24 #include <w32debug.h> |
|
25 #include "teflogextensions.h" |
|
26 #include "t_wsdynamicreswinbase.h" |
|
27 #include "globalsettings.h" |
|
28 #include <bitdraw.h> |
|
29 #include <bitdrawinterfaceid.h> |
|
30 #include <u32hal.h> |
|
31 #include <dispchannel.h> |
|
32 #include <graphics/displaycontrol.h> |
|
33 |
|
34 #if (!defined(K_DISPLAY_CH_MAJOR_VERSION_NUMBER) && !defined(K_DISPLAY_CH_MINOR_VERSION_NUMBER)) |
|
35 #define MODE_CHANGE_BASE_FUNCTIONALITY_NOT_PRESENT_IN_HEADER |
|
36 #endif |
|
37 |
|
38 _LIT(KMonospaceTestFontTypefaceName,"Arial"); |
|
39 const TInt KMaxFontSize = 150; |
|
40 TBool CWsDynamicResWinBase::iTransparencyEnabled=EFalse; |
|
41 |
|
42 CWsDynamicResWinBase::CWsDynamicResWinBase(): |
|
43 iDoTearDown(EFalse), |
|
44 iSession(TGlobalSettings::Instance().iScreen) |
|
45 { |
|
46 } |
|
47 |
|
48 void CWsDynamicResWinBase::SetupL() |
|
49 { |
|
50 SetupL(EFalse); |
|
51 } |
|
52 CActiveScheduler CWsDynamicResWinBase::iScheduler; |
|
53 |
|
54 void CWsDynamicResWinBase::SetupL(TBool aUseOtherScreenForInfo) |
|
55 { |
|
56 if (CActiveScheduler::Current()!=&iScheduler) |
|
57 { |
|
58 new (&iScheduler) CActiveScheduler; |
|
59 CActiveScheduler::Install(&iScheduler); |
|
60 } |
|
61 iDoTearDown=ETrue; |
|
62 iRed.SetInternal(0xFFFF0000); |
|
63 iGreen.SetInternal(0xFF00FF00); |
|
64 iBlue.SetInternal(0xFF0000FF); |
|
65 iCyan.SetInternal(0xFF00FFFF); |
|
66 iMagenta.SetInternal(0xFFFF00FF); |
|
67 iYellow.SetInternal(0xFFFFFF00); |
|
68 iWhite.SetInternal(0xFFFFFFFF); |
|
69 iLastGceHoleColor.SetInternal(0); |
|
70 TITLE_BACKGROUND=iCyan; |
|
71 COMPARE_BACKGROUND=iBlue; |
|
72 |
|
73 ASSERT_EQUALS_X(iSession.Connect(), KErrNone); |
|
74 |
|
75 {//Stolen from TAuto CloseAllPanicWindows() |
|
76 TInt idFocus = iSession.GetFocusWindowGroup(); |
|
77 TWsEvent event; |
|
78 event.SetType(EEventKey); //EEventKeyDown |
|
79 TKeyEvent *keyEvent = event.Key(); |
|
80 keyEvent->iCode = EKeyEscape; |
|
81 keyEvent->iScanCode = EStdKeyEscape; |
|
82 keyEvent->iModifiers = 0; |
|
83 TInt theLimit = 50; |
|
84 while(idFocus != NULL && (theLimit-- > 0)) |
|
85 { |
|
86 iSession.SendEventToAllWindowGroups(event); |
|
87 TInt idNewFocus = iSession.GetFocusWindowGroup(); |
|
88 if (idNewFocus!=idFocus) |
|
89 { |
|
90 INFO_PRINTF1(_L("A window was closed [probably a panic box from the previous test].")); |
|
91 } |
|
92 idFocus=idNewFocus; |
|
93 } |
|
94 } |
|
95 TInt err = KErrNone; |
|
96 |
|
97 TRAP(err, iScreenDevice = new (ELeave) CWsScreenDevice(iSession)); |
|
98 PRINT_ON_ERROR2_L(err, _L("Failed to create screen device: %d"), err); |
|
99 ASSERT_EQUALS_X(iScreenDevice->Construct(TGlobalSettings::Instance().iScreen), KErrNone); |
|
100 iDisplayMode = iScreenDevice->DisplayMode(); // Get default display mode |
|
101 |
|
102 CheckAndConnectScreen(); |
|
103 |
|
104 TRAP(err, iGc = new (ELeave) CWindowGc(iScreenDevice)); |
|
105 PRINT_ON_ERROR2_L(err, _L("Failed to create graphics context: %d"), err); |
|
106 ASSERT_EQUALS_X(iGc->Construct(), KErrNone); |
|
107 |
|
108 iGroup = RWindowGroup(iSession); |
|
109 ASSERT_EQUALS_X(iGroup.Construct(++iWindowHandle,iScreenDevice), KErrNone); |
|
110 iGroup.SetOrdinalPositionErr(0, KPasswordWindowGroupPriority - 1); // Added code ---- Fastpath |
|
111 iSession.Flush(); |
|
112 |
|
113 if (aUseOtherScreenForInfo) |
|
114 { |
|
115 if (iSession.NumberOfScreens()>1) |
|
116 { //Create server objects for info windows to appear on alternate screen |
|
117 TInt alternateScreenNum=iSession.NumberOfScreens()-1; |
|
118 if (TGlobalSettings::Instance().iScreen==alternateScreenNum) |
|
119 { //Alternate screen is last screen, or first screen if that is being tested. |
|
120 alternateScreenNum=0; |
|
121 } |
|
122 |
|
123 TRAP(err, iInfoScreenDevice = new (ELeave) CWsScreenDevice(iSession)); |
|
124 PRINT_ON_ERROR2_L(err, _L("Failed to create second screen device: %d"), err); |
|
125 ASSERT_EQUALS_X(iInfoScreenDevice->Construct(alternateScreenNum), KErrNone); |
|
126 |
|
127 TRAP(err, iInfoGc = new (ELeave) CWindowGc(iInfoScreenDevice)); |
|
128 PRINT_ON_ERROR2_L(err, _L("Failed to create second graphics context: %d"), err); |
|
129 ASSERT_EQUALS_X(iInfoGc->Construct(), KErrNone); |
|
130 |
|
131 iInfoGroupInstance = RWindowGroup(iSession); |
|
132 ASSERT_EQUALS_X(iInfoGroupInstance.Construct(++iWindowHandle,iInfoScreenDevice), KErrNone); |
|
133 iInfoGroup=&iInfoGroupInstance; |
|
134 } |
|
135 else |
|
136 { //If alternate screen is not available then no text or compare windows should be created! |
|
137 iInfoScreenDevice=iScreenDevice; //it is "convenient" for the device to still be good. |
|
138 iInfoGc=NULL; |
|
139 iInfoGroup=NULL; |
|
140 } |
|
141 } |
|
142 else |
|
143 { // |
|
144 iInfoScreenDevice=iScreenDevice; |
|
145 iInfoGc=iGc; |
|
146 iInfoGroup=&iGroup; |
|
147 } |
|
148 |
|
149 if (iInfoGroup && iInfoGc) |
|
150 { |
|
151 // Add a plain background window to obscure anything else that |
|
152 // happens to be behind the test. Setting this window's display mode is also |
|
153 // used to set the screen device display mode, and hence the composition |
|
154 // mode: alpha or chroma key. |
|
155 iBackground = RBlankWindow(iSession); |
|
156 ASSERT_EQUALS_X(iBackground.Construct(*iInfoGroup, ++iWindowHandle), KErrNone); |
|
157 |
|
158 iBackground.SetOrdinalPosition(100); // Behind anything else in this group. |
|
159 iBackground.SetColor(TRgb(iWhite)); |
|
160 //iBackground.SetExtent(TPoint(-1000,-1000),TSize(3000,3000)); |
|
161 iBackground.Activate(); |
|
162 iBackground.SetVisible(ETrue); |
|
163 } |
|
164 iSession.Flush(); |
|
165 |
|
166 RWindow testTrans(iSession); |
|
167 ASSERT_EQUALS_X(testTrans.Construct(iGroup, ++iWindowHandle), KErrNone); |
|
168 iTransparencyEnabled=(testTrans.SetTransparencyFactor(iWhite)==KErrNone); |
|
169 if (iTransparencyEnabled) |
|
170 { |
|
171 TTestName testName; |
|
172 testName.Format(_L("Screen %i, depth %i: Found Trans Man"), |
|
173 TGlobalSettings::Instance().iScreen |
|
174 ); |
|
175 UpdateTitleWindowL(testName,KMaxInfoLines-1); |
|
176 } |
|
177 else |
|
178 { |
|
179 TTestName testName; |
|
180 testName.Format(_L("Screen %i, depth %i: No Trans Man"), |
|
181 TGlobalSettings::Instance().iScreen |
|
182 ); |
|
183 UpdateTitleWindowL(testName,KMaxInfoLines-1); |
|
184 } |
|
185 testTrans.Close(); |
|
186 } |
|
187 |
|
188 |
|
189 void CWsDynamicResWinBase::CheckAndConnectScreen() |
|
190 { |
|
191 if (TGlobalSettings::Instance().iDisconnected) //set from script file to match wsini keyword SIMULATE_STARTUP_DISCONNECTED |
|
192 { |
|
193 //Verify that the display really is disconnected |
|
194 ASSERT_TRUE_X(iScreenDevice != NULL); |
|
195 MDisplayControl* interface = static_cast<MDisplayControl*>(iScreenDevice->GetInterface(MDisplayControl::ETypeId)); |
|
196 ASSERT_TRUE_X(interface != NULL); |
|
197 RArray<MDisplayControl::TResolution> resolutions; |
|
198 const TInt err = interface->GetResolutions(resolutions); |
|
199 ASSERT_EQUALS_X(err, KErrDisconnected); |
|
200 resolutions.Close(); |
|
201 } |
|
202 |
|
203 #ifndef MODE_CHANGE_BASE_FUNCTIONALITY_NOT_PRESENT_IN_HEADER |
|
204 //make sure display is attached to screen (only if I/F is available at compile time...) |
|
205 TInt displayState = ENormalResolution; |
|
206 UserSvr::HalFunction(EHalGroupDisplay | (TGlobalSettings::Instance().iScreen<<16), EDisplayHalSetDisplayState, &displayState, NULL); |
|
207 Pause(200); |
|
208 #endif |
|
209 |
|
210 if (TGlobalSettings::Instance().iDisconnected) |
|
211 { |
|
212 //Verify that the display now is connected |
|
213 MDisplayControl* interface = static_cast<MDisplayControl*>(iScreenDevice->GetInterface(MDisplayControl::ETypeId)); |
|
214 RArray<MDisplayControl::TResolution> resolutions; |
|
215 const TInt err = interface->GetResolutions(resolutions); |
|
216 ASSERT_EQUALS_X(err, KErrNone); |
|
217 const_cast<TGlobalSettings&>(TGlobalSettings::Instance()).iDisconnected = EFalse; |
|
218 resolutions.Close(); |
|
219 } |
|
220 } |
|
221 |
|
222 /** |
|
223 Common tear down code for all tests. |
|
224 |
|
225 Windows, group and session created are closed. Screen device is destroyed. |
|
226 Surfaces, manager and update session are closed. |
|
227 */ |
|
228 void CWsDynamicResWinBase::TearDownL() |
|
229 { |
|
230 iDoTearDown=EFalse; |
|
231 if (iInfoGc!=iGc) |
|
232 delete iInfoGc; |
|
233 delete iGc; |
|
234 if (iInfoScreenDevice!=iScreenDevice) |
|
235 delete iInfoScreenDevice; |
|
236 delete iScreenDevice; |
|
237 |
|
238 iGroup.Close(); |
|
239 if (iInfoGroupInstance.WsHandle()) |
|
240 iInfoGroupInstance.Close(); |
|
241 iSession.Flush(); |
|
242 iSession.Close(); |
|
243 } |
|
244 /** |
|
245 * Note that this is not the ideal mechanism. |
|
246 * A derived class may thinks its TearDown is safe to do from delete, but in the class it is derived from it may not be safe |
|
247 **/ |
|
248 void CWsDynamicResWinBase::TearDownFromDeleteL() |
|
249 { |
|
250 CWsDynamicResWinBase::TearDownL(); //Explicitly call the non-derived implementation. |
|
251 } |
|
252 |
|
253 CWsDynamicResWinBase::~CWsDynamicResWinBase() |
|
254 { |
|
255 if (iDoTearDown) |
|
256 TearDownFromDeleteL(); //This mechanism is not entirely clean to use. |
|
257 } |
|
258 /** |
|
259 Pause for the given number of milliseconds. |
|
260 |
|
261 @param aMilliseconds Time to wait in milliseconds. |
|
262 */ |
|
263 void CWsDynamicResWinBase::Pause(TInt aMilliseconds) |
|
264 { |
|
265 User::After(TTimeIntervalMicroSeconds32(aMilliseconds * 1000)); |
|
266 } |
|
267 // This handles any non-member uses of the extended ASSERT_XXX macros |
|
268 void TefUnitFailLeaveL() |
|
269 { |
|
270 |
|
271 User::Leave(KErrTEFUnitFail); |
|
272 } |
|
273 /** |
|
274 * side-effect: log the state info just before I leave! |
|
275 * Note that this only logs intentional assertion failures. |
|
276 * Fails due to panics or throws won't log this info. |
|
277 **/ |
|
278 void CWsDynamicResWinBase::TefUnitFailLeaveL() |
|
279 { |
|
280 for (TInt line=0;line<KMaxInfoLines;line++) |
|
281 if (iTestInfo[line].Length()) |
|
282 Logger().LogExtra((TText8*)"Test state at fail - line",line, ESevrAll, iTestInfo[line]); |
|
283 |
|
284 User::Leave(KErrTEFUnitFail); |
|
285 } |
|
286 |
|
287 /** Creates the LHS info window, annd a middle window to display a representation of the expected result. |
|
288 * Also sets up a rectangle representing the space on the right to be used for the test |
|
289 * @param aTitle The title to display on the info window |
|
290 * @param aDetail Optional text to display on the first line under the title |
|
291 **/ |
|
292 void CWsDynamicResWinBase::MakeTitleAndCompareWindowsL(TRefByValue<const TDesC16> aTitle,TRefByValue<const TDesC16> aDetail) |
|
293 { |
|
294 iTestName=aTitle; |
|
295 iTestInfo[0]=aDetail; |
|
296 |
|
297 TRect screenSize(iInfoScreenDevice->SizeInPixels()); |
|
298 TPoint oneThird(screenSize.iBr.iX/3,screenSize.iBr.iY/3); |
|
299 TRect winSize(0,0,oneThird.iX,oneThird.iY); |
|
300 |
|
301 if (oneThird.iX>oneThird.iY) |
|
302 { |
|
303 oneThird.iY=0; |
|
304 winSize.iBr.iY=screenSize.iBr.iY; |
|
305 } |
|
306 else |
|
307 { |
|
308 oneThird.iX=0; |
|
309 winSize.iBr.iX=screenSize.iBr.iX; |
|
310 } |
|
311 winSize.Shrink(5,5); |
|
312 |
|
313 if (iInfoGc) |
|
314 { |
|
315 iTitle=RWindow(iSession); |
|
316 ASSERT_EQUALS_X(iTitle.Construct(*iInfoGroup, ++iWindowHandle), KErrNone); |
|
317 iTitle.SetBackgroundColor(iCyan); |
|
318 iTitle.SetExtent(winSize.iTl,winSize.Size()); |
|
319 iTitle.Activate(); |
|
320 |
|
321 RepaintTitleWindowL(); |
|
322 iTitle.SetVisible(ETrue); |
|
323 |
|
324 winSize.Move(oneThird); |
|
325 iCompare=RWindow(iSession); |
|
326 ASSERT_EQUALS_X(iCompare.Construct(*iInfoGroup, ++iWindowHandle), KErrNone); |
|
327 iCompare.SetBackgroundColor(COMPARE_BACKGROUND); |
|
328 iCompare.SetExtent(winSize.iTl,winSize.Size()); |
|
329 iCompare.Activate(); |
|
330 iCompare.BeginRedraw(); |
|
331 ActivateWithWipe(iInfoGc,iCompare,COMPARE_BACKGROUND); |
|
332 |
|
333 TFontSpec fspec(KMonospaceTestFontTypefaceName,KMaxFontSize); |
|
334 CFont *font=NULL; |
|
335 ASSERT_EQUALS(iScreenDevice->GetNearestFontToDesignHeightInTwips(font,fspec),KErrNone); |
|
336 iInfoGc->UseFont(font); |
|
337 iInfoGc->DrawText(_L("Simulation"),winSize.Size(),winSize.Size().iHeight-5,iGc->ECenter); |
|
338 |
|
339 iInfoGc->Deactivate(); |
|
340 iCompare.EndRedraw(); |
|
341 iCompare.SetVisible(ETrue); |
|
342 if (iScreenDevice!=iInfoScreenDevice) |
|
343 { |
|
344 winSize.Move(-oneThird); |
|
345 } |
|
346 else |
|
347 { |
|
348 winSize.Move(oneThird); |
|
349 } |
|
350 } |
|
351 else |
|
352 { |
|
353 winSize=iScreenDevice->SizeInPixels(); |
|
354 } |
|
355 |
|
356 iTestPos=winSize; |
|
357 iTestPointCentre=winSize.Center(); |
|
358 iCenteredFrontWinRect=winSize; |
|
359 iCenteredFrontWinRect.Shrink(winSize.Size().iWidth/3,winSize.Size().iHeight/3); |
|
360 |
|
361 } |
|
362 /** Makes the compare window larger by covering the test window area as well. |
|
363 * Copes with vertically aligned screens, but will be naughty if called multiple times!!! |
|
364 * @param aGoLarger If set false, resets the size back. |
|
365 **/ |
|
366 void CWsDynamicResWinBase::LargerCompareWindow(TBool aGoLarger) |
|
367 { |
|
368 TPoint currPos=iCompare.AbsPosition(); |
|
369 TSize currSize=iCompare.Size(); |
|
370 if (currPos.iX<currPos.iY) |
|
371 { |
|
372 if (aGoLarger) |
|
373 currSize.iHeight<<=1; |
|
374 else |
|
375 currSize.iHeight>>=1; |
|
376 } |
|
377 else |
|
378 { |
|
379 if (aGoLarger) |
|
380 currSize.iWidth<<=1; |
|
381 else |
|
382 currSize.iWidth>>=1; |
|
383 } |
|
384 iCompare.SetSize(currSize); |
|
385 } |
|
386 |
|
387 |
|
388 /** Puts a line of text on the LHS window. |
|
389 * Repaints the window. The line of text will also be shown in the log if the test fails. |
|
390 * @param aDetail The text to display |
|
391 * @param aIndex The row number to display at |
|
392 **/ |
|
393 void CWsDynamicResWinBase::UpdateTitleWindowL(TRefByValue<const TDesC16> aDetail,TInt aIndex) |
|
394 { |
|
395 ASSERT(aIndex>=0 && aIndex<KMaxInfoLines); |
|
396 iTestInfo[aIndex]=aDetail; |
|
397 |
|
398 RepaintTitleWindowL(); |
|
399 |
|
400 } |
|
401 /** Activate the GC onto the Window. |
|
402 * In non-transparent mode it also performs a wipe background as the WServ system does not necessarily do this. |
|
403 * @param aGc The GC to associate |
|
404 * @param aWin The window to associate |
|
405 * @param aColor The color to use as the wipe. Default is transparent, which means no wipe. |
|
406 **/ |
|
407 TBool CWsDynamicResWinBase::ActivateWithWipe(CWindowGc* aGc,RWindow& aWin,TRgb aColor) |
|
408 { |
|
409 aGc->Activate(aWin); |
|
410 aGc->SetBrushColor(aColor); |
|
411 aGc->SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
412 if (aColor!=TRgb(0,0) && !iTransparencyEnabled) //presume that all redraw-stored windows will draw background |
|
413 { |
|
414 aGc->Clear(); |
|
415 return ETrue; //window was cleared |
|
416 } |
|
417 return EFalse; |
|
418 } |
|
419 |
|
420 CWindowGc* CWsDynamicResWinBase::GcForWindow(RWindow& aWin) |
|
421 { |
|
422 if (aWin.WsHandle()==NULL) |
|
423 return NULL; //can't activate uninitialised window. |
|
424 CWindowGc* gc=iGc; |
|
425 if (iGc!=iInfoGc) |
|
426 if (&aWin==&iCompare || &aWin==&iTitle) |
|
427 gc=iInfoGc; |
|
428 else if (iInfoGroup && aWin.WindowGroupId()==iInfoGroup->WindowGroupId()) |
|
429 gc=iInfoGc; |
|
430 return gc; |
|
431 } |
|
432 /** Activates an appropriate predefined GC on the specified window and wipes the background if necessary. |
|
433 * @param aWin The window to wipe |
|
434 * @param aColor The colour to wipe with (if necessary) |
|
435 * @return the GC to use for drawing and deactivate at end. This may be NULL if the window is not "live" |
|
436 **/ |
|
437 CWindowGc* CWsDynamicResWinBase::BeginActivateWithWipe(TBool aInvalidate,RWindow& aWin,TRgb aColor) |
|
438 { |
|
439 CWindowGc* gc=GcForWindow(aWin); |
|
440 iSession.Flush(); |
|
441 if (gc==NULL) |
|
442 return gc; //can't activate uninitialised window. |
|
443 if (aInvalidate) |
|
444 aWin.Invalidate(); |
|
445 iSession.Flush(); |
|
446 aWin.BeginRedraw(); |
|
447 iSession.Flush(); |
|
448 ActivateWithWipe(gc,aWin,aColor); |
|
449 return gc; |
|
450 } |
|
451 |
|
452 /** Activates an appropriate predefined GC on the specified window and wipes the background if necessary. |
|
453 * @param aWin The window to wipe |
|
454 * @param aColor The colour to wipe with (if necessary) |
|
455 * @return the GC to use for drawing and deactivate at end. This may be NULL if the window is not "live" |
|
456 **/ |
|
457 CWindowGc* CWsDynamicResWinBase::BeginActivateWithWipe(TBool aInvalidate,TRect aRect,RWindow& aWin,TRgb aColor) |
|
458 { |
|
459 if (aWin.WsHandle()==NULL) |
|
460 return NULL; //can't activate uninitialised window. |
|
461 if (aInvalidate) |
|
462 aWin.Invalidate(aRect); |
|
463 aWin.BeginRedraw(aRect); |
|
464 CWindowGc* gc=iGc; |
|
465 if (iGc!=iInfoGc) |
|
466 if (&aWin==&iCompare || &aWin==&iTitle) |
|
467 gc=iInfoGc; |
|
468 else if (aWin.WindowGroupId()==iInfoGroup->WindowGroupId()) |
|
469 gc=iInfoGc; |
|
470 ActivateWithWipe(gc,aWin,aColor); |
|
471 return gc; |
|
472 } |
|
473 |
|
474 TBool CWsDynamicResWinBase::InvalidateRegion(const TRegion& aRegion,RWindow& aWin) |
|
475 { |
|
476 if (aWin.WsHandle()==NULL) |
|
477 return false; //can't activate uninitialised window. |
|
478 for (TInt ii = 0; ii < aRegion.Count(); ii++) |
|
479 { |
|
480 aWin.Invalidate(aRegion[ii]); |
|
481 } |
|
482 return true; |
|
483 } |
|
484 |
|
485 CWindowGc* CWsDynamicResWinBase::BeginActivateWithWipe(const TRegion& aRegion,RWindow& aWin,TRgb aColor) |
|
486 { |
|
487 if (!InvalidateRegion(aRegion,aWin)) |
|
488 return NULL; //can't activate uninitialised window. |
|
489 |
|
490 aWin.BeginRedraw(); |
|
491 CWindowGc* gc=iGc; |
|
492 if (iGc!=iInfoGc) |
|
493 if (&aWin==&iCompare || &aWin==&iTitle) |
|
494 gc=iInfoGc; |
|
495 else if (aWin.WindowGroupId()==iInfoGroup->WindowGroupId()) |
|
496 gc=iInfoGc; |
|
497 ActivateWithWipe(gc,aWin,aColor); |
|
498 return gc; |
|
499 } |
|
500 |
|
501 |
|
502 /** Paints the LHS window with rows of text. |
|
503 * |
|
504 **/ |
|
505 void CWsDynamicResWinBase::RepaintTitleWindowL() |
|
506 { |
|
507 if (iTitle.WsHandle()) |
|
508 { |
|
509 iTitle.Invalidate(); |
|
510 |
|
511 iTitle.BeginRedraw(); |
|
512 ActivateWithWipe(iInfoGc,iTitle,TITLE_BACKGROUND); |
|
513 iInfoGc->SetUnderlineStyle(EUnderlineOn); |
|
514 TSize winSize=iTitle.Size(); |
|
515 TRect textRect(winSize); |
|
516 textRect.iBr.iY/=4; |
|
517 TFontSpec fspec(KMonospaceTestFontTypefaceName,KMaxFontSize); |
|
518 CFont *font=NULL; |
|
519 ASSERT_EQUALS(iInfoScreenDevice->GetNearestFontToDesignHeightInTwips(font,fspec),KErrNone); |
|
520 iInfoGc->UseFont(font); |
|
521 iInfoGc->DrawText(iTestName,textRect,textRect.iBr.iY/2,iGc->ECenter); |
|
522 iInfoGc->SetUnderlineStyle(EUnderlineOff); |
|
523 textRect.iTl.iY=textRect.iBr.iY; |
|
524 TInt rowHeight=winSize.iHeight*3/(4*(KMaxInfoLines+1)); |
|
525 textRect.iBr.iY+=rowHeight; |
|
526 for (TInt index=0;index<KMaxInfoLines;index++) |
|
527 { |
|
528 if (iTestInfo[index].Length()) |
|
529 iInfoGc->DrawText(iTestInfo[index],textRect,textRect.Size().iHeight*3/4,iInfoGc->ECenter); |
|
530 textRect.Move(0,rowHeight); |
|
531 } |
|
532 iInfoGc->DiscardFont(); |
|
533 iInfoGc->Deactivate(); |
|
534 iTitle.EndRedraw(); |
|
535 iInfoScreenDevice->ReleaseFont(font); |
|
536 |
|
537 iSession.Flush(); |
|
538 iSession.Finish(); |
|
539 } |
|
540 } |
|
541 |
|
542 /** Useful test culled from other GCE test classes. |
|
543 * |
|
544 * |
|
545 * |
|
546 **/ |
|
547 TBool CWsDynamicResWinBase::DisplayHasAlpha() const |
|
548 { |
|
549 return (iDisplayMode == EColor16MA || iDisplayMode == EColor16MAP); |
|
550 } |
|
551 /** Test using an indipendent method that GCE version of WServ is running |
|
552 * This method can only be called after the testcase is started |
|
553 * |
|
554 * @return true if WServ version is GCE technology, false if legacy technology |
|
555 **/ |
|
556 TBool CWsDynamicResWinBase::GCEIsSupported() const |
|
557 { |
|
558 CFbsDrawDevice* screenDevice=NULL; |
|
559 TDisplayMode displayMode=iScreenDevice->DisplayMode(); |
|
560 TRAPD(err, screenDevice = CFbsDrawDevice::NewScreenDeviceL(TGlobalSettings::Instance().iScreen, displayMode)); |
|
561 TBool rv=EFalse; |
|
562 if(err == KErrNone) |
|
563 { |
|
564 TAny* p=NULL; |
|
565 rv=(screenDevice->GetInterface(KSurfaceInterfaceID, p)==KErrNone); |
|
566 delete screenDevice; |
|
567 } |
|
568 return rv; |
|
569 } |
|
570 /** Test using an indipendent method that GCE version of WServ is running |
|
571 * This method can be called at any time, even by external code, but creates temporary window session objects |
|
572 * |
|
573 * @return true if WServ version is GCE technology, false if legacy technology |
|
574 **/ |
|
575 TBool CWsDynamicResWinBase::GCEIsSupportedStatic() |
|
576 { |
|
577 CFbsDrawDevice* screenDevice=NULL; |
|
578 RWsSession session; |
|
579 if (session.Connect()!=KErrNone) |
|
580 { |
|
581 return EFalse; |
|
582 } |
|
583 TDisplayMode displayMode=ENone; |
|
584 {CWsScreenDevice screen(session); |
|
585 if (screen.Construct(TGlobalSettings::Instance().iScreen)!=KErrNone) |
|
586 { |
|
587 return EFalse; |
|
588 } |
|
589 displayMode=screen.DisplayMode(); |
|
590 }//screen destroyed |
|
591 TRAPD(err, screenDevice = CFbsDrawDevice::NewScreenDeviceL(TGlobalSettings::Instance().iScreen, displayMode)); |
|
592 TBool rv=EFalse; |
|
593 if(err == KErrNone) |
|
594 { |
|
595 TAny* p=NULL; |
|
596 rv=(screenDevice->GetInterface(KSurfaceInterfaceID, p)==KErrNone); |
|
597 delete screenDevice; |
|
598 } |
|
599 return rv; |
|
600 }//session destroyed |
|
601 /** |
|
602 Use the full-screen background window to select a display mode that doesn't use |
|
603 alpha (anything other than EColor16MA or EColor16MAP). Record the mode for use |
|
604 in setting all other windows. |
|
605 @return ETrue if an appropriate mode was selected, EFalse otherwise. |
|
606 */ |
|
607 TBool CWsDynamicResWinBase::SelectChromaCompositionMode() |
|
608 { |
|
609 // Request EColor64K, but as long as the actual mode doesn't use alpha, it |
|
610 // doesn't matter too much which one is used. |
|
611 if (iInfoGc==iGc) |
|
612 { |
|
613 iDisplayMode = (TDisplayMode)iBackground.SetRequiredDisplayMode(EColor64K); |
|
614 iSession.Flush(); // Force switching to the display mode. |
|
615 } |
|
616 return !DisplayHasAlpha(); |
|
617 } |
|
618 /** Returns the colour used by WServ to paint holes in UI layer to reveal the GCE behind. |
|
619 * The window should have a surface attached. |
|
620 * If the method is called after the surface has been detached or the window was removed then |
|
621 * the previous recorded hole color is returned. |
|
622 **/ |
|
623 TRgb CWsDynamicResWinBase::GceHoleColor( RWindowBase& aWin)const |
|
624 { |
|
625 if (aWin.WsHandle()==NULL) |
|
626 { |
|
627 return iLastGceHoleColor; |
|
628 } |
|
629 TRgb retVal=aWin.KeyColor(); |
|
630 if (retVal==TRgb(0,0)) |
|
631 { |
|
632 return iLastGceHoleColor; |
|
633 } |
|
634 else |
|
635 { |
|
636 iLastGceHoleColor=retVal; |
|
637 return retVal; |
|
638 } |
|
639 } |
|
640 |
|
641 |
|
642 /** |
|
643 Use the full-screen background window to select a display mode that can use |
|
644 alpha (either EColor16MA or EColor16MAP). Record the mode for use in setting all |
|
645 other windows. |
|
646 @return ETrue if an appropriate mode was selected, EFalse otherwise. |
|
647 */ |
|
648 TBool CWsDynamicResWinBase::SelectAlphaCompositionMode(TDisplayMode aMode) |
|
649 { |
|
650 // Request EColor16MA, but as long as the actual mode can use alpha, it |
|
651 // doesn't matter too much which one is used. |
|
652 if (iInfoGc==iGc) |
|
653 { |
|
654 iDisplayMode = (TDisplayMode)iBackground.SetRequiredDisplayMode(aMode); |
|
655 iSession.Flush(); // Force switching to the display mode. |
|
656 } |
|
657 return DisplayHasAlpha(); |
|
658 } |
|
659 |
|
660 /** |
|
661 * Interesting UI pattern used by other GCE tests. |
|
662 * |
|
663 * |
|
664 **/ |
|
665 void CWsDynamicResWinBase::DrawUIContent(RWindow& aWindow) |
|
666 { |
|
667 aWindow.BeginRedraw(); |
|
668 CWindowGc* gc=(&aWindow==&iCompare)?iInfoGc:iGc; |
|
669 |
|
670 gc->Activate(aWindow); |
|
671 |
|
672 TBool hasAlpha = DisplayHasAlpha(); |
|
673 |
|
674 // Draw a red-green graduated box in the central portion of the window, |
|
675 // with alpha if available. |
|
676 TPoint start; |
|
677 TPoint end; |
|
678 TInt halfW = KSurfaceWidth / 2; |
|
679 TInt quarterW = halfW / 2; |
|
680 TInt halfH = KSurfaceHeight / 2; |
|
681 TInt quarterH = halfH / 2; |
|
682 |
|
683 // Set constant ordinals for non-alpha case. |
|
684 start.iX = quarterW; |
|
685 end.iX = quarterW + halfW; |
|
686 |
|
687 for (TInt yy = 0; yy < halfH; yy++) |
|
688 { |
|
689 TInt yval = yy * 255 / (halfH - 1); |
|
690 start.iY = yy + quarterH; |
|
691 end.iY = start.iY; |
|
692 |
|
693 if (hasAlpha) |
|
694 { |
|
695 for (TInt xx = 0; xx < halfW; xx++) |
|
696 { |
|
697 TInt xval = xx * 255 / (halfW - 1); |
|
698 start.iX = xx + quarterW; |
|
699 end.iX = start.iX + 1; |
|
700 gc->SetPenColor(TRgb(yval, 255 - yval, 0, xval)); |
|
701 gc->DrawLine(start, end); |
|
702 } |
|
703 } |
|
704 else |
|
705 { |
|
706 gc->SetPenColor(TRgb(yval, 255 - yval, 0)); |
|
707 gc->DrawLine(start, end); |
|
708 } |
|
709 } |
|
710 |
|
711 gc->Deactivate(); |
|
712 aWindow.EndRedraw(); |
|
713 } |
|
714 |
|
715 /** |
|
716 * Causes the given window to be redrawn. |
|
717 * Doesn't draw anything except the background wipe, when the transparency manager hasn't |
|
718 * |
|
719 **/ |
|
720 void CWsDynamicResWinBase::DrawPlainUI(RWindow& aWindow,TBool aInvalidate,TRgb aWipeColor) |
|
721 { |
|
722 if (CWindowGc* gc=BeginActivateWithWipe(aInvalidate,aWindow,aWipeColor)) |
|
723 { |
|
724 //actually does nothing! |
|
725 gc->Deactivate(); |
|
726 aWindow.EndRedraw(); |
|
727 } |
|
728 } |
|
729 /** |
|
730 * Interesting UI pattern used by other GCE tests. |
|
731 * |
|
732 * |
|
733 **/ |
|
734 void CWsDynamicResWinBase::DrawCross(RWindow& aWindow, TRgb aColor, TInt aThickness) |
|
735 { |
|
736 aWindow.BeginRedraw(); |
|
737 CWindowGc* gc=(&aWindow==&iCompare)?iInfoGc:iGc; |
|
738 gc->Activate(aWindow); |
|
739 |
|
740 // Draw a red diagonal cross in the window. |
|
741 gc->SetPenColor(aColor); |
|
742 gc->SetPenSize(TSize(aThickness, aThickness)); |
|
743 gc->DrawLine(TPoint(0, 0), TPoint(KSurfaceWidth, KSurfaceHeight)); |
|
744 gc->DrawLine(TPoint(KSurfaceWidth, 0), TPoint(0, KSurfaceHeight)); |
|
745 |
|
746 gc->Deactivate(); |
|
747 aWindow.EndRedraw(); |
|
748 } |
|
749 |
|
750 /** |
|
751 * Checks the RGB value |
|
752 * |
|
753 * |
|
754 **/ |
|
755 void CWsDynamicResWinBase::TestPixelL(TPoint aPt, TRgb aColor, TBool aMatch) |
|
756 { |
|
757 TRect screenArea(iScreenDevice->SizeInPixels()); |
|
758 if (aPt.iX < screenArea.iTl.iX) |
|
759 { |
|
760 aPt.iX = screenArea.iTl.iX; |
|
761 } |
|
762 else if (aPt.iX >= screenArea.iBr.iX) |
|
763 { |
|
764 aPt.iX = screenArea.iBr.iX - 1; |
|
765 } |
|
766 if (aPt.iY < screenArea.iTl.iY) |
|
767 { |
|
768 aPt.iY = screenArea.iTl.iY; |
|
769 } |
|
770 else if (aPt.iY >= screenArea.iBr.iY) |
|
771 { |
|
772 aPt.iY = screenArea.iBr.iY - 1; |
|
773 } |
|
774 |
|
775 TRgb pixel; |
|
776 iScreenDevice->GetPixel(pixel, aPt); |
|
777 if (aMatch) |
|
778 { |
|
779 ASSERT_EQUALS_X(pixel.Internal(), aColor.Internal()); |
|
780 } |
|
781 else |
|
782 { |
|
783 ASSERT_NOT_EQUALS_X(pixel.Internal(), aColor.Internal()); |
|
784 } |
|
785 } |
|
786 |
|
787 struct CountColour |
|
788 { |
|
789 TRgb iColor; |
|
790 TInt iCount; |
|
791 TBool operator < (const CountColour& aRhs)const |
|
792 { return iColor.Value()<aRhs.iColor.Value(); } |
|
793 |
|
794 CountColour(TRgb aColor,TInt aCount=0): |
|
795 iColor(aColor),iCount(aCount) {} |
|
796 |
|
797 CountColour(const CountColour& aRhs): |
|
798 iColor(aRhs.iColor),iCount(aRhs.iCount) {} |
|
799 }; |
|
800 |
|
801 void LogColorL(TRgb aPixel,RArray<CountColour>& aColors) |
|
802 { |
|
803 //I am sure one of the find methods would do this, but life is too short! |
|
804 TInt existingIndex; |
|
805 for (existingIndex=0;existingIndex<aColors.Count();existingIndex++) |
|
806 if (aColors[existingIndex].iColor==aPixel) |
|
807 break; |
|
808 if (existingIndex==aColors.Count()) |
|
809 aColors.AppendL(CountColour(aPixel,1)); |
|
810 else |
|
811 aColors[existingIndex].iCount++; |
|
812 } |
|
813 |
|
814 /** |
|
815 * Tests the outline of the given rectangle to verify that it has the expected inner and outer colors |
|
816 * There may be a limited number of other colors present. |
|
817 * If the given count of other colors is exceeded then false is returned |
|
818 * If the majority of inner and outer edge pixels are not the given colors then returns false |
|
819 * If the colors are repeated on inside and outside then returns false |
|
820 * If there are corners then the insides of the corners are also check for outside color |
|
821 * Note that the right and bottom edge coordinates are outside the rectangle. |
|
822 * Note that I am not performing any safety clipping at present. The rectangle must be on-screen! |
|
823 * A negative value for corner size indicates that the window may or may not have corners that size. |
|
824 * Only leaves if fatal memory condition! |
|
825 **/ |
|
826 TBool CWsDynamicResWinBase::TestRectL(TRect aRect,TRgb aInnerColor,TInt aOtherInnerColors,TRgb aOuterColor,TInt aOtherOuterColors,TInt aExpectedCornerSize) |
|
827 { |
|
828 if (aRect.iTl.iX<=0 || aRect.iTl.iY<=0) |
|
829 return ETrue; //can't perform the test against the outside of the screen |
|
830 //quantise the expectation based on the current mode. |
|
831 TDisplayMode displayMode=iScreenDevice->DisplayMode(); |
|
832 switch (displayMode) |
|
833 { |
|
834 case EColor4K: |
|
835 aInnerColor=aInnerColor.Color4K(aInnerColor.Color4K()); |
|
836 aOuterColor=aOuterColor.Color4K(aOuterColor.Color4K()); |
|
837 break; |
|
838 case EColor64K: |
|
839 aInnerColor=aInnerColor.Color64K(aInnerColor.Color64K()); |
|
840 aOuterColor=aOuterColor.Color64K(aOuterColor.Color64K()); |
|
841 break; |
|
842 case EColor16M: |
|
843 case EColor16MU: |
|
844 case EColor16MA: |
|
845 case EColor16MAP: |
|
846 break; |
|
847 default: |
|
848 ASSERT_EQUALS(EColor16MA,displayMode); //Can't quantise color for this display mode! |
|
849 } |
|
850 |
|
851 RArray<CountColour> innerColors; |
|
852 innerColors.AppendL(aInnerColor); |
|
853 RArray<CountColour> outerColors; |
|
854 outerColors.AppendL(aOuterColor); |
|
855 TInt cornerSize=aExpectedCornerSize>=0?aExpectedCornerSize:-aExpectedCornerSize; |
|
856 //Check outside first! |
|
857 TRgb pixelVal; |
|
858 for(TPoint pixelPos(aRect.iTl.iX-1,aRect.iTl.iY-1);pixelPos.iX<aRect.iBr.iX;pixelPos.iX++) |
|
859 { |
|
860 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
861 LogColorL(pixelVal,outerColors); |
|
862 } |
|
863 for(TPoint pixelPos(aRect.iTl.iX,aRect.iBr.iY);pixelPos.iX<=aRect.iBr.iX;pixelPos.iX++) |
|
864 { |
|
865 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
866 LogColorL(pixelVal,outerColors); |
|
867 } |
|
868 for(TPoint pixelPos(aRect.iTl.iX-1,aRect.iTl.iY);pixelPos.iY<=aRect.iBr.iY;pixelPos.iY++) |
|
869 { |
|
870 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
871 LogColorL(pixelVal,outerColors); |
|
872 } |
|
873 for(TPoint pixelPos(aRect.iBr.iX,aRect.iTl.iY-1);pixelPos.iY<aRect.iBr.iY;pixelPos.iY++) |
|
874 { |
|
875 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
876 LogColorL(pixelVal,outerColors); |
|
877 } |
|
878 TInt cornerStart=1; |
|
879 if (cornerSize) |
|
880 { |
|
881 cornerStart=cornerSize; |
|
882 if (aExpectedCornerSize>0) |
|
883 { |
|
884 iScreenDevice->GetPixel(pixelVal, aRect.iTl); |
|
885 LogColorL(pixelVal,outerColors); |
|
886 iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX,aRect.iBr.iY-1)); |
|
887 LogColorL(pixelVal,outerColors); |
|
888 iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1,aRect.iTl.iY)); |
|
889 LogColorL(pixelVal,outerColors); |
|
890 iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1)); |
|
891 LogColorL(pixelVal,outerColors); |
|
892 } |
|
893 } |
|
894 |
|
895 //test inside edges (excluding 4 corner pixels - do them seperately) |
|
896 for(TPoint pixelPos(aRect.iTl.iX+cornerStart,aRect.iTl.iY);pixelPos.iX<aRect.iBr.iX-cornerStart;pixelPos.iX++) |
|
897 { |
|
898 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
899 LogColorL(pixelVal,innerColors); |
|
900 } |
|
901 for(TPoint pixelPos(aRect.iTl.iX+cornerStart,aRect.iBr.iY-1);pixelPos.iX<aRect.iBr.iX-cornerStart;pixelPos.iX++) |
|
902 { |
|
903 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
904 LogColorL(pixelVal,innerColors); |
|
905 } |
|
906 for(TPoint pixelPos(aRect.iTl.iX,aRect.iTl.iY+cornerStart);pixelPos.iY<aRect.iBr.iY-cornerStart;pixelPos.iY++) |
|
907 { |
|
908 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
909 LogColorL(pixelVal,innerColors); |
|
910 } |
|
911 for(TPoint pixelPos(aRect.iBr.iX-1,aRect.iTl.iY+cornerStart);pixelPos.iY<aRect.iBr.iY-cornerStart;pixelPos.iY++) |
|
912 { |
|
913 iScreenDevice->GetPixel(pixelVal, pixelPos); |
|
914 LogColorL(pixelVal,innerColors); |
|
915 } |
|
916 //the 4 corner cells - not checking the whole corner area... |
|
917 if (aExpectedCornerSize>=0) |
|
918 { |
|
919 iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX+cornerSize,aRect.iTl.iY+cornerSize)); |
|
920 LogColorL(pixelVal,innerColors); |
|
921 iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX+cornerSize,aRect.iBr.iY-1-cornerSize)); |
|
922 LogColorL(pixelVal,innerColors); |
|
923 iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1-cornerSize,aRect.iBr.iY-1-cornerSize)); |
|
924 LogColorL(pixelVal,innerColors); |
|
925 iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1-cornerSize,aRect.iTl.iY+cornerSize)); |
|
926 LogColorL(pixelVal,innerColors); |
|
927 } |
|
928 //OK... that has tested all the pixels, now check the result |
|
929 if (innerColors.Count()>aOtherInnerColors+1) |
|
930 return EFalse; |
|
931 if (outerColors.Count()>aOtherOuterColors+1) |
|
932 return EFalse; |
|
933 for (TInt index=1;index<innerColors.Count();index++) |
|
934 if (innerColors[0].iCount<innerColors[index].iCount) |
|
935 { |
|
936 return EFalse; |
|
937 } |
|
938 for (TInt index=1;index<outerColors.Count();index++) |
|
939 if (outerColors[0].iCount<outerColors[index].iCount) |
|
940 { |
|
941 return EFalse; |
|
942 } |
|
943 for (TInt indexIn=1;indexIn<innerColors.Count();indexIn++) |
|
944 for (TInt indexOut=0;indexOut<outerColors.Count();indexOut++) |
|
945 if (innerColors[indexIn].iColor.Value()==outerColors[indexOut].iColor.Value()) |
|
946 { |
|
947 return EFalse; |
|
948 } |
|
949 return ETrue; |
|
950 } |
|
951 |
|
952 TRect CWsDynamicResWinBase::PentCellRect(const TRect& aFullRect,char aStartLetter,char aEndLetter) |
|
953 { |
|
954 if (aEndLetter==0) |
|
955 aEndLetter=aStartLetter; |
|
956 aStartLetter&=0x1f; |
|
957 aEndLetter&=0x1f; |
|
958 TInt startx=(aStartLetter-1)%5; |
|
959 TInt starty=(aStartLetter-1)/5; |
|
960 TInt endx=(aEndLetter-1)%5; |
|
961 TInt endy=(aEndLetter-1)/5; |
|
962 if (starty>endy) |
|
963 { //swap // s e |
|
964 starty-=endy; // s-e |
|
965 endy+=starty; // s |
|
966 starty=endy-starty; // e |
|
967 } |
|
968 if (startx>endx) |
|
969 { //swap // s e |
|
970 startx-=endx; // s-e |
|
971 endx+=startx; // s |
|
972 startx=endx-startx; // e |
|
973 } |
|
974 TSize fullSize=aFullRect.Size(); |
|
975 return TRect( aFullRect.iTl.iX+fullSize.iWidth*startx/5, |
|
976 aFullRect.iTl.iY+fullSize.iHeight*starty/5, |
|
977 aFullRect.iTl.iX+fullSize.iWidth*(endx+1)/5, |
|
978 aFullRect.iTl.iY+fullSize.iHeight*(endy+1)/5 |
|
979 ); |
|
980 } |