--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fep/frontendprocessor/test/src/FepSwitch.cpp Tue Feb 02 01:02:04 2010 +0200
@@ -0,0 +1,420 @@
+// Copyright (c) 2005-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:
+//
+
+#include <e32std.h>
+#include <e32keys.h>
+#include <centralrepository.h>
+#include <w32std.h>
+#include <coedef.h>
+#include <fepbase.h>
+#include <apgwgnam.h>
+#include <graphics/cone/coedefkeys.h>
+
+class CFepKeyDataListener;
+
+const TUid KFepSwitchAppUid = {0xfabbabba}; // fake uid
+
+// class definitions
+
+class CFepSwitcher : public CActive
+ {
+public:
+ static CFepSwitcher* NewLC();
+ virtual ~CFepSwitcher();
+ void SetOnOrOffKeyDataL(TInt aError, const TFepOnOrOffKeyData& aNewKeyData, TInt32 CFepSwitcher::* aCaptureKeyHandleOrError, TFepOnOrOffKeyData CFepSwitcher::* aKeyDataToAssignTo);
+ void RetryFailedKeyCaptures(TBool& aNeedFurtherRetry);
+private:
+ class CRetryOnError : public CTimer
+ {
+ public:
+ static CRetryOnError* NewL(CFepSwitcher& aFepSwitcher);
+ virtual ~CRetryOnError();
+ void Activate();
+ private:
+ CRetryOnError(CFepSwitcher& aFepSwitcher);
+ void DoActivate();
+ // from CActive (via CTimer)
+ virtual void RunL();
+ private:
+ CFepSwitcher& iFepSwitcher;
+ TInt iRetryCount;
+ };
+private:
+ CFepSwitcher();
+ void ConstructL();
+ void Queue();
+ static TBool MatchesKeyData(const TKeyEvent& aKeyEvent, const TFepOnOrOffKeyData& aKeyData);
+ // from CActive
+ virtual void DoCancel();
+ virtual void RunL();
+private:
+ TUint iFlags;
+ TInt32 iOnKey_CaptureKeyHandleOrError;
+ TInt32 iOffKey_CaptureKeyHandleOrError; // a capture-key handle
+ RWsSession iWsSession;
+ RWindowGroup iWindowGroup;
+ CFepGenericGlobalSettings* iFepGenericGlobalSettings;
+ CRetryOnError* iRetryOnError;
+ TFepOnOrOffKeyData iOnKeyData;
+ TFepOnOrOffKeyData iOffKeyData;
+ CFepKeyDataListener* iFepKeyDataListener_OnKey;
+ CFepKeyDataListener* iFepKeyDataListener_OffKey;
+ };
+
+class CFepKeyDataListener : public CActive
+ {
+public:
+ static CFepKeyDataListener* NewLC(CFepSwitcher& aFepSwitcher, TUint32 aRepositoryKeyMask_OnOrOff, TInt32 CFepSwitcher::* aCaptureKeyHandleOrError, TFepOnOrOffKeyData CFepSwitcher::* aKeyDataToAssignTo);
+ virtual ~CFepKeyDataListener();
+private:
+ CFepKeyDataListener(CFepSwitcher& aFepSwitcher, TUint32 aRepositoryKeyMask_OnOrOff, TInt32 CFepSwitcher::* aCaptureKeyHandleOrError, TFepOnOrOffKeyData CFepSwitcher::* aKeyDataToAssignTo);
+ void ConstructL();
+ void SetFepSwitcherL();
+ void Queue();
+ // from CActive
+ virtual void DoCancel();
+ virtual void RunL();
+private:
+ CFepSwitcher& iFepSwitcher;
+ const TUint32 iRepositoryKeyMask_OnOrOff;
+ CRepository* iRepository;
+ TInt32 CFepSwitcher::* const iCaptureKeyHandleOrError;
+ TFepOnOrOffKeyData CFepSwitcher::* const iKeyDataToAssignTo;
+ };
+
+// CFepSwitcher
+
+CFepSwitcher* CFepSwitcher::NewLC()
+ {
+ CFepSwitcher* const self=new(ELeave) CFepSwitcher;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+CFepSwitcher::~CFepSwitcher()
+ {
+ Cancel();
+ if (iWindowGroup.WsHandle()!=0)
+ {
+ if (iOnKey_CaptureKeyHandleOrError>0)
+ {
+ iWindowGroup.CancelCaptureKey(iOnKey_CaptureKeyHandleOrError);
+ }
+ if (iOffKey_CaptureKeyHandleOrError>0)
+ {
+ iWindowGroup.CancelCaptureKey(iOffKey_CaptureKeyHandleOrError);
+ }
+ iWindowGroup.Close();
+ }
+ iWsSession.Close();
+ delete iFepGenericGlobalSettings;
+ delete iRetryOnError;
+ delete iFepKeyDataListener_OnKey;
+ delete iFepKeyDataListener_OffKey;
+ }
+
+void CFepSwitcher::SetOnOrOffKeyDataL(TInt aError, const TFepOnOrOffKeyData& aNewKeyData, TInt32 CFepSwitcher::* aCaptureKeyHandleOrError, TFepOnOrOffKeyData CFepSwitcher::* aKeyDataToAssignTo)
+ {
+ // change the state of this object
+ TInt32& captureKeyHandleOrError=this->*aCaptureKeyHandleOrError;
+ TInt32 captureKeyToCancel=0;
+ if (aError!=KErrNone)
+ {
+ captureKeyToCancel=captureKeyHandleOrError;
+ captureKeyHandleOrError=0;
+ }
+ else if (this->*aKeyDataToAssignTo!=aNewKeyData)
+ {
+ this->*aKeyDataToAssignTo=aNewKeyData;
+ captureKeyToCancel=captureKeyHandleOrError;
+ captureKeyHandleOrError=iWindowGroup.CaptureKey(aNewKeyData.CharacterCodeForFoldedMatch(), aNewKeyData.ModifierMask(), aNewKeyData.ModifierValues());
+ }
+ if (captureKeyToCancel>0)
+ {
+ iWindowGroup.CancelCaptureKey(captureKeyToCancel);
+ }
+
+ // kick-off or stop iRetryOnError, if need be
+ if ((iOnKey_CaptureKeyHandleOrError>=0) && (iOffKey_CaptureKeyHandleOrError>=0))
+ {
+ iRetryOnError->Cancel();
+ }
+ else if (!iRetryOnError->IsActive())
+ {
+ iRetryOnError->Activate();
+ }
+ }
+
+void CFepSwitcher::RetryFailedKeyCaptures(TBool& aNeedFurtherRetry)
+ {
+ __ASSERT_DEBUG((iOnKey_CaptureKeyHandleOrError<0) || (iOffKey_CaptureKeyHandleOrError<0), User::Invariant());
+ if (iOnKey_CaptureKeyHandleOrError<0)
+ {
+ iOnKey_CaptureKeyHandleOrError=iWindowGroup.CaptureKey(iOnKeyData.CharacterCodeForFoldedMatch(), iOnKeyData.ModifierMask(), iOnKeyData.ModifierValues());
+ }
+ if (iOffKey_CaptureKeyHandleOrError<0)
+ {
+ iOffKey_CaptureKeyHandleOrError=iWindowGroup.CaptureKey(iOffKeyData.CharacterCodeForFoldedMatch(), iOffKeyData.ModifierMask(), iOffKeyData.ModifierValues());
+ }
+ aNeedFurtherRetry=((iOnKey_CaptureKeyHandleOrError<0) || (iOffKey_CaptureKeyHandleOrError<0));
+ }
+
+CFepSwitcher::CFepSwitcher()
+ :CActive(EPriorityStandard),
+ iFlags(0),
+ iOnKey_CaptureKeyHandleOrError(0),
+ iOffKey_CaptureKeyHandleOrError(0),
+ iFepGenericGlobalSettings(NULL),
+ iRetryOnError(NULL),
+ iOnKeyData(0, 0, 0),
+ iOffKeyData(0, 0, 0),
+ iFepKeyDataListener_OnKey(NULL),
+ iFepKeyDataListener_OffKey(NULL)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CFepSwitcher::ConstructL()
+ {
+ User::LeaveIfError(iWsSession.Connect());
+ iWindowGroup=RWindowGroup(iWsSession);
+ User::LeaveIfError(iWindowGroup.Construct(REINTERPRET_CAST(TUint32, this), EFalse));
+ CApaWindowGroupName* wgName=CApaWindowGroupName::NewLC(iWsSession,iWindowGroup.Identifier());
+ wgName->SetHidden(ETrue);
+ wgName->SetAppUid(KFepSwitchAppUid);
+ wgName->SetWindowGroupName(iWindowGroup);
+ CleanupStack::PopAndDestroy(wgName);
+ iFepGenericGlobalSettings=CFepGenericGlobalSettings::NewL();
+ iRetryOnError=CRetryOnError::NewL(*this);
+ iFepKeyDataListener_OnKey=CFepKeyDataListener::NewLC(*this, ERepositoryKeyMask_OnKeyData, &CFepSwitcher::iOnKey_CaptureKeyHandleOrError, &CFepSwitcher::iOnKeyData);
+ iFepKeyDataListener_OffKey=CFepKeyDataListener::NewLC(*this, ERepositoryKeyMask_OffKeyData, &CFepSwitcher::iOffKey_CaptureKeyHandleOrError, &CFepSwitcher::iOffKeyData);
+ Queue();
+ }
+
+void CFepSwitcher::Queue()
+ {
+ iWsSession.EventReady(&iStatus);
+ SetActive();
+ }
+
+TBool CFepSwitcher::MatchesKeyData(const TKeyEvent& aKeyEvent, const TFepOnOrOffKeyData& aKeyData)
+ { // static
+ return ((User::Fold(aKeyEvent.iCode)==User::Fold(aKeyData.CharacterCodeForFoldedMatch())) &&
+ ((aKeyEvent.iModifiers&aKeyData.ModifierMask())==aKeyData.ModifierValues()));
+ }
+
+void CFepSwitcher::DoCancel()
+ {
+ iWsSession.EventReadyCancel();
+ }
+
+void CFepSwitcher::RunL()
+ {
+ const TInt error=iStatus.Int();
+ if (error<KErrNone)
+ {
+ Queue();
+ User::Leave(error);
+ }
+ TWsEvent event;
+ iWsSession.GetEvent(event); // need to call this *before* Queue (which calls iWsSession.EventReady), otherwise Wserv panics us
+ Queue();
+ if (event.Type()==EEventKey)
+ {
+ const TBool isOn=iFepGenericGlobalSettings->IsOn();
+ const TKeyEvent& keyEvent=*event.Key();
+ if ((!isOn) && MatchesKeyData(keyEvent, iOnKeyData))
+ {
+ iFepGenericGlobalSettings->SetIsOn(ETrue);
+ iFepGenericGlobalSettings->StoreChangesAndBroadcastL();
+ }
+ else if (isOn && MatchesKeyData(keyEvent, iOffKeyData))
+ {
+ iFepGenericGlobalSettings->SetIsOn(EFalse);
+ iFepGenericGlobalSettings->StoreChangesAndBroadcastL();
+ }
+ }
+ }
+
+// CFepSwitcher::CRetryOnError
+
+CFepSwitcher::CRetryOnError* CFepSwitcher::CRetryOnError::NewL(CFepSwitcher& aFepSwitcher)
+ { // static
+ CRetryOnError* const self=new(ELeave) CRetryOnError(aFepSwitcher);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CFepSwitcher::CRetryOnError::~CRetryOnError()
+ {
+ Cancel();
+ }
+
+void CFepSwitcher::CRetryOnError::Activate()
+ {
+ iRetryCount=0;
+ DoActivate();
+ }
+
+CFepSwitcher::CRetryOnError::CRetryOnError(CFepSwitcher& aFepSwitcher)
+ :CTimer(EPriorityStandard+1),
+ iFepSwitcher(aFepSwitcher)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CFepSwitcher::CRetryOnError::DoActivate()
+ {
+ // retry every second for a minute, followed by every minute for an hour, followed by every hour
+ TInt timeInterval=1000000;
+ if (iRetryCount>=120)
+ {
+ timeInterval*=(60*60); // up it to every hour
+ }
+ else if (iRetryCount>=60)
+ {
+ timeInterval*=60; // up it to every minute
+ }
+ After(TTimeIntervalMicroSeconds32(timeInterval));
+ }
+
+void CFepSwitcher::CRetryOnError::RunL()
+ {
+ const TInt error=iStatus.Int();
+ TBool needFurtherRetry=ETrue;
+ iFepSwitcher.RetryFailedKeyCaptures(needFurtherRetry);
+ if (needFurtherRetry)
+ {
+ ++iRetryCount;
+ DoActivate();
+ }
+ User::LeaveIfError(error);
+ }
+
+// CFepKeyDataListener
+
+CFepKeyDataListener* CFepKeyDataListener::NewLC(CFepSwitcher& aFepSwitcher, TUint32 aRepositoryKeyMask_OnOrOff, TInt32 CFepSwitcher::* aCaptureKeyHandleOrError, TFepOnOrOffKeyData CFepSwitcher::* aKeyDataToAssignTo)
+ {
+ CFepKeyDataListener* const self=new(ELeave) CFepKeyDataListener(aFepSwitcher, aRepositoryKeyMask_OnOrOff, aCaptureKeyHandleOrError, aKeyDataToAssignTo);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+CFepKeyDataListener::~CFepKeyDataListener()
+ {
+ Cancel();
+ delete iRepository;
+ }
+
+CFepKeyDataListener::CFepKeyDataListener(CFepSwitcher& aFepSwitcher, TUint32 aRepositoryKeyMask_OnOrOff, TInt32 CFepSwitcher::* aCaptureKeyHandleOrError, TFepOnOrOffKeyData CFepSwitcher::* aKeyDataToAssignTo)
+ :CActive(EPriorityStandard-1),
+ iFepSwitcher(aFepSwitcher),
+ iRepositoryKeyMask_OnOrOff(aRepositoryKeyMask_OnOrOff),
+ iRepository(NULL),
+ iCaptureKeyHandleOrError(aCaptureKeyHandleOrError),
+ iKeyDataToAssignTo(aKeyDataToAssignTo)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CFepKeyDataListener::ConstructL()
+ {
+ iRepository=CRepository::NewL(TUid::Uid(KUidFepFrameworkRepository));
+ SetFepSwitcherL();
+ Queue();
+ }
+
+void CFepKeyDataListener::SetFepSwitcherL()
+ {
+ TFepOnOrOffKeyData onOrOffKeyData(0, 0, 0);
+ TInt error=KErrNone;
+ CFepGenericGlobalSettings::ReadOnOrOffKeyData(*iRepository, onOrOffKeyData, iRepositoryKeyMask_OnOrOff, &error);
+ iFepSwitcher.SetOnOrOffKeyDataL(error, onOrOffKeyData, iCaptureKeyHandleOrError, iKeyDataToAssignTo);
+ }
+
+void CFepKeyDataListener::Queue()
+ {
+#if defined(_DEBUG)
+ const TInt error=
+#endif
+ iRepository->NotifyRequest(iRepositoryKeyMask_OnOrOff, ERepositoryKeyMask_OnKeyData|ERepositoryKeyMask_OffKeyData, iStatus);
+ __ASSERT_DEBUG(error==KErrNone, User::Invariant());
+ SetActive();
+ }
+
+void CFepKeyDataListener::DoCancel()
+ {
+ iRepository->NotifyCancel(iRepositoryKeyMask_OnOrOff, ERepositoryKeyMask_OnKeyData|ERepositoryKeyMask_OffKeyData);
+ }
+
+void CFepKeyDataListener::RunL()
+ {
+ const TInt error=iStatus.Int();
+ Queue();
+ User::LeaveIfError(error);
+ SetFepSwitcherL();
+ }
+
+// CNonPanickingScheduler
+
+class CNonPanickingScheduler : public CActiveScheduler
+ {
+public:
+ static CNonPanickingScheduler* NewLC();
+private:
+ // from CActiveScheduler
+ virtual void Error(TInt aError) const;
+ };
+
+CNonPanickingScheduler* CNonPanickingScheduler::NewLC()
+ { // static
+ CNonPanickingScheduler* const scheduler=new(ELeave) CNonPanickingScheduler;
+ CleanupStack::PushL(scheduler);
+ return scheduler;
+ }
+
+void CNonPanickingScheduler::Error(TInt) const
+ {
+ // don't panic here, like CActiveScheduler::Error does
+ }
+
+// top-level functions
+
+LOCAL_C void MainL()
+ {
+ CActiveScheduler* const activeScheduler=CNonPanickingScheduler::NewLC();
+ CActiveScheduler::Install(activeScheduler);
+ CFepSwitcher* const fepSwitcher=CFepSwitcher::NewLC();
+ RProcess::Rendezvous(KErrNone);
+ CActiveScheduler::Start();
+ CleanupStack::PopAndDestroy(2, activeScheduler);
+ }
+
+GLDEF_C TInt E32Main()
+ {
+ CTrapCleanup* const cleanup=CTrapCleanup::New();
+ if(cleanup == NULL)
+ {
+ return KErrNoMemory;
+ }
+ TRAPD(error, MainL());
+ delete cleanup;
+ return error;
+ }
+