diff -r 000000000000 -r eb1f2e154e89 fep/frontendprocessor/test/feps/TFEP2.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fep/frontendprocessor/test/feps/TFEP2.CPP Tue Feb 02 01:02:04 2010 +0200 @@ -0,0 +1,1694 @@ +// 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: +// + +/** + @file + @internalComponent +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tfep2.hrh" +#include "TFEP2.H" +#include "tfep2com.h" + +#define DEBUGGING_MESSAGES +#if defined(DEBUGGING_MESSAGES) +#include +#endif + +// constants + +enum TPanic + { + EPanicTimerActive1=1, + EPanicTimerActive2, + EPanicUnexpectedError1, + EPanicUnexpectedError2, + EPanicUnexpectedError3, + EPanicUnexpectedError4, + EPanicUnexpectedError5, + EPanicUnexpectedError6, + EPanicBadIndex1, + EPanicBadIndex2, + EPanicBadAttributeUid1, + EPanicBadAttributeUid2, + EPanicBadAttributeUid3, + EPanicBadAttributeUid4, + EPanicLowLevelFlagsDoNotReflectStateOfRemoteObjects, + EPanicArithmeticConfusion, + EPanicBadLengthOfTextBeforeSelection, + EPanicSelectionExtendsPastEndOfDocument, + EPanicBadLengthOfTextAfterSelection, + EPanicBadLengthOfSelection, + EPanicBadKeyCode1, + EPanicBadKeyCode2, + EPanicBadHeight, + EPanicIsAlreadyActive, + EPanicInconsistentUpperCaseSetting, + EPanicBadFlagAffectingWhetherActive, + EPanicBadKeyResponse, + EPanicBadCheckBoxState, + EPanicUnexpectedButtonId, + EPanicBadNumberOfAttributes + }; + +#if defined(_UNICODE) +const TUint KEllipsisCharacter=0x2026; +#else +const TUint KEllipsisCharacter=0x85; +#endif +_LIT(KLitTFEP2, "TFEP2"); +_LIT(KLitBitmapHandleSynchronizationMutexName, "0x10003eaa-Mutex"); // using the same UID here as in the MMP file +_LIT(KLitDllNameOfWindowServerPlugIn, "\\system\\fep\\TFEP2BE.ANI"); +_LIT(KLitStatusFontTypefaceName, "arial"); +_LIT(KLitNotAvailable, "[not available]"); +//_LIT(KLitTooLong, "[too long]"); +_LIT(KLitQuotationMark, "\""); +_LIT(KLitTextBeforeSelectionColonSpace, "Text before selection: "); +_LIT(KLitTextAfterSelectionColonSpace, "Text after selection: "); +_LIT(KLitSelectionColonSpace, "Selection: "); +_LIT(KLitUpperCaseColonSpace, "Upper case: "); +_LIT(KLitOn, "on"); +_LIT(KLitOff, "off"); +_LIT(KLitScribbleAreaColonSpace, "Scribble area: "); +_LIT(KLitWholeScreen, "whole screen"); +_LIT(KLitWindow, "window"); +_LIT(KLitPointerBufferColonSpace, "Pointer buffer: "); +_LIT(KLitEnabled, "enabled"); +_LIT(KLitDisabled, "disabled"); +_LIT(KLitOpeningSquareBracket, "["); +_LIT(KLitCaptionColonSpace, "Caption: "); +_LIT(KLitInputCapabilitiesColonSpace, "Input-capabilities: "); +_LIT(KLitNone, "none"); +_LIT(KLitWesternNumericIntegerPositive, "Western numeric integer positive"); +_LIT(KLitWesternNumericIntegerNegative, "Western numeric integer negative"); +_LIT(KLitWesternNumericReal, "Western numeric real"); +_LIT(KLitWesternAlphabetic, "Western alphabetic"); +_LIT(KLitJapaneseHiragana, "Japanese hiragana"); +_LIT(KLitJapaneseKatakanaHalfWidth, "Japanese katakana half-width"); +_LIT(KLitJapaneseKatakanaFullWidth, "Japanese katakana full-width"); +_LIT(KLitDialableCharacters, "dialable characters"); +_LIT(KLitSecretText, "secret text"); +_LIT(KLitAllText, "all text"); +_LIT(KLitNavigation, "navigation"); +_LIT(KLitCommaSpace, ", "); +_LIT(KLitClosingSquareBracket, "]"); + +// local and global functions + +LOCAL_C void Panic(TPanic aPanic) + { + User::Panic(KLitTFEP2, aPanic); + } + +GLDEF_C TInt E32Dll( + ) + { + return KErrNone; + } + +// CTstScribbleWindow + +CTstScribbleWindow* CTstScribbleWindow::NewL(CTstFep& aFep, RWindowTreeNode& aParent) + { + CTstScribbleWindow* const scribbleWindow=new(ELeave) CTstScribbleWindow(aFep); + CleanupStack::PushL(scribbleWindow); + scribbleWindow->ConstructL(aParent); + CleanupStack::Pop(); // scribbleWindow + return scribbleWindow; + } + +CTstScribbleWindow::~CTstScribbleWindow() + { + // there is no need here to call FreePointerMoveBuffer on the window, as the buffer gets freed when the window gets destroyed + iArrayOfPolyLines.ResetAndDestroy(); + iArrayOfPolyLines.Close(); + delete iTimeOutTimer; + } + +void CTstScribbleWindow::SetPointerBufferEnabled(TBool aPointerBufferEnabled) + { + RDrawableWindow& window=*DrawableWindow(); + if (!aPointerBufferEnabled!=!(iFlags&EFlagPointerBufferActuallyEnabled)) // fold non-zero values on both sides before comparing for inequality + { + if (aPointerBufferEnabled) + { + window.EnablePointerMoveBuffer(); + iFlags|=EFlagPointerBufferActuallyEnabled; + } + else + { + window.DisablePointerMoveBuffer(); + iFlags&=~EFlagPointerBufferActuallyEnabled; + } + } + } + +void CTstScribbleWindow::HandleTimeOutL() + { + TInt i; + TInt minimumX=KMaxTInt; + TInt maximumX=KMinTInt; + for (i=iArrayOfPolyLines.Count()-1; i>=0; --i) + { + const CArrayFix& polyLine=*iArrayOfPolyLines[i]; + for (TInt j=polyLine.Count()-1; j>=0; --j) + { + const TInt x=polyLine[j].iX; + if (minimumX>x) + { + minimumX=x; + } + if (maximumX* arrayOfCharacters=new(ELeave) CArrayFixFlat(numberOfCharacters); // a RArray would be better than a CArrayFix, but unfortunately RArray doesn't (yet) have a TArray interface + CleanupStack::PushL(arrayOfCharacters); + const TUint baseCharacter=iFep.UpperCase()? 'A': 'a'; + TTime homeTime; + homeTime.HomeTime(); + TInt64 seedForRandomNumber=homeTime.Int64(); + for (i=0; iAppendL(baseCharacter+(Math::Rand(seedForRandomNumber)%26)); + } + iFep.SimulateKeyEventsL(arrayOfCharacters->Array()); + CancelTransactionAndDrawNow(); + CleanupStack::PopAndDestroy(); // arrayOfCharacters + } + +void CTstScribbleWindow::CancelTransactionAndDrawNow() + { + TBool changeWasMade; + CancelTransaction(changeWasMade); + if (changeWasMade) + { + DrawNow(); + } + } + +void CTstScribbleWindow::CancelTransaction(TBool& aChangeWasMade) + { + aChangeWasMade=EFalse; + iTimeOutTimer->Cancel(); + if (iArrayOfPolyLines.Count()>0) + { + iArrayOfPolyLines.ResetAndDestroy(); + aChangeWasMade=ETrue; + } + } + +void CTstScribbleWindow::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + switch (aPointerEvent.iType) + { + case TPointerEvent::EDrag: + { + if (iFlags&EFlagPointerIsDown) // this test is needed in the case where there was a "leave" when handling the TRawEvent::EButton1Down event + { + __ASSERT_DEBUG(!iTimeOutTimer->IsActive(), Panic(EPanicTimerActive1)); + CArrayFix& polyLine=*iArrayOfPolyLines[iArrayOfPolyLines.Count()-1]; + polyLine.AppendL(aPointerEvent.iPosition); + ActivateGc(); + CWindowGc& graphicsContext=SystemGc(); + graphicsContext.SetPenStyle(CGraphicsContext::ESolidPen); + graphicsContext.SetPenColor(KRgbBlack); + graphicsContext.DrawLine(polyLine[polyLine.Count()-2], aPointerEvent.iPosition); + graphicsContext.Plot(aPointerEvent.iPosition); + DeactivateGc(); + } + } + break; + case TPointerEvent::EButton1Down: + { + iTimeOutTimer->Cancel(); + CArrayFix* const polyLine=new(ELeave) CArrayFixSeg(50); + CleanupStack::PushL(polyLine); + polyLine->AppendL(aPointerEvent.iPosition); + User::LeaveIfError(iArrayOfPolyLines.Append(polyLine)); + CleanupStack::Pop(); // polyLine + ActivateGc(); + CWindowGc& graphicsContext=SystemGc(); + graphicsContext.SetPenStyle(CGraphicsContext::ESolidPen); + graphicsContext.SetPenColor(KRgbBlack); + graphicsContext.Plot(aPointerEvent.iPosition); + DeactivateGc(); + iFlags|=EFlagPointerIsDown; + if (iArrayOfPolyLines.Count()==1) + { + iCoeEnv->ForEachFepObserverCall(FepObserverHandleStartOfTransactionL); // called at the end of handling this event as it may launch a waiting dialog + } + } + break; + case TPointerEvent::EButton1Up: + if (iFlags&EFlagPointerIsDown) // this test is needed in the cases where (i) there was a "leave" when handling the TRawEvent::EButton1Down event, and (ii) the window server sends a TPointerEvent::EButton1Up event if ClaimPointerGrab is called when the pointer is not down (this behaviour is the window-server's spec, it is not a bug) + { + __ASSERT_DEBUG(!iTimeOutTimer->IsActive(), Panic(EPanicTimerActive2)); + iTimeOutTimer->After(ETimeOutInMicroSeconds); + iFlags&=~EFlagPointerIsDown; + } + break; +#if defined(__GCC32__) + default: + break; +#endif + } + } + +void CTstScribbleWindow::HandlePointerBufferReadyL() + { + TPoint arrayOfPoints[ENumberOfPointsInBuffer]; + TPtr8 bufferOfPoints(REINTERPRET_CAST(TUint8*, arrayOfPoints), 0, ENumberOfPointsInBuffer*sizeof(TPoint)); + User::LeaveIfError(DrawableWindow()->RetrievePointerMoveBuffer(bufferOfPoints)); + if (iFlags&EFlagPointerIsDown) // this test is needed in the case where there was a "leave" when handling the TRawEvent::EButton1Down event + { + const TInt numberOfPointsInBuffer=bufferOfPoints.Length()/sizeof(TPoint); + if (numberOfPointsInBuffer>0) + { + CArrayFix& polyLine=*iArrayOfPolyLines[iArrayOfPolyLines.Count()-1]; + for (TInt i=0; i=0; --i) + { + graphicsContext.DrawPolyLine(iArrayOfPolyLines[i]); // draws the end-point of the last line segment of the poly-line + } + } + +// CTstScribbleWindow::CTimeOutTimer + +CTstScribbleWindow::CTimeOutTimer* CTstScribbleWindow::CTimeOutTimer::NewL(CTstScribbleWindow& aScribbleWindow) + { + CTimeOutTimer* const timeOutTimer=new(ELeave) CTimeOutTimer(aScribbleWindow); + CleanupStack::PushL(timeOutTimer); + CActiveScheduler::Add(timeOutTimer); + timeOutTimer->ConstructL(); + CleanupStack::Pop(); // timeOutTimer + return timeOutTimer; + } + +CTstScribbleWindow::CTimeOutTimer::~CTimeOutTimer() + { + Cancel(); + } + +CTstScribbleWindow::CTimeOutTimer::CTimeOutTimer(CTstScribbleWindow& aScribbleWindow) + :CTimer(EPriorityLow), + iScribbleWindow(aScribbleWindow) + { + } + +void CTstScribbleWindow::CTimeOutTimer::RunL() + { + iScribbleWindow.HandleTimeOutL(); + } + +// CTstWholeScreenScribbleArea + +CTstWholeScreenScribbleArea* CTstWholeScreenScribbleArea::NewL(RWsSession& aWindowServerSession, RWindowGroup& aWindowGroup, const TSize& aScreenSize, TDisplayMode aDisplayMode, const TDesC& aDllName) + { + CTstWholeScreenScribbleArea* const wholeScreenScribbleArea=new(ELeave) CTstWholeScreenScribbleArea(aWindowServerSession); + CleanupStack::PushL(wholeScreenScribbleArea); + wholeScreenScribbleArea->ConstructL(aWindowGroup, aScreenSize, aDisplayMode, aDllName); + CleanupStack::Pop(); // wholeScreenScribbleArea + return wholeScreenScribbleArea; + } + +CTstWholeScreenScribbleArea::~CTstWholeScreenScribbleArea() + { + if (iFlags&EFlagMutexIsConstructed) + { + iMutex.Wait(); + iHandWritingRecognizer.Close(); + iSprite.Close(); + iDll.Close(); + delete iSpriteMember.iBitmap; + delete iSpriteMember.iMaskBitmap; + iMutex.Signal(); + } + } + +CTstWholeScreenScribbleArea::CTstWholeScreenScribbleArea(RWsSession& aWindowServerSession) + :iFlags(0), + iDll(aWindowServerSession), + iSprite(aWindowServerSession) + { + iSpriteMember.iBitmap=NULL; + iSpriteMember.iMaskBitmap=NULL; + } + +void CTstWholeScreenScribbleArea::ConstructL(RWindowGroup& aWindowGroup, const TSize& aScreenSize, TDisplayMode aDisplayMode, const TDesC& aDllName) + { + // the mutex *must* be created first as it is used in the construction and destruction routines of this class + TInt error=iMutex.CreateGlobal(KLitBitmapHandleSynchronizationMutexName); + if (error==KErrAlreadyExists) + { + error=iMutex.OpenGlobal(KLitBitmapHandleSynchronizationMutexName); + } + User::LeaveIfError(error); + iFlags|=EFlagMutexIsConstructed; + iMutex.Wait(); + CleanupStack::PushL(TCleanupItem(SignalMutex, &iMutex)); + User::LeaveIfError(iDll.Load(aDllName)); + User::LeaveIfError(iSprite.Construct(aWindowGroup, TPoint(0, 0), ESpriteNoChildClip|ESpriteNoShadows)); + STstBitmapHandles bitmapHandles; + iHandWritingRecognizer=RHandWritingRecognizer(iDll); + iHandWritingRecognizer.ConstructL(iSprite, bitmapHandles); + iSpriteMember.iBitmap=CreateBitmapL(bitmapHandles.iMain, aScreenSize, aDisplayMode); + iSpriteMember.iMaskBitmap=CreateBitmapL(bitmapHandles.iMask, aScreenSize, aDisplayMode); + iSpriteMember.iInvertMask=ETrue; + iSpriteMember.iDrawMode=CGraphicsContext::EDrawModePEN; + iSpriteMember.iOffset.iX=0; + iSpriteMember.iOffset.iY=0; + iSpriteMember.iInterval=0; + User::LeaveIfError(iSprite.AppendMember(iSpriteMember)); + iHandWritingRecognizer.FinishConstructionL(); + CleanupStack::PopAndDestroy(); // TCleanupItem(SignalMutex, &iMutex) + } + +CFbsBitmap* CTstWholeScreenScribbleArea::CreateBitmapL(TInt aHandleOfBitmapToUse, const TSize& aScreenSize, TDisplayMode aDisplayMode) + { + CFbsBitmap* const bitmap=new(ELeave) CFbsBitmap; + CleanupStack::PushL(bitmap); + if (aHandleOfBitmapToUse!=0) + { + User::LeaveIfError(bitmap->Duplicate(aHandleOfBitmapToUse)); + } + else + { + User::LeaveIfError(bitmap->Create(aScreenSize, aDisplayMode)); // bitmaps are automatically cleared to white when first created + } + CleanupStack::Pop(); // bitmap + return bitmap; + } + +void CTstWholeScreenScribbleArea::SignalMutex(TAny* aMutex) + { + STATIC_CAST(RMutex*, aMutex)->Signal(); + } + +// CTstWholeScreenScribbleArea::RHandWritingRecognizer + +void CTstWholeScreenScribbleArea::RHandWritingRecognizer::ConstructL(const RWsSprite& aSprite, STstBitmapHandles& aBitmapHandles) + { + TPckg bitmapHandles(aBitmapHandles); + TIpcArgs ipcArgs; + ipcArgs.Set(EIpcSlot, &bitmapHandles); + User::LeaveIfError(RAnim::Construct(aSprite, EAnimTypeHandWritingRecognizer, KNullDesC8, ipcArgs)); + } + +void CTstWholeScreenScribbleArea::RHandWritingRecognizer::FinishConstructionL() + { + const TInt error=CommandReply(EHandWritingRecognizerCommandFinishConstructionL, KNullDesC8()); + __ASSERT_ALWAYS(error==KErrNone, Panic(EPanicUnexpectedError1)); + } + +void CTstWholeScreenScribbleArea::RHandWritingRecognizer::RequestNotificationOfStartOfTransaction(TRequestStatus& aRequestStatus) + { + AsyncCommandReply(aRequestStatus, EHandWritingRecognizerCommandRequestNotificationOfStartOfTransaction, TIpcArgs()); + } + +void CTstWholeScreenScribbleArea::RHandWritingRecognizer::CancelRequestForNotificationOfStartOfTransaction() + { + const TInt error=CommandReply(EHandWritingRecognizerCommandCancelRequestForNotificationOfStartOfTransaction); + __ASSERT_ALWAYS(error==KErrNone, Panic(EPanicUnexpectedError3)); + } + +void CTstWholeScreenScribbleArea::RHandWritingRecognizer::RequestCharacters(TRequestStatus& aRequestStatus, TDes8& aCharacterBuffer, TBool /*aUpperCase*/) + { + TIpcArgs ipcArgs; + ipcArgs.Set(EAsyncIpcSlot, &aCharacterBuffer); + AsyncCommandReply(aRequestStatus, EHandWritingRecognizerCommandRequestCharacters, ipcArgs); + } + +void CTstWholeScreenScribbleArea::RHandWritingRecognizer::CancelRequestForCharacters() + { + const TInt error=CommandReply(EHandWritingRecognizerCommandCancelRequestForCharacters); + __ASSERT_ALWAYS(error==KErrNone, Panic(EPanicUnexpectedError5)); + } + +void CTstWholeScreenScribbleArea::RHandWritingRecognizer::SetUpperCase(TBool aUpperCase) + { + TPckgBuf parameters; + parameters().iUpperCase=aUpperCase; + const TInt error=CommandReply(EHandWritingRecognizerCommandSetUpperCase, parameters); + __ASSERT_ALWAYS(error==KErrNone, Panic(EPanicUnexpectedError6)); + } + +// CTstControl + +CTstControl* CTstControl::NewL(CTstFep& aFep) + { + CTstControl* const control=new(ELeave) CTstControl(aFep); + CleanupStack::PushL(control); + control->ConstructL(); + CleanupStack::Pop(); // control + return control; + } + +CTstControl::~CTstControl() + { + delete iScribbleWindow; + delete iHandlerForStartOfTransaction; + delete iHandlerForCharacters; + delete iWholeScreenScribbleArea; // must be deleted after iHandlerForStartOfTransaction and iHandlerForCharacters as they both have a reference to it + iCoeEnv->ReleaseScreenFont(iStatusFont); + STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi())->RemoveFromStack(this); + } + +void CTstControl::CancelTransaction() + { + iScribbleWindow->CancelTransactionAndDrawNow(); + } + +void CTstControl::IsOnHasChangedState() + { + ChangeSetupAndDrawNow(NULL); + } + +void CTstControl::OfferPointerEventL(CCoeFep::TEventResponse& aEventResponse, const TPointerEvent& aPointerEvent, const CCoeControl* aWindowOwningControl) + { + // this function must correctly set aEventResponse *before* calling anything that can leave + if (aWindowOwningControl==this) + { + aEventResponse=CCoeFep::EEventWasConsumed; + HandlePointerEventL(aPointerEvent); + } + else if (aWindowOwningControl==iScribbleWindow) + { + aEventResponse=CCoeFep::EEventWasConsumed; + iScribbleWindow->HandlePointerEventL(aPointerEvent); + } + else + { + aEventResponse=CCoeFep::EEventWasNotConsumed; + } + } + +void CTstControl::OfferPointerBufferReadyEventL(CCoeFep::TEventResponse& aEventResponse, const CCoeControl* aWindowOwningControl) + { + // this function must correctly set aEventResponse *before* calling anything that can leave + if (aWindowOwningControl==iScribbleWindow) + { + aEventResponse=CCoeFep::EEventWasConsumed; + iScribbleWindow->HandlePointerBufferReadyL(); + } + else + { + aEventResponse=CCoeFep::EEventWasNotConsumed; + } + } + +TInt CTstControl::NumberOfAttributes() + { + return 3; + } + +TUid CTstControl::AttributeAtIndex(TInt aIndex) + { + switch (aIndex) + { + case 0: + return TUid::Uid(ETstUpperCaseUid); + case 1: + return TUid::Uid(ETstWholeScreenUid); + case 2: + return TUid::Uid(ETstPointerBufferEnabledUid); +#if defined(_DEBUG) + default: + Panic(EPanicBadIndex1); + break; +#endif + } + return KNullUid; + } + +void CTstControl::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream) const + { + switch (aAttributeUid.iUid) + { + case ETstUpperCaseUid: + aStream.WriteUint8L((iFlags&EFlagUpperCase)!=0); + break; + case ETstWholeScreenUid: + aStream.WriteUint8L((iFlags&EFlagWholeScreen)!=0); + break; + case ETstPointerBufferEnabledUid: + aStream.WriteUint8L((iFlags&EFlagPointerBufferEnabled)!=0); + break; +#if defined(_DEBUG) + default: + Panic(EPanicBadAttributeUid1); + break; +#endif + } + } + +void CTstControl::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream) + { + switch (aAttributeUid.iUid) + { + case ETstUpperCaseUid: + ChangeSetupAndDrawNow(SetUpperCase, aStream.ReadUint8L()); + break; + case ETstWholeScreenUid: + ChangeSetupAndDrawNow(SetWholeScreen, aStream.ReadUint8L()); + break; + case ETstPointerBufferEnabledUid: + ChangeSetupAndDrawNow(SetPointerBufferEnabled, aStream.ReadUint8L()); + break; +#if defined(_DEBUG) + default: + Panic(EPanicBadAttributeUid2); + break; +#endif + } + } + +void CTstControl::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream, TBool aUpperCase, TBool aWholeScreen, TBool aPointerBufferEnabled) + { + switch (aAttributeUid.iUid) + { + case ETstUpperCaseUid: + aStream.WriteUint8L(aUpperCase!=EFalse); + break; + case ETstWholeScreenUid: + aStream.WriteUint8L(aWholeScreen!=EFalse); + break; + case ETstPointerBufferEnabledUid: + aStream.WriteUint8L(aPointerBufferEnabled!=EFalse); + break; +#if defined(_DEBUG) + default: + Panic(EPanicBadAttributeUid3); + break; +#endif + } + } + +void CTstControl::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream, TBool& aUpperCase, TBool& aWholeScreen, TBool& aPointerBufferEnabled) + { + switch (aAttributeUid.iUid) + { + case ETstUpperCaseUid: + aUpperCase=aStream.ReadUint8L(); + break; + case ETstWholeScreenUid: + aWholeScreen=aStream.ReadUint8L(); + break; + case ETstPointerBufferEnabledUid: + aPointerBufferEnabled=aStream.ReadUint8L(); + break; +#if defined(_DEBUG) + default: + Panic(EPanicBadAttributeUid4); + break; +#endif + } + } + +void CTstControl::HandleGainingForeground() + { + DrawableWindow()->MoveToGroup(iCoeEnv->WsSession().GetFocusWindowGroup()); // ignore the error returned + ChangeSetupAndDrawNow(SetForeground, ETrue); + } + +void CTstControl::HandleLosingForeground() + { + ChangeSetupAndDrawNow(SetForeground, EFalse); + } + +void CTstControl::HandleChangeInFocus() + { + ChangeSetupAndDrawNow(SetInputCapabilities); + } + +void CTstControl::HandleDestructionOfFocusedItem() + { + if (!IsBeingDestroyed()) + { + ChangeSetupAndDrawNow(SetInputCapabilities); + } + } + +CTstControl::CTstControl(CTstFep& aFep) + :iFep(aFep), + iFlags(0), + iInputCapabilities(TCoeInputCapabilities::ENone), + iScribbleWindow(NULL), + iWholeScreenScribbleArea(NULL), + iHandlerForStartOfTransaction(NULL), + iHandlerForCharacters(NULL), + iStatusFont(NULL), + iPositionOnWindowBeingDragged(0, 0) + { + } + +void CTstControl::ConstructL() + { + RWindowGroup& windowGroup=iCoeEnv->RootWin(); + CreateWindowL(); + EnableDragEvents(); + ClaimPointerGrab(); + SetNonFocusing(); + RDrawableWindow& window=*DrawableWindow(); + window.SetOrdinalPosition(0, ECoeWinPriorityFep); + window.SetShadowHeight(3); + iScribbleWindow=CTstScribbleWindow::NewL(iFep, window); + RWsSession& windowServerSession=iCoeEnv->WsSession(); + CWsScreenDevice& screenDevice=*iCoeEnv->ScreenDevice(); + const TSize screenSize=screenDevice.SizeInPixels(); + iWholeScreenScribbleArea=CTstWholeScreenScribbleArea::NewL(windowServerSession, windowGroup, screenSize, screenDevice.DisplayMode(), KLitDllNameOfWindowServerPlugIn); + iHandlerForStartOfTransaction=CHandlerForStartOfTransaction::NewL(*iWholeScreenScribbleArea, *iCoeEnv); + const TBool foreground=(windowGroup.Identifier()==windowServerSession.GetFocusWindowGroup()); + iHandlerForCharacters=CHandlerForCharacters::NewL(*iWholeScreenScribbleArea, iFep, foreground); + iStatusFont=iCoeEnv->CreateScreenFontL(TFontSpec(KLitStatusFontTypefaceName, 120)); + const TInt statusFontHeightInPixels=iStatusFont->HeightInPixels(); + const TSize size(320, 1+EHeightOfScribbleWindow+EGapAboveTopLine+statusFontHeightInPixels+(4*(EGapBetweenEachLine+statusFontHeightInPixels))+EGapBelowBottomLine+1); + SetExtent(TPoint(screenSize.iWidth-(size.iWidth+10), screenSize.iHeight-(size.iHeight+10)), size); + iScribbleWindow->SetExtent(TPoint(1, 1), TSize(size.iWidth-2, EHeightOfScribbleWindow)); + STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi())->AddToStackL(this, ECoeStackPriorityFep, ECoeStackFlagRefusesFocus|ECoeStackFlagSharable); + __ASSERT_DEBUG((iFlags&EFlagActuallyWholeScreen)==0, Panic(EPanicLowLevelFlagsDoNotReflectStateOfRemoteObjects)); + ChangeSetupAndDrawNow(SetForeground, foreground); + ChangeSetupAndDrawNow(SetFocus, EFalse); + ChangeSetupAndDrawNow(SetUpperCase, EFalse); + ChangeSetupAndDrawNow(SetWholeScreen, ETrue); + ChangeSetupAndDrawNow(SetPointerBufferEnabled, ETrue); + ChangeSetupAndDrawNow(SetInputCapabilities); + } + +void CTstControl::SetForeground(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter) + { + SetFlag(aControl, aChangeWasMade, aParameter, EFlagForeground); + if (aChangeWasMade) + { + aControl.iHandlerForCharacters->SetForeground(aParameter); // background TFEP2 instances must not have a request for characters outstanding, as the corresponding server-side object may intercept raw events from the rightful TFEP2 instance in the foreground, hence the need for this function + if (aParameter) + { + aControl.iHandlerForCharacters->SetUpperCase(aControl.iFlags&EFlagUpperCase); + aControl.DoSetWholeScreen(aControl.iFlags&EFlagWholeScreen); + aControl.iScribbleWindow->SetPointerBufferEnabled(aControl.iFlags&EFlagPointerBufferEnabled); + } + } + } + +void CTstControl::SetFocus(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter) + { + aChangeWasMade=EFalse; + if (!aParameter!=!aControl.IsFocused()) // fold non-zero values on both sides before comparing for inequality + { + CCoeAppUi& appUi=*STATIC_CAST(CCoeAppUi*, aControl.iCoeEnv->AppUi()); + appUi.UpdateStackedControlFlags(&aControl, (aParameter? 0: ECoeStackFlagRefusesFocus), ECoeStackFlagRefusesFocus); + appUi.HandleStackChanged(); + aControl.iScribbleWindow->MakeVisible(!aParameter); + aChangeWasMade=ETrue; + } + } + +void CTstControl::SetUpperCase(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter) + { + SetFlag(aControl, aChangeWasMade, aParameter, EFlagUpperCase); + if (aChangeWasMade && (aControl.iFlags&EFlagForeground)) + { + aControl.iHandlerForCharacters->SetUpperCase(aParameter); + } + } + +void CTstControl::SetWholeScreen(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter) + { + SetFlag(aControl, aChangeWasMade, aParameter, EFlagWholeScreen); + if (aChangeWasMade && (aControl.iFlags&EFlagForeground)) + { + aControl.DoSetWholeScreen(aParameter); + } + } + +void CTstControl::SetPointerBufferEnabled(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter) + { + SetFlag(aControl, aChangeWasMade, aParameter, EFlagPointerBufferEnabled); + if (aChangeWasMade && (aControl.iFlags&EFlagForeground)) + { + aControl.iScribbleWindow->SetPointerBufferEnabled(aParameter); + } + } + +void CTstControl::SetInputCapabilities(CTstControl& aControl, TBool& aChangeWasMade, TInt) + { + aChangeWasMade=EFalse; + if (!aControl.IsFocused()) + { + const TCoeInputCapabilities inputCapabilities(STATIC_CAST(const CCoeAppUi*, aControl.iCoeEnv->AppUi())->InputCapabilities()); + if (aControl.iInputCapabilities!=inputCapabilities) + { + aControl.iInputCapabilities=inputCapabilities; + aChangeWasMade=ETrue; + } + } + } + +void CTstControl::SetFlag(CTstControl& aControl, TBool& aChangeWasMade, TInt aParameter, TUint aFlag) + { + aChangeWasMade=EFalse; + if (!aParameter!=!(aControl.iFlags&aFlag)) // fold non-zero values on both sides before comparing for inequality + { + aControl.iFlags^=aFlag; + aChangeWasMade=ETrue; + } + } + +void CTstControl::DoSetWholeScreen(TBool aWholeScreen) + { + if (!aWholeScreen!=!(iFlags&EFlagActuallyWholeScreen)) // fold non-zero values on both sides before comparing for inequality + { + TInt windowAdjustmentY; + TInt scribbleWindowPositionY; + if (aWholeScreen) + { + windowAdjustmentY=EHeightOfScribbleWindow; + scribbleWindowPositionY=-EHeightOfScribbleWindow; + iFlags|=EFlagActuallyWholeScreen; + } + else + { + windowAdjustmentY=-EHeightOfScribbleWindow; + scribbleWindowPositionY=1; + iFlags&=~EFlagActuallyWholeScreen; + } + iHandlerForCharacters->SetWholeScreen(aWholeScreen); + iScribbleWindow->SetPosition(TPoint(1, scribbleWindowPositionY)); + TRect rectangle(Position(), Size()); // creating rectangle from Rect() will give the wrong result as this control owns a window (its top left position would come out as TPoint(0, 0) rather than what Position() returns) + rectangle.iTl.iY+=windowAdjustmentY; + SetRect(rectangle); + } + } + +void CTstControl::ChangeSetupAndDrawNow(FChangeFunction aChangeFunction, TInt aParameter) + { + TBool needToDraw=EFalse; + { + TBool changeWasMade; + iScribbleWindow->CancelTransaction(changeWasMade); + if (changeWasMade) + { + needToDraw=ETrue; + } + } + if (aChangeFunction!=NULL) + { + TBool changeWasMade; + (*aChangeFunction)(*this, changeWasMade, aParameter); + if (changeWasMade) + { + needToDraw=ETrue; + } + } + const TBool isOn=iFep.IsOn(); + iHandlerForCharacters->SetIsOn(isOn); + const TBool shouldBeVisible=(isOn && (iFlags&EFlagForeground)); + if (!IsVisible()!=!shouldBeVisible) // fold non-zero values on both sides before comparing for inequality + { + MakeVisible(shouldBeVisible); + needToDraw=EFalse; + } + if (needToDraw) + { + DrawNow(); + } + } + +TKeyResponse CTstControl::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aEventCode) + { + // CTstFep::OfferKeyEventL assumes that this will not leave if it returns EKeyWasNotConsumed + FEP_START_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, aEventCode); + const TBool isFocused=IsFocused(); + const TCharUC keyCodeInUpperCase=aKeyEvent.iCode; + if ((aKeyEvent.iModifiers&EModifierRightShift) && !isFocused) + { + switch (keyCodeInUpperCase) + { + case 'F': + ChangeSetupAndDrawNow(SetFocus, ETrue); + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + case 'C': + ChangeSetupAndDrawNow(SetUpperCase, !(iFlags&EFlagUpperCase)); + iFep.WriteAttributeDataAndBroadcastL(TUid::Uid(ETstUpperCaseUid)); + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + case 'W': + ChangeSetupAndDrawNow(SetWholeScreen, !(iFlags&EFlagWholeScreen)); + iFep.WriteAttributeDataAndBroadcastL(TUid::Uid(ETstWholeScreenUid)); + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + case 'P': + ChangeSetupAndDrawNow(SetPointerBufferEnabled, !(iFlags&EFlagPointerBufferEnabled)); + iFep.WriteAttributeDataAndBroadcastL(TUid::Uid(ETstPointerBufferEnabledUid)); + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + case 'N': + { + const MCoeFepAwareTextEditor* const fepAwareTextEditor=iInputCapabilities.FepAwareTextEditor(); + if (fepAwareTextEditor==NULL) + { + User::InfoPrint(KLitNotAvailable); + } + else + { + TCursorSelection cursorSelection; + fepAwareTextEditor->GetCursorSelectionForFep(cursorSelection); + TPoint position; + TInt height; + TInt ascent; + fepAwareTextEditor->GetScreenCoordinatesForFepL(position,height,ascent,cursorSelection.LowerPos()); + position.iY+=height-ascent; + const TSize screenSize(iCoeEnv->ScreenDevice()->SizeInPixels()); + const TInt xMaximum=screenSize.iWidth-iSize.iWidth; + if ((position.iX<0) || (xMaximum<0)) + { + position.iX=0; + } + else if (position.iX>xMaximum) + { + position.iX=xMaximum; + } + const TInt yMaximum=screenSize.iHeight-iSize.iHeight; + if ((position.iY<0) || (yMaximum<0)) + { + position.iY=0; + } + else + { + const TInt yOverlapIfFepIsBelow=position.iY-yMaximum; + if (yOverlapIfFepIsBelow>0) + { + const TInt yPositionIfFepIsAbove=Max(0, position.iY-(height+iSize.iHeight)); + const TInt yOverlapIfFepIsAbove=(yPositionIfFepIsAbove+iSize.iHeight)-(position.iY-height); + if (yOverlapIfFepIsAbove textToDisplay; + if (fepAwareTextEditor==NULL) + { + textToDisplay=KLitNotAvailable; + } + else + { + TCursorSelection cursorSelection; + fepAwareTextEditor->GetCursorSelectionForFep(cursorSelection); + switch (keyCodeInUpperCase) + { + case 'B': + { + TInt lengthToRetrieve=EMaximumLengthOfDisplayOfContextInformation+1; + TInt documentPositionBeforeSelection=cursorSelection.LowerPos()-lengthToRetrieve; + if (documentPositionBeforeSelection<0) + { + lengthToRetrieve+=documentPositionBeforeSelection; // same as doing "lengthToRetrieve=cursorSelection.LowerPos()", hence the assert below + __ASSERT_DEBUG(lengthToRetrieve==cursorSelection.LowerPos(), Panic(EPanicArithmeticConfusion)); + documentPositionBeforeSelection=0; + } + fepAwareTextEditor->GetEditorContentForFep(textToDisplay, documentPositionBeforeSelection, lengthToRetrieve); + const TInt lengthOfTextBeforeSelection=textToDisplay.Length(); + if (lengthOfTextBeforeSelection>EMaximumLengthOfDisplayOfContextInformation) + { + textToDisplay.Delete(0, (lengthOfTextBeforeSelection-EMaximumLengthOfDisplayOfContextInformation)-1); + __ASSERT_DEBUG(textToDisplay.Length()==EMaximumLengthOfDisplayOfContextInformation+1, Panic(EPanicBadLengthOfTextBeforeSelection)); + textToDisplay[0]=KEllipsisCharacter; + } + } + textToDisplay.Insert(0, KLitQuotationMark); + textToDisplay.Append(KLitQuotationMark); + textToDisplay.Insert(0, KLitTextBeforeSelectionColonSpace); + break; + case 'A': + { + const TInt documentLength=fepAwareTextEditor->DocumentLengthForFep(); + const TInt documentPositionAfterSelection=cursorSelection.HigherPos()+1; + if (documentPositionAfterSelection>documentLength) + { + __ASSERT_DEBUG(documentPositionAfterSelection==documentLength+1, Panic(EPanicSelectionExtendsPastEndOfDocument)); + } + else + { + fepAwareTextEditor->GetEditorContentForFep(textToDisplay, documentPositionAfterSelection, EMaximumLengthOfDisplayOfContextInformation+1); + const TInt lengthOfTextAfterSelection=textToDisplay.Length(); + if (lengthOfTextAfterSelection>EMaximumLengthOfDisplayOfContextInformation) + { + textToDisplay.Delete(EMaximumLengthOfDisplayOfContextInformation, (lengthOfTextAfterSelection-EMaximumLengthOfDisplayOfContextInformation)-1); + __ASSERT_DEBUG(textToDisplay.Length()==EMaximumLengthOfDisplayOfContextInformation+1, Panic(EPanicBadLengthOfTextAfterSelection)); + textToDisplay[EMaximumLengthOfDisplayOfContextInformation]=KEllipsisCharacter; + } + } + } + textToDisplay.Insert(0, KLitQuotationMark); + textToDisplay.Append(KLitQuotationMark); + textToDisplay.Insert(0, KLitTextAfterSelectionColonSpace); + break; + case 'S': + fepAwareTextEditor->GetEditorContentForFep(textToDisplay, cursorSelection.LowerPos(), EMaximumLengthOfDisplayOfContextInformation+1); + { + const TInt lengthOfSelection=textToDisplay.Length(); + if (lengthOfSelection>EMaximumLengthOfDisplayOfContextInformation) + { + textToDisplay.Delete(EMaximumLengthOfDisplayOfContextInformation, (lengthOfSelection-EMaximumLengthOfDisplayOfContextInformation)-1); + __ASSERT_DEBUG(textToDisplay.Length()==EMaximumLengthOfDisplayOfContextInformation+1, Panic(EPanicBadLengthOfSelection)); + textToDisplay[EMaximumLengthOfDisplayOfContextInformation]=KEllipsisCharacter; + } + } + textToDisplay.Insert(0, KLitQuotationMark); + textToDisplay.Append(KLitQuotationMark); + textToDisplay.Insert(0, KLitSelectionColonSpace); + break; +#if defined(_DEBUG) + default: + Panic(EPanicBadKeyCode1); + break; +#endif + } + } + User::InfoPrint(textToDisplay); + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + } + } + } + switch (keyCodeInUpperCase) + { + case EKeyEnter: + case EKeyEscape: + if (isFocused) + { + ChangeSetupAndDrawNow(SetFocus, EFalse); + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + } + break; + case EKeyHome: + case EKeyEnd: + case EKeyPageUp: + case EKeyPageDown: + case EKeyLeftArrow: + case EKeyRightArrow: + case EKeyUpArrow: + case EKeyDownArrow: + if (isFocused) + { + TPoint offset(0, 0); + TInt magnification=10; + switch (keyCodeInUpperCase) + { + case EKeyLeftArrow: + offset.iX=-1; + break; + case EKeyRightArrow: + offset.iX=1; + break; + case EKeyUpArrow: + offset.iY=-1; + break; + case EKeyDownArrow: + offset.iY=1; + break; + case EKeyHome: + offset.iX=-iPosition.iX; + offset.iY=-iPosition.iY; + magnification=1; + break; + case EKeyEnd: + { + const TSize screenWidth(iCoeEnv->ScreenDevice()->SizeInPixels()); + offset.iX=(screenWidth.iWidth-iSize.iWidth)-iPosition.iX; + offset.iY=(screenWidth.iHeight-iSize.iHeight)-iPosition.iY; + } + magnification=1; + break; + case EKeyPageUp: + offset.iY=-iSize.iHeight; + magnification=1; + break; + case EKeyPageDown: + offset.iY=iSize.iHeight; + magnification=1; + break; +#if defined(_DEBUG) + default: + Panic(EPanicBadKeyCode2); + break; +#endif + } + if (aKeyEvent.iModifiers&EModifierCtrl) + { + offset.iX*=magnification; + offset.iY*=magnification; + } + SetPosition(TPoint(iPosition.iX+offset.iX, iPosition.iY+offset.iY)); + if (iFlags&EFlagWindowIsBeingDragged) + { + iPositionOnWindowBeingDragged.iX-=offset.iX; + iPositionOnWindowBeingDragged.iY-=offset.iY; + } + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + } + break; + default: + if (isFocused) + { + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasConsumed); // returns from this function + } + break; + } + FEP_END_KEY_EVENT_HANDLER_L(iFep, aKeyEvent, EKeyWasNotConsumed); // returns from this function + } + +void CTstControl::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + switch (aPointerEvent.iType) + { + case TPointerEvent::EButton1Down: + case TPointerEvent::EDrag: + if (iFlags&EFlagWindowIsBeingDragged) + { + SetPosition(aPointerEvent.iParentPosition-iPositionOnWindowBeingDragged); + } + else + { + iFlags|=EFlagWindowIsBeingDragged; + iPositionOnWindowBeingDragged=aPointerEvent.iPosition; + } + break; + case TPointerEvent::EButton1Up: + iFlags&=~EFlagWindowIsBeingDragged; + break; +#if defined(__GCC32__) + default: + break; +#endif + } + } + +TInt CTstControl::CountComponentControls() const + { + return 1; + } + +CCoeControl* CTstControl::ComponentControl(TInt aIndex) const + { + switch (aIndex) + { + case 0: + return iScribbleWindow; + default: +#if defined(_DEBUG) + Panic(EPanicBadIndex2); +#endif + return NULL; + } + } + +void CTstControl::Draw(const TRect&) const + { + CWindowGc& graphicsContext=SystemGc(); + graphicsContext.SetPenStyle(CGraphicsContext::ESolidPen); + graphicsContext.SetPenColor(KRgbBlack); + graphicsContext.SetBrushStyle(CGraphicsContext::ENullBrush); + TRect rectangle(Rect()); + graphicsContext.DrawRect(rectangle); + rectangle.Shrink(1, 1); + graphicsContext.SetBrushStyle(CGraphicsContext::ESolidBrush); + if (IsFocused()) + { + // the pen color is still black here + graphicsContext.SetBrushColor(KRgbBlack); + graphicsContext.DrawRect(rectangle); + const TPoint center=rectangle.Center(); + graphicsContext.SetPenColor(KRgbWhite); + const TPoint leftArrowHead((rectangle.iTl.iX+center.iX)/2, center.iY); + const TPoint rightArrowHead((center.iX+rectangle.iBr.iX)/2, center.iY); + const TPoint topArrowHead(center.iX, (rectangle.iTl.iY+center.iY)/2); + const TPoint bottomArrowHead(center.iX, (center.iY+rectangle.iBr.iY)/2); + graphicsContext.DrawLine(leftArrowHead, rightArrowHead); + graphicsContext.Plot(rightArrowHead); + graphicsContext.DrawLine(topArrowHead, bottomArrowHead); + graphicsContext.Plot(bottomArrowHead); + graphicsContext.DrawLine(TPoint(leftArrowHead.iX+EArrowHeadSize, leftArrowHead.iY+EArrowHeadSize), leftArrowHead); + graphicsContext.DrawLine(TPoint(leftArrowHead.iX+EArrowHeadSize, leftArrowHead.iY-EArrowHeadSize), leftArrowHead); + graphicsContext.DrawLine(TPoint(rightArrowHead.iX-EArrowHeadSize, rightArrowHead.iY-EArrowHeadSize), rightArrowHead); + graphicsContext.DrawLine(TPoint(rightArrowHead.iX-EArrowHeadSize, rightArrowHead.iY+EArrowHeadSize), rightArrowHead); + graphicsContext.DrawLine(TPoint(topArrowHead.iX-EArrowHeadSize, topArrowHead.iY+EArrowHeadSize), topArrowHead); + graphicsContext.DrawLine(TPoint(topArrowHead.iX+EArrowHeadSize, topArrowHead.iY+EArrowHeadSize), topArrowHead); + graphicsContext.DrawLine(TPoint(bottomArrowHead.iX+EArrowHeadSize, bottomArrowHead.iY-EArrowHeadSize), bottomArrowHead); + graphicsContext.DrawLine(TPoint(bottomArrowHead.iX-EArrowHeadSize, bottomArrowHead.iY-EArrowHeadSize), bottomArrowHead); + } + else + { + TRect temp(rectangle); + if (~iFlags&EFlagWholeScreen) + { + temp.iTl.iY+=EHeightOfScribbleWindow; + } + temp.iBr.iY=temp.iTl.iY; + graphicsContext.SetBrushColor(KRgbGray); + graphicsContext.UseFont(iStatusFont); + TBuf<200> textToDisplay; + const TInt statusFontHeightInPixels=iStatusFont->HeightInPixels(); + const TInt statusFontAscentInPixels=iStatusFont->AscentInPixels(); + textToDisplay=KLitUpperCaseColonSpace; + textToDisplay.Append((iFlags&EFlagUpperCase)? KLitOn(): KLitOff()); + temp.iBr.iY+=EGapAboveTopLine+statusFontHeightInPixels+EGapBetweenEachLine; + graphicsContext.DrawText(textToDisplay, temp, EGapAboveTopLine+statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine); + textToDisplay=KLitScribbleAreaColonSpace; + textToDisplay.Append((iFlags&EFlagWholeScreen)? KLitWholeScreen(): KLitWindow()); + temp.iTl.iY=temp.iBr.iY; + temp.iBr.iY+=statusFontHeightInPixels+EGapBetweenEachLine; + graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine); + textToDisplay=KLitPointerBufferColonSpace; + textToDisplay.Append((iFlags&EFlagPointerBufferEnabled)? KLitEnabled(): KLitDisabled()); + temp.iTl.iY=temp.iBr.iY; + temp.iBr.iY+=statusFontHeightInPixels+EGapBetweenEachLine; + graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine); + textToDisplay=KLitOpeningSquareBracket; + textToDisplay.Append(KLitCaptionColonSpace); + textToDisplay.Append(KLitQuotationMark); + const MCoeCaptionRetrieverForFep* captionRetrieverForFep=iInputCapabilities.CaptionRetrieverForFep(); + if (captionRetrieverForFep!=NULL) + { + TBuf<51> caption; + captionRetrieverForFep->GetCaptionForFep(caption); + const TInt captionLength=caption.Length(); + if (captionLength==caption.MaxLength()) + { + caption[captionLength-1]=KEllipsisCharacter; + } + textToDisplay.Append(caption); + } + textToDisplay.Append(KLitQuotationMark); + textToDisplay.Append(KLitClosingSquareBracket); + temp.iTl.iY=temp.iBr.iY; + temp.iBr.iY+=statusFontHeightInPixels+EGapBetweenEachLine; + graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine); + textToDisplay=KLitOpeningSquareBracket; + textToDisplay.Append(KLitInputCapabilitiesColonSpace); + if (iInputCapabilities.IsNone()) + { + textToDisplay.Append(KLitNone); + } + else + { + TBool deleteLastSeparator=EFalse; + if (iInputCapabilities.SupportsWesternNumericIntegerPositive()) + { + textToDisplay.Append(KLitWesternNumericIntegerPositive); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsWesternNumericIntegerNegative()) + { + textToDisplay.Append(KLitWesternNumericIntegerNegative); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsWesternNumericReal()) + { + textToDisplay.Append(KLitWesternNumericReal); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsWesternAlphabetic()) + { + textToDisplay.Append(KLitWesternAlphabetic); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsJapaneseHiragana()) + { + textToDisplay.Append(KLitJapaneseHiragana); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsJapaneseKatakanaHalfWidth()) + { + textToDisplay.Append(KLitJapaneseKatakanaHalfWidth); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsJapaneseKatakanaFullWidth()) + { + textToDisplay.Append(KLitJapaneseKatakanaFullWidth); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsDialableCharacters()) + { + textToDisplay.Append(KLitDialableCharacters); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsSecretText()) + { + textToDisplay.Append(KLitSecretText); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsAllText()) + { + textToDisplay.Append(KLitAllText); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (iInputCapabilities.SupportsNavigation()) + { + textToDisplay.Append(KLitNavigation); + textToDisplay.Append(KLitCommaSpace); + deleteLastSeparator=ETrue; + } + if (deleteLastSeparator) + { + const TInt lengthToDelete=KLitCommaSpace().Length(); + textToDisplay.Delete(textToDisplay.Length()-lengthToDelete, lengthToDelete); + } + } + textToDisplay.Append(KLitClosingSquareBracket); + temp.iTl.iY=temp.iBr.iY; + temp.iBr.iY=rectangle.iBr.iY; + __ASSERT_DEBUG(temp.iBr.iY==temp.iTl.iY+statusFontHeightInPixels+EGapBelowBottomLine, Panic(EPanicBadHeight)); + graphicsContext.DrawText(textToDisplay, temp, statusFontAscentInPixels, CGraphicsContext::ELeft, EGapLeftOfEachLine); + graphicsContext.DiscardFont(); + } + } + +// CTstControl::CHandlerForStartOfTransaction + +CTstControl::CHandlerForStartOfTransaction* CTstControl::CHandlerForStartOfTransaction::NewL(CTstWholeScreenScribbleArea& aWholeScreenScribbleArea, CCoeEnv& aConeEnvironment) + { + return new(ELeave) CHandlerForStartOfTransaction(aWholeScreenScribbleArea, aConeEnvironment); + } + +CTstControl::CHandlerForStartOfTransaction::~CHandlerForStartOfTransaction() + { + Cancel(); + } + +CTstControl::CHandlerForStartOfTransaction::CHandlerForStartOfTransaction(CTstWholeScreenScribbleArea& aWholeScreenScribbleArea, CCoeEnv& aConeEnvironment) + :CActive(EActivePriorityWsEvents), + iWholeScreenScribbleArea(aWholeScreenScribbleArea), + iConeEnvironment(aConeEnvironment) + { + CActiveScheduler::Add(this); + RequestNotificationOfStartOfTransaction(); + } + +void CTstControl::CHandlerForStartOfTransaction::RequestNotificationOfStartOfTransaction() + { + iWholeScreenScribbleArea.RequestNotificationOfStartOfTransaction(iStatus); + SetActive(); + } + +void CTstControl::CHandlerForStartOfTransaction::DoCancel() + { + iWholeScreenScribbleArea.CancelRequestForNotificationOfStartOfTransaction(); + } + +void CTstControl::CHandlerForStartOfTransaction::RunL() + { + RequestNotificationOfStartOfTransaction(); + iConeEnvironment.ForEachFepObserverCall(FepObserverHandleStartOfTransactionL); // called at the end of handling this event as it may launch a waiting dialog + } + +// CTstControl::CHandlerForCharacters + +CTstControl::CHandlerForCharacters* CTstControl::CHandlerForCharacters::NewL(CTstWholeScreenScribbleArea& aWholeScreenScribbleArea, CTstFep& aFep, TBool aForeground) + { + return new(ELeave) CHandlerForCharacters(aWholeScreenScribbleArea, aFep, aForeground); + } + +CTstControl::CHandlerForCharacters::~CHandlerForCharacters() + { + Cancel(); + } + +void CTstControl::CHandlerForCharacters::SetUpperCase(TBool aUpperCase) + { + if (!aUpperCase!=!(iFlags&EFlagUpperCase)) // fold non-zero values on both sides before comparing for inequality + { + iFlags^=EFlagUpperCase; + if (IsActive()) + { + iWholeScreenScribbleArea.SetUpperCase(aUpperCase); + } + } + __ASSERT_DEBUG(!(iFlags&EFlagUpperCase)==!aUpperCase, Panic(EPanicInconsistentUpperCaseSetting)); // fold non-zero values on both sides before comparing for equality + } + +CTstControl::CHandlerForCharacters::CHandlerForCharacters(CTstWholeScreenScribbleArea& aWholeScreenScribbleArea, CTstFep& aFep, TBool aForeground) + :CActive(EActivePriorityWsEvents), + iWholeScreenScribbleArea(aWholeScreenScribbleArea), + iFep(aFep), + iFlags(aForeground? EFlagForeground: 0) + { + CActiveScheduler::Add(this); + } + +void CTstControl::CHandlerForCharacters::SetFlagAffectingWhetherActive(TUint aFlagAffectingWhetherActive, TBool aSetting) + { + const TUint flagsAffectingWhetherActive=(EFlagWholeScreen|EFlagIsOn|EFlagForeground); + __ASSERT_DEBUG(aFlagAffectingWhetherActive&flagsAffectingWhetherActive, Panic(EPanicBadFlagAffectingWhetherActive)); + const TUint oldFlags=iFlags; + if (aSetting) + { + iFlags|=aFlagAffectingWhetherActive; + } + else + { + iFlags&=~aFlagAffectingWhetherActive; + } + if ((iFlags^oldFlags)&flagsAffectingWhetherActive) + { + if ((iFlags&flagsAffectingWhetherActive)==flagsAffectingWhetherActive) + { + RequestCharacters(); + } + else if ((oldFlags&flagsAffectingWhetherActive)==flagsAffectingWhetherActive) + { + Cancel(); + } + } + } + +void CTstControl::CHandlerForCharacters::RequestCharacters() + { + iWholeScreenScribbleArea.RequestCharacters(iStatus, iCharacterBuffer, iFlags&EFlagUpperCase); + SetActive(); + } + +TInt CTstControl::CHandlerForCharacters::NumberOfCharactersInBuffer(const CBase* aCharacterBuffer) + { + const TDesC8& characterBuffer=*REINTERPRET_CAST(const TDesC8*, aCharacterBuffer); + return characterBuffer.Length()/sizeof(TUint); + } + +const TAny* CTstControl::CHandlerForCharacters::CharacterInBuffer(const CBase* aCharacterBuffer, TInt aIndex) + { + const TDesC8& characterBuffer=*REINTERPRET_CAST(const TDesC8*, aCharacterBuffer); + return characterBuffer.Ptr()+(aIndex*sizeof(TUint)); + } + +void CTstControl::CHandlerForCharacters::DoCancel() + { + iWholeScreenScribbleArea.CancelRequestForCharacters(); + } + +void CTstControl::CHandlerForCharacters::RunL() + { + TBuf8 characterBuffer=iCharacterBuffer; + RequestCharacters(); // calling RequestCharacters may complete immediately (thus trashing iCharacterBuffer), hence why iCharacterBuffer was copied to a temporary buffer first + iFep.SimulateKeyEventsL(TArray(NumberOfCharactersInBuffer, CharacterInBuffer, REINTERPRET_CAST(const CBase*, &characterBuffer))); + } + +// CTstFep + +CTstFep::CTstFep(CCoeEnv& aConeEnvironment) + :CCoeFep(aConeEnvironment) + { + } + +void CTstFep::ConstructL(const CCoeFepParameters& aFepParameters) + { + BaseConstructL(aFepParameters); + iControl=CTstControl::NewL(*this); + ReadAllAttributesL(); + iControl->ActivateL(); + } + +CTstFep::~CTstFep() + { + delete iControl; + } + +void CTstFep::CancelTransaction() + { + iControl->CancelTransaction(); + } + +void CTstFep::IsOnHasChangedState() + { + iControl->IsOnHasChangedState(); + } + +void CTstFep::OfferKeyEventL(TEventResponse& aEventResponse, const TKeyEvent& aKeyEvent, TEventCode aEventCode) + { + // this function must correctly set aEventResponse *before* calling anything that can leave + aEventResponse=EEventWasConsumed; // this assumes that CTstControl::OfferKeyEventL will not leave if it returns EKeyWasNotConsumed + switch (iControl->OfferKeyEventL(aKeyEvent, aEventCode)) + { + case EKeyWasNotConsumed: + aEventResponse=EEventWasNotConsumed; + break; + case EKeyWasConsumed: + aEventResponse=EEventWasConsumed; + break; +#if defined(_DEBUG) + default: + Panic(EPanicBadKeyResponse); + break; +#endif + } + } + +void CTstFep::OfferPointerEventL(TEventResponse& aEventResponse, const TPointerEvent& aPointerEvent, const CCoeControl* aWindowOwningControl) + { + iControl->OfferPointerEventL(aEventResponse, aPointerEvent, aWindowOwningControl); + } + +void CTstFep::OfferPointerBufferReadyEventL(TEventResponse& aEventResponse, const CCoeControl* aWindowOwningControl) + { + iControl->OfferPointerBufferReadyEventL(aEventResponse, aWindowOwningControl); + } + +TInt CTstFep::NumberOfAttributes() const + { + return CTstControl::NumberOfAttributes(); + } + +TUid CTstFep::AttributeAtIndex(TInt aIndex) const + { + return CTstControl::AttributeAtIndex(aIndex); + } + +void CTstFep::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream) const + { + iControl->WriteAttributeDataToStreamL(aAttributeUid, aStream); + } + +void CTstFep::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream) + { + iControl->ReadAttributeDataFromStreamL(aAttributeUid, aStream); + } + +void CTstFep::HandleGainingForeground() + { + iControl->HandleGainingForeground(); + } + +void CTstFep::HandleLosingForeground() + { + iControl->HandleLosingForeground(); + } + +void CTstFep::HandleChangeInFocus() + { + iControl->HandleChangeInFocus(); + } + +void CTstFep::HandleDestructionOfFocusedItem() + { + iControl->HandleDestructionOfFocusedItem(); + } + +// TTstResourceFileId + +#pragma warning(disable: 4355) // "'this' : used in base member initializer list" + +TTstResourceFileId::TTstResourceFileId(CCoeEnv& aConeEnvironment, TInt aResourceFileId) + :TCleanupItem(UnloadResourceFile, this), + iConeEnvironment(aConeEnvironment), + iResourceFileId(aResourceFileId) + { + } + +#pragma warning(default: 4355) + +void TTstResourceFileId::UnloadResourceFile(TAny* aThis) + { + TTstResourceFileId& resourceFileId=*STATIC_CAST(TTstResourceFileId*, aThis); + resourceFileId.iConeEnvironment.DeleteResourceFile(resourceFileId.iResourceFileId); + } + +// CTstSettingsDialog + +CTstSettingsDialog::CTstSettingsDialog() + :iFlags(0) + { + } + +TUint CTstSettingsDialog::CheckBoxStateAsFlag(TInt aControlId, TUint aFlag) const + { + switch (STATIC_CAST(CEikCheckBox*, Control(aControlId))->State()) + { + case CEikButtonBase::EClear: + return 0; + case CEikButtonBase::ESet: + return aFlag; + case CEikButtonBase::EIndeterminate: + default: +#if defined(_DEBUG) + Panic(EPanicBadCheckBoxState); +#endif + return 0; + } + } + +void CTstSettingsDialog::SetCheckBoxState(TInt aControlId, TUint aFlag) + { + STATIC_CAST(CEikCheckBox*, Control(aControlId))->SetState(iFlags&aFlag? CEikButtonBase::ESet: CEikButtonBase::EClear); + } + +TBool CTstSettingsDialog::OkToExitL(TInt aButtonId) + { + __ASSERT_ALWAYS(aButtonId==EEikBidOk, Panic(EPanicUnexpectedButtonId)); + iFlags=CheckBoxStateAsFlag(EControlIdUpperCase, EFlagUpperCase)| + CheckBoxStateAsFlag(EControlIdWholeScreen, EFlagWholeScreen)| + CheckBoxStateAsFlag(EControlIdPointerBufferEnabled, EFlagPointerBufferEnabled); + TFixedArray attributeUids; + __ASSERT_DEBUG(NumberOfAttributes()==3, Panic(EPanicBadNumberOfAttributes)); + attributeUids[0].iUid=AttributeAtIndex(0).iUid; + attributeUids[1].iUid=AttributeAtIndex(1).iUid; + attributeUids[2].iUid=AttributeAtIndex(2).iUid; + WriteAttributeDataAndBroadcastL(*iCoeEnv, attributeUids.Array()); + return ETrue; + } + +void CTstSettingsDialog::PreLayoutDynInitL() + { + ReadAllAttributesL(*iCoeEnv); + SetCheckBoxState(EControlIdUpperCase, EFlagUpperCase); + SetCheckBoxState(EControlIdWholeScreen, EFlagWholeScreen); + SetCheckBoxState(EControlIdPointerBufferEnabled, EFlagPointerBufferEnabled); + } + +TInt CTstSettingsDialog::NumberOfAttributes() const + { + return CTstControl::NumberOfAttributes(); + } + +TUid CTstSettingsDialog::AttributeAtIndex(TInt aIndex) const + { + return CTstControl::AttributeAtIndex(aIndex); + } + +void CTstSettingsDialog::WriteAttributeDataToStreamL(TUid aAttributeUid, RWriteStream& aStream) const + { + CTstControl::WriteAttributeDataToStreamL(aAttributeUid, aStream, iFlags&EFlagUpperCase, iFlags&EFlagWholeScreen, iFlags&EFlagPointerBufferEnabled); + } + +void CTstSettingsDialog::ReadAttributeDataFromStreamL(TUid aAttributeUid, RReadStream& aStream) + { + TBool upperCase; + TBool wholeScreen; + TBool pointerBufferEnabled; + CTstControl::ReadAttributeDataFromStreamL(aAttributeUid, aStream, upperCase, wholeScreen, pointerBufferEnabled); + iFlags=0; + if (upperCase) + { + iFlags|=EFlagUpperCase; + } + if (wholeScreen) + { + iFlags|=EFlagWholeScreen; + } + if (pointerBufferEnabled) + { + iFlags|=EFlagPointerBufferEnabled; + } + } +