--- /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<TSpriteMember*>(aSpriteMember);
+ delete member->iBitmap;
+ member->iBitmap=NULL;
+ delete member->iMaskBitmap;
+ member->iMaskBitmap=NULL;
+ }
+
+CCustomTextCursor::~CCustomTextCursor()
+ {
+ const TInt count = iSpriteMemberArray.Count();
+ for (TInt index=0; index<count; ++index)
+ {
+ DeleteSpriteMember(&iSpriteMemberArray[index]);
+ }
+ iSpriteMemberArray.Close();
+ }
+
+CCustomTextCursor::CCustomTextCursor(CTestBase* aTest)
+ : iTest(aTest)
+ {
+ }
+
+void CCustomTextCursor::ConstructL(TInt aScreenNumber,TInt aBmpIndex)
+ {
+ ASSERT(aBmpIndex < KNumberOfCustoTextCursors);
+
+
+ TSpriteMember spriteMember;
+ spriteMember.iBitmap = NULL;
+ spriteMember.iMaskBitmap = NULL;
+ spriteMember.iInvertMask =EFalse;
+ spriteMember.iDrawMode = CGraphicsContext::EDrawModePEN;
+ spriteMember.iOffset = TPoint();
+ spriteMember.iInterval = TTimeIntervalMicroSeconds32(0);
+ CleanupStack::PushL(TCleanupItem(DeleteSpriteMember, &spriteMember));
+ spriteMember.iBitmap = new (ELeave) CFbsBitmap;
+ User::LeaveIfError(spriteMember.iBitmap->Load(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<CCustomTextCursor>& CustomTextCursorsArray();
+ inline CCustomTextCursor& CustomTextCursor(TInt aIndex);
+private:
+ void ConstructL(TInt aScreenNumber,CTestBase* aTest);
+private:
+ RPointerArray<CCustomTextCursor> iCustomTextCursors;
+ };
+
+inline RPointerArray<CCustomTextCursor>& 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; index<KNumberOfCustoTextCursors; ++index)
+ {
+ CCustomTextCursor* customTextCursor=CCustomTextCursor::CreateCustomTextCursorL(aScreenNumber,index, aTest);
+ CleanupStack::PushL(customTextCursor);
+ User::LeaveIfError(iCustomTextCursors.Append(customTextCursor));
+ CleanupStack::Pop(customTextCursor);
+ }
+ }
+
+CTCursorTest::CTCursorTest(CTestStep* aStep) :
+ CTWsGraphicsBase(aStep)
+ {
+ iCursorType = TTextCursor::ETypeFirst;
+ iStaticTest=iTest;
+ }
+
+CTCursorTest::~CTCursorTest()
+ {
+ delete iWorkInProgress;
+ delete iComparisonWindow;
+ }
+
+TInt CTCursorTest::DoPanicTest(TInt aInt, TAny *aScreenNumber)
+ {
+ RWsSession ws;
+ if (ws.Connect()==KErrNone)
+ {
+ // use correct screen
+ CWsScreenDevice* screen = new (ELeave) CWsScreenDevice(ws);
+ User::LeaveIfError(screen->Construct((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<TSpriteMember> 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<TUint>(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; index<count; ++index)
+ {
+ CCustomTextCursor& customTextCursor = customTextCursorsWrapper->CustomTextCursor(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; index<count; ++index)
+ {
+ CCustomTextCursor& customTextCursor = customTextCursorsWrapper->CustomTextCursor(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;mode<TheClient->iScreenModes.Count();mode++)
+ {
+ TPixelsTwipsAndRotation testModeSize;
+ TheClient->iScreen->GetScreenModeSizeAndRotation(mode,testModeSize);
+ if ( testModeSize.iPixelSize.iWidth<currModeSize.iPixelSize.iWidth-10
+ || testModeSize.iPixelSize.iHeight<currModeSize.iPixelSize.iHeight-10
+ )
+ {
+ testMode=mode;
+ break;
+ }
+ }
+ if (testMode==currMode)
+ {
+ _LIT(KLog,"No smaller screen-size modes available - INC117232 test skipped");
+ LOG_MESSAGE(KLog);
+ //iStep->SetTestStepResult(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; i<KIterations; i++)
+ {
+ // move the cursor to its new position
+ TheClient->iGroup->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)