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