sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Test the text cursor. sl@0: // sl@0: // This suite of tests checks to see if the TextCursors are operating sl@0: // correctly for a number of use case scenarios; see doxygen comments sl@0: // for each sub-test. This test suite is applicable on both winscw sl@0: // emulator and armv5 target hardware. However, it must be noted that sl@0: // text cursors are special due to their timeliness. The text cursor sl@0: // must flash every second: half a second ON, half a second OFF. One sl@0: // consequence of this is that when the test suite is run on emulator, sl@0: // the PC must be otherwise quiescent. No other IO or CPU intensive sl@0: // activities may occur on the system, because these will cause delays sl@0: // to the flashing of the text cursor giving unreliable results. sl@0: // Where timeliness is a consideration, we use TEST_SOFTFAIL_WINSCW so sl@0: // that if the test fails and we are running on the PC emulator, we only sl@0: // record the fact, but don't mark the test as failing. sl@0: sl@0: /** sl@0: @file sl@0: @test sl@0: @internalComponent - Internal Symbian test code sl@0: */ sl@0: sl@0: #include "TTEXTCURS.H" sl@0: #include "graphics/windowserverconstants.h" sl@0: sl@0: const TInt KNumberOfCustoTextCursors = 3; sl@0: const TInt KTextCursorInitialIdValue = 1001; sl@0: const TInt KTextCursorPanicUid1 = 200; sl@0: const TInt KTextCursorPanicUid2 = 2000; sl@0: const TInt KTextCursorPanicUid3 = 3000; sl@0: const TInt KTextCursorPanicUid4 = 4000; sl@0: const TInt KTextCursorPanicUid5 = 5000; sl@0: sl@0: CTestBase* CTCursorTest::iStaticTest = NULL; sl@0: const TInt kWinWidth=400; sl@0: const TInt kWinHeight=100; sl@0: const TSize kWinSize(kWinWidth,kWinHeight); sl@0: const TInt kWinXPos=150; sl@0: const TInt kCursorWidth = 10; sl@0: const TInt kCursorHeight = 20; sl@0: const TSize kCursorSize(kCursorWidth,kCursorHeight); sl@0: const TPoint kWin1TopLeft(kWinXPos,0); sl@0: const TPoint kWin2TopLeft(kWinXPos,kWinHeight+10); sl@0: sl@0: LOCAL_D void DeleteSpriteMember(TAny* aSpriteMember) sl@0: { sl@0: TSpriteMember* member=reinterpret_cast(aSpriteMember); sl@0: delete member->iBitmap; sl@0: member->iBitmap=NULL; sl@0: delete member->iMaskBitmap; sl@0: member->iMaskBitmap=NULL; sl@0: } sl@0: sl@0: CCustomTextCursor::~CCustomTextCursor() sl@0: { sl@0: const TInt count = iSpriteMemberArray.Count(); sl@0: for (TInt index=0; indexLoad(TEST_BITMAP_NAME, EMbmWsautotestBmp1)); sl@0: spriteMember.iMaskBitmap = new (ELeave) CFbsBitmap; sl@0: User::LeaveIfError(spriteMember.iMaskBitmap->Load(TEST_BITMAP_NAME, EMbmWsautotestBmp1mask)); sl@0: sl@0: User::LeaveIfError(iSpriteMemberArray.Append(spriteMember)); sl@0: CleanupStack::Pop(&spriteMember); sl@0: sl@0: // create unique-id accross screens sl@0: // sl@0: iIdentifier = KTextCursorInitialIdValue + aScreenNumber*KNumberOfCustoTextCursors + aBmpIndex; sl@0: iAlignment = (RWsSession::TCustomTextCursorAlignment)(aBmpIndex); sl@0: } sl@0: sl@0: CCustomTextCursor* CCustomTextCursor::CreateCustomTextCursorL(TInt aScreenNumber,TInt aBmpIndex,CTestBase* aTest) sl@0: { sl@0: CCustomTextCursor* customTextCursor = new (ELeave) CCustomTextCursor(aTest); sl@0: CleanupStack::PushL(customTextCursor); sl@0: customTextCursor->ConstructL(aScreenNumber,aBmpIndex); sl@0: CleanupStack::Pop(customTextCursor); sl@0: return customTextCursor; sl@0: } sl@0: sl@0: /* sl@0: * Wrapper class for a list of custom text cursor. sl@0: */ sl@0: class CCustomTextCursorsWrapper : public CBase sl@0: { sl@0: public: sl@0: static CCustomTextCursorsWrapper* NewLC(TInt aScreenNumber,CTestBase* aTest); sl@0: ~CCustomTextCursorsWrapper(); sl@0: inline RPointerArray& CustomTextCursorsArray(); sl@0: inline CCustomTextCursor& CustomTextCursor(TInt aIndex); sl@0: private: sl@0: void ConstructL(TInt aScreenNumber,CTestBase* aTest); sl@0: private: sl@0: RPointerArray iCustomTextCursors; sl@0: }; sl@0: sl@0: inline RPointerArray& CCustomTextCursorsWrapper::CustomTextCursorsArray() sl@0: { sl@0: return iCustomTextCursors; sl@0: } sl@0: sl@0: inline CCustomTextCursor& CCustomTextCursorsWrapper::CustomTextCursor(TInt aIndex) sl@0: { sl@0: return *(iCustomTextCursors[aIndex]); sl@0: } sl@0: sl@0: CCustomTextCursorsWrapper* CCustomTextCursorsWrapper::NewLC(TInt aScreenNumber,CTestBase* aTest) sl@0: { sl@0: CCustomTextCursorsWrapper* self = new(ELeave) CCustomTextCursorsWrapper(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aScreenNumber,aTest); sl@0: return self; sl@0: } sl@0: sl@0: CCustomTextCursorsWrapper::~CCustomTextCursorsWrapper() sl@0: { sl@0: iCustomTextCursors.ResetAndDestroy(); sl@0: iCustomTextCursors.Close(); sl@0: } sl@0: sl@0: void CCustomTextCursorsWrapper::ConstructL(TInt aScreenNumber, CTestBase* aTest) sl@0: { sl@0: for (TInt index=0; indexConstruct((TInt)aScreenNumber)); sl@0: RWindowGroup group(ws); sl@0: if (group.Construct(444)==KErrNone) sl@0: { sl@0: group.EnableReceiptOfFocus(EFalse); // Stop auto group switching on close sl@0: RWindow wnd(ws); sl@0: if (wnd.Construct(group, TInt32(&ws))==KErrNone) sl@0: { sl@0: TTextCursor tc; sl@0: tc.iHeight=10; sl@0: tc.iAscent=5; sl@0: tc.iWidth=10; sl@0: tc.iFlags=0; sl@0: tc.iColor=TRgb(0,0,0); sl@0: switch(aInt) sl@0: { sl@0: case 0: sl@0: { sl@0: /* TESTCASE: 6.1 sl@0: * TITLE: Invalid use of a custom text cursor ID (basic text cursor). sl@0: * IMPORTANCE: 1 sl@0: * REQUIREMENT: Unknown. sl@0: * sl@0: * ACTION: This test tries to set a text cursor using an ID which is invalid. sl@0: * sl@0: * CHECK: The thread should panic with the exit reason EWservPanicInvalidTextCursor sl@0: */ sl@0: tc.iType=(TTextCursor::EType)KTextCursorPanicUid1; sl@0: group.SetTextCursor(wnd,TPoint(10,10),tc); sl@0: } sl@0: break; sl@0: case 1: sl@0: { sl@0: /* TESTCASE: 6.2 sl@0: * TITLE: Invalid use of a window for a text cursor. sl@0: * IMPORTANCE: 1 sl@0: * REQUIREMENT: REQ 1079, CR RDEF-5F7Q24 (10/04/2003). sl@0: * sl@0: * ACTION: This test tries to set a text cursor using a window which is not part sl@0: * of the window group calling the setting API. sl@0: * sl@0: * CHECK: The thread should panic with the exit reason EWservPanicWindow sl@0: */ sl@0: tc.iType=(TTextCursor::EType)KTextCursorPanicUid2; sl@0: group.SetTextCursor(*TestWin->Win(),TPoint(10,10),tc); sl@0: } sl@0: break; sl@0: case 2: sl@0: { sl@0: /* TESTCASE: 6.3 sl@0: * TITLE: Invalid use of a custom text cursor ID. sl@0: * IMPORTANCE: 1 sl@0: * REQUIREMENT: REQ 1079, CR RDEF-5F7Q24 (10/04/2003). sl@0: * sl@0: * ACTION: This test tries to set a text cursor using an ID which is associated to sl@0: * an non-existing custom text cursor. sl@0: * sl@0: * CHECK: The thread should panic with the exit reason EWservPanicNoCustomTextCursor sl@0: */ sl@0: tc.iType=(TTextCursor::EType)KTextCursorPanicUid3; sl@0: group.SetTextCursor(wnd,TPoint(10,10),tc); sl@0: } sl@0: break; sl@0: case 3: sl@0: { sl@0: /* TESTCASE: 6.4 sl@0: * TITLE: Invalid use of a custom text cursor ID. sl@0: * IMPORTANCE: 1 sl@0: * REQUIREMENT: REQ 1079, CR RDEF-5F7Q24 (10/04/2003). sl@0: * sl@0: * ACTION: This test tries to set a custom text cursor which has been set to use sl@0: * an invalid alignment. sl@0: * sl@0: * CHECK: The thread should panic with the exit reason EWservPanicCustomTextCursorAlign sl@0: */ sl@0: CCustomTextCursor* customTextCursor=NULL; sl@0: TRAPD(error, customTextCursor=CCustomTextCursor::CreateCustomTextCursorL((TInt)aScreenNumber,0,iStaticTest)); sl@0: if (error==KErrNone) sl@0: { sl@0: error = ws.SetCustomTextCursor(KTextCursorPanicUid4, customTextCursor->iSpriteMemberArray.Array(), 0, (RWsSession::TCustomTextCursorAlignment)(RWsSession::ECustomTextCursorAlignBottom+1)); sl@0: if (error==KErrNone || error==KErrAlreadyExists) sl@0: { sl@0: tc.iType=(TTextCursor::EType)KTextCursorPanicUid4; sl@0: group.SetTextCursor(wnd,TPoint(10,10),tc); sl@0: } sl@0: } sl@0: delete customTextCursor; sl@0: } sl@0: break; sl@0: case 4: sl@0: { sl@0: /* TESTCASE: 6.5 sl@0: * TITLE: Use of an invalid custom text cursor sl@0: * IMPORTANCE: 1 sl@0: * REQUIREMENT: REQ 1079, CR RDEF-5F7Q24 (10/04/2003). sl@0: * sl@0: * ACTION: This test tries to set a custom text cursor which does not have sl@0: * any sprite member set. sl@0: * sl@0: * CHECK: The thread should panic with the exit reason EWservPanicNoSpriteMember sl@0: */ sl@0: RArray spriteMemberArray; sl@0: const TInt error = ws.SetCustomTextCursor(KTextCursorPanicUid5, spriteMemberArray.Array(), 0, (RWsSession::TCustomTextCursorAlignment)(RWsSession::ECustomTextCursorAlignBottom)); sl@0: if (error==KErrNone || error==KErrAlreadyExists) sl@0: { sl@0: tc.iType=(TTextCursor::EType)KTextCursorPanicUid5; sl@0: group.SetTextCursor(wnd,TPoint(10,10),tc); sl@0: } sl@0: } sl@0: break; sl@0: case 5: sl@0: { sl@0: // Uncover set.cursor.iType < TTextCursor::ETypeFirst code path sl@0: tc.iType=(TTextCursor::EType)TTextCursor::ETypeFirst - 1; sl@0: group.SetTextCursor(wnd,TPoint(10,10),tc); sl@0: } sl@0: break; sl@0: case 6: sl@0: { sl@0: // Uncover (set.cursor.iFlags&static_cast(TTextCursor::EPrivateFlags) code path sl@0: tc.iFlags=ETextCursorPrivateFlags; sl@0: group.SetTextCursor(wnd,TPoint(10,10),tc); sl@0: } sl@0: break; sl@0: case 7: sl@0: { sl@0: // Uncover (iGroupWin != searchWin) i.e. bogus group window sl@0: tc.iType=(TTextCursor::EType)TTextCursor::ETypeRectangle; sl@0: RWindow windowNotAssociatedWithAGroup(ws); sl@0: group.SetTextCursor(windowNotAssociatedWithAGroup, TPoint(10,10),tc); sl@0: } sl@0: break; sl@0: } sl@0: } sl@0: ws.Flush(); sl@0: } sl@0: } sl@0: return(EWsExitReasonBad); sl@0: } sl@0: sl@0: void CTCursorTest::TestPanicsL() sl@0: { sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicInvalidTextCursor, 0, (TAny*)iTest->iScreenNumber)); sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicWindow, 1, (TAny*)iTest->iScreenNumber)); sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicNoCustomTextCursor, 2, (TAny*)iTest->iScreenNumber)); sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicCustomTextCursorAlign, 3, (TAny*)iTest->iScreenNumber)); sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicNoSpriteMember, 4, (TAny*)iTest->iScreenNumber)); sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicInvalidTextCursor, 5, (TAny*)iTest->iScreenNumber)); sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicInvalidTextCursor, 6, (TAny*)iTest->iScreenNumber)); sl@0: TEST(iTest->TestWsPanicL(DoPanicTest, EWservPanicWindow, 7, (TAny*)iTest->iScreenNumber)); sl@0: iTest->CloseAllPanicWindows(); sl@0: } sl@0: sl@0: void CTCursorTest::TextCursorSetLCoverageTests() sl@0: { sl@0: ValidateWin(BaseWin,TRgb::Gray256(255)); sl@0: ValidateWin(TestWin,TRgb::Gray256(255)); sl@0: TTextCursor textCursor; sl@0: textCursor.iHeight = 10; sl@0: textCursor.iAscent = 0; sl@0: textCursor.iWidth = 10; sl@0: textCursor.iFlags = 0; sl@0: textCursor.iColor = KRgbBlack; sl@0: textCursor.iType = (TTextCursor::EType)TTextCursor::ETypeRectangle; sl@0: TPoint position(10, 10); sl@0: TRect clipRect0(10, 10, 10, 10); sl@0: TRect clipRect1(10, 10, 5, 5); sl@0: RWindowGroup *group = TheClient->iGroup->GroupWin(); sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: /* sl@0: * Duplicate the previous SetTextCursor command to uncover the code which checks for any delta in SetL sl@0: * compared to the current settings. sl@0: */ sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: /* sl@0: * Change the type only to pick up that difference in SetL. sl@0: */ sl@0: textCursor.iType++; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: textCursor.iType--; sl@0: /* sl@0: * Vary the clipping rectangle. sl@0: */ sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor, clipRect0); sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor, clipRect1); sl@0: /* sl@0: * Vary the color. sl@0: */ sl@0: textCursor.iColor = KRgbGreen; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: textCursor.iColor = KRgbBlack; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: /* sl@0: * Vary the target Window. sl@0: */ sl@0: group->SetTextCursor(*BaseWin->Win(), position, textCursor); sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: /* sl@0: * Vary the size of the cursor. sl@0: */ sl@0: textCursor.iWidth++; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: textCursor.iWidth--; sl@0: /* sl@0: * Set different custom cursors. sl@0: */ sl@0: CCustomTextCursorsWrapper* customTextCursorsWrapper = CCustomTextCursorsWrapper::NewLC(iTest->iScreenNumber, iTest); sl@0: const TInt count = customTextCursorsWrapper->CustomTextCursorsArray().Count(); sl@0: for (TInt index=0; indexCustomTextCursor(index); sl@0: textCursor.iType = customTextCursor.iIdentifier; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: } sl@0: CleanupStack::PopAndDestroy(customTextCursorsWrapper); sl@0: /* sl@0: * Set the last custom cursor from the above loop again so the sl@0: * product code sees the same Custom Text Cursor settings come sl@0: * in a second time. sl@0: */ sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: textCursor.iType = (TTextCursor::EType)TTextCursor::ETypeRectangle; sl@0: /* sl@0: * Vary the horizontal clipping. sl@0: */ sl@0: textCursor.iFlags = TTextCursor::EFlagClipHorizontal; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: /* sl@0: * Vary the horizontal clipping. sl@0: */ sl@0: textCursor.iFlags = TTextCursor::EFlagClipVertical; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: /* sl@0: * Try both horizontal and vertical clipping. sl@0: */ sl@0: textCursor.iFlags = TTextCursor::EFlagClipVertical|TTextCursor::EFlagClipHorizontal; sl@0: group->SetTextCursor(*TestWin->Win(), position, textCursor); sl@0: textCursor.iFlags = 0; sl@0: sl@0: TheClient->iWs.Flush(); sl@0: CancelTextCursor(); sl@0: } sl@0: sl@0: void CTCursorTest::SetCursor(const TPoint &aPos,const TSize &aSize,TRgb aColor, const TRect &aRect, TUint aFlags) sl@0: { sl@0: TTextCursor tc; sl@0: tc.iType=iCursorType; sl@0: tc.iHeight=aSize.iHeight; sl@0: tc.iAscent=aSize.iHeight*4/5; sl@0: tc.iWidth=aSize.iWidth; sl@0: tc.iFlags=aFlags; sl@0: tc.iColor=aColor; sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*TestWin->Win(),TPoint(aPos.iX,aPos.iY+tc.iAscent),tc,aRect); sl@0: } sl@0: sl@0: void CTCursorTest::SetCursor(const TPoint &aPos,const TSize &aSize,TRgb aColor, TUint aFlags) sl@0: { sl@0: TTextCursor tc; sl@0: tc.iType=iCursorType; sl@0: tc.iHeight=aSize.iHeight; sl@0: tc.iAscent=aSize.iHeight*4/5; sl@0: tc.iWidth=aSize.iWidth; sl@0: tc.iFlags=aFlags; sl@0: tc.iColor=aColor; sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*TestWin->Win(),TPoint(aPos.iX,aPos.iY+tc.iAscent),tc); sl@0: } sl@0: sl@0: void CTCursorTest::SetCursorPlusBox(const TPoint &aPos,const TSize &aSize,TRgb aColor, const TRect *aClipRect, TUint aFlags) sl@0: { sl@0: if (aClipRect) sl@0: SetCursor(aPos,aSize,aColor,*aClipRect,aFlags); sl@0: else sl@0: SetCursor(aPos,aSize,aColor,aFlags); sl@0: TRect rect(aPos,aSize); sl@0: if (aClipRect) sl@0: rect.Intersection(*aClipRect); sl@0: rect.Grow(2,2); sl@0: sl@0: TheClient->iGc->Activate(*(TestWin->Win())); sl@0: TestWin->Invalidate(rect); sl@0: TestWin->Win()->BeginRedraw(rect); sl@0: TheClient->iGc->SetPenColor(aColor); sl@0: TheClient->iGc->SetDrawMode(CGraphicsContext::EDrawModeXOR); sl@0: sl@0: TheClient->iGc->DrawRect(rect); sl@0: TheClient->iGc->Deactivate(); sl@0: TestWin->Win()->EndRedraw(); sl@0: sl@0: } sl@0: sl@0: void CTCursorTest::CancelTextCursor() sl@0: { sl@0: TheClient->iGroup->GroupWin()->CancelTextCursor(); sl@0: } sl@0: sl@0: void CTCursorTest::ConstructL() sl@0: { sl@0: // for allocating some cached memory sl@0: CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; sl@0: CleanupStack::PushL(bitmap); sl@0: User::LeaveIfError(bitmap->Load(TEST_BITMAP_NAME, 0)); sl@0: CleanupStack::PopAndDestroy(bitmap); sl@0: sl@0: CCustomTextCursorsWrapper* customTextCursorsWrapper = CCustomTextCursorsWrapper::NewLC(iTest->iScreenNumber, iTest); sl@0: const TInt count = customTextCursorsWrapper->CustomTextCursorsArray().Count(); sl@0: for (TInt index=0; indexCustomTextCursor(index); sl@0: TInt err = TheClient->iWs.SetCustomTextCursor(customTextCursor.iIdentifier, customTextCursor.iSpriteMemberArray.Array(), customTextCursor.iSpriteFlags, customTextCursor.iAlignment); sl@0: TEST(err == KErrNone || err == KErrAlreadyExists); sl@0: if (err!=KErrNone && err != KErrAlreadyExists) sl@0: INFO_PRINTF4(_L("TheClient->iWs.SetCustomTextCursor return value - Expected: %d or %d, Actual: %d"), KErrNone, KErrAlreadyExists, err); sl@0: sl@0: __UHEAP_MARK; sl@0: err = TheClient->iWs.SetCustomTextCursor(customTextCursor.iIdentifier, customTextCursor.iSpriteMemberArray.Array(), customTextCursor.iSpriteFlags, customTextCursor.iAlignment); sl@0: __UHEAP_MARKEND; sl@0: TEST(err == KErrAlreadyExists); sl@0: if (err != KErrAlreadyExists) sl@0: INFO_PRINTF3(_L("TheClient->iWs.SetCustomTextCursor return value - Expected: %d, Actual: %d"), KErrAlreadyExists, err); sl@0: sl@0: } sl@0: _LIT(KLog,"Text Cursor: Loaded %d Custom Cursors"); sl@0: TLogMessageText buf; sl@0: buf.Format(KLog,count); sl@0: TheClient->LogMessage(buf); sl@0: CleanupStack::PopAndDestroy(customTextCursorsWrapper); sl@0: // sl@0: ValidateWin(BaseWin,TRgb::Gray256(204)); sl@0: ValidateWin(TestWin,TRgb::Gray256(204)); sl@0: // sl@0: SetCursor(TPoint(10,90),TSize(80,100),TRgb(255,255,255)); sl@0: // sl@0: iWinState=0; sl@0: iWinPos=TPoint(2*TheClient->iGroup->Size().iWidth/3,0); sl@0: // sl@0: iMoveWin=new(ELeave) CBlankWindow(TRgb::Gray256(220)); sl@0: TDisplayMode mode=EGray16; sl@0: TInt testWinWidth = TestWin->Size().iWidth; sl@0: TInt halfTestWinWidth = testWinWidth/2; sl@0: TInt halfTestWinHeight = TestWin->Size().iHeight/2; sl@0: sl@0: iMoveWin->SetUpL(iWinPos,TSize(halfTestWinHeight,halfTestWinHeight), sl@0: TheClient->iGroup,*TheClient->iGc,&mode); sl@0: sl@0: iCheckWin=new(ELeave) CBlankWindow(TRgb::Gray256(220)); sl@0: iCheckWin->SetUpL(TPoint(testWinWidth+halfTestWinWidth,halfTestWinHeight), sl@0: TSize(halfTestWinWidth,halfTestWinHeight), sl@0: TheClient->iGroup,*TheClient->iGc,&mode); sl@0: } sl@0: sl@0: void CTCursorTest::DeleteMoveWindows() sl@0: { sl@0: delete iMoveWin; sl@0: delete iCheckWin; sl@0: CancelTextCursor(); sl@0: } sl@0: sl@0: void CTCursorTest::ResetMoveWindowsL() sl@0: { sl@0: SetCursor(TPoint(10,90),TSize(80,100),TRgb(255,255,255)); sl@0: iWinState=0; sl@0: iWinPos=TPoint(2*TheClient->iGroup->Size().iWidth/3,0); sl@0: iMoveWin->SetExtL(iWinPos,TSize(TestWin->Size().iWidth/2,TestWin->Size().iHeight/2)); sl@0: iCheckWin->SetExtL(TPoint(TestWin->Size().iWidth+(TestWin->Size().iWidth>>1),TestWin->Size().iHeight>>1), sl@0: TSize(TestWin->Size().iWidth/2,TestWin->Size().iHeight/2)); sl@0: } sl@0: sl@0: TBool CTCursorTest::MoveWindow() sl@0: { sl@0: TSize scrSize(TheClient->iScreen->SizeInPixels()); sl@0: iWinState++; sl@0: if (iWinState<20) sl@0: iWinPos+=TPoint((4*scrSize.iWidth)/640,(4*scrSize.iHeight)/240); sl@0: else if (iWinState<40) sl@0: iWinPos+=TPoint((1*scrSize.iWidth)/640,(-3*scrSize.iHeight)/240); sl@0: else if (iWinState<60) sl@0: iWinPos+=TPoint((-6*scrSize.iWidth)/640,(3*scrSize.iHeight)/240); sl@0: else sl@0: iWinPos+=TPoint((1*scrSize.iWidth)/640,(-2*scrSize.iHeight)/240); sl@0: iMoveWin->SetPos(iWinPos); sl@0: return (iWinState==80); sl@0: } sl@0: sl@0: void CTCursorTest::ValidateWin(TestWindow *aWin, TRgb aColor) sl@0: { sl@0: aWin->Win()->Invalidate(); sl@0: RedrawWin(*aWin->Win(),aColor); sl@0: } sl@0: sl@0: void CTCursorTest::RedrawWin(RWindow &aWin, TRgb aColor) sl@0: { sl@0: aWin.BeginRedraw(); sl@0: TheClient->iGc->Activate(aWin); sl@0: TheClient->iGc->SetBrushColor(aColor); sl@0: TheClient->iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: TheClient->iGc->SetPenStyle(CGraphicsContext::ENullPen); sl@0: TheClient->iGc->Clear(); sl@0: TheClient->iGc->Deactivate(); sl@0: aWin.EndRedraw(); sl@0: } sl@0: sl@0: void CTCursorTest::ScrollTest() sl@0: { sl@0: const TSize size(20,40); sl@0: ValidateWin(TestWin,TRgb::Gray256(255)); sl@0: sl@0: SetCursor(TPoint(10,20),size,TRgb::Gray256(255),TTextCursor::EFlagNoFlash); sl@0: TheClient->iWs.Flush(); sl@0: TheClient->WaitForRedrawsToFinish(); sl@0: TheClient->iWs.Finish(); sl@0: sl@0: for(TInt ii=0;ii<20;ii++) sl@0: { sl@0: TInt dist=(ii&3)*2; sl@0: TInt nx=ii&0x1?1:-1; sl@0: TInt ny=ii&0x2?1:-1; sl@0: TestWin->Win()->Scroll(TPoint(dist*nx,dist*ny),TRect(10,20,30,40)); sl@0: TheClient->iWs.Flush(); sl@0: } sl@0: TheClient->WaitForRedrawsToFinish(); sl@0: TheClient->iWs.Finish(); sl@0: sl@0: BaseWin->Win()->Invalidate(); sl@0: BaseWin->Win()->BeginRedraw(); sl@0: TheClient->iGc->Activate(*(BaseWin->Win())); sl@0: TheClient->iGc->Clear(); sl@0: TheClient->iGc->SetBrushColor(TRgb::Gray256(255)); sl@0: TheClient->iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: TheClient->iGc->SetPenStyle(CGraphicsContext::ENullPen); sl@0: TheClient->iGc->Clear(TRect(TPoint(10,20),size)); sl@0: TheClient->iGc->Deactivate(); sl@0: BaseWin->Win()->EndRedraw(); sl@0: sl@0: TheClient->iWs.Flush(); sl@0: TheClient->WaitForRedrawsToFinish(); sl@0: TheClient->iWs.Finish(); sl@0: sl@0: /* sl@0: * NOTE: Reason for removal of COMPARE_WINDOWS_SOFTFAIL_WINSCW sl@0: * Due to the new implementation of sprites in wserv2, the sprites no longer keep a sl@0: * backup bitmap of what the screen looks like beneath them. As it is not possible to sl@0: * move the sprites associated with the custom text cursors that were created in second sl@0: * phase construction of the CTCursorTest object, the COMPARE_WINDOWS_SOFTFAIL_WINSCW; sl@0: * macro function has been removed. Otherwise the test case is going to subject to the sl@0: * timing of the flashing sprite. An alternative solution would be to assign NULL values sl@0: * to the sprite bitmaps in second phase construction, but this is avoided as it would sl@0: * trigger failures in some test cases later on (that are depended on these "embedded" sl@0: * sprite images). sl@0: */ sl@0: CancelTextCursor(); sl@0: } sl@0: sl@0: void DrawTestSprite(CBitmapContext *aGc,TInt , const TSize &aSize, TBool aDoMask, TAny *) sl@0: { sl@0: aGc->SetBrushColor(TRgb::Gray4(aDoMask ? 0 : 2)); sl@0: aGc->SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: aGc->SetPenStyle(CGraphicsContext::ENullPen); sl@0: aGc->DrawRect(TRect(aSize)); sl@0: aGc->SetPenStyle(CGraphicsContext::ESolidPen); sl@0: aGc->SetPenColor(TRgb::Gray4(aDoMask ? 3 : 0)); sl@0: aGc->SetBrushColor(TRgb::Gray4(aDoMask ? 3 : 1)); sl@0: aGc->DrawEllipse(TRect(aSize)); sl@0: } sl@0: sl@0: CTSprite *CTCursorTest::CreateTestSpriteLC(RWindowTreeNode &aWindow, const TPoint &aPos, TInt aCount) sl@0: // sl@0: // At the moment aCount must be 1 or 2 sl@0: // sl@0: { sl@0: TSpriteCreateParams params(TSize(30,70),TPoint(0,0),DrawTestSprite); sl@0: TSpriteCreateParams paramarray[2]; sl@0: params.iInterval=TTimeIntervalMicroSeconds32(200000); sl@0: sl@0: paramarray[0]=params; sl@0: paramarray[1]=params; sl@0: paramarray[1].iSize=TSize(100,10); sl@0: CTSprite *sprite=new(ELeave) CTSprite(TheClient->iWs); sl@0: CleanupStack::PushL(sprite); sl@0: sprite->ConstructL(aWindow,aPos,aCount,¶marray[0],0); sl@0: return(sprite); sl@0: } sl@0: sl@0: void CTCursorTest::doMoveWindowTestL() sl@0: { sl@0: RBlankWindow blankwin(TheClient->iWs); sl@0: User::LeaveIfError(blankwin.Construct(*TestWin->Win(),1)); sl@0: CleanupStack::PushL(TCleanupItem(CleanUpWindow,&blankwin)); sl@0: // sl@0: blankwin.SetExtent(TPoint(35,165),TSize(40,40)); sl@0: blankwin.SetColor(TRgb::Gray256(220)); sl@0: blankwin.Activate(); sl@0: TheClient->iWs.SetAutoFlush(ETrue); sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(25,55)); sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(30,160)); sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(12,22)); // Almost totally covering sprite sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(-100,-100)); // Totally off the sprite sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(10,20)); // Write on top of sprite sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(24,24)); // moving off... sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(38,28)); // ... sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(58,48)); // ... sl@0: User::After(500000); sl@0: blankwin.SetPosition(TPoint(92,62)); // ... off sl@0: User::After(500000); sl@0: CleanupStack::PopAndDestroy(); // blank window sl@0: TheClient->iWs.Flush(); sl@0: TheClient->WaitForRedrawsToFinish(); sl@0: TheClient->iWs.Finish(); sl@0: sl@0: TheClient->iWs.SetAutoFlush(EFalse); sl@0: } sl@0: sl@0: void CTCursorTest::MoveWindowTest1L() sl@0: { sl@0: ValidateWin(TestWin,TRgb::Gray256(255)); sl@0: // Check it with a static sprite sl@0: CTSprite * sprite_static = CreateTestSpriteLC(*TestWin->Win(), TPoint(10,20), 1); sl@0: doMoveWindowTestL(); sl@0: (sprite_static->Sprite()).SetPosition(TPoint(500,500)); //move the sprite out of the viewing area before the window comparison sl@0: CleanupStack::PopAndDestroy(1); // sprite sl@0: // Check it an animated sprite sl@0: CTSprite * sprite_anim = CreateTestSpriteLC(*TestWin->Win(), TPoint(10,20), 2); sl@0: doMoveWindowTestL(); sl@0: (sprite_anim->Sprite()).SetPosition(TPoint(500,500)); //move the sprite out of the viewing area before the window comparison sl@0: CleanupStack::PopAndDestroy(1); // sprite sl@0: } sl@0: sl@0: void CTCursorTest::MoveWindowTest2L() sl@0: { sl@0: const TSize size(20,40); sl@0: // Check it with a text cursor sl@0: ValidateWin(TestWin,TRgb::Gray256(255)); sl@0: SetCursor(TPoint(10,25),size,TRgb::Gray256(255),TTextCursor::EFlagNoFlash); sl@0: doMoveWindowTestL(); sl@0: CancelTextCursor(); sl@0: // Check it with an anaimated sprite and a text cursor sl@0: ValidateWin(TestWin,TRgb::Gray256(255)); sl@0: CTSprite * sprite_anim = CreateTestSpriteLC(*TestWin->Win(), TPoint(10,20), 2); sl@0: SetCursor(TPoint(10,45),size,TRgb::Gray256(255),TTextCursor::EFlagNoFlash); sl@0: doMoveWindowTestL(); sl@0: (sprite_anim->Sprite()).SetPosition(TPoint(500,500)); sl@0: CancelTextCursor(); sl@0: CleanupStack::PopAndDestroy(1); // sprite sl@0: } sl@0: sl@0: TBool CTCursorTest::IncrementCursorType() sl@0: { sl@0: // each screen has it own set of cursor sl@0: // sl@0: // the values would be ETypeLast=2 ETypeLastBasic=1009 sl@0: // sl@0: if (iCursorType == TTextCursor::ETypeFirst) sl@0: { sl@0: iCursorType = (TTextCursor::EType)(TTextCursor::ETypeLastBasic + 1 + iTest->iScreenNumber*KNumberOfCustoTextCursors); sl@0: return ETrue; sl@0: } sl@0: else if (iCursorType >= TTextCursor::ETypeLastBasic + (iTest->iScreenNumber+1)*KNumberOfCustoTextCursors) sl@0: { sl@0: iCursorType = TTextCursor::ETypeFirst; sl@0: return EFalse; sl@0: } sl@0: else sl@0: { sl@0: iCursorType = (TTextCursor::EType)(iCursorType + 1); sl@0: return ETrue; sl@0: } sl@0: } sl@0: sl@0: void CTCursorTest::GeneralTestsL() sl@0: { sl@0: const TInt winColor=255; //Best to use Light Grey that is 170, but this code is bugged and doing so shows them up. sl@0: ValidateWin(BaseWin,TRgb::Gray256(255)); sl@0: ValidateWin(TestWin,TRgb::Gray256(255)); sl@0: SetCursor(TPoint(-1000,10),TSize(10,30),TRgb::Gray256(255)); sl@0: TheClient->iWs.Flush(); sl@0: SetCursor(TPoint(10,10),TSize(10,30),TRgb::Gray256(255)); sl@0: TheClient->iWs.Flush(); sl@0: TRect rect(15,15,18,25); sl@0: SetCursorPlusBox(TPoint(10,10),TSize(10,30),TRgb::Gray256(255), &rect); sl@0: CancelTextCursor(); sl@0: // sl@0: ValidateWin(BaseWin,TRgb::Gray256(255)); sl@0: ValidateWin(TestWin,TRgb::Gray256(255)); sl@0: TheClient->iWs.Flush(); sl@0: for(TInt winType=0;winType<3;winType++) sl@0: { sl@0: RWindowBase *cursorwin=NULL; sl@0: RBackedUpWindow backcursorwin(TheClient->iWs); sl@0: RWindow backwindow(TheClient->iWs); sl@0: RBlankWindow backblankwin(TheClient->iWs); sl@0: switch(winType) sl@0: { sl@0: case 0: sl@0: cursorwin=&backcursorwin; sl@0: User::LeaveIfError(backcursorwin.Construct(*TestWin->BaseWin(),EGray4,1)); sl@0: break; sl@0: case 1: sl@0: cursorwin=&backwindow; sl@0: User::LeaveIfError(backwindow.Construct(*TestWin->BaseWin(),1)); sl@0: break; sl@0: case 2: sl@0: cursorwin=&backblankwin; sl@0: User::LeaveIfError(backblankwin.Construct(*TestWin->BaseWin(),1)); sl@0: break; sl@0: } sl@0: CleanupStack::PushL(TCleanupItem(CleanUpWindow,cursorwin)); sl@0: User::LeaveIfError(cursorwin->SetSizeErr(TestWin->BaseWin()->Size())); sl@0: cursorwin->Activate(); sl@0: // sl@0: TTextCursor tc; sl@0: tc.iType=iCursorType; sl@0: tc.iHeight=30; sl@0: tc.iAscent=0; sl@0: tc.iWidth=50; sl@0: tc.iFlags=0; sl@0: tc.iColor=TRgb::Gray256(255); sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*cursorwin,TPoint(10,10),tc); sl@0: // sl@0: CreateTestSpriteLC(*cursorwin, TPoint(10,20), 2); sl@0: // sl@0: if (cursorwin==&backwindow) sl@0: RedrawWin(backwindow,TRgb::Gray256(255)); sl@0: for(TInt count=0;count<9;count++) sl@0: { sl@0: RWindowBase *pwin=NULL; sl@0: RBackedUpWindow backedup(TheClient->iWs); sl@0: RWindow window(TheClient->iWs); sl@0: RBlankWindow blankwin(TheClient->iWs); sl@0: switch(count%3) sl@0: { sl@0: case 0: sl@0: pwin=&window; sl@0: window.Construct(*cursorwin,2); sl@0: window.SetBackgroundColor(TRgb(winColor,winColor,winColor)); sl@0: break; sl@0: case 1: sl@0: pwin=&backedup; sl@0: backedup.Construct(*cursorwin,EGray4,2); sl@0: break; sl@0: case 2: sl@0: pwin=&blankwin; sl@0: blankwin.Construct(*cursorwin,2); sl@0: blankwin.SetColor(TRgb(winColor,winColor,winColor)); sl@0: break; sl@0: } sl@0: CleanupStack::PushL(TCleanupItem(CleanUpWindow,pwin)); sl@0: pwin->SetExtentErr(TPoint(30,30),TSize(50,80)); sl@0: pwin->Activate(); sl@0: TheClient->iWs.Flush(); sl@0: CleanupStack::PopAndDestroy(); // window sl@0: if (cursorwin==&backwindow) sl@0: RedrawWin(backwindow,TRgb::Gray256(255)); sl@0: TheClient->iWs.Flush(); sl@0: TheClient->WaitForRedrawsToFinish(); sl@0: COMPARE_WINDOWS_SOFTFAIL_WINSCW; sl@0: User::After(200000); // Wait a fifth of a second to make sure the test is run during different states of flashing sl@0: } sl@0: for(TInt count2=0;count2<4;count2++) sl@0: { sl@0: cursorwin->SetPosition(TPoint(10,5)); sl@0: TheClient->iWs.Flush(); sl@0: User::After(100000); sl@0: cursorwin->SetPosition(TPoint(5,10)); sl@0: TheClient->iWs.Flush(); sl@0: User::After(100000); sl@0: cursorwin->SetPosition(TPoint(0,0)); sl@0: TheClient->iWs.Flush(); sl@0: User::After(100000); sl@0: TheClient->WaitForRedrawsToFinish(); sl@0: COMPARE_WINDOWS_SOFTFAIL_WINSCW; sl@0: } sl@0: CleanupStack::PopAndDestroy(2); // sprite & window containing sprite and cursor sl@0: } sl@0: CancelTextCursor(); sl@0: } sl@0: sl@0: void CTCursorTest::INC040489L() sl@0: { sl@0: INFO_PRINTF1(_L("AUTO_TCur INC040489 ")); sl@0: RWindowGroup group1(TheClient->iWs); sl@0: PushWindowL(&group1); sl@0: User::LeaveIfError(group1.Construct(ENullWsHandle)); sl@0: RBlankWindow blank1(TheClient->iWs); sl@0: PushWindowL(&blank1); sl@0: User::LeaveIfError(blank1.Construct(group1,ENullWsHandle)); sl@0: blank1.SetRequiredDisplayMode(EColor4K); sl@0: blank1.SetColor(TRgb(250,150,0)); sl@0: blank1.Activate(); sl@0: RWindowGroup group2(TheClient->iWs); sl@0: PushWindowL(&group2); sl@0: User::LeaveIfError(group2.Construct(ENullWsHandle)); sl@0: RBlankWindow blank2(TheClient->iWs); sl@0: PushWindowL(&blank2); sl@0: User::LeaveIfError(blank2.Construct(group2,ENullWsHandle)); sl@0: blank2.SetRequiredDisplayMode(EColor4K); sl@0: blank2.SetColor(TRgb(75,200,125)); sl@0: blank2.Activate(); sl@0: TheClient->Flush(); sl@0: INFO_PRINTF1(_L(" Created Windows ")); sl@0: TTextCursor tc; sl@0: tc.iType=KTextCursorInitialIdValue + iTest->iScreenNumber*KNumberOfCustoTextCursors; sl@0: tc.iHeight=80; sl@0: tc.iAscent=10; sl@0: tc.iWidth=30; sl@0: tc.iFlags=0; sl@0: tc.iColor=TRgb::Gray256(255); sl@0: INFO_PRINTF1(_L(" About to Set Text Cursor 1 ")); sl@0: group2.SetTextCursor(blank2,TPoint(20,20),tc); sl@0: TheClient->Flush(); sl@0: INFO_PRINTF1(_L(" Set Text Cursor 1 ")); sl@0: User::After(2000000); //2sec sl@0: TheClient->iWs.PrepareForSwitchOff(); sl@0: TheClient->Flush(); sl@0: User::After(2000000); //2sec sl@0: group1.SetOrdinalPosition(0); sl@0: group2.CancelTextCursor(); sl@0: TheClient->Flush(); sl@0: INFO_PRINTF1(_L(" Canceled Text Cursor ")); sl@0: User::After(2000000); //2sec sl@0: // sl@0: // Before applying the fix, the following operations makes the Custom Text sl@0: // Cursor Sprite invisible (happens even without wserv heartbeat suppression) sl@0: INFO_PRINTF1(_L(" About to Set Text Cursor 2 ")); sl@0: group1.SetOrdinalPosition(2); sl@0: group2.SetTextCursor(blank2,TPoint(20,20),tc); sl@0: TheClient->Flush(); sl@0: INFO_PRINTF1(_L(" Set Text Cursor 2 ")); sl@0: User::After(2000000); //2sec sl@0: TRawEvent event; sl@0: event.Set(TRawEvent::EActive); sl@0: TheClient->iWs.SimulateRawEvent(event); sl@0: TheClient->Flush(); sl@0: INFO_PRINTF1(_L(" Simulated Active Event ")); sl@0: User::After(2000000); //2sec sl@0: CleanupStack::PopAndDestroy(4, &group1); sl@0: INFO_PRINTF1(_L(" End of test ")); sl@0: } sl@0: sl@0: void CTCursorTest::CursorUpdatedBeforeWindowRenderedL() sl@0: { sl@0: INFO_PRINTF1(_L("CursorUpdatedBeforeWindowRenderedL")); sl@0: TheClient->iGroup->WinTreeNode()->SetOrdinalPosition(0); sl@0: // We use some unique looking colors otherwise its harder sl@0: // to spot which test is which sl@0: TRgb kAqua(134, 242, 251); sl@0: sl@0: iWorkInProgress = new(ELeave) CBlankWindow(kAqua); sl@0: iComparisonWindow = new(ELeave) CBlankWindow(kAqua); sl@0: CancelTextCursor(); sl@0: sl@0: const TSize screenSize=TheClient->iGroup->Size(); sl@0: const TInt kPad = 5; sl@0: const TInt kThirdOfScreenWidth = screenSize.iWidth/3; sl@0: const TInt kWinWidth = kThirdOfScreenWidth - 2*kPad; sl@0: const TInt kWinHeight = screenSize.iHeight - 2*kPad; sl@0: const TSize kWinSize(kWinWidth, kWinHeight); sl@0: const TPoint kCursorPos(30, 30); sl@0: iComparisonWindow->SetUpL(TPoint(2*kThirdOfScreenWidth + kPad, kPad), kWinSize, TheClient->iGroup, *TheClient->iGc); sl@0: iWorkInProgress->SetUpL( TPoint( kThirdOfScreenWidth + kPad, kPad), kWinSize, TheClient->iGroup, *TheClient->iGc); sl@0: sl@0: TTextCursor nonFlashingCursor; sl@0: nonFlashingCursor.iType = TTextCursor::ETypeRectangle; sl@0: nonFlashingCursor.iHeight=kCursorHeight; sl@0: nonFlashingCursor.iAscent=0; sl@0: nonFlashingCursor.iWidth=kCursorWidth; sl@0: nonFlashingCursor.iFlags=TTextCursor::EFlagNoFlash; sl@0: nonFlashingCursor.iColor = KRgbBlack; sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*iWorkInProgress->BaseWin(), kCursorPos, nonFlashingCursor); sl@0: sl@0: // Up till this point, there has not been a CWsWindow::Render() for iWorkInProgress sl@0: // because the window has not been invalid sl@0: sl@0: /* sl@0: * Here is the crux of the test. We want to create the following condition in a window group: sl@0: * 1) None of its windows have yet been Rendered using CWsWindow::Render() sl@0: * 2) A text cursor is present sl@0: * 3) Focus is lost then received sl@0: * sl@0: * It used to be the case that Wserv picked up the handle to the Render Stage Text Cursor sl@0: * drawer upon a Refresh caused by Rendering the window. But drawing the Text Cursor could sl@0: * come either from a Window Render or a change to the state of the Text Cursor, such as sl@0: * receiving focus in the window. A bug was experienced when the Text Cursor was drawn in sl@0: * a window which never had been rendered. This meant that the handle was not set up causing sl@0: * an assert. sl@0: * sl@0: * The code has been modified since then, to setup the handle to the Render Stage Text sl@0: * Cursor during Wserv initialisation. However, to guard against future changes, its sl@0: * worthwhile to have this corner case test to ensure it is possible to receive focus sl@0: * in a window which has never been rendered. That is because the text cursor state sl@0: * is updated in such circumstances, and that might trigger a draw of the cursor in a sl@0: * future version of the text cursor code. sl@0: */ sl@0: TheClient->iGroup->WinTreeNode()->SetOrdinalPosition(1); // lose focus sl@0: TheClient->iWs.Finish(); sl@0: TheClient->iGroup->WinTreeNode()->SetOrdinalPosition(0); // gain focus sl@0: TheClient->iWs.Finish(); sl@0: sl@0: // If we get this far without a panic or assert, we have passed this test. sl@0: sl@0: // Now allow CWsWindow::Render() to occur in iWorkInProgress sl@0: // The reason for doing this is so that when you watch the test sl@0: // progress you can see visual confirmation via the progress message and sl@0: // the coloured windows appear on the screen. Otherwise you would think sl@0: // that the test had either been skipped or had broken. sl@0: iWorkInProgress->Invalidate(); sl@0: iWorkInProgress->Redraw(); sl@0: iComparisonWindow->Invalidate(); sl@0: iComparisonWindow->Redraw(); sl@0: TheClient->iWs.Finish(); sl@0: delete iWorkInProgress; sl@0: iWorkInProgress = NULL; sl@0: delete iComparisonWindow; sl@0: iComparisonWindow = NULL; sl@0: INFO_PRINTF1(_L("End of test")); sl@0: } sl@0: sl@0: void CTCursorTest::INC097774() sl@0: { sl@0: TTimeIntervalMicroSeconds32 initialRepeatRate; sl@0: TTimeIntervalMicroSeconds32 repeatRate; sl@0: TheClient->iWs.GetKeyboardRepeatRate(initialRepeatRate,repeatRate); sl@0: sl@0: //simulates a text cursor moving across the screen as if a user was holding down sl@0: //a key to scroll the cursor through a section of text. sl@0: //before applying the fix the cursor only shows up intermittently instead of smoothly sl@0: //scrolling across the screen. sl@0: const TSize cursorSize(3,20); sl@0: const TInt moveInterval=10; sl@0: SetCursor(TPoint(0,20),cursorSize,TRgb::Gray256(255),TTextCursor::EFlagNoFlash); sl@0: TheClient->Flush(); sl@0: User::After(initialRepeatRate); sl@0: for(TInt offset=10;offset<=100;offset+=moveInterval) sl@0: { sl@0: SetCursor(TPoint(offset,20),cursorSize,TRgb::Gray256(255),TTextCursor::EFlagNoFlash); sl@0: TheClient->Flush(); sl@0: User::After(repeatRate); sl@0: } sl@0: sl@0: //simulate clipped text cursor moving accross the screen sl@0: TRect rect(0,20,3,40); sl@0: SetCursor(TPoint(0,20),cursorSize,TRgb::Gray256(255),rect,TTextCursor::EFlagNoFlash); sl@0: TheClient->Flush(); sl@0: User::After(initialRepeatRate); sl@0: for(TInt offset=10;offset<=100;offset+=moveInterval) sl@0: { sl@0: rect.Move(moveInterval,0); sl@0: SetCursor(TPoint(offset,20),cursorSize,TRgb::Gray256(255),rect,TTextCursor::EFlagNoFlash); sl@0: TheClient->Flush(); sl@0: User::After(repeatRate); sl@0: } sl@0: } sl@0: /** What happens when a cursor becomes off-screen when the screen is resized/rotated? sl@0: * sl@0: * sl@0: **/ sl@0: void CTCursorTest::INC117232() sl@0: { sl@0: const TInt initialRepeatRate=300000; // 3/10 seconds should be long enough to update everything! sl@0: TInt currMode=TheClient->iScreen->CurrentScreenMode(); sl@0: TInt testMode=currMode; sl@0: TPixelsTwipsAndRotation currModeSize; sl@0: TheClient->iScreen->GetScreenModeSizeAndRotation(currMode, currModeSize); sl@0: //find a (rotated) mode where the dimensions of the screen shrank sl@0: for (TInt mode=0;modeiScreenModes.Count();mode++) sl@0: { sl@0: TPixelsTwipsAndRotation testModeSize; sl@0: TheClient->iScreen->GetScreenModeSizeAndRotation(mode,testModeSize); sl@0: if ( testModeSize.iPixelSize.iWidthSetTestStepResult(EInconclusive); //With this line the whole test fails which is too drastic sl@0: return; sl@0: } sl@0: //enable a cursor on the bottom right corner of the screen sl@0: TestWin->SetFullScreenExtL(); sl@0: TheClient->Flush(); sl@0: iCursorType=TTextCursor::ETypeRectangle; sl@0: SetCursor(TPoint(-20,-20)+TestWin->Size(),TSize(40,40),KRgbDarkMagenta,TTextCursor::EFlagNoFlash); sl@0: TheClient->Flush(); sl@0: User::After(initialRepeatRate); sl@0: //shrink the screen sl@0: TheClient->iScreen->SetScreenMode(testMode); sl@0: TheClient->iScreen->SetAppScreenMode(testMode); sl@0: //The defect was that WServ would now crash! sl@0: TheClient->Flush(); sl@0: User::After(initialRepeatRate); sl@0: //Set everything back sl@0: TheClient->iScreen->SetScreenMode(currMode); sl@0: TheClient->iScreen->SetAppScreenMode(currMode); sl@0: TheClient->Flush(); sl@0: User::After(initialRepeatRate); sl@0: } sl@0: sl@0: #ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA sl@0: /** sl@0: * Sets up a text cursor whose attributes indicate it should not be flashing sl@0: * and then checks to ensure this is the actual behaviour. sl@0: */ sl@0: void CTCursorTest::TextCursorNoFlashTestL() sl@0: { sl@0: TheClient->iGroup->WinTreeNode()->SetOrdinalPosition(0); sl@0: // We use some unique looking colors otherwise its harder sl@0: // to spot which test is which sl@0: TRgb kGentleYellow(251, 249, 198); sl@0: TRgb kGentlePink(253, 196, 221); sl@0: sl@0: iWorkInProgress = new(ELeave) CBlankWindow(kGentleYellow); sl@0: iComparisonWindow = new(ELeave) CBlankWindow(kGentleYellow); sl@0: CancelTextCursor(); sl@0: TheClient->Flush(); sl@0: sl@0: const TSize screenSize=TheClient->iGroup->Size(); sl@0: const TInt kPad = 5; sl@0: const TInt kThirdOfScreenWidth = screenSize.iWidth/3; sl@0: const TInt kWinWidth = kThirdOfScreenWidth - 2*kPad; sl@0: const TInt kWinHeight = screenSize.iHeight - 2*kPad; sl@0: const TSize kWinSize(kWinWidth, kWinHeight); sl@0: const TPoint kCursorPos(30, 30); sl@0: iWorkInProgress->SetUpL( TPoint( kThirdOfScreenWidth + kPad, kPad), kWinSize, TheClient->iGroup, *TheClient->iGc); sl@0: iComparisonWindow->SetUpL(TPoint(2*kThirdOfScreenWidth + kPad, kPad), kWinSize, TheClient->iGroup, *TheClient->iGc); sl@0: sl@0: TTextCursor nonFlashingCursor; sl@0: sl@0: nonFlashingCursor.iType = TTextCursor::ETypeRectangle; sl@0: nonFlashingCursor.iHeight=kCursorHeight; sl@0: nonFlashingCursor.iAscent=0; sl@0: nonFlashingCursor.iWidth=kCursorWidth; sl@0: nonFlashingCursor.iFlags=TTextCursor::EFlagNoFlash; sl@0: nonFlashingCursor.iColor = kGentlePink; // We expect a Flicker Buffer Render Stage to ignore this color sl@0: sl@0: iWorkInProgress->Invalidate(); sl@0: iWorkInProgress->Redraw(); sl@0: iComparisonWindow->Invalidate(); sl@0: iComparisonWindow->Redraw(); sl@0: sl@0: DrawTextCursorSimilarToRenderStage(*TheClient->iGc, *iComparisonWindow->Win(), kCursorPos, nonFlashingCursor); sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*iWorkInProgress->BaseWin(), kCursorPos, nonFlashingCursor); sl@0: TheClient->Flush(); sl@0: sl@0: CheckCursorDoesNotFlash(iWorkInProgress->BaseWin()->Size()); sl@0: sl@0: delete iWorkInProgress; sl@0: iWorkInProgress = NULL; sl@0: delete iComparisonWindow; sl@0: iComparisonWindow = NULL; sl@0: } sl@0: sl@0: void CTCursorTest::TextCursorFlashTestL() sl@0: { sl@0: TheClient->iGroup->WinTreeNode()->SetOrdinalPosition(0); sl@0: // We use some unique looking colors otherwise its harder sl@0: // to spot which test is which sl@0: TRgb kMildPurple(218, 155, 244); sl@0: TRgb kPaleGreen(146, 190, 12); sl@0: sl@0: iWorkInProgress = new(ELeave) CBlankWindow(kMildPurple); sl@0: iComparisonWindow = new(ELeave) CBlankWindow(kMildPurple); sl@0: CancelTextCursor(); sl@0: TheClient->Flush(); sl@0: sl@0: const TSize screenSize=TheClient->iGroup->Size(); sl@0: const TInt kPad = 5; sl@0: const TInt kThirdOfScreenWidth = screenSize.iWidth/3; sl@0: const TInt kWinWidth = kThirdOfScreenWidth - 2*kPad; sl@0: const TInt kWinHeight = screenSize.iHeight - 2*kPad; sl@0: const TSize kWinSize(kWinWidth, kWinHeight); sl@0: const TPoint kCursorPos(30, 30); sl@0: iWorkInProgress->SetUpL( TPoint( kThirdOfScreenWidth + kPad, kPad), kWinSize, TheClient->iGroup, *TheClient->iGc); sl@0: iComparisonWindow->SetUpL(TPoint(2*kThirdOfScreenWidth + kPad, kPad), kWinSize, TheClient->iGroup, *TheClient->iGc); sl@0: sl@0: TTextCursor flashingCursor; sl@0: sl@0: flashingCursor.iType = TTextCursor::ETypeRectangle; sl@0: flashingCursor.iHeight=kCursorHeight; sl@0: flashingCursor.iAscent=0; sl@0: flashingCursor.iWidth=kCursorWidth; sl@0: flashingCursor.iFlags=0; // implies that cursor SHOULD flash sl@0: flashingCursor.iColor = kPaleGreen; // We expect a Flicker Buffer Render Stage to ignore this color sl@0: sl@0: iWorkInProgress->Invalidate(); sl@0: iWorkInProgress->Redraw(); sl@0: iComparisonWindow->Invalidate(); sl@0: iComparisonWindow->Redraw(); sl@0: sl@0: DrawTextCursorSimilarToRenderStage(*TheClient->iGc, *iComparisonWindow->Win(), kCursorPos, flashingCursor); sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*iWorkInProgress->BaseWin(), kCursorPos, flashingCursor); sl@0: TheClient->Flush(); sl@0: sl@0: CheckCursorDoesFlash(kCursorPos, flashingCursor, kMildPurple); sl@0: CancelTextCursor(); sl@0: TheClient->Flush(); sl@0: sl@0: delete iWorkInProgress; sl@0: iWorkInProgress = NULL; sl@0: delete iComparisonWindow; sl@0: iComparisonWindow = NULL; sl@0: } sl@0: sl@0: void CTCursorTest::DrawTextCursorSimilarToRenderStage(CWindowGc& aGc, RWindow& aWin, const TPoint& aPos, const TTextCursor& aTextCursor) sl@0: { sl@0: // This method duplicates the way in which the default FlickerBuffer Render sl@0: // Stage draws a Text Cursor of ETypeRectangle. @see CFbRenderStage::DrawTextCursor sl@0: // This code must be kept in sync with the FlickerBuffer Render Stage sl@0: sl@0: ASSERT(aTextCursor.iType == TTextCursor::ETypeRectangle); sl@0: const TRect updatedRegion(aPos,TSize(aTextCursor.iWidth,aTextCursor.iHeight)); sl@0: aWin.Invalidate(); sl@0: aWin.BeginRedraw(); sl@0: aGc.Activate(aWin); sl@0: aGc.Clear(); sl@0: aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: aGc.SetBrushColor(KRgbBlack); sl@0: aGc.SetPenStyle(CGraphicsContext::ENullPen); sl@0: aGc.Clear(updatedRegion); sl@0: aGc.Deactivate(); sl@0: aWin.EndRedraw(); sl@0: } sl@0: sl@0: void CTCursorTest::CheckCursorDoesNotFlash(const TSize& aSize) sl@0: { sl@0: const TInt kSampleTime = 100000; // one tenth of a second sl@0: const TInt kSampleLimit = 100; sl@0: TInt sampleIteration = 0; sl@0: TBool comparisonOkay = EFalse; sl@0: sl@0: while (sampleIteration < kSampleLimit) sl@0: { sl@0: comparisonOkay = DoCheckRect(iWorkInProgress, iComparisonWindow, TRect(TPoint(), aSize), CWsScreenDevice::EIncludeTextCursor); sl@0: if (!comparisonOkay) sl@0: { sl@0: INFO_PRINTF2(_L("CheckCursorDoesNotFlash difference found after %d milliseconds"), sampleIteration*100); sl@0: break; sl@0: } sl@0: sampleIteration++; sl@0: User::After(kSampleTime); sl@0: } sl@0: TEST(comparisonOkay); sl@0: } sl@0: sl@0: void CTCursorTest::UpdateCountersOnCursorTransition( sl@0: const TBool aTransitionedToOn, sl@0: TTime& aNow, sl@0: TInt64& aDeltaTime, sl@0: TTime& aLastDeltaTime, sl@0: TInt& aWarmUpIterations, sl@0: const TInt& aFlashChangeTime, sl@0: const TInt& aToleranceMargin, sl@0: TInt& aSampleNumber, sl@0: TInt& aToleranceViolations sl@0: ) sl@0: { sl@0: _LIT(KTxtOn, " On"); sl@0: _LIT(KTxtOff, "Off"); sl@0: TBufC<3> transitionType; sl@0: transitionType = aTransitionedToOn ? KTxtOn : KTxtOff; sl@0: sl@0: aNow.UniversalTime(); sl@0: aDeltaTime = aNow.MicroSecondsFrom(aLastDeltaTime).Int64(); sl@0: aLastDeltaTime = aNow; sl@0: sl@0: if (aWarmUpIterations > 0) sl@0: { sl@0: aWarmUpIterations--; sl@0: } sl@0: else sl@0: { sl@0: if (aDeltaTime > aFlashChangeTime + aToleranceMargin || sl@0: aDeltaTime < aFlashChangeTime - aToleranceMargin) sl@0: { sl@0: INFO_PRINTF5(_L(" Iteration %d, Cursor %S after %d, errorDelta %d microseconds"), sl@0: aSampleNumber, &transitionType, I64INT(aDeltaTime), I64INT(aDeltaTime - aFlashChangeTime)); sl@0: aToleranceViolations++; sl@0: } sl@0: } sl@0: } sl@0: void CTCursorTest::CheckCursorDoesFlash(const TPoint& aPos, const TTextCursor& aTextCursor, TRgb /* aBackgroundColor */) sl@0: { sl@0: sl@0: /** sl@0: * Quality of Service based thresholding sl@0: * sl@0: * The idea behind this test is to identify tolerances which would either sl@0: * cause the test to fail when the user would perceive the text cursor as sl@0: * not flashing uniformly, or would point to an unexpected delay outside sl@0: * the way the flashing (and scheduling of animations) is supposed to work. sl@0: * sl@0: * Potentially the cursor can be late if we miss a V-SYNC from hardware. In sl@0: * such cases we expect to see the cursor on the next frame. Since the V-SYNC sl@0: * is typically 1/50 second, a tolerance of two frames, or 1/25 second is reasonable. sl@0: * sl@0: * If the cursor is delayed longer than this, say a long time of 1 second, but this sl@0: * does not happen too often, then the user is likely to still be happy. So we sl@0: * set the period of testing to 60 seconds, and set the violations limit to 2. sl@0: */ sl@0: const TInt kOneSecond = 1000000; sl@0: const TInt kFlashPeriod = kOneSecond; // comprises one "ON" and one "OFF" sl@0: const TInt kToleranceFactor = 25; // meaning 1/25 of a Flash Period sl@0: const TInt kNumberTestFlashPeriods = 60; // meaning 60 Flash Periods worth of testing sl@0: const TInt kMaximumToleranceViolations = 2; // number of times an occassional flash may be late or early sl@0: sl@0: const TInt kToleranceMargin = kFlashPeriod / kToleranceFactor; sl@0: const TInt kNumberSamples = kNumberTestFlashPeriods * kToleranceFactor; sl@0: const TInt kFlashChangeTime = kFlashPeriod / 2; sl@0: sl@0: // The first couple of changes to the cursor should be ignored because sl@0: // when the test is started, the cursor may have been on for a while. sl@0: // Then when the cursor goes off, it appears to have switched to the sl@0: // off state too early. We therefore ignore the first two changes sl@0: // so we start cleanly. sl@0: TInt warmUpIterations = 2; sl@0: sl@0: // Empirically we see that cursors mostly flash with good timeliness apart from sl@0: // occasional events causing them to be either early or late. In order to keep sl@0: // a tight tolerance (1/50 second is around the screen refresh time) but still sl@0: // allow for the occasional variance (seen to be 1/23 second) we use a counter sl@0: // toleranceViolations < kMaximumToleranceViolations sl@0: TInt toleranceViolations = 0; sl@0: TBool cursorShownLastTime = EFalse; sl@0: TBool cursorShown = EFalse; sl@0: TTime lastDeltaTime; sl@0: TTime now; sl@0: TInt64 deltaTime = 0; sl@0: lastDeltaTime.UniversalTime(); sl@0: now.UniversalTime(); sl@0: sl@0: TRect textCursorRect(TRect(aPos, TSize(aTextCursor.iWidth, aTextCursor.iHeight))); sl@0: sl@0: for (TInt sampleNumber = 0; sampleNumber < kNumberSamples; sampleNumber++) sl@0: { sl@0: cursorShown = DoCheckRect(iWorkInProgress, iComparisonWindow, textCursorRect, CWsScreenDevice::EIncludeTextCursor); sl@0: sl@0: if (cursorShown && !cursorShownLastTime) sl@0: { sl@0: cursorShownLastTime = ETrue; sl@0: UpdateCountersOnCursorTransition( sl@0: cursorShownLastTime, now, deltaTime, lastDeltaTime, warmUpIterations, kFlashChangeTime, sl@0: kToleranceMargin, sampleNumber, toleranceViolations); sl@0: } sl@0: else if (!cursorShown && cursorShownLastTime) sl@0: { sl@0: cursorShownLastTime = EFalse; sl@0: UpdateCountersOnCursorTransition( sl@0: cursorShownLastTime, now, deltaTime, lastDeltaTime, warmUpIterations, kFlashChangeTime, sl@0: kToleranceMargin, sampleNumber, toleranceViolations); sl@0: } sl@0: sl@0: if (toleranceViolations > kMaximumToleranceViolations) sl@0: break; sl@0: sl@0: User::After(kToleranceMargin); sl@0: } sl@0: // Check was some flashing sl@0: TEST_SOFTFAIL_WINSCW(warmUpIterations == 0); sl@0: // Check cursor flashed on and off, regularly and on-time sl@0: TEST_SOFTFAIL_WINSCW(toleranceViolations <= kMaximumToleranceViolations); sl@0: } sl@0: #endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA sl@0: sl@0: void CTCursorTest::MakeCursors(TTextCursor& aTextCursor, TTextCursor& aCustomCursor) sl@0: { sl@0: aCustomCursor.iType = KTextCursorInitialIdValue + iTest->iScreenNumber*KNumberOfCustoTextCursors; // custom text cursor sl@0: aCustomCursor.iAscent=0; sl@0: aCustomCursor.iHeight=kCursorHeight; sl@0: aCustomCursor.iWidth=kCursorWidth; sl@0: aCustomCursor.iFlags=TTextCursor::EFlagNoFlash; sl@0: aCustomCursor.iColor=TRgb::Color256(217); sl@0: sl@0: // Create a standard cursor for the tests sl@0: aTextCursor.iType = TTextCursor::ETypeRectangle; // Normal rectangular text cursor sl@0: aTextCursor.iHeight=kCursorHeight; sl@0: aTextCursor.iAscent=0; sl@0: aTextCursor.iWidth=kCursorWidth; sl@0: aTextCursor.iFlags=TTextCursor::EFlagNoFlash; sl@0: } sl@0: sl@0: void CTCursorTest::StartDoubleCursorTestL(TInt aTestNumber) sl@0: { sl@0: // general setup sl@0: CBlankWindow* win1=new(ELeave) CBlankWindow(KRgbWhite); sl@0: CleanupStack::PushL(win1); sl@0: sl@0: win1->SetUpL(kWin1TopLeft,kWinSize,TheClient->iGroup,*TheClient->iGc,EColor64K); sl@0: sl@0: win1->Redraw(); sl@0: sl@0: // Create the second window sl@0: CBlankWindow* win2=new(ELeave) CBlankWindow(KRgbWhite); sl@0: CleanupStack::PushL(win2); sl@0: sl@0: win2->SetUpL(kWin2TopLeft,kWinSize,TheClient->iGroup,*TheClient->iGc,EColor64K); sl@0: win2->Redraw(); sl@0: sl@0: // Create normal and custom cursor for the tests sl@0: TTextCursor textCursor; sl@0: TTextCursor customCursor; sl@0: MakeCursors(textCursor, customCursor); sl@0: sl@0: TheClient->Flush(); sl@0: CWindowGc* winGc = TheClient->iGc; sl@0: sl@0: switch(aTestNumber) sl@0: { sl@0: case 1: sl@0: CheckNoDoubleCursorTest1L(win1, win2, textCursor, customCursor, winGc); sl@0: break; sl@0: sl@0: case 2: sl@0: CheckNoDoubleCursorTest2L(win1, win2, textCursor, customCursor, winGc); sl@0: break; sl@0: sl@0: case 3: sl@0: CheckNoDoubleCursorTest3L(win1, win2, textCursor, customCursor, winGc); sl@0: break; sl@0: sl@0: default: sl@0: TEST(EFalse); sl@0: break; sl@0: } sl@0: CleanupStack::PopAndDestroy(2); sl@0: } sl@0: sl@0: // DEF098704 sl@0: void CTCursorTest::CheckNoDoubleCursorTest1L(CBlankWindow* aWin1, CBlankWindow* aWin2, TTextCursor& /*aTextCursor*/, TTextCursor& aCustomCursor, CWindowGc* aWinGc) sl@0: { sl@0: // Test that changing the focus of a custom text cursor does not leave that cursor drawn where it was (INC093898) sl@0: sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*aWin1->BaseWin(),TPoint(),aCustomCursor); sl@0: sl@0: // Bit blit the TEST_BITMAP_NAME image to the second window to use as a comparison sl@0: // this is the same image that the custom cursor is using sl@0: CFbsBitmap* bitmap = new(ELeave) CFbsBitmap; sl@0: CleanupStack::PushL(bitmap); sl@0: TEST(KErrNone == bitmap->Load(TEST_BITMAP_NAME,0,ETrue)); sl@0: sl@0: aWinGc->Activate(*aWin2->Win()); sl@0: TRect updateArea(TPoint(0,0), bitmap->SizeInPixels()); sl@0: aWin2->Win()->Invalidate(updateArea); sl@0: aWin2->Win()->BeginRedraw(updateArea); sl@0: aWinGc->BitBlt(TPoint(0,0),bitmap); sl@0: aWinGc->Deactivate(); sl@0: aWin2->Win()->EndRedraw(); sl@0: TheClient->Flush(); sl@0: doCheckNoDoubleCursor(aWin1,aWin2,kWin1TopLeft,kWin2TopLeft,aCustomCursor,bitmap->SizeInPixels(),CWsScreenDevice::EIncludeSprite); sl@0: CleanupStack::PopAndDestroy(1); // bitmap sl@0: } sl@0: sl@0: // DEF098704 sl@0: void CTCursorTest::CheckNoDoubleCursorTest2L(CBlankWindow* aWin1, CBlankWindow* aWin2, TTextCursor& /*aTextCursor*/, TTextCursor& aCustomCursor, CWindowGc* aWinGc) sl@0: { sl@0: //TEST 2: Checks that no artifacts are left behind when a text cursor is moved from under a transparent sprite sl@0: sl@0: // Construct the window win1 with a transparent sprite sl@0: sl@0: // Clear the top and bottom windows sl@0: ResetWindows(aWinGc,aWin1,aWin2); sl@0: sl@0: // Create a bitmap and a corresponding bitmap mask sl@0: CFbsBitmap* bitmap = new(ELeave) CFbsBitmap; sl@0: CleanupStack::PushL(bitmap); sl@0: TEST(KErrNone == bitmap->Load(TEST_BITMAP_NAME,0,ETrue)); sl@0: CBitmap* spriteBitmap=CBitmap::NewL(kWinSize,EColor256); sl@0: CleanupStack::PushL(spriteBitmap); sl@0: spriteBitmap->Gc().SetBrushColor(KRgbBlack); sl@0: spriteBitmap->Gc().SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: spriteBitmap->Gc().SetPenStyle(CGraphicsContext::ESolidPen); sl@0: spriteBitmap->Gc().DrawRect(TRect(kWinSize)); sl@0: CBitmap* mask=CBitmap::NewL(kWinSize,EColor256); sl@0: CleanupStack::PushL(mask); sl@0: mask->Gc().SetBrushStyle(CGraphicsContext::ESolidBrush); sl@0: mask->Gc().SetBrushColor(KRgbBlack); sl@0: mask->Gc().DrawRect(TRect(kWinSize)); sl@0: sl@0: // Create a sprite sl@0: RWsSprite sprite = RWsSprite(TheClient->iWs); sl@0: CleanupClosePushL(sprite); sl@0: TEST(KErrNone == sprite.Construct(*aWin1->BaseWin(),TPoint(),0)); sl@0: sl@0: // Add the bitmap to the sprite sl@0: TSpriteMember member; sl@0: member.iInvertMask=EFalse; sl@0: member.iDrawMode=CGraphicsContext::EDrawModePEN; sl@0: member.iOffset=TPoint(); sl@0: member.iInterval=TTimeIntervalMicroSeconds32(0); sl@0: member.iBitmap = &spriteBitmap->Bitmap(); sl@0: member.iMaskBitmap = &mask->Bitmap(); sl@0: TEST(KErrNone == sprite.AppendMember(member)); sl@0: sl@0: // Activate the sprite in win1 sl@0: TEST(KErrNone == sprite.Activate()); sl@0: sl@0: // Put a cursor in win1 sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*aWin1->BaseWin(),TPoint(),aCustomCursor); sl@0: sl@0: // Bit blit the matching bitmap to the bottom window sl@0: TRect bitmapArea(TPoint(0,0), bitmap->SizeInPixels()); sl@0: aWin2->Win()->Invalidate(bitmapArea); sl@0: aWin2->Win()->BeginRedraw(bitmapArea); sl@0: aWinGc->Activate(*aWin2->Win()); sl@0: aWinGc->BitBlt(TPoint(),bitmap); sl@0: aWinGc->Deactivate(); sl@0: aWin2->Win()->EndRedraw(); sl@0: sl@0: TheClient->Flush(); sl@0: doCheckNoDoubleCursor(aWin1,aWin2,kWin1TopLeft,kWin2TopLeft,aCustomCursor,bitmap->SizeInPixels(),CWsScreenDevice::EIncludeSprite); sl@0: CleanupStack::PopAndDestroy(4); // sprite, mask, spriteBitmap, bitmap sl@0: } sl@0: sl@0: // DEF098704 sl@0: void CTCursorTest::CheckNoDoubleCursorTest3L(CBlankWindow* aWin1, CBlankWindow* aWin2, TTextCursor& aTextCursor,TTextCursor& aCustomCursor, CWindowGc* aWinGc) sl@0: { sl@0: // sl@0: // TEST 3: Test a flashing text cursor does not leave artifacts when a redraw + change position happens during sl@0: // the time the cursor flashing 'off' sl@0: // sl@0: // This test moves a flashing cursor a number of times over a two second period to a seconds position. sl@0: // it does it a number of times so some of the redraws will occur during the 'flash off' period sl@0: // We then compare the 'after' position to what we expect sl@0: // sl@0: // There are four possible outcomes when we look at the bitmap after the redraw + move sl@0: // Position 1 is the original position, position 2 is the new position after the redraw sl@0: // sl@0: // cursor artifact @ pos1 and flashed on cursor @ pos2 sl@0: // cursor artifact at pos1 and flashed off cursor @ pos2 sl@0: // no artifact at pos1 and flashed off cursor @ pos2 sl@0: // no artifact at pos1 and flashed on cursor @ pos2 sl@0: // sl@0: // any artifacts left over will cause the complete test to fail. sl@0: // sl@0: sl@0: // sl@0: // PART A: sl@0: aTextCursor.iFlags=0; // flashing sl@0: sl@0: ResetWindows(aWinGc,aWin1,aWin2); sl@0: TestForArtifacts(aWin1, aTextCursor); sl@0: sl@0: // sl@0: // PART B - For a non-custom text cursor sl@0: aCustomCursor.iFlags=0; // flashing sl@0: sl@0: ResetWindows(aWinGc,aWin1,aWin2); sl@0: TestForArtifacts(aWin1, aCustomCursor); sl@0: } sl@0: sl@0: // moves the cursor between two positions while flashing and tests no artifacts are left at the position it moved from sl@0: // The moves take place in a loop so it is tested happening when the cursor is flashed on and also off sl@0: void CTCursorTest::TestForArtifacts(CBlankWindow* aWin1, TTextCursor& aCursor) sl@0: { sl@0: const TInt KIterations = 30; sl@0: const TPoint kStartPos(0,0); sl@0: const TPoint kMoveToPos(200,0); sl@0: TRect r1(kWin1TopLeft,kCursorSize); sl@0: TRect r2(kWin2TopLeft,kCursorSize); sl@0: const TPoint kWin1TopLeft; sl@0: const TPoint kWin2TopLeft; sl@0: const TSize aCursorSize; sl@0: sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*aWin1->BaseWin(),kStartPos,aCursor); sl@0: TheClient->Flush(); sl@0: sl@0: TInt initialRepeatRate = 1000000; sl@0: const TInt KIncrement = 30000; sl@0: TInt i=0; sl@0: sl@0: for(i=0; iiGroup->GroupWin()->SetTextCursor(*aWin1->BaseWin(),kMoveToPos,aCursor); sl@0: TheClient->Flush(); sl@0: sl@0: User::After(initialRepeatRate); sl@0: sl@0: // check no artifact was left in position 1 by comparing against (blank) win2 sl@0: if(!TheClient->iScreen->RectCompare( r1,r2, CWsScreenDevice::EIncludeTextCursor)) sl@0: { sl@0: break; // detected an artifact remaining, test failed sl@0: } sl@0: sl@0: // move the cursor back to its start position, this resets the flash timer which is why we increment initialRepeatRate sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*aWin1->BaseWin(),kStartPos,aCursor); sl@0: TheClient->Flush(); sl@0: initialRepeatRate += KIncrement; sl@0: } sl@0: sl@0: // if all went well i should equal KIterations, if it doesnt its because we detected sl@0: // an artifact and quit the test early sl@0: TEST_SOFTFAIL_WINSCW(i==KIterations); sl@0: } sl@0: sl@0: sl@0: // Tests the two windows match, moves the cursor off win 1 then tests they no longer match sl@0: void CTCursorTest::doCheckNoDoubleCursor(CBlankWindow* aWin1, sl@0: CBlankWindow* aWin2, sl@0: const TPoint& aWin1Tl, sl@0: const TPoint& aWin2Tl, sl@0: const TTextCursor& aCursor, sl@0: const TSize& aCursorSize, sl@0: CWsScreenDevice::TSpriteInCompare aFlags) sl@0: { sl@0: TRect r1(aWin1Tl,aCursorSize); sl@0: TRect r2(aWin2Tl,aCursorSize); sl@0: sl@0: TInt compareTries = 0; sl@0: const TInt compareLimit = 5; sl@0: sl@0: TBool correctComparison = EFalse; sl@0: while (!correctComparison && compareTries < compareLimit) sl@0: { sl@0: compareTries++; sl@0: User::After(500000); sl@0: correctComparison = TheClient->iScreen->RectCompare(r1,r2, aFlags); sl@0: } sl@0: sl@0: INFO_PRINTF3(_L("Result Before %d (attempts %d)"), correctComparison, compareTries); sl@0: TEST_SOFTFAIL_WINSCW(correctComparison); sl@0: sl@0: sl@0: // Change the focus off win1, by drawing the text cursor on the second window sl@0: TheClient->iGroup->GroupWin()->SetTextCursor(*aWin2->BaseWin(),aWin2Tl,aCursor); sl@0: TheClient->Flush(); sl@0: sl@0: // Cause a redraw sl@0: aWin1->CTWin::DrawNow(); sl@0: TheClient->WaitForRedrawsToFinish(); sl@0: sl@0: // make sure any cursor has actually moved sl@0: User::After(1000000); // 1 sec sl@0: sl@0: TBool resultAfter; sl@0: resultAfter = !TheClient->iScreen->RectCompare(r1,r2, aFlags); sl@0: INFO_PRINTF2(_L("Result After %d"), resultAfter); sl@0: TEST_SOFTFAIL_WINSCW(resultAfter); sl@0: } sl@0: sl@0: // resets the windows to their initial state sl@0: void CTCursorTest::ResetWindows(CWindowGc* aWinGc,CBlankWindow* aWin1,CBlankWindow* aWin2) sl@0: { sl@0: TheClient->iGroup->GroupWin()->CancelTextCursor(); sl@0: aWinGc->Activate(*aWin1->Win()); sl@0: aWinGc->Reset(); sl@0: aWinGc->Clear(); sl@0: aWinGc->Deactivate(); sl@0: sl@0: aWin1->Invalidate(); sl@0: aWin1->Redraw(); sl@0: aWin2->Invalidate(); sl@0: aWin2->Redraw(); sl@0: TheClient->Flush(); sl@0: } sl@0: sl@0: void CTCursorTest::RunTestCaseL(TInt /*aCurTestCase*/) sl@0: { sl@0: TBool deleteMove=EFalse; sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName); sl@0: sl@0: switch(++iTest->iState) sl@0: { sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0241 sl@0: sl@0: @SYMDEF DEF081259 sl@0: sl@0: @SYMTestCaseDesc Test the text cursor functions properly as a window is moved sl@0: sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Move a window about the screen and meanwhile check the text sl@0: cursor functions correctly sl@0: sl@0: @SYMTestExpectedResults The text cursor functions correctly as the window is moved sl@0: */ sl@0: case 1: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0241")); sl@0: while (!deleteMove) sl@0: { sl@0: if (iCursorType==TTextCursor::ETypeFirst) sl@0: iTest->LogSubTest(_L("Cursor 1")); sl@0: if (MoveWindow()) sl@0: { sl@0: if (IncrementCursorType()) sl@0: { sl@0: ResetMoveWindowsL(); sl@0: } sl@0: else sl@0: { sl@0: DeleteMoveWindows(); sl@0: deleteMove =true; sl@0: } sl@0: } sl@0: } sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0242 sl@0: sl@0: @SYMDEF DEF081259 sl@0: sl@0: @SYMTestCaseDesc Test the text cursor functions properly as the window is scrolled sl@0: sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Scroll the window and meanwhile check the text cursor functions correctly sl@0: sl@0: @SYMTestExpectedResults The text cursor functions correctly as the window is scrolled sl@0: */ sl@0: case 2: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0242")); sl@0: iTest->LogSubTest(_L("Cursor 2")); sl@0: iCursorType=TTextCursor::ETypeRectangle; sl@0: ScrollTest(); sl@0: iCursorType=TTextCursor::ETypeFirst; sl@0: break; sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0244 sl@0: sl@0: @SYMDEF DEF081259 sl@0: sl@0: @SYMTestCaseDesc Test the text cursor functions properly as a blank window is moved sl@0: sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Move a blank window about the screen and meanwhile check the text sl@0: cursor functions correctly sl@0: sl@0: @SYMTestExpectedResults The text cursor functions correctly as the blank window is moved sl@0: */ sl@0: case 3: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0244")); sl@0: iTest->LogSubTest(_L("Move window1")); sl@0: MoveWindowTest1L(); sl@0: break; sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0245 sl@0: sl@0: @SYMDEF DEF081259 sl@0: sl@0: @SYMTestCaseDesc Test that a non flashing text cursor functions properly as a sl@0: blank window is moved sl@0: sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Move a blank window about the screen and meanwhile check that a non sl@0: flashing text cursor functions correctly sl@0: sl@0: @SYMTestExpectedResults The text cursor functions correctly as the blank window is moved sl@0: */ sl@0: case 4: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0245")); sl@0: while (IncrementCursorType()) sl@0: { sl@0: iTest->LogSubTest(_L("Move window2")); sl@0: MoveWindowTest2L(); sl@0: } sl@0: break; sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0247 sl@0: sl@0: @SYMDEF DEF081259 sl@0: sl@0: @SYMTestCaseDesc Tests a Custom Text Cursor Sprite visibility after wserv hearbeat suppression sl@0: REQUIREMENT: INC040489. sl@0: sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Create a window group with an associated window for it, then activate it. sl@0: Create another window group with an associated window along with a custom cursor, sl@0: then active it. Make a call to suppress the wserv hearbeat, which will stop sl@0: the custom cursor from flashing with flash ON state. Bring the first window sl@0: group to the foreground and cancel the custom test cursor in the second window group. sl@0: After that, put the first window group to the background and set the custom test sl@0: cursor in the second window group. Simulate a raw key event to start sl@0: the wserv heartbeat, which will make the custom cursor flashing. sl@0: sl@0: @SYMTestExpectedResults The Custom text cursor in the second window group should be visible and flashing, sl@0: when it comes to the foreground after the first window group sent to the background. sl@0: */ sl@0: case 5: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0247")); sl@0: iTest->LogSubTest(_L("Custom Text Cursor Sprite visibility")); sl@0: INC040489L(); sl@0: break; sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-2095-0015 sl@0: sl@0: @SYMTestCaseDesc Text Cursor allows Update before Rendering the owning window sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Create a window group and two windows, one with a Text Cursor. sl@0: Stimulate a state change in the Text Cursor by receiving sl@0: window focus, but before the Window has ever been Rendered. sl@0: This shakes out logic in RWsTextCursor which depends on sl@0: side effects arising from having executed CWsWindow::Render() sl@0: sl@0: @SYMTestExpectedResults sl@0: There should be no panic or assertion. sl@0: */ sl@0: case 6: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-2095-0015")); sl@0: iTest->LogSubTest(_L("Update before Render")); sl@0: CursorUpdatedBeforeWindowRenderedL(); sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0248 sl@0: sl@0: @SYMDEF DEF081259 sl@0: sl@0: @SYMTestCaseDesc Tests a bad use of text cursor functionality from a client. sl@0: REQ 1079, CR RDEF-5F7Q24 (10/04/2003). sl@0: sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions This test case checks whether the window server is able to detect a bad sl@0: use of the text cursor functionality (including the custom text cursor) sl@0: by a client. sl@0: This test case launches several threads and each of them will try sl@0: to use the text cursor functionality in a non-proper way. sl@0: sl@0: @SYMTestExpectedResults Each new thread has panic code associated to it. This is the expected panic when sl@0: the thread dies. sl@0: The thread once launched is expected to panic and the returning panic code should sl@0: match the expected one. sl@0: */ sl@0: case 7: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0248")); sl@0: iTest->LogSubTest(_L("Panic")); sl@0: TestPanicsL(); sl@0: break; sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0400 sl@0: sl@0: @SYMDEF PDEF099013 sl@0: sl@0: @SYMTestCaseDesc Cursor moves slowly in text editors. sl@0: sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions This test case is a VISUAL TEST only on whether a scrolling text cursor is drawn to the sl@0: screen correctly. 2 types of cursor are checked both clipped and non clipped cursors. sl@0: In each case the test simulates a text cursor moving across the screen as if a user were sl@0: holding down a key to scroll the cursor through a section of text. sl@0: sl@0: @SYMTestExpectedResults The text cursor in both cases should scroll smoothly to the centre of the screen. sl@0: In versions prior to this fix the cursor was not correctly drawn and appeared to move sl@0: slowly. sl@0: */ sl@0: case 8: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0400")); sl@0: iTest->LogSubTest(_L("Text Cursor Update Tests")); sl@0: INC097774(); sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0401 sl@0: sl@0: @SYMDEF DEF098704 sl@0: sl@0: @SYMTestCaseDesc Test code for implemented fix to remove double cursors sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions This test case tests for artifacts left over when normal/custon flashing/non-flashing cursors are drawn. sl@0: Test that changing the focus of a custom text cursor does not leave that cursor drawn where it was (INC093898) sl@0: sl@0: @SYMTestExpectedResults sl@0: */ sl@0: case 9: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0401")); sl@0: iTest->LogSubTest(_L("Double cursors test 1")); sl@0: StartDoubleCursorTestL(1); sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0402 sl@0: sl@0: @SYMDEF DEF098704 sl@0: sl@0: @SYMTestCaseDesc Test code for implemented fix to remove double cursors sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Checks that no artifacts are left behind when a text cursor is moved from under a transparent sprite sl@0: sl@0: @SYMTestExpectedResults sl@0: */ sl@0: case 10: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0402")); sl@0: iTest->LogSubTest(_L("Double cursors test 2")); sl@0: StartDoubleCursorTestL(2); sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0403 sl@0: sl@0: @SYMDEF DEF098704 sl@0: sl@0: @SYMTestCaseDesc Test code for implemented fix to remove double cursors sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions This test moves a flashing cursor a number of times over a two second period to a seconds position. sl@0: it does it a number of times so some of the redraws will occur during the 'flash off' period sl@0: We then compare the 'after' position to what we expect sl@0: sl@0: @SYMTestExpectedResults sl@0: */ sl@0: case 11: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0403")); sl@0: iTest->LogSubTest(_L("Double cursors test 3")); sl@0: StartDoubleCursorTestL(3); sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-0483 sl@0: sl@0: @SYMDEF INC117232 sl@0: sl@0: @SYMTestCaseDesc Test code: Refreshing cursors becoming offscreen due to screen size change should not panic sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Create a cursor on bottom right of screen, change to a screen mode that excludes that coordinate sl@0: sl@0: @SYMTestExpectedResults sl@0: The server should not panic. sl@0: */ sl@0: case 12: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0483")); sl@0: iTest->LogSubTest(_L("Screen resize invalidate cursor off-screen")); sl@0: INC117232(); sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-2095-0016 sl@0: sl@0: @SYMTestCaseDesc Text Cursor flag TTextCursor::EFlagNoFlash honored sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Create a text cursor with the TTextCursor::EFlagNoFlash setting. Observe the screen over sl@0: a short period of time to verify that it remains continuously in the Flash ON state. sl@0: sl@0: @SYMTestExpectedResults sl@0: The text cursor should be always shown. sl@0: */ sl@0: case 13: sl@0: #ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-2095-0016")); sl@0: iTest->LogSubTest(_L("Text cursor EFlagNoFlash test")); sl@0: TextCursorNoFlashTestL(); sl@0: #endif sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-2095-0009 sl@0: sl@0: @SYMTestCaseDesc Text Cursor flashes when flag value is 0 sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Create a text cursor with the 0 flag setting. Observe the screen over sl@0: a short period of time to verify that the cursor flashes ON and OFF at sl@0: the correct period of one second. sl@0: sl@0: @SYMTestExpectedResults sl@0: The text cursor should flash. sl@0: */ sl@0: case 14: sl@0: #ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-2095-0009")); sl@0: iTest->LogSubTest(_L("Text cursor will Flash test")); sl@0: TextCursorFlashTestL(); sl@0: #endif sl@0: break; sl@0: sl@0: /** sl@0: @SYMTestCaseID GRAPHICS-WSERV-2095-0017 sl@0: sl@0: @SYMTestCaseDesc Text Cursor handles different valid Cursor Setttings sl@0: sl@0: @SYMTestPriority Normal sl@0: sl@0: @SYMTestStatus Implemented sl@0: sl@0: @SYMTestActions Create a text cursor and then issue a SetTextCursor. Then repeatedly sl@0: call SetTextCursor, varying the arguments relating to the Text Cursor sl@0: as well as keeping the arguments the same on one occassion. sl@0: sl@0: @SYMTestExpectedResults sl@0: The system should not panic as the arguments supplied are never invalid. sl@0: */ sl@0: case 15: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-2095-0017")); sl@0: iTest->LogSubTest(_L("SetTextCursor test")); sl@0: TextCursorSetLCoverageTests(); sl@0: break; sl@0: sl@0: default: sl@0: ((CTCursorTestStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName); sl@0: ((CTCursorTestStep*)iStep)->CloseTMSGraphicsStep(); sl@0: TestComplete(); sl@0: break; sl@0: } sl@0: ((CTCursorTestStep*)iStep)->RecordTestResultL(); sl@0: } sl@0: sl@0: __WS_CONSTRUCT_STEP__(CursorTest)