sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // Test capture key
sl@0: // 
sl@0: //
sl@0: 
sl@0: #include <e32std.h>
sl@0: #include <e32svr.h>
sl@0: #include "W32STD.H"
sl@0: #include "../tlib/testbase.h"
sl@0: #include "TMAN.H"
sl@0: 
sl@0: enum THotKeyRetValues
sl@0: 	{
sl@0: 	EHotKeyOkay,
sl@0: 	EHotKeyRetry,
sl@0: 	EHotKeyFail,
sl@0: 	};
sl@0: 
sl@0: struct SHotKeyParams
sl@0: 	{
sl@0: 	THotKey hotKey;
sl@0: 	TUint keyCode;
sl@0: 	TUint mod_mask;
sl@0: 	TUint modifiers;
sl@0: 	};
sl@0: 
sl@0: struct SHotKeyTestParams
sl@0: 	{
sl@0: 	TText *txt;			// Text message telling user what to do
sl@0: 	};
sl@0: 
sl@0: LOCAL_D SHotKeyParams HotKeys[]={
sl@0: 	{EHotKeyEnableLogging,'e',EModifierFunc|EModifierCtrl|EModifierShift,0},
sl@0: 	{EHotKeyDisableLogging,'d',EModifierFunc|EModifierCtrl|EModifierShift,EModifierFunc},
sl@0: 	{EHotKeyOfDeath,'q',0},
sl@0: 	{EHotKeyOfDeath,'w',0},
sl@0: 	};
sl@0: 	
sl@0: LOCAL_D SHotKeyTestParams HotKeyTests[]={
sl@0: 	{(TText *)_S("Use \"e\" to enable logging")},
sl@0: 	{(TText *)_S("Use \"<Alt>d\" to disable logging")},
sl@0: 	{(TText *)_S("Use \"q\" to kill the foreground app")},
sl@0: 	{(TText *)_S("Use \"w\" to kill the foreground app")},
sl@0: 	{(TText *)_S("Use \"<Cntrl><Alt><Shift>K\" to kill the foreground app")},
sl@0: 	};
sl@0: 
sl@0: LOCAL_D TBool HotKeyTestIsDeathTest[]={EFalse, EFalse, ETrue, ETrue, ETrue};
sl@0: 
sl@0: struct SErrorHotKey
sl@0: 	{
sl@0: 	THotKey hotKey;
sl@0: 	TUint keyCode;
sl@0: 	TUint mod_mask;
sl@0: 	TUint modifiers;
sl@0: 	};
sl@0: 
sl@0: LOCAL_D SErrorHotKey errorKeys[]={
sl@0: 	{EHotKeyEnableLogging,'a',EModifierFunc|EModifierShift,EModifierFunc|EModifierCtrl},
sl@0: 	{EHotKeyDisableLogging,'1',0,EModifierFunc},
sl@0: 	{EHotKeyEnableLogging,3,EModifierCtrl,EModifierCtrl|EModifierShift},
sl@0: 	{EHotKeyDisableLogging,'a',EModifierFunc|EModifierShift,EModifierFunc|EModifierCtrl},
sl@0: 	{(THotKey)100,'1',0,EModifierFunc},
sl@0: 	{(THotKey)200, 3,EModifierCtrl,EModifierCtrl|EModifierShift},
sl@0: 	};
sl@0: 
sl@0: const TInt numHotKeys=sizeof(HotKeys)/sizeof(HotKeys[0]);
sl@0: const TInt numHotKeyTests=sizeof(HotKeyTests)/sizeof(HotKeyTests[0]);
sl@0: const TInt numErrorKeys=sizeof(errorKeys)/sizeof(errorKeys[0]);
sl@0: 
sl@0: class SHKWindow;
sl@0: class THotKeyTest;
sl@0: class SHKConnection;
sl@0: 
sl@0: class SHKDeath : public CActive
sl@0: 	{
sl@0: public:
sl@0: 	SHKDeath(TInt aPriority);
sl@0: 	void SetConnection(SHKConnection *aConn);
sl@0: 	virtual void DoCancel();
sl@0: 	virtual void RunL();
sl@0: 	void Request();
sl@0: private:
sl@0: 	SHKConnection *iConn;
sl@0: 	};
sl@0: 
sl@0: class SHKWindowGroup : public CTWindowGroup
sl@0: 	{
sl@0: public:
sl@0: 	SHKWindowGroup(CTClient *aClient);
sl@0: 	void KeyL(const TKeyEvent &aKey,const TTime &aTime);
sl@0: 	};
sl@0: 
sl@0: class SHKConnection : public CTClient
sl@0: 	{
sl@0: public:
sl@0: 	SHKConnection(THotKeyTest *aTest, TInt aMode);
sl@0: 	~SHKConnection();
sl@0: 	void ConstructL();
sl@0: 	void KeyL(const TKeyEvent &aKey);
sl@0: 	void SubStateChangedL();
sl@0: 	void CompleteL();
sl@0: protected:
sl@0: 	TInt iMode;
sl@0: 	SHKDeath iDeath;
sl@0: 	THotKeyTest *iTest;
sl@0: 	CTWin *iWin;
sl@0: 	static TInt iMainWinId;
sl@0: 	};
sl@0: 
sl@0: class SHKWindow : public CTWin
sl@0: 	{
sl@0: public:
sl@0: 	SHKWindow(THotKeyTest *aTest);
sl@0: 	void SetUpL(TPoint pos,TSize size,CTWinBase *parent, CWindowGc &aGc);
sl@0: 	void Draw();
sl@0: protected:
sl@0: 	THotKeyTest *iTest;
sl@0: 	TRgb iBack;
sl@0: 	};
sl@0: 
sl@0: class SHKWindow2 : public CTWin
sl@0: 	{
sl@0: public:
sl@0: 	SHKWindow2();
sl@0: 	void SetUpL(TPoint pos,TSize size,CTWinBase *parent, CWindowGc &aGc);
sl@0: 	void Draw();
sl@0: 	};
sl@0: 
sl@0: class THotKeyTest : public CTestBase
sl@0: 	{
sl@0: public:
sl@0: 	THotKeyTest();
sl@0: 	~THotKeyTest();
sl@0: 	TestState DoTestL();
sl@0: 	void ConstructL();
sl@0: 	void EndCaptureKeyTest();
sl@0: 	TInt SubState() const;
sl@0: 	void IncSubStateL();
sl@0: 	void BadParamsL();
sl@0: private:
sl@0: 	SHKConnection *iConn1;
sl@0: 	TSize iWinSize;
sl@0: 	TInt iState;
sl@0: 	TInt iSubState;
sl@0: 	TBool iIsInActiveScheduler;
sl@0: 	};
sl@0: 
sl@0: TInt SHKConnection::iMainWinId;
sl@0: 
sl@0: TInt SubThread(TAny *);
sl@0: 
sl@0: GLDEF_C CTestBase *CreateHotKeyTest()
sl@0: 	{
sl@0: 	return(new(ELeave) THotKeyTest());
sl@0: 	}
sl@0: 
sl@0: THotKeyTest::THotKeyTest() : CTestBase(_L("Hot Key"))
sl@0: 	{}
sl@0: 
sl@0: THotKeyTest::~THotKeyTest()
sl@0: 	{
sl@0: 	User::SetJustInTime(ETrue);
sl@0: 	for(TInt index=0;index<numHotKeys;index++)
sl@0: 		{
sl@0: 		Client()->iWs.ClearHotKeys(HotKeys[index].hotKey);
sl@0: 		Client()->iWs.RestoreDefaultHotKey(HotKeys[index].hotKey);
sl@0: 		}
sl@0: 	delete iConn1;
sl@0: 	if (iIsInActiveScheduler)
sl@0: 		CActiveScheduler::Stop();
sl@0: 	}
sl@0: 
sl@0: void THotKeyTest::EndCaptureKeyTest()
sl@0: 	{
sl@0: 	Request();
sl@0: 	}
sl@0: 
sl@0: void THotKeyTest::ConstructL()
sl@0: 	{
sl@0: 	iConn1=new(ELeave) SHKConnection(this, EFalse);
sl@0: 	iConn1->ConstructL();
sl@0: 	for(TInt index=0;index<numHotKeys;index++)
sl@0: 		User::LeaveIfError(Client()->iWs.SetHotKey(HotKeys[index].hotKey, HotKeys[index].keyCode,HotKeys[index].mod_mask,HotKeys[index].modifiers));
sl@0: 	User::SetJustInTime(EFalse);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // SHKDeath //
sl@0: //
sl@0: 
sl@0: SHKDeath::SHKDeath(TInt aPriority) : CActive(aPriority)
sl@0: 	{
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	}
sl@0: 
sl@0: void SHKDeath::SetConnection(SHKConnection *aConn)
sl@0: 	{
sl@0: 	iConn=aConn;
sl@0: 	}
sl@0: 
sl@0: void SHKDeath::DoCancel()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: void SHKDeath::RunL()
sl@0: 	{
sl@0: 	iConn->CompleteL();
sl@0: 	}
sl@0: 
sl@0: void SHKDeath::Request()
sl@0: 	{
sl@0: 	SetActive();
sl@0: 	}
sl@0: 
sl@0: //
sl@0: 
sl@0: SHKWindowGroup::SHKWindowGroup(CTClient *aClient) : CTWindowGroup(aClient)
sl@0: 	{}
sl@0: 
sl@0: void SHKWindowGroup::KeyL(const TKeyEvent &aKey,const TTime &)
sl@0: 	{
sl@0: 	((SHKConnection *)iClient)->KeyL(aKey);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // SHKConnection
sl@0: 
sl@0: SHKConnection::SHKConnection(THotKeyTest *aTest, TInt aMode) : iMode(aMode), iDeath(100), iTest(aTest)
sl@0: 	{
sl@0: 	iDeath.SetConnection(this);
sl@0: 	}
sl@0: 
sl@0: SHKConnection::~SHKConnection()
sl@0: 	{
sl@0: 	iGroup->GroupWin()->EnableReceiptOfFocus(EFalse);
sl@0: 	CTWin::Delete(iWin);
sl@0: 	}
sl@0: 
sl@0: void SHKConnection::KeyL(const TKeyEvent &aKey)
sl@0: 	{
sl@0: 	if (iTest)
sl@0: 		{
sl@0: 		if (aKey.iCode==EKeyEnter && !HotKeyTestIsDeathTest[iTest->SubState()])
sl@0: 			iTest->IncSubStateL();
sl@0: 		else if (aKey.iCode==EKeyEscape)
sl@0: 			iTest->AbortL();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void SHKConnection::CompleteL()
sl@0: 	{
sl@0: 	iTest->IncSubStateL();
sl@0: 	}
sl@0: 
sl@0: void SHKConnection::SubStateChangedL()
sl@0: 	{
sl@0: 	if (HotKeyTestIsDeathTest[iTest->SubState()])
sl@0: 		{
sl@0: 		RThread thread;
sl@0: 		iMainWinId=iGroup->GroupWin()->Identifier();
sl@0: 		TInt subState=iTest->SubState();
sl@0: 		User::After(100000);
sl@0: 		User::LeaveIfError(thread.Create(_L("SubThread"),SubThread,KDefaultStackSize,0x2000,0x2000,&subState,EOwnerThread));
sl@0: 		thread.Logon(iDeath.iStatus);
sl@0: 		iDeath.Request();
sl@0: 		thread.Resume();
sl@0: 		thread.Close();
sl@0: 		}
sl@0: 	iWin->Invalidate();
sl@0: 	iWs.Flush();
sl@0: 	}
sl@0: 
sl@0: void SHKConnection::ConstructL()
sl@0: 	{
sl@0: 	CTClient::ConstructL();
sl@0: 	iGroup=new(ELeave) SHKWindowGroup(this);
sl@0: 	iGroup->ConstructL();
sl@0: 	TSize screenSize=iGroup->Size();
sl@0: 	iGroup->GroupWin()->AutoForeground(EFalse);		// Don't allow clicking to cause foreground, might mess up test
sl@0: 	TInt winWidth;
sl@0: 	TInt winHeight;
sl@0: 	if (iMode==0)
sl@0: 		{
sl@0: 		winWidth=screenSize.iWidth/2;
sl@0: 		winHeight=screenSize.iHeight-10;
sl@0: 		SHKWindow *win=new(ELeave) SHKWindow(iTest);
sl@0: 		win->SetUpL(TPoint(5,5),TSize(winWidth,winHeight),iGroup,*iGc);
sl@0: 		iWin=win;
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		winWidth=150;
sl@0: 		winHeight=50;
sl@0: 		iGroup->GroupWin()->SetOwningWindowGroup(iMainWinId);
sl@0: 		SHKWindow2 *win=new(ELeave) SHKWindow2();
sl@0: 		win->SetUpL(TPoint((screenSize.iWidth-winWidth)/2,(screenSize.iHeight-winHeight)/2),TSize(winWidth,winHeight),iGroup,*iGc);
sl@0: 		iWin=win;
sl@0: 		}
sl@0: 	iWs.Flush();
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // SHKWindow, class //
sl@0: //
sl@0: 
sl@0: SHKWindow::SHKWindow(THotKeyTest *aTest) : CTWin(), iTest(aTest)
sl@0: 	{
sl@0: 	iBack=TRgb::Gray256(230);
sl@0: 	}
sl@0: 
sl@0: void SHKWindow::SetUpL(TPoint pos,TSize size,CTWinBase *parent, CWindowGc &aGc)
sl@0: 	{
sl@0: 	ConstructExtLD(*parent,pos,size);
sl@0: 	iWin.SetBackgroundColor(iBack);
sl@0: 	Activate();
sl@0: 	AssignGC(aGc);
sl@0: 	}
sl@0: 
sl@0: void SHKWindow::Draw()
sl@0: 	{
sl@0: 	iGc->Clear();
sl@0: 	iGc->DrawText(TPtrC(HotKeyTests[iTest->SubState()].txt), TPoint(10,20));
sl@0: 	iGc->DrawText(TPtrC(_L("Press <Enter> when tested okay")), TPoint(10,35));
sl@0: 	iGc->DrawText(TPtrC(_L("or escape to abort tests")), TPoint(10,50));
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // SHKWindow2, class //
sl@0: //
sl@0: 
sl@0: SHKWindow2::SHKWindow2() : CTWin()
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: void SHKWindow2::SetUpL(TPoint pos,TSize size,CTWinBase *parent, CWindowGc &aGc)
sl@0: 	{
sl@0: 	ConstructExtLD(*parent,pos,size);
sl@0: 	iWin.SetBackgroundColor(TRgb(0,0,0));
sl@0: 	Activate();
sl@0: 	AssignGC(aGc);
sl@0: 	}
sl@0: 
sl@0: void SHKWindow2::Draw()
sl@0: 	{
sl@0: 	iGc->SetBrushColor(TRgb::Gray4(1));
sl@0: 	iGc->Clear();
sl@0: 	iGc->SetPenColor(TRgb::Gray4(3));
sl@0: 	iGc->DrawText(TPtrC(_L("Kill me!!!")), TPoint(10,15));
sl@0: 	}
sl@0: 
sl@0: //
sl@0: 
sl@0: TInt THotKeyTest::SubState() const
sl@0: 	{
sl@0: 	return(iSubState);
sl@0: 	}
sl@0: 
sl@0: void THotKeyTest::IncSubStateL()
sl@0: 	{
sl@0: 	if (iSubState==(numHotKeyTests-1))
sl@0: 		EndCaptureKeyTest();
sl@0: 	else
sl@0: 		{
sl@0: 		iSubState++;
sl@0: 		iConn1->SubStateChangedL();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void THotKeyTest::BadParamsL()
sl@0: 	{
sl@0: 	TInt resCount=Client()->iWs.ResourceCount();
sl@0: 	for(TInt index=0;index<numErrorKeys;index++)
sl@0: 		TestL(Client()->iWs.SetHotKey(errorKeys[index].hotKey, errorKeys[index].keyCode,errorKeys[index].mod_mask,errorKeys[index].modifiers)==KErrArgument);
sl@0: 	TestL(Client()->iWs.ResourceCount()==resCount);
sl@0: 	}
sl@0: 
sl@0: TestState THotKeyTest::DoTestL()
sl@0: 	{
sl@0: 	switch(iState)
sl@0: 		{
sl@0: 		case 0:
sl@0: 			LogSubTest(_L("Errors"),1);
sl@0: 			BadParamsL();
sl@0: 			LogSubTest(_L("CaptureKey"),2);
sl@0: 			iState++;
sl@0: 			return(EContinue);
sl@0: 		default:
sl@0: 			return(EFinished);
sl@0: 		}
sl@0:  	}
sl@0: 
sl@0: //======================================================//
sl@0: // Sub thread to do tests and get shot by window server //
sl@0: //======================================================//
sl@0: 
sl@0: void SubThreadMain()
sl@0: 	{
sl@0: 	CActiveScheduler *TheActiveScheduler=new(ELeave) CActiveScheduler;
sl@0: 	CActiveScheduler::Install(TheActiveScheduler);
sl@0: 	SHKConnection *conn=new(ELeave) SHKConnection(NULL, ETrue);
sl@0: 	conn->ConstructL();
sl@0: 	CActiveScheduler::Start();
sl@0: 	delete TheActiveScheduler;
sl@0: 	}
sl@0: 
sl@0: TInt SubThread(TAny *)
sl@0: 	{
sl@0: 	CTrapCleanup* CleanUpStack=CTrapCleanup::New();
sl@0: 	TRAPD(err,SubThreadMain());
sl@0: 	delete CleanUpStack;
sl@0: 	return(err);
sl@0: 	}