sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Keyboard repeat test sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include "W32STD.H" sl@0: #include "../tlib/testbase.h" sl@0: #include "TMAN.H" sl@0: sl@0: class CRKWindow; sl@0: sl@0: class TKRepeatTest : public CTestBase sl@0: { sl@0: public: sl@0: TKRepeatTest(); sl@0: ~TKRepeatTest(); sl@0: TestState DoTestL(); sl@0: void ConstructL(); sl@0: void TestKeyboardRepeatRateL(const TTimeIntervalMicroSeconds32 &aInitialTime, const TTimeIntervalMicroSeconds32 &aTime); sl@0: TBool CheckReportL(); sl@0: public: sl@0: TBool iAbort; sl@0: private: sl@0: TTimeIntervalMicroSeconds32 iOldInitialTime; sl@0: TTimeIntervalMicroSeconds32 iOldTime; sl@0: CRKWindow *iWin; sl@0: TSize iWinSize; sl@0: TInt iState; sl@0: }; sl@0: sl@0: class CRKWindow : public CTWin sl@0: { sl@0: enum TRKStates { sl@0: EStateWaitingForKeyDown, sl@0: EStateWaitingForKeyCode, sl@0: EStateWaitingForFirstRepeat, sl@0: EStateWaitingForNthRepeat, sl@0: EStateWaitingForKeyUp, sl@0: EStateInactive, sl@0: EStateError, sl@0: }; sl@0: public: sl@0: CRKWindow(TKRepeatTest *aTest); sl@0: void SetUpL(TPoint pos,TSize size,CTWinBase *parent, CWindowGc &aGc); sl@0: void SetState(TRKStates aState); sl@0: void SetKeyboardRepeatRate(const TTimeIntervalMicroSeconds32 &aInitialTime, const TTimeIntervalMicroSeconds32 &aTime); sl@0: void WinKeyL(const TKeyEvent &,const TTime &); sl@0: void KeyUpL(const TKeyEvent &aKey,const TTime &aTime); sl@0: void KeyDownL(const TKeyEvent &aKey,const TTime &aTime); sl@0: void Draw(); sl@0: TDesC& Report(); sl@0: TBool CheckResults(); sl@0: protected: sl@0: TInt iConnIndex; sl@0: TKRepeatTest *iTest; sl@0: TRgb iBack; sl@0: TRKStates iState; sl@0: TInt iDownCode; sl@0: TInt iRepCount; sl@0: TTimeIntervalMicroSeconds32 iInitialRepeatSet; sl@0: TTimeIntervalMicroSeconds32 iRepeatSet; sl@0: TTime iPrevTime; sl@0: TTimeIntervalMicroSeconds32 iInitialGap; sl@0: TTimeIntervalMicroSeconds32 iTotalGap; sl@0: TTimeIntervalMicroSeconds32 iMinGap; sl@0: TTimeIntervalMicroSeconds32 iMaxGap; sl@0: TBuf<0x40> iReport; sl@0: }; sl@0: sl@0: GLDEF_C CTestBase *CreateKRepeatTest() sl@0: { sl@0: return(new(ELeave) TKRepeatTest()); sl@0: } sl@0: sl@0: // sl@0: // CRKWindow, class // sl@0: // sl@0: sl@0: CRKWindow::CRKWindow(TKRepeatTest *aTest) : CTWin(), iTest(aTest) sl@0: { sl@0: } sl@0: sl@0: void CRKWindow::SetUpL(TPoint pos,TSize size,CTWinBase *parent, CWindowGc &aGc) sl@0: { sl@0: ConstructExtLD(*parent,pos,size); sl@0: iWin.SetBackgroundColor(TRgb::Gray256(230)); sl@0: Activate(); sl@0: AssignGC(aGc); sl@0: } sl@0: sl@0: void CRKWindow::Draw() sl@0: { sl@0: iGc->Clear(); sl@0: switch(iState) sl@0: { sl@0: case EStateWaitingForKeyDown: sl@0: iGc->DrawText(_L("Press and hold the space bar"), TPoint(10,20)); sl@0: break; sl@0: case EStateWaitingForFirstRepeat: sl@0: case EStateWaitingForNthRepeat: sl@0: { sl@0: TBuf<0x40> buf; sl@0: buf.Format(TRefByValue(_L("Keep space bar down (%d repeats so far)")),iRepCount); sl@0: iGc->DrawText(buf, TPoint(10,20)); sl@0: } sl@0: break; sl@0: case EStateWaitingForKeyUp: sl@0: iGc->DrawText(_L("Release space bar"), TPoint(10,20)); sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: void CRKWindow::SetState(TRKStates aState) sl@0: { sl@0: iState=aState; sl@0: DrawNow(); sl@0: } sl@0: sl@0: TBool CRKWindow::CheckResults() sl@0: { sl@0: // sl@0: // Checks repeat results, first convert everything to 10th's as that what is actually used sl@0: // for the timer in the window server. sl@0: // sl@0: // Return ETrue if the inacuracy in the average time is greater than 1/10th either way sl@0: // Allow initial 2/10ths either sl@0: // Allow min 2/10ths below sl@0: // Allow max 2/10ths above sl@0: // sl@0: if (iState!=EStateInactive) sl@0: return(ETrue); sl@0: TInt initial=iInitialGap.Int()/100000; sl@0: TInt initialX=iInitialRepeatSet.Int()/100000; sl@0: if (initialX==0) sl@0: initialX=1; sl@0: TInt average=(iTotalGap.Int()/100000)/(iRepCount-1); sl@0: TInt repeatX=iRepeatSet.Int()/100000; sl@0: if (repeatX==0) sl@0: repeatX=1; sl@0: TInt min=iMinGap.Int()/100000; sl@0: TInt max=iMaxGap.Int()/100000; sl@0: if (average>(repeatX+1) || average<(repeatX-1)) sl@0: return(ETrue); sl@0: if (initial>(initialX+2) || initial<(initialX-2)) sl@0: return(ETrue); sl@0: if (min>(repeatX+1) || min<(repeatX-2)) sl@0: return(ETrue); sl@0: if (max>(repeatX+3) || max(_L("Initial=%d [%d], Av=%d [%d], Min=%d, Max=%d")),initial,initialX,average,repeatX,min,max); sl@0: } sl@0: return(iReport); sl@0: } sl@0: sl@0: void CRKWindow::KeyDownL(const TKeyEvent &aKey,const TTime &) sl@0: { sl@0: switch(iState) sl@0: { sl@0: case EStateWaitingForKeyDown: sl@0: SetState(EStateWaitingForKeyCode); sl@0: iDownCode=aKey.iScanCode; sl@0: break; sl@0: default:; sl@0: } sl@0: } sl@0: sl@0: void CRKWindow::KeyUpL(const TKeyEvent &aKey,const TTime &) sl@0: { sl@0: if (aKey.iScanCode==iDownCode) sl@0: { sl@0: switch(iState) sl@0: { sl@0: case EStateWaitingForKeyUp: sl@0: SetState(EStateInactive); sl@0: break; sl@0: default: sl@0: SetState(EStateError); sl@0: break; sl@0: } sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: } sl@0: sl@0: void CRKWindow::WinKeyL(const TKeyEvent &aKey,const TTime &aTime) sl@0: { sl@0: if (aKey.iCode==EKeyEscape) sl@0: { sl@0: CActiveScheduler::Stop(); sl@0: iTest->iAbort=ETrue; sl@0: } sl@0: if (aKey.iCode==32) sl@0: { sl@0: switch(iState) sl@0: { sl@0: case EStateWaitingForKeyCode: sl@0: SetState(EStateWaitingForFirstRepeat); sl@0: iPrevTime=aTime; sl@0: break; sl@0: case EStateWaitingForFirstRepeat: sl@0: iRepCount=1; sl@0: iInitialGap = I64LOW(aTime.MicroSecondsFrom(iPrevTime).Int64()); sl@0: SetState(EStateWaitingForNthRepeat); sl@0: break; sl@0: case EStateWaitingForNthRepeat: sl@0: if (iRepCount==5) sl@0: SetState(EStateWaitingForKeyUp); sl@0: else sl@0: { sl@0: TTimeIntervalMicroSeconds32 gap(I64LOW(aTime.MicroSecondsFrom(iPrevTime).Int64())); sl@0: if (gapiMaxGap) sl@0: iMaxGap=gap; sl@0: iTotalGap=iTotalGap.Int()+gap.Int(); // Horrible way to do a += sl@0: iRepCount++; sl@0: SetState(EStateWaitingForNthRepeat); sl@0: } sl@0: case EStateWaitingForKeyUp: // Do nothing here sl@0: break; sl@0: default: sl@0: iTest->TestL(EFalse); sl@0: } sl@0: iPrevTime=aTime; sl@0: } sl@0: } sl@0: sl@0: void CRKWindow::SetKeyboardRepeatRate(const TTimeIntervalMicroSeconds32 &aInitialTime, const TTimeIntervalMicroSeconds32 &aTime) sl@0: { sl@0: iInitialRepeatSet=aInitialTime; sl@0: iRepeatSet=aTime; sl@0: iMinGap=TTimeIntervalMicroSeconds32(100000000); // Any very big number will do sl@0: iMaxGap=TTimeIntervalMicroSeconds32(0); sl@0: iTotalGap=TTimeIntervalMicroSeconds32(0); sl@0: SetState(EStateWaitingForKeyDown); sl@0: Client()->iWs.Flush(); sl@0: } sl@0: sl@0: // sl@0: sl@0: TKRepeatTest::TKRepeatTest() : CTestBase(_L("KRepeat")) sl@0: {} sl@0: sl@0: TKRepeatTest::~TKRepeatTest() sl@0: { sl@0: CTWin::Delete(iWin); sl@0: Client()->iWs.SetKeyboardRepeatRate(iOldInitialTime, iOldTime); sl@0: } sl@0: sl@0: void TKRepeatTest::ConstructL() sl@0: { sl@0: iWin=new(ELeave) CRKWindow(this); sl@0: TSize screenSize=Client()->iGroup->Size(); sl@0: iWin->SetUpL(TPoint(5,5),TSize(screenSize.iWidth/2,screenSize.iHeight-10),Client()->iGroup,*Client()->iGc); sl@0: Client()->iGroup->SetCurrentWindow(iWin); sl@0: Client()->iWs.GetKeyboardRepeatRate(iOldInitialTime, iOldTime); sl@0: } sl@0: sl@0: TInt TKRepeatTest::CheckReportL() sl@0: { sl@0: if (iWin->CheckResults()) sl@0: { sl@0: CTDialog *dialog=new(ELeave) CTDialog(); sl@0: dialog->SetTitle(_L("Keyboard repeat innacuracies")); sl@0: dialog->SetLine1(iWin->Report()); sl@0: dialog->SetNumButtons(2); sl@0: dialog->SetButtonText(0,_L("Okay")); sl@0: dialog->SetButtonText(1,_L("Retest")); sl@0: dialog->SetButtonText(2,_L("Fail")); sl@0: dialog->ConstructLD(*Client()->iGroup,*Client()->iGc); sl@0: switch(dialog->Display()) sl@0: { sl@0: case 0: sl@0: break; sl@0: case 1: sl@0: return(ETrue); // Redo test sl@0: case 2: sl@0: TestL(EFalse); sl@0: break; sl@0: } sl@0: } sl@0: return(EFalse); sl@0: } sl@0: sl@0: void TKRepeatTest::TestKeyboardRepeatRateL(const TTimeIntervalMicroSeconds32 &aInitialTime, const TTimeIntervalMicroSeconds32 &aTime) sl@0: { sl@0: do sl@0: { sl@0: Client()->iWs.SetKeyboardRepeatRate(aInitialTime, aTime); sl@0: iWin->SetKeyboardRepeatRate(aInitialTime, aTime); sl@0: CActiveScheduler::Start(); sl@0: if (iAbort) sl@0: AbortL(); sl@0: } while(CheckReportL()); sl@0: } sl@0: sl@0: TestState TKRepeatTest::DoTestL() sl@0: { sl@0: switch(iState) sl@0: { sl@0: case 0: sl@0: LogSubTest(_L("Keyboard Repeat"),1); sl@0: TestKeyboardRepeatRateL(TTimeIntervalMicroSeconds32(1000000), TTimeIntervalMicroSeconds32(500000)); sl@0: LogSubTest(_L("Keyboard Repeat"),2); sl@0: TestKeyboardRepeatRateL(TTimeIntervalMicroSeconds32(200000), TTimeIntervalMicroSeconds32(100000)); sl@0: LogSubTest(_L("Keyboard Repeat"),3); sl@0: TestKeyboardRepeatRateL(TTimeIntervalMicroSeconds32(0), TTimeIntervalMicroSeconds32(100000)); sl@0: LogSubTest(_L("Keyboard Repeat"),4); sl@0: TestKeyboardRepeatRateL(TTimeIntervalMicroSeconds32(100000), TTimeIntervalMicroSeconds32(100000)); sl@0: iState++; sl@0: break; sl@0: default: sl@0: return(EFinished); sl@0: } sl@0: return(ENext); sl@0: } sl@0: